From 645caf36dfb92dcba140abe25f13b9eff06ed329 Mon Sep 17 00:00:00 2001 From: Dimitar Tasev <dimtasev@gmail.com> Date: Fri, 19 May 2017 17:47:14 +0100 Subject: [PATCH] Re #xxx remove tomo files --- Framework/Algorithms/CMakeLists.txt | 11 - .../MantidAlgorithms/Tomography/FBPTomopy.h | 45 - .../MantidAlgorithms/Tomography/tomopy/fbp.h | 34 - .../Tomography/tomopy/utils.h | 103 - .../src/ImggTomographicReconstruction.cpp | 405 ---- .../Algorithms/src/Tomography/FBPTomopy.cpp | 15 - .../Algorithms/src/Tomography/tomopy/fbp.c | 160 -- .../Algorithms/src/Tomography/tomopy/utils.c | 207 -- .../test/Tomography/FBPTomopyTest.h | 114 - Framework/DataHandling/CMakeLists.txt | 3 - .../MantidDataHandling/LoadSavuTomoConfig.h | 75 - .../src/ImggAggregateWavelengths.cpp | 906 -------- .../DataHandling/src/LoadSavuTomoConfig.cpp | 206 -- .../DataHandling/src/SaveSavuTomoConfig.cpp | 206 -- .../test/LoadSavuTomoConfigTest.h | 189 -- .../test/SaveSavuTomoConfigTest.h | 177 -- .../src/SCARFTomoReconstruction.cpp | 1498 ------------- .../test/SCARFTomoReconstructionTest.h | 683 ------ MantidQt/CustomInterfaces/CMakeLists.txt | 65 - .../Tomography/IImggFormatsConvertPresenter.h | 60 - .../Tomography/IImggFormatsConvertView.h | 183 -- .../Tomography/ITomographyIfacePresenter.h | 73 - .../Tomography/ITomographyIfaceView.h | 323 --- .../Tomography/ITomographyROIPresenter.h | 85 - .../Tomography/ITomographyROIView.h | 290 --- .../Tomography/ImageSelectCoRAndRegions.ui | 933 -------- .../Tomography/ImageStackPreParams.h | 62 - .../Tomography/ImggFormats.h | 55 - .../Tomography/ImggFormatsConvert.ui | 350 --- .../Tomography/ImggFormatsConvertPresenter.h | 105 - .../ImggFormatsConvertViewQtWidget.h | 129 -- .../Tomography/StackOfImagesDirs.h | 102 - .../Tomography/TomoPathsConfig.h | 145 -- .../Tomography/TomoRecToolConfig.h | 121 -- .../Tomography/TomoReconFiltersSettings.h | 52 - .../Tomography/TomoReconPostprocSettings.h | 44 - .../Tomography/TomoReconPreprocSettings.h | 58 - .../Tomography/TomoReconToolsUserSettings.h | 55 - .../Tomography/TomoSystemSettings.h | 75 - .../Tomography/TomoSystemSettingsLocal.h | 58 - .../Tomography/TomoSystemSettingsRemote.h | 53 - .../Tomography/TomoToolConfigAstra.ui | 206 -- .../Tomography/TomoToolConfigCustom.ui | 135 -- .../Tomography/TomoToolConfigDialogAstra.h | 38 - .../Tomography/TomoToolConfigDialogBase.h | 153 -- .../Tomography/TomoToolConfigDialogCustom.h | 37 - .../Tomography/TomoToolConfigDialogSavu.h | 71 - .../Tomography/TomoToolConfigDialogTomoPy.h | 37 - .../Tomography/TomoToolConfigSavu.ui | 392 ---- .../Tomography/TomoToolConfigTomoPy.ui | 210 -- .../Tomography/TomographyIfaceModel.h | 330 --- .../Tomography/TomographyIfacePresenter.h | 185 -- .../Tomography/TomographyIfaceQtGUI.ui | 106 - .../Tomography/TomographyIfaceQtTabEnergy.ui | 400 ---- .../TomographyIfaceQtTabFiltersSettings.ui | 604 ------ .../Tomography/TomographyIfaceQtTabRun.ui | 802 ------- .../TomographyIfaceQtTabSystemSettings.ui | 790 ------- .../TomographyIfaceQtTabVisualize.ui | 236 -- .../Tomography/TomographyIfaceViewQtGUI.h | 402 ---- .../Tomography/TomographyProcess.h | 105 - .../Tomography/TomographyROIPresenter.h | 158 -- .../Tomography/TomographyROIViewQtWidget.h | 311 --- .../Tomography/TomographyThread.h | 115 - .../Tomography/ToolConfigAstraToolbox.h | 74 - .../Tomography/ToolConfigCustom.h | 63 - .../Tomography/ToolConfigTomoPy.h | 69 - .../src/Tomography/EnergyBandsViewQtGUI.cpp | 163 -- .../src/Tomography/ImageStackPreParams.cpp | 12 - .../src/Tomography/ImggFormats.cpp | 94 - .../ImggFormatsConvertPresenter.cpp | 359 ---- .../ImggFormatsConvertViewQtWidget.cpp | 375 ---- .../src/Tomography/StackOfImagesDirs.cpp | 208 -- .../src/Tomography/TomoPathsConfig.cpp | 18 - .../Tomography/TomoReconPostprocSettings.cpp | 15 - .../Tomography/TomoReconPreprocSettings.cpp | 17 - .../src/Tomography/TomoSystemSettings.cpp | 28 - .../Tomography/TomoSystemSettingsLocal.cpp | 55 - .../Tomography/TomoSystemSettingsRemote.cpp | 21 - .../Tomography/TomoToolConfigDialogAstra.cpp | 45 - .../Tomography/TomoToolConfigDialogBase.cpp | 36 - .../Tomography/TomoToolConfigDialogCustom.cpp | 71 - .../Tomography/TomoToolConfigDialogSavu.cpp | 632 ------ .../Tomography/TomoToolConfigDialogTomoPy.cpp | 47 - .../src/Tomography/TomographyIfaceModel.cpp | 1048 --------- .../Tomography/TomographyIfacePresenter.cpp | 929 -------- .../Tomography/TomographyIfaceViewQtGUI.cpp | 1894 ----------------- .../src/Tomography/TomographyROIPresenter.cpp | 603 ------ .../Tomography/TomographyROIViewQtWidget.cpp | 1366 ------------ .../src/Tomography/ToolConfig.cpp | 85 - .../test/ImggFormatsConvertPresenterTest.h | 108 - .../test/ImggFormatsConvertViewMock.h | 74 - .../test/StackOfImagesDirsTest.h | 111 - .../test/TomographyIfaceModelTest.h | 406 ---- .../test/TomographyIfacePresenterTest.h | 732 ------- .../test/TomographyROIPresenterTest.h | 679 ------ .../test/TomographyROIViewMock.h | 112 - .../test/TomographyViewMock.h | 139 -- .../ImggAggregateWavelengths-v1.rst | 163 -- .../ImggTomographicReconstruction-v1.rst | 125 -- .../algorithms/LoadSavuTomoConfig-v1.rst | 76 - .../algorithms/SCARFTomoReconstruction-v1.rst | 89 - .../algorithms/SaveSavuTomoConfig-v1.rst | 66 - .../interfaces/Tomographic_Reconstruction.rst | 497 ----- scripts/Imaging/IMAT/__init__.py | 23 - scripts/Imaging/IMAT/agg_energy_bands.py | 87 - scripts/Imaging/IMAT/prep/__init__.py | 36 - .../IMAT/prep/energy_bands_aggregator.py | 365 ---- scripts/Imaging/IMAT/prep/filters.py | 208 -- scripts/Imaging/IMAT/prep/filters_adv.py | 135 -- scripts/Imaging/IMAT/tomo_reconstruct.py | 411 ---- scripts/Imaging/IMAT/tomorec/__init__.py | 54 - scripts/Imaging/IMAT/tomorec/configs.py | 195 -- scripts/Imaging/IMAT/tomorec/io.py | 578 ----- .../IMAT/tomorec/reconstruction_command.py | 1365 ------------ scripts/Imaging/IMAT/tomorec/tool_imports.py | 69 - 115 files changed, 29566 deletions(-) delete mode 100644 Framework/Algorithms/inc/MantidAlgorithms/Tomography/FBPTomopy.h delete mode 100644 Framework/Algorithms/inc/MantidAlgorithms/Tomography/tomopy/fbp.h delete mode 100644 Framework/Algorithms/inc/MantidAlgorithms/Tomography/tomopy/utils.h delete mode 100644 Framework/Algorithms/src/ImggTomographicReconstruction.cpp delete mode 100644 Framework/Algorithms/src/Tomography/FBPTomopy.cpp delete mode 100644 Framework/Algorithms/src/Tomography/tomopy/fbp.c delete mode 100644 Framework/Algorithms/src/Tomography/tomopy/utils.c delete mode 100644 Framework/Algorithms/test/Tomography/FBPTomopyTest.h delete mode 100644 Framework/DataHandling/inc/MantidDataHandling/LoadSavuTomoConfig.h delete mode 100644 Framework/DataHandling/src/ImggAggregateWavelengths.cpp delete mode 100644 Framework/DataHandling/src/LoadSavuTomoConfig.cpp delete mode 100644 Framework/DataHandling/src/SaveSavuTomoConfig.cpp delete mode 100644 Framework/DataHandling/test/LoadSavuTomoConfigTest.h delete mode 100644 Framework/DataHandling/test/SaveSavuTomoConfigTest.h delete mode 100644 Framework/RemoteAlgorithms/src/SCARFTomoReconstruction.cpp delete mode 100644 Framework/RemoteAlgorithms/test/SCARFTomoReconstructionTest.h delete mode 100644 MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/IImggFormatsConvertPresenter.h delete mode 100644 MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/IImggFormatsConvertView.h delete mode 100644 MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/ITomographyIfacePresenter.h delete mode 100644 MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/ITomographyIfaceView.h delete mode 100644 MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/ITomographyROIPresenter.h delete mode 100644 MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/ITomographyROIView.h delete mode 100644 MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/ImageSelectCoRAndRegions.ui delete mode 100644 MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/ImageStackPreParams.h delete mode 100644 MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/ImggFormats.h delete mode 100644 MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/ImggFormatsConvert.ui delete mode 100644 MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/ImggFormatsConvertPresenter.h delete mode 100644 MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/ImggFormatsConvertViewQtWidget.h delete mode 100644 MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/StackOfImagesDirs.h delete mode 100644 MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomoPathsConfig.h delete mode 100644 MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomoRecToolConfig.h delete mode 100644 MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomoReconFiltersSettings.h delete mode 100644 MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomoReconPostprocSettings.h delete mode 100644 MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomoReconPreprocSettings.h delete mode 100644 MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomoReconToolsUserSettings.h delete mode 100644 MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomoSystemSettings.h delete mode 100644 MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomoSystemSettingsLocal.h delete mode 100644 MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomoSystemSettingsRemote.h delete mode 100644 MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomoToolConfigAstra.ui delete mode 100644 MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomoToolConfigCustom.ui delete mode 100644 MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomoToolConfigDialogAstra.h delete mode 100644 MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomoToolConfigDialogBase.h delete mode 100644 MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomoToolConfigDialogCustom.h delete mode 100644 MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomoToolConfigDialogSavu.h delete mode 100644 MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomoToolConfigDialogTomoPy.h delete mode 100644 MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomoToolConfigSavu.ui delete mode 100644 MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomoToolConfigTomoPy.ui delete mode 100644 MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomographyIfaceModel.h delete mode 100644 MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomographyIfacePresenter.h delete mode 100644 MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomographyIfaceQtGUI.ui delete mode 100644 MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomographyIfaceQtTabEnergy.ui delete mode 100644 MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomographyIfaceQtTabFiltersSettings.ui delete mode 100644 MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomographyIfaceQtTabRun.ui delete mode 100644 MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomographyIfaceQtTabSystemSettings.ui delete mode 100644 MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomographyIfaceQtTabVisualize.ui delete mode 100644 MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomographyIfaceViewQtGUI.h delete mode 100644 MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomographyProcess.h delete mode 100644 MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomographyROIPresenter.h delete mode 100644 MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomographyROIViewQtWidget.h delete mode 100644 MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomographyThread.h delete mode 100644 MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/ToolConfigAstraToolbox.h delete mode 100644 MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/ToolConfigCustom.h delete mode 100644 MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/ToolConfigTomoPy.h delete mode 100644 MantidQt/CustomInterfaces/src/Tomography/EnergyBandsViewQtGUI.cpp delete mode 100644 MantidQt/CustomInterfaces/src/Tomography/ImageStackPreParams.cpp delete mode 100644 MantidQt/CustomInterfaces/src/Tomography/ImggFormats.cpp delete mode 100644 MantidQt/CustomInterfaces/src/Tomography/ImggFormatsConvertPresenter.cpp delete mode 100644 MantidQt/CustomInterfaces/src/Tomography/ImggFormatsConvertViewQtWidget.cpp delete mode 100644 MantidQt/CustomInterfaces/src/Tomography/StackOfImagesDirs.cpp delete mode 100644 MantidQt/CustomInterfaces/src/Tomography/TomoPathsConfig.cpp delete mode 100644 MantidQt/CustomInterfaces/src/Tomography/TomoReconPostprocSettings.cpp delete mode 100644 MantidQt/CustomInterfaces/src/Tomography/TomoReconPreprocSettings.cpp delete mode 100644 MantidQt/CustomInterfaces/src/Tomography/TomoSystemSettings.cpp delete mode 100644 MantidQt/CustomInterfaces/src/Tomography/TomoSystemSettingsLocal.cpp delete mode 100644 MantidQt/CustomInterfaces/src/Tomography/TomoSystemSettingsRemote.cpp delete mode 100644 MantidQt/CustomInterfaces/src/Tomography/TomoToolConfigDialogAstra.cpp delete mode 100644 MantidQt/CustomInterfaces/src/Tomography/TomoToolConfigDialogBase.cpp delete mode 100644 MantidQt/CustomInterfaces/src/Tomography/TomoToolConfigDialogCustom.cpp delete mode 100644 MantidQt/CustomInterfaces/src/Tomography/TomoToolConfigDialogSavu.cpp delete mode 100644 MantidQt/CustomInterfaces/src/Tomography/TomoToolConfigDialogTomoPy.cpp delete mode 100644 MantidQt/CustomInterfaces/src/Tomography/TomographyIfaceModel.cpp delete mode 100644 MantidQt/CustomInterfaces/src/Tomography/TomographyIfacePresenter.cpp delete mode 100644 MantidQt/CustomInterfaces/src/Tomography/TomographyIfaceViewQtGUI.cpp delete mode 100644 MantidQt/CustomInterfaces/src/Tomography/TomographyROIPresenter.cpp delete mode 100644 MantidQt/CustomInterfaces/src/Tomography/TomographyROIViewQtWidget.cpp delete mode 100644 MantidQt/CustomInterfaces/src/Tomography/ToolConfig.cpp delete mode 100644 MantidQt/CustomInterfaces/test/ImggFormatsConvertPresenterTest.h delete mode 100644 MantidQt/CustomInterfaces/test/ImggFormatsConvertViewMock.h delete mode 100644 MantidQt/CustomInterfaces/test/StackOfImagesDirsTest.h delete mode 100644 MantidQt/CustomInterfaces/test/TomographyIfaceModelTest.h delete mode 100644 MantidQt/CustomInterfaces/test/TomographyIfacePresenterTest.h delete mode 100644 MantidQt/CustomInterfaces/test/TomographyROIPresenterTest.h delete mode 100644 MantidQt/CustomInterfaces/test/TomographyROIViewMock.h delete mode 100644 MantidQt/CustomInterfaces/test/TomographyViewMock.h delete mode 100644 docs/source/algorithms/ImggAggregateWavelengths-v1.rst delete mode 100644 docs/source/algorithms/ImggTomographicReconstruction-v1.rst delete mode 100644 docs/source/algorithms/LoadSavuTomoConfig-v1.rst delete mode 100644 docs/source/algorithms/SCARFTomoReconstruction-v1.rst delete mode 100644 docs/source/algorithms/SaveSavuTomoConfig-v1.rst delete mode 100644 docs/source/interfaces/Tomographic_Reconstruction.rst delete mode 100644 scripts/Imaging/IMAT/__init__.py delete mode 100644 scripts/Imaging/IMAT/agg_energy_bands.py delete mode 100644 scripts/Imaging/IMAT/prep/__init__.py delete mode 100644 scripts/Imaging/IMAT/prep/energy_bands_aggregator.py delete mode 100644 scripts/Imaging/IMAT/prep/filters.py delete mode 100644 scripts/Imaging/IMAT/prep/filters_adv.py delete mode 100644 scripts/Imaging/IMAT/tomo_reconstruct.py delete mode 100644 scripts/Imaging/IMAT/tomorec/__init__.py delete mode 100644 scripts/Imaging/IMAT/tomorec/configs.py delete mode 100644 scripts/Imaging/IMAT/tomorec/io.py delete mode 100644 scripts/Imaging/IMAT/tomorec/reconstruction_command.py delete mode 100644 scripts/Imaging/IMAT/tomorec/tool_imports.py diff --git a/Framework/Algorithms/CMakeLists.txt b/Framework/Algorithms/CMakeLists.txt index a770b9938ec..6a30372e559 100644 --- a/Framework/Algorithms/CMakeLists.txt +++ b/Framework/Algorithms/CMakeLists.txt @@ -293,7 +293,6 @@ set ( SRC_FILES src/TimeAtSampleStrategyDirect.cpp src/TimeAtSampleStrategyElastic.cpp src/TimeAtSampleStrategyIndirect.cpp - src/Tomography/FBPTomopy.cpp src/Transpose.cpp src/UnGroupWorkspace.cpp src/UnaryOperation.cpp @@ -311,12 +310,6 @@ set ( SRC_FILES src/XDataConverter.cpp ) -# C as they originally come from a different project (tomopy) -set ( C_SRC_FILES - src/Tomography/tomopy/fbp.c - src/Tomography/tomopy/utils.c -) - set ( INC_FILES inc/MantidAlgorithms/AbsorptionCorrection.h inc/MantidAlgorithms/AddLogDerivative.h @@ -619,9 +612,6 @@ set ( INC_FILES inc/MantidAlgorithms/TimeAtSampleStrategyDirect.h inc/MantidAlgorithms/TimeAtSampleStrategyElastic.h inc/MantidAlgorithms/TimeAtSampleStrategyIndirect.h - inc/MantidAlgorithms/Tomography/FBPTomopy.h - inc/MantidAlgorithms/Tomography/tomopy/fbp.h - inc/MantidAlgorithms/Tomography/tomopy/utils.h inc/MantidAlgorithms/Transpose.h inc/MantidAlgorithms/UnGroupWorkspace.h inc/MantidAlgorithms/UnaryOperation.h @@ -924,7 +914,6 @@ set ( TEST_FILES TimeAtSampleStrategyDirectTest.h TimeAtSampleStrategyElasticTest.h TimeAtSampleStrategyIndirectTest.h - Tomography/FBPTomopyTest.h TransposeTest.h UnGroupWorkspaceTest.h UnaryOperationTest.h diff --git a/Framework/Algorithms/inc/MantidAlgorithms/Tomography/FBPTomopy.h b/Framework/Algorithms/inc/MantidAlgorithms/Tomography/FBPTomopy.h deleted file mode 100644 index 0d295f82a82..00000000000 --- a/Framework/Algorithms/inc/MantidAlgorithms/Tomography/FBPTomopy.h +++ /dev/null @@ -1,45 +0,0 @@ -#ifndef MANTID_ALGORITHMS_TOMOGRAPHY_FBPTOMOPY_H_ -#define MANTID_ALGORITHMS_TOMOGRAPHY_FBPTOMOPY_H_ - -#include "MantidAlgorithms/DllConfig.h" - -namespace Mantid { -namespace Algorithms { -namespace Tomography { - -/** - Wrapper for C function(s) that implement tomopy reconstruction - methods. - - Copyright © 2016 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> -*/ - -/// FBP - Filtered Back-Projection routine as implemented in tomopy -void MANTID_ALGORITHMS_DLL FBPTomopy(const float *data, int dy, int dt, int dx, - const float *center, const float *theta, - float *recon, int ngridx, int ngridy); - -} // namespace Tomography -} // namespace Algorithms -} // namespace Mantid - -#endif /* MANTID_ALGORITHMS_TOMOGRAPHY_FBPTOMOPY_H_ */ diff --git a/Framework/Algorithms/inc/MantidAlgorithms/Tomography/tomopy/fbp.h b/Framework/Algorithms/inc/MantidAlgorithms/Tomography/tomopy/fbp.h deleted file mode 100644 index ade127406da..00000000000 --- a/Framework/Algorithms/inc/MantidAlgorithms/Tomography/tomopy/fbp.h +++ /dev/null @@ -1,34 +0,0 @@ -/** - fbp function from Tomopy - FBP reconstruction method - - Copyright © 2016 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> -*/ -#ifndef MANTID_ALGORITHMS_TOMOGRAPHY_TOMOPY_FBP_H_ -#define MANTID_ALGORITHMS_TOMOGRAPHY_TOMOPY_FBP_H_ - -extern "C" { -void fbp(const float *data, int dy, int dt, int dx, const float *center, - const float *theta, float *recon, int ngridx, int ngridy, - const char * /*fname*/, const float * /*filter_par*/); -} - -#endif /* MANTID_ALGORITHMS_TOMOGRAPHY_TOMOPY_FBP_H_ */ diff --git a/Framework/Algorithms/inc/MantidAlgorithms/Tomography/tomopy/utils.h b/Framework/Algorithms/inc/MantidAlgorithms/Tomography/tomopy/utils.h deleted file mode 100644 index 607160a3be2..00000000000 --- a/Framework/Algorithms/inc/MantidAlgorithms/Tomography/tomopy/utils.h +++ /dev/null @@ -1,103 +0,0 @@ -/** - Common functions for different reconstruction methods in Tomopy - - Copyright © 2016 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> -*/ -/** - * This file is substantially modified but originally based on the - * file utils.h from tomopy (available from - * https:github.com/tomopy/tomopy/blob/master/src/utils.h) which is: - */ -/* - Copyright (c) 2015, UChicago Argonne, LLC. All rights reserved. - - Copyright 2015. UChicago Argonne, LLC. This software was produced - under U.S. Government contract DE-AC02-06CH11357 for Argonne National - Laboratory (ANL), which is operated by UChicago Argonne, LLC for the - U.S. Department of Energy. The U.S. Government has rights to use, - reproduce, and distribute this software. NEITHER THE GOVERNMENT NOR - UChicago Argonne, LLC MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR - ASSUMES ANY LIABILITY FOR THE USE OF THIS SOFTWARE. If software is - modified to produce derivative works, such modified software should - be clearly marked, so as not to confuse it with the version available - from ANL. - - Additionally, redistribution and use in source and binary forms, with - or without modification, are permitted provided that the following - conditions are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the - distribution. - - * Neither the name of UChicago Argonne, LLC, Argonne National - Laboratory, ANL, the U.S. Government, nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY UChicago Argonne, LLC AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL UChicago - Argonne, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. -*/ -#ifndef MANTID_ALGORITHMS_TOMOGRAPHY_TOMOPY_UTILS_H_ -#define MANTID_ALGORITHMS_TOMOGRAPHY_TOMOPY_UTILS_H_ - -void preprocessing(int ngridx, int ngridy, int dz, float center, float *mov, - float *gridx, float *gridy); - -int calc_quadrant(float theta_p); - -void calc_coords(int ngridx, int ngridy, float xi, float yi, float sin_p, - float cos_p, const float *gridx, const float *gridy, - float *coordx, float *coordy); - -void trim_coords(int ngridx, int ngridy, const float *coordx, - const float *coordy, const float *gridx, const float *gridy, - int *asize, float *ax, float *ay, int *bsize, float *bx, - float *by); - -void sort_intersections(int ind_condition, int asize, const float *ax, - const float *ay, int bsize, const float *bx, - const float *by, int *csize, float *coorx, - float *coory); - -void calc_dist(int ngridx, int ngridy, int csize, const float *coorx, - const float *coory, int *indi, float *dist); - -void calc_simdata(int s, int p, int d, int ngridx, int ngridy, int dt, int dx, - int csize, const int *indi, const float *dist, - const float *model, float *simdata); - -#endif /* MANTID_ALGORITHMS_TOMOGRAPHY_TOMOPY_UTILS_H_ */ diff --git a/Framework/Algorithms/src/ImggTomographicReconstruction.cpp b/Framework/Algorithms/src/ImggTomographicReconstruction.cpp deleted file mode 100644 index 9f7657ae22a..00000000000 --- a/Framework/Algorithms/src/ImggTomographicReconstruction.cpp +++ /dev/null @@ -1,405 +0,0 @@ -#include "MantidAlgorithms/ImggTomographicReconstruction.h" -#include "MantidAlgorithms/Tomography/FBPTomopy.h" -#include "MantidAPI/AlgorithmManager.h" -#include "MantidAPI/CommonBinsValidator.h" -#include "MantidAPI/FileProperty.h" -#include "MantidAPI/HistogramValidator.h" -#include "MantidAPI/MatrixWorkspace.h" -#include "MantidAPI/WorkspaceUnitValidator.h" -#include "MantidAPI/WorkspaceFactory.h" -#include "MantidAPI/WorkspaceGroup.h" -#include "MantidDataObjects/Workspace2D.h" -#include "MantidKernel/BoundedValidator.h" -#include "MantidKernel/CompositeValidator.h" -#include "MantidKernel/ListValidator.h" -#include "MantidKernel/make_unique.h" - -namespace Mantid { -namespace Algorithms { - -// Register the algorithm into the AlgorithmFactory -DECLARE_ALGORITHM(ImggTomographicReconstruction) - -namespace { -// Just to have explicit double => float casts in std::copy/transform -struct DoubleToFloatStd { - float operator()(const double &dblValue) const { - return static_cast<float>(dblValue); - } -}; -} - -//---------------------------------------------------------------------------------------------- - -/// Algorithms name for identification. @see Algorithm::name -const std::string ImggTomographicReconstruction::name() const { - return "ImggTomographicReconstruction"; -} - -/// Algorithm's version for identification. @see Algorithm::version -int ImggTomographicReconstruction::version() const { return 1; } - -/// Algorithm's category for identification. @see Algorithm::category -const std::string ImggTomographicReconstruction::category() const { - return "Diffraction\\Imaging;Diffraction\\Tomography"; -} - -/// Algorithm's summary for use in the GUI and help. @see Algorithm::summary -const std::string ImggTomographicReconstruction::summary() const { - return "Reconstruct a 3D volume from 2D imaging projection data"; -} - -namespace { -const std::string PROP_INPUT_WS = "InputWorkspace"; -const std::string PROP_METHOD = "Method"; -const std::string PROP_OUTPUT_WS = "OutputWorkspace"; -const std::string PROP_COR = "CenterOfRotation"; -const std::string PROP_RELAXATION_PARAM = "RelaxationParameter"; -const std::string PROP_MAX_CORES = "MaximumCores"; -const std::string PROP_MIN_PROJ_ANGLE = "MinProjectionAngle"; -const std::string PROP_MAX_PROJ_ANGLE = "MaxProjectionAngle"; -} - -//---------------------------------------------------------------------------------------------- -/** Initialize the algorithm's properties. - */ -void ImggTomographicReconstruction::init() { - - declareProperty( - Kernel::make_unique<API::WorkspaceProperty<API::Workspace>>( - PROP_INPUT_WS, "", Kernel::Direction::Input), - "Group of workspace holding images (with one spectrum per pixel row)."); - - std::vector<std::string> methods{"FBP (tomopy)"}; - declareProperty( - PROP_METHOD, methods.front(), - boost::make_shared<Kernel::ListValidator<std::string>>(methods), - "Reconstruction method", Kernel::Direction::Input); - - declareProperty( - Kernel::make_unique<API::WorkspaceProperty<API::WorkspaceGroup>>( - PROP_OUTPUT_WS, "", Kernel::Direction::Output), - "Output reconstructed volume, as a group of workspaces where " - "each workspace holds one slice of the volume."); - - auto zeroOrPosInt = boost::make_shared<Kernel::BoundedValidator<int>>(); - zeroOrPosInt->setLower(-1); - declareProperty(PROP_COR, -1, zeroOrPosInt, - "Center of rotation for the reconstruction (in pixels)."); - - auto zeroOrPosDbl = boost::make_shared<Kernel::BoundedValidator<double>>(); - zeroOrPosDbl->setLower(0.0); - declareProperty(PROP_RELAXATION_PARAM, 0.5, zeroOrPosDbl, - "Relaxation parameter for the reconstruction method."); - - zeroOrPosInt->setLower(0); - declareProperty(PROP_MAX_CORES, 0, zeroOrPosInt, - "Maximum number of cores to use for parallel runs. Leave " - "empty to use all available cores."); - - declareProperty(PROP_MIN_PROJ_ANGLE, 0.0, zeroOrPosDbl, - "Minimum projection angle."); - - declareProperty(PROP_MAX_PROJ_ANGLE, 180.0, zeroOrPosDbl, - "Maximum projection angle (assuming a uniform angle increase " - "from first to last projection."); -} - -std::map<std::string, std::string> -ImggTomographicReconstruction::validateInputs() { - std::map<std::string, std::string> result; - - API::Workspace_const_sptr inWks = getProperty(PROP_INPUT_WS); - API::WorkspaceGroup_const_sptr inGrp = - boost::dynamic_pointer_cast<const API::WorkspaceGroup>(inWks); - if (!inGrp) { - result[PROP_INPUT_WS] = "The current version of this algorithm only " - "supports input workspaces of type WorkspaceGroup"; - } else { - if (inGrp->size() < 2) { - result[PROP_INPUT_WS] = "The input workspace must have at least two " - "workspaces (projection images)"; - } - - auto first = inGrp->getItem(0); - auto fwks = boost::dynamic_pointer_cast<API::MatrixWorkspace>(first); - if (!fwks) { - result[PROP_INPUT_WS] = - "Unable to get a matrix workspace from the first " - "item of the input workspace group " + - first->getTitle() + - ". It must contain workspaces of type MatrixWorkspace"; - } else { - int cor = getProperty(PROP_COR); - size_t bsize = fwks->blocksize(); - if (cor < 0 || cor >= static_cast<int>(bsize)) { - result[PROP_COR] = - "The center of rotation must be between 0 and the " - "number of columns in the input projection images (0 to " + - std::to_string(bsize - 1) + ")"; - } - } - // Not validating requirements on all input workspaces here (there could be - // many) - } - - double minAngle = getProperty(PROP_MIN_PROJ_ANGLE); - double maxAngle = getProperty(PROP_MAX_PROJ_ANGLE); - - if (minAngle >= maxAngle) { - result[PROP_MIN_PROJ_ANGLE] = PROP_MIN_PROJ_ANGLE + - " cannot be equal to or lower than " + - PROP_MAX_PROJ_ANGLE; - } - return result; -} - -//---------------------------------------------------------------------------------------------- -/** Execute the algorithm. - */ -void ImggTomographicReconstruction::exec() { - throw std::runtime_error( - "This algorithm cannot be executed with a single workspace as input"); -} - -bool ImggTomographicReconstruction::processGroups() { - API::Workspace_const_sptr inWks = getProperty("InputWorkspace"); - - API::WorkspaceGroup_const_sptr wks = - boost::dynamic_pointer_cast<const API::WorkspaceGroup>(inWks); - - if (!wks) { - g_log.error( - "Could not retrieve the input workspace as a workspace group: "); - return false; - } - - // TODO: apply validators here on every input image/workspace - for (size_t idx = 0; idx < wks->size(); idx++) { - auto item = wks->getItem(0); - auto mWS = boost::dynamic_pointer_cast<API::MatrixWorkspace>(item); - if (!mWS) { - throw std::runtime_error("Unable to get a matrix workspace from the " - "element of te workspace group with title " + - item->getTitle()); - } - - auto wsValidator = boost::make_shared<Kernel::CompositeValidator>(); - wsValidator->add<API::CommonBinsValidator>(); - wsValidator->add<API::HistogramValidator>(); - // Probably we won't need this: - // wsValidator->add<API::WorkspaceUnitValidator>("Label"); - const std::string validation = wsValidator->isValid(mWS); - if (validation != "") { - throw std::runtime_error( - "Validation of input image / matrix workspace failed: " + validation); - } - } - - double minAngle = getProperty(PROP_MIN_PROJ_ANGLE); - double maxAngle = getProperty(PROP_MAX_PROJ_ANGLE); - auto angles = prepareProjectionAngles(wks, minAngle, maxAngle); - - // these values are expected as 'int' by the tompy routines - const int ysize = static_cast<int>(ySizeProjections(wks)); - const int projSize = static_cast<int>(angles->size()); - const int xsize = static_cast<int>(xSizeProjections(wks)); - // total size of input data in voxels - size_t totalInSize = ysize * projSize * xsize; - // total size of the reconstructed volume - size_t totalReconSize = ysize * ysize * xsize; - - auto inVol = prepareInputData(totalInSize, wks); - auto reconVol = prepareDataVol(totalReconSize); - - int cor = getProperty(PROP_COR); - auto centers = prepareCenters(cor, ysize); - - Mantid::Algorithms::Tomography::FBPTomopy( - inVol->data(), ysize, projSize, xsize, centers->data(), angles->data(), - reconVol->data(), xsize, ysize); - - size_t expectedVox = ysize * ysize * xsize; - if (reconVol->size() != expectedVox) { - std::stringstream stream; - stream << std::string("The reconstructed volume data block does not " - "have the expected dimensions. It has ") - << reconVol->size() << " voxels, whereas I was expecting: " << ysize - << " slices by " << ysize << " rows by " << xsize - << " columns = " << expectedVox << " voxels in total"; - throw std::runtime_error(stream.str()); - } - - const auto outputGrp = buildOutputWks(*reconVol, xsize, ysize, ysize); - setProperty(PROP_OUTPUT_WS, outputGrp); - - g_log.notice() << "Finished reconstruction of volume from workspace " - << wks->getTitle() << " with " << projSize - << " input projections, " << ysize << " rows by " << xsize - << " columns.\n"; - - return true; -} - -std::unique_ptr<std::vector<float>> -ImggTomographicReconstruction::prepareProjectionAngles( - API::WorkspaceGroup_const_sptr wks, double minAngle, - double maxAngle) const { - - auto projCount = wks->size(); - auto angles = Kernel::make_unique<std::vector<float>>(projCount); - - auto vec = *angles; - if (vec.empty()) - return angles; - - double factor = (maxAngle - minAngle); - vec[0] = static_cast<float>(minAngle); - for (size_t idx = 1; idx < projCount; ++idx) { - vec[idx] = static_cast<float>(minAngle + - factor * static_cast<double>(idx) / - static_cast<double>(projCount - 1)); - } - - return angles; -} - -std::unique_ptr<std::vector<float>> -ImggTomographicReconstruction::prepareInputData( - size_t totalSize, API::WorkspaceGroup_const_sptr wksg) { - auto data = prepareDataVol(totalSize); - - if (!wksg || 0 == wksg->size()) - return data; - - auto first = wksg->getItem(0); - auto fwks = boost::dynamic_pointer_cast<API::MatrixWorkspace>(first); - if (!fwks) { - throw std::runtime_error( - "Unable to get a matrix workspace from the first " - "item of the input workspace group " + - first->getTitle() + - ". It must contain workspaces of type MatrixWorkspace"); - } - - size_t ysize = fwks->getNumberHistograms(); - size_t xsize = fwks->blocksize(); - const size_t oneSliceSize = xsize * ysize; - - PARALLEL_FOR_NO_WSP_CHECK() - for (int slice = 0; slice < static_cast<int>(wksg->size()); ++slice) { - size_t startSlice = slice * oneSliceSize; - for (size_t row = 0; row < ysize; ++row) { - const auto &dataY = fwks->getSpectrum(row).readY(); - size_t startRow = startSlice + row * ysize; - // MSVC will produce C4244 warnings in <xutility> (double=>float - // converstion) - // std::copy(dataY.begin(), dataY.end(), data->begin() + startRow); - std::transform(dataY.begin(), dataY.end(), data->begin() + startRow, - DoubleToFloatStd()); - } - } - - return data; -} - -std::unique_ptr<std::vector<float>> -ImggTomographicReconstruction::prepareDataVol(size_t totalSize) { - return Kernel::make_unique<std::vector<float>>(totalSize); -} - -std::unique_ptr<std::vector<float>> -ImggTomographicReconstruction::prepareCenters(int cor, size_t totalSize) { - auto centers = Kernel::make_unique<std::vector<float>>(totalSize); - - for (auto &cnt : *centers) { - cnt = static_cast<float>(cor); - } - - return centers; -} - -size_t ImggTomographicReconstruction::xSizeProjections( - API::WorkspaceGroup_const_sptr wks) const { - auto first = wks->getItem(0); - - auto wksItem = boost::dynamic_pointer_cast<API::MatrixWorkspace>(first); - if (!wksItem) { - throw std::runtime_error("Unable to get a matrix workspace from the first " - "item of the workspace group " + - first->getTitle()); - } - - return wksItem->getNumberHistograms(); -} - -size_t ImggTomographicReconstruction::pSizeProjections( - API::WorkspaceGroup_const_sptr wks) const { - return wks->size(); -} - -size_t ImggTomographicReconstruction::ySizeProjections( - API::WorkspaceGroup_const_sptr wks) const { - auto first = wks->getItem(0); - - auto wksItem = boost::dynamic_pointer_cast<API::MatrixWorkspace>(first); - if (!wksItem) { - throw std::runtime_error("Unable to get a matrix workspace from the first " - "item of the workspace group " + - first->getTitle()); - } - - return wksItem->blocksize(); -} - -/** - * Transfer data from a numpy/tomopy style data volume to a workspace - * group of MatrixWorkspaces. This will typically have ysize slices - * (images) of dimensions ysize rows by xsize columns. - - * - * @param dataVol a 3D data volume that may have been generated as - * output from a reconstruction - * @param xsize image x dimension or number of columns (bins) - * @param ysize image y dimension or number of rows (spectra) - * @param sliceSize number of slices - * - * @return a workspace group with reconstruction slices - */ -API::WorkspaceGroup_sptr -ImggTomographicReconstruction::buildOutputWks(const std::vector<float> &dataVol, - size_t xsize, size_t ysize, - size_t sliceSize) { - - // auto wsGroup = boost::make_shared<API::WorkspaceGroup>(); - auto wsGroup = API::WorkspaceGroup_sptr(new API::WorkspaceGroup()); - wsGroup->setTitle("Reconstructed volume from imaging projection data"); - - const size_t oneSliceSize = xsize * ysize; - PARALLEL_FOR_NO_WSP_CHECK() - for (int slice = 0; slice < static_cast<int>(sliceSize); ++slice) { - // individual slices as Workspace2D/MatrixWorkspace - DataObjects::Workspace2D_sptr sliceWS = - boost::dynamic_pointer_cast<DataObjects::Workspace2D>( - API::WorkspaceFactory::Instance().create("Workspace2D", ysize, - xsize + 1, xsize)); - size_t startSlice = slice * oneSliceSize; - for (size_t row = 0; row < ysize; ++row) { - auto &specRow = sliceWS->getSpectrum(row); - auto &dataX = specRow.dataX(); - std::fill(dataX.begin(), dataX.end(), static_cast<double>(row)); - - size_t startRow = startSlice + row * ysize; - size_t endRow = startRow + xsize; - auto &dataY = specRow.dataY(); - std::transform(dataVol.begin() + startRow, dataVol.begin() + endRow, - dataY.begin(), DoubleToFloatStd()); - } - wsGroup->addWorkspace(sliceWS); - } - - return wsGroup; -} - -} // namespace Algorithms -} // namespace Mantid diff --git a/Framework/Algorithms/src/Tomography/FBPTomopy.cpp b/Framework/Algorithms/src/Tomography/FBPTomopy.cpp deleted file mode 100644 index 807ece8f292..00000000000 --- a/Framework/Algorithms/src/Tomography/FBPTomopy.cpp +++ /dev/null @@ -1,15 +0,0 @@ -#include "MantidAlgorithms/Tomography/FBPTomopy.h" -#include "MantidAlgorithms/Tomography/tomopy/fbp.h" - -namespace Mantid { -namespace Algorithms { -namespace Tomography { - -void FBPTomopy(const float *data, int dy, int dt, int dx, const float *center, - const float *theta, float *recon, int ngridx, int ngridy) { - fbp(data, dy, dt, dx, center, theta, recon, ngridx, ngridy, nullptr, nullptr); -} - -} // namespace Tomography -} // namespace Algorithms -} // namespace Mantid diff --git a/Framework/Algorithms/src/Tomography/tomopy/fbp.c b/Framework/Algorithms/src/Tomography/tomopy/fbp.c deleted file mode 100644 index b0451a11807..00000000000 --- a/Framework/Algorithms/src/Tomography/tomopy/fbp.c +++ /dev/null @@ -1,160 +0,0 @@ -/** - This file is originally based on the implementation of the FBP (Filtered - Back-Projection) method of tomopy, available from - https:github.com/tomopy/tomopy/blob/master/src/fbp.c, which is: - */ -/* - Copyright (c) 2015, UChicago Argonne, LLC. All rights reserved. - - Copyright 2015. UChicago Argonne, LLC. This software was produced - under U.S. Government contract DE-AC02-06CH11357 for Argonne National - Laboratory (ANL), which is operated by UChicago Argonne, LLC for the - U.S. Department of Energy. The U.S. Government has rights to use, - reproduce, and distribute this software. NEITHER THE GOVERNMENT NOR - UChicago Argonne, LLC MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR - ASSUMES ANY LIABILITY FOR THE USE OF THIS SOFTWARE. If software is - modified to produce derivative works, such modified software should - be clearly marked, so as not to confuse it with the version available - from ANL. - - Additionally, redistribution and use in source and binary forms, with - or without modification, are permitted provided that the following - conditions are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the - distribution. - - * Neither the name of UChicago Argonne, LLC, Argonne National - Laboratory, ANL, the U.S. Government, nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY UChicago Argonne, LLC AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL UChicago - Argonne, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. -*/ - -#include "MantidAlgorithms/Tomography/tomopy/utils.h" - -#include <assert.h> -#include <math.h> -#include <stdlib.h> - -void fbp(const float *data, int dy, int dt, int dx, const float *center, - const float *theta, float *recon, int ngridx, int ngridy, - const char *fname, const float *filter_par) { - - int s, p, d, n; - int quadrant; - float theta_p, sin_p, cos_p; - float mov, xi, yi; - int asize, bsize, csize; - int ind_data, ind_recon; - - float *gridx, *gridy, *coordx, *coordy, *ax, *ay, *bx, *by, *coorx, *coory, - *dist; - int *indi; - - gridx = (float *)malloc((size_t)(ngridx + 1) * sizeof(float)); - gridy = (float *)malloc((size_t)(ngridy + 1) * sizeof(float)); - coordx = (float *)malloc((size_t)(ngridy + 1) * sizeof(float)); - coordy = (float *)malloc((size_t)(ngridx + 1) * sizeof(float)); - ax = (float *)malloc((size_t)(ngridx + ngridy) * sizeof(float)); - ay = (float *)malloc((size_t)(ngridx + ngridy) * sizeof(float)); - bx = (float *)malloc((size_t)(ngridx + ngridy) * sizeof(float)); - by = (float *)malloc((size_t)(ngridx + ngridy) * sizeof(float)); - coorx = (float *)malloc((size_t)(ngridx + ngridy) * sizeof(float)); - coory = (float *)malloc((size_t)(ngridx + ngridy) * sizeof(float)); - dist = (float *)malloc((size_t)(ngridx + ngridy) * sizeof(float)); - indi = (int *)malloc((size_t)(ngridx + ngridy) * sizeof(int)); - - /* unused arguments: */ - (void)fname; - (void)filter_par; - - assert(coordx != NULL && coordy != NULL && ax != NULL && ay != NULL && - by != NULL && bx != NULL && coorx != NULL && coory != NULL && - dist != NULL && indi != NULL); - - /* For each slice */ - for (s = 0; s < dy; s++) { - preprocessing(ngridx, ngridy, dx, center[s], &mov, gridx, - gridy); /* Outputs: mov, gridx, gridy */ - - /* For each projection angle */ - for (p = 0; p < dt; p++) { - /* - Calculate the sin and cos values - of the projection angle and find - at which quadrant on the cartesian grid. - */ - theta_p = (float)fmod(theta[p], 2 * M_PI); - quadrant = calc_quadrant(theta_p); - sin_p = sinf(theta_p); - cos_p = cosf(theta_p); - - /* For each detector pixel */ - for (d = 0; d < dx; d++) { - /* Calculate coordinates */ - xi = (float)(-ngridx - ngridy); - yi = (float)(1 - dx) / 2.0f + (float)d + mov; - calc_coords(ngridx, ngridy, xi, yi, sin_p, cos_p, gridx, gridy, coordx, - coordy); - - /* Merge the (coordx, gridy) and (gridx, coordy) */ - trim_coords(ngridx, ngridy, coordx, coordy, gridx, gridy, &asize, ax, - ay, &bsize, bx, by); - - /* - Sort the array of intersection points (ax, ay) and - (bx, by). The new sorted intersection points are - stored in (coorx, coory). Total number of points - are csize. - */ - sort_intersections(quadrant, asize, ax, ay, bsize, bx, by, &csize, - coorx, coory); - - /* - Calculate the distances (dist) between the - intersection points (coorx, coory). Find the - indices of the pixels on the reconstruction grid. - */ - calc_dist(ngridx, ngridy, csize, coorx, coory, indi, dist); - - /* Update */ - ind_recon = s * ngridx * ngridy; - ind_data = d + p * dx + s * dt * dx; - for (n = 0; n < csize - 1; n++) { - recon[indi[n] + ind_recon] += data[ind_data] * dist[n]; - } - } - } - } - - free(gridx); - free(gridy); - free(coordx); - free(coordy); - free(ax); - free(ay); - free(bx); - free(by); - free(coorx); - free(coory); - free(dist); - free(indi); -} diff --git a/Framework/Algorithms/src/Tomography/tomopy/utils.c b/Framework/Algorithms/src/Tomography/tomopy/utils.c deleted file mode 100644 index 6b5248d5bac..00000000000 --- a/Framework/Algorithms/src/Tomography/tomopy/utils.c +++ /dev/null @@ -1,207 +0,0 @@ -/** - This file is originally based on the implementation of the FBP (Filtered - Back-Projection) method of tomopy, available from - https:github.com/tomopy/tomopy/blob/master/src/fbp.c, which is: - */ -/* - Copyright (c) 2015, UChicago Argonne, LLC. All rights reserved. - - Copyright 2015. UChicago Argonne, LLC. This software was produced - under U.S. Government contract DE-AC02-06CH11357 for Argonne National - Laboratory (ANL), which is operated by UChicago Argonne, LLC for the - U.S. Department of Energy. The U.S. Government has rights to use, - reproduce, and distribute this software. NEITHER THE GOVERNMENT NOR - UChicago Argonne, LLC MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR - ASSUMES ANY LIABILITY FOR THE USE OF THIS SOFTWARE. If software is - modified to produce derivative works, such modified software should - be clearly marked, so as not to confuse it with the version available - from ANL. - - Additionally, redistribution and use in source and binary forms, with - or without modification, are permitted provided that the following - conditions are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the - distribution. - - * Neither the name of UChicago Argonne, LLC, Argonne National - Laboratory, ANL, the U.S. Government, nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY UChicago Argonne, LLC AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL UChicago - Argonne, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. -*/ - -#include "MantidAlgorithms/Tomography/tomopy/utils.h" - -#include <math.h> - -void preprocessing(int ry, int rz, int num_pixels, float center, float *mov, - float *gridx, float *gridy) { - int i; - - for (i = 0; i <= ry; i++) { - gridx[i] = ((float)-ry / 2.f + (float)i); - } - - for (i = 0; i <= rz; i++) { - gridy[i] = ((float)-rz / 2.f + (float)i); - } - - *mov = ((float)num_pixels - 1) / 2.0f - center; - if (*mov - floor(*mov) < 0.01f) { - *mov += 0.01f; - } - *mov += 0.5f; -} - -int calc_quadrant(float theta_p) { - int quadrant; - if ((theta_p >= 0 && theta_p < M_PI / 2) || - (theta_p >= M_PI && theta_p < 3 * M_PI / 2) || - (theta_p >= -M_PI && theta_p < -M_PI / 2) || - (theta_p >= -2 * M_PI && theta_p < -3 * M_PI / 2)) { - quadrant = 1; - } else { - quadrant = 0; - } - return quadrant; -} - -void calc_coords(int ry, int rz, float xi, float yi, float sin_p, float cos_p, - const float *gridx, const float *gridy, float *coordx, - float *coordy) { - float srcx, srcy, detx, dety; - float slope, islope; - int n; - - srcx = xi * cos_p - yi * sin_p; - srcy = xi * sin_p + yi * cos_p; - detx = -xi * cos_p - yi * sin_p; - dety = -xi * sin_p + yi * cos_p; - - slope = (srcy - dety) / (srcx - detx); - islope = 1 / slope; - for (n = 0; n <= ry; n++) { - coordy[n] = slope * (gridx[n] - srcx) + srcy; - } - for (n = 0; n <= rz; n++) { - coordx[n] = islope * (gridy[n] - srcy) + srcx; - } -} - -void trim_coords(int ry, int rz, const float *coordx, const float *coordy, - const float *gridx, const float *gridy, int *asize, float *ax, - float *ay, int *bsize, float *bx, float *by) { - int n; - - *asize = 0; - *bsize = 0; - for (n = 0; n <= rz; n++) { - if (coordx[n] >= gridx[0] + 1e-2) { - if (coordx[n] <= gridx[ry] - 1e-2) { - ax[*asize] = coordx[n]; - ay[*asize] = gridy[n]; - (*asize)++; - } - } - } - for (n = 0; n <= ry; n++) { - if (coordy[n] >= gridy[0] + 1e-2) { - if (coordy[n] <= gridy[rz] - 1e-2) { - bx[*bsize] = gridx[n]; - by[*bsize] = coordy[n]; - (*bsize)++; - } - } - } -} - -void sort_intersections(int ind_condition, int asize, const float *ax, - const float *ay, int bsize, const float *bx, - const float *by, int *csize, float *coorx, - float *coory) { - int i = 0, j = 0, k = 0; - int a_ind; - while (i < asize && j < bsize) { - a_ind = (ind_condition) ? i : (asize - 1 - i); - if (ax[a_ind] < bx[j]) { - coorx[k] = ax[a_ind]; - coory[k] = ay[a_ind]; - i++; - k++; - } else { - coorx[k] = bx[j]; - coory[k] = by[j]; - j++; - k++; - } - } - while (i < asize) { - a_ind = (ind_condition) ? i : (asize - 1 - i); - coorx[k] = ax[a_ind]; - coory[k] = ay[a_ind]; - i++; - k++; - } - while (j < bsize) { - coorx[k] = bx[j]; - coory[k] = by[j]; - j++; - k++; - } - *csize = asize + bsize; -} - -void calc_dist(int ry, int rz, int csize, const float *coorx, - const float *coory, int *indi, float *dist) { - int n; - - for (n = 0; n < csize - 1; n++) { - int i1, i2; - float x1, x2; - float diffx, diffy, midx, midy; - int indx, indy; - - diffx = coorx[n + 1] - coorx[n]; - diffy = coory[n + 1] - coory[n]; - dist[n] = (float)sqrt(diffx * diffx + diffy * diffy); - midx = (coorx[n + 1] + coorx[n]) / 2; - midy = (coory[n + 1] + coory[n]) / 2; - x1 = midx + (float)ry / 2.f; - x2 = midy + (float)rz / 2.f; - i1 = (int)(midx + ry / 2.); - i2 = (int)(midy + rz / 2.); - indx = i1 - (i1 > x1); - indy = i2 - (i2 > x2); - indi[n] = indy + (indx * rz); - } -} - -void calc_simdata(int s, int p, int d, int ry, int rz, int dt, int dx, - int csize, const int *indi, const float *dist, - const float *model, float *simdata) { - int n; - - int index_model = s * ry * rz; - int index_data = d + p * dx + s * dt * dx; - for (n = 0; n < csize - 1; n++) { - simdata[index_data] += model[indi[n] + index_model] * dist[n]; - } -} diff --git a/Framework/Algorithms/test/Tomography/FBPTomopyTest.h b/Framework/Algorithms/test/Tomography/FBPTomopyTest.h deleted file mode 100644 index 091844e6134..00000000000 --- a/Framework/Algorithms/test/Tomography/FBPTomopyTest.h +++ /dev/null @@ -1,114 +0,0 @@ -#ifndef MANTID_ALGORITHMS_FBPTOMOPYTEST_H_ -#define MANTID_ALGORITHMS_FBPTOMOPYTEST_H_ - -#include <cxxtest/TestSuite.h> - -#include "MantidAlgorithms/Tomography/FBPTomopy.h" -#include "MantidAPI/AlgorithmManager.h" -#include "MantidKernel/Exception.h" - -#include "MantidTestHelpers/WorkspaceCreationHelper.h" - -#include <numeric> - -using namespace Mantid::Algorithms::Tomography; - -class FBPTomopyTest : public CxxTest::TestSuite { - -public: - // This pair of boilerplate methods prevent the suite being created statically - // This means the constructor isn't called when running other tests - static FBPTomopyTest *createSuite() { return new FBPTomopyTest(); } - - static void destroySuite(FBPTomopyTest *suite) { delete suite; } - - void test_null() { - FBPTomopy(nullptr, 0, 0, 0, nullptr, nullptr, nullptr, 0, 0); - } - - void test_small_buffer_flat() { - const size_t numProj = 3; - const size_t ysize = 8; - const size_t xsize = 8; - const size_t projSize = numProj * ysize * xsize; - std::array<float, projSize> projImages; - std::fill(projImages.begin(), projImages.end(), 33.0f); - - const size_t reconSize = ysize * ysize * xsize; - std::array<float, reconSize> reconVol; - std::fill(reconVol.begin(), reconVol.end(), 0.0f); - - const size_t numAngles = numProj; - std::array<float, numAngles> angles{{0.0, 90.0, 180.0}}; - - const size_t numCenters = ysize; - std::array<float, numCenters> centers{{4, 3, 3, 4, 4, 4, 4, 3}}; - - FBPTomopy(projImages.data(), ysize, numProj, xsize, centers.data(), - angles.data(), reconVol.data(), xsize, ysize); - - TS_ASSERT_DELTA(reconVol.front(), 66.7519, 1); - TS_ASSERT_DELTA(reconVol[1], 67.9431, 1); - TS_ASSERT_DELTA(reconVol[2], 90.9802, 1); - TS_ASSERT_DELTA(reconVol[3], 111.1035, 1); - TS_ASSERT_DELTA(reconVol[4], 88.6847, 1); - TS_ASSERT_DELTA(reconVol[20], 102.3709, 1); - TS_ASSERT_DELTA(reconVol[50], 97.4173, 1); - TS_ASSERT_DELTA(reconVol[100], 97.4172, 1); - TS_ASSERT_DELTA(reconVol[150], 99.8273, 1); - TS_ASSERT_DELTA(reconVol[projSize - 5], 82.4248, 1); - TS_ASSERT_DELTA(reconVol[projSize - 4], 74.1906, 1); - TS_ASSERT_DELTA(reconVol[projSize - 3], 60.5043, 1); - TS_ASSERT_DELTA(reconVol[projSize - 2], 67.9431, 1); - TS_ASSERT_DELTA(reconVol.back(), 66.7519, 1); - } - - void test_buffer_idx() { - const size_t numProj = 8; - const size_t ysize = 16; - const size_t xsize = 16; - const size_t projSize = numProj * ysize * xsize; - std::array<float, projSize> projImages; - std::iota(projImages.begin(), projImages.end(), 0.0f); - - // inconsistent/stressing values - std::fill(projImages.begin() + 300, projImages.begin() + 400, 333.0f); - std::fill(projImages.begin() + 600, projImages.begin() + 850, 999.0f); - std::fill(projImages.begin() + 990, projImages.begin() + 1100, 1000.0f); - std::fill(projImages.begin() + 1500, projImages.begin() + 1700, -444.0f); - std::fill(projImages.begin() + 1900, projImages.begin() + 2000, 765.0f); - - const size_t reconSize = ysize * ysize * xsize; - std::array<float, reconSize> reconVol; - std::fill(reconVol.begin(), reconVol.end(), 0.0f); - - const size_t numAngles = numProj; - std::array<float, numAngles> angles{ - {0.0, 45.0, 90.0, 135.0, 180.0, 225.0, 270.0, 315.0}}; - - const size_t numCenters = ysize; - std::array<float, numCenters> centers; - std::fill(centers.begin(), centers.end(), 7.5f); - - FBPTomopy(projImages.data(), ysize, numProj, xsize, centers.data(), - angles.data(), reconVol.data(), xsize, ysize); - - TS_ASSERT_DELTA(reconVol.front(), 241.6610, 1); - TS_ASSERT_DELTA(reconVol[1], 286.6727, 1); - TS_ASSERT_DELTA(reconVol[2], 392.6853, 1); - TS_ASSERT_DELTA(reconVol[3], 350.0282, 1); - TS_ASSERT_DELTA(reconVol[4], 429.8395, 1); - TS_ASSERT_DELTA(reconVol[200], 516.5272, 1); - TS_ASSERT_DELTA(reconVol[500], 1202.6435, 1); - TS_ASSERT_DELTA(reconVol[1000], 3604.5090, 1); - TS_ASSERT_DELTA(reconVol[1500], 8092.9765, 1); - TS_ASSERT_DELTA(reconVol[1900], 7941.9135, 1); - TS_ASSERT_DELTA(reconVol[projSize - 5], 6829.1318, 1); - TS_ASSERT_DELTA(reconVol[projSize - 4], 5662.6342, 1); - TS_ASSERT_DELTA(reconVol[projSize - 3], 5747.1845, 1); - TS_ASSERT_DELTA(reconVol[projSize - 2], 6034.2163, 1); - TS_ASSERT_DELTA(reconVol.back(), 3736.5483, 1); - } -}; - -#endif /* MANTID_ALGORITHM_FBPTOMOPYTEST_H_ */ diff --git a/Framework/DataHandling/CMakeLists.txt b/Framework/DataHandling/CMakeLists.txt index 5c2c065eb7e..c6ee3ac5eb9 100644 --- a/Framework/DataHandling/CMakeLists.txt +++ b/Framework/DataHandling/CMakeLists.txt @@ -101,7 +101,6 @@ set ( SRC_FILES src/LoadSPE.cpp src/LoadSampleDetailsFromRaw.cpp src/LoadSassena.cpp - src/LoadSavuTomoConfig.cpp src/LoadSpec.cpp src/LoadSpice2D.cpp src/LoadSpiceAscii.cpp @@ -271,7 +270,6 @@ set ( INC_FILES inc/MantidDataHandling/LoadSPE.h inc/MantidDataHandling/LoadSampleDetailsFromRaw.h inc/MantidDataHandling/LoadSassena.h - inc/MantidDataHandling/LoadSavuTomoConfig.h inc/MantidDataHandling/LoadSpec.h inc/MantidDataHandling/LoadSpice2D.h inc/MantidDataHandling/LoadSpiceAscii.h @@ -440,7 +438,6 @@ set ( TEST_FILES LoadSampleDetailsFromRawTest.h LoadSassenaTest.h LoadSaveAsciiTest.h - LoadSavuTomoConfigTest.h LoadSpice2dTest.h LoadSpiceAsciiTest.h LoadSpiceXML2DDetTest.h diff --git a/Framework/DataHandling/inc/MantidDataHandling/LoadSavuTomoConfig.h b/Framework/DataHandling/inc/MantidDataHandling/LoadSavuTomoConfig.h deleted file mode 100644 index 9e9e34655d7..00000000000 --- a/Framework/DataHandling/inc/MantidDataHandling/LoadSavuTomoConfig.h +++ /dev/null @@ -1,75 +0,0 @@ -#ifndef MANTID_DATAHANDLING_LOADSAVUTOMOCONFIG_H_ -#define MANTID_DATAHANDLING_LOADSAVUTOMOCONFIG_H_ - -#include "MantidAPI/Algorithm.h" -#include "MantidAPI/ITableWorkspace_fwd.h" - -namespace NeXus { -class File; -} - -namespace Mantid { -namespace DataHandling { - -/** - LoadSavuTomoConfig : Load a tomographic reconstruction parameters - file (as used in the savu tomography reconstructin pipeline) into a - TableWorkspace - - Copyright © 2015 ISIS Rutherford Appleton Laboratory, NScD Oak Ridge - National Laboratory & European Spallation Source - - This file is part of Mantid. - - Mantid is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - Mantid is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. - - File change history is stored at: <https://github.com/mantidproject/mantid> - Code Documentation is available at: <http://doxygen.mantidproject.org> -*/ -class DLLExport LoadSavuTomoConfig : public API::Algorithm { -public: - /// Algorithm's name for identification overriding a virtual method - const std::string name() const override { return "LoadSavuTomoConfig"; } - /// Summary of algorithms purpose - const std::string summary() const override { - return "Load configuration parameters from a tomographic " - "reconstruction parameter file."; - } - - /// Algorithm's version for identification overriding a virtual method - int version() const override { return 1; } - - /// Algorithm's category for identification overriding a virtual method - const std::string category() const override { - return "DataHandling\\Imaging"; - } - -private: - /// Implement abstract Algorithm methods - void init() override; - /// Implement abstract Algorithm methods - void exec() override; - - // do the real loading - Mantid::API::ITableWorkspace_sptr loadFile(std::string &fname, - std::string &wsName); - - // open file safely and carefully checking potential issues - bool checkOpenFile(std::string fname, boost::shared_ptr<NeXus::File> &f); -}; - -} // namespace DataHandling -} // namespace Mantid - -#endif /* MANTID_DATAHANDLING_LOADSAVUTOMOCONFIG_H_ */ diff --git a/Framework/DataHandling/src/ImggAggregateWavelengths.cpp b/Framework/DataHandling/src/ImggAggregateWavelengths.cpp deleted file mode 100644 index 63273b693ec..00000000000 --- a/Framework/DataHandling/src/ImggAggregateWavelengths.cpp +++ /dev/null @@ -1,906 +0,0 @@ -#include "MantidDataHandling/ImggAggregateWavelengths.h" -#include "MantidAPI/AlgorithmManager.h" -#include "MantidAPI/FileProperty.h" -#include "MantidAPI/MatrixWorkspace.h" -#include "MantidAPI/WorkspaceGroup.h" -#include "MantidKernel/BoundedValidator.h" -#include "MantidKernel/ListValidator.h" -#include "MantidKernel/make_unique.h" -#include "MantidKernel/MandatoryValidator.h" -#include "MantidKernel/StringTokenizer.h" - -#include <fstream> -#include <iomanip> - -#include <Poco/File.h> -#include <Poco/DirectoryIterator.h> -#include <Poco/Path.h> - -namespace Mantid { -namespace DataHandling { - -const std::string ImggAggregateWavelengths::outPrefixProjections = - "sum_projection_"; -const std::string ImggAggregateWavelengths::outPrefixBands = "bands_"; -const std::string ImggAggregateWavelengths::indexRangesPrefix = "idx_"; -const std::string ImggAggregateWavelengths::tofRangesPrefix = "tof_"; -const std::string ImggAggregateWavelengths::outSubdirsPrefixUniformBands = - "bands_uniform_"; -const std::string ImggAggregateWavelengths::outSubdirsPrefixIndexBands = - "bands_by_index_"; -const std::string ImggAggregateWavelengths::outSubdirsPrefixToFBands = - "bands_by_tof_"; - -using Mantid::Kernel::Direction; -using Mantid::API::WorkspaceProperty; - -// Register the algorithm into the AlgorithmFactory -DECLARE_ALGORITHM(ImggAggregateWavelengths) - -//---------------------------------------------------------------------------------------------- - -/// Algorithms name for identification. @see Algorithm::name -const std::string ImggAggregateWavelengths::name() const { - return "ImggAggregateWavelengths"; -} - -/// Algorithm's version for identification. @see Algorithm::version -int ImggAggregateWavelengths::version() const { return 1; } - -/// Algorithm's category for identification. @see Algorithm::category -const std::string ImggAggregateWavelengths::category() const { - return "DataHandling\\Imaging"; -} - -/// Algorithm's summary for use in the GUI and help. @see Algorithm::summary -const std::string ImggAggregateWavelengths::summary() const { - return "Aggregates images from multiple energy bands or wavelengths"; -} - -namespace { -const std::string PROP_INPUT_PATH = "InputPath"; -const std::string PROP_OUTPUT_PATH = "OutputPath"; -const std::string PROP_UNIFORM_BANDS = "UniformBands"; -const std::string PROP_INDEX_RANGES = "IndexRanges"; -const std::string PROP_TOF_RANGES = "ToFRanges"; -const std::string PROP_NUM_PROJECTIONS_PROCESSED = "NumProjections"; -const std::string PROP_NUM_BANDS_PROCESSED = "NumBands"; -const std::string PROP_OUTPUT_PREFIX_PROJECTIONS = "OutputProjectionsPrefix"; -const std::string PROP_OUTPUT_PREFIX_BANDS = "OutputBandPrefix"; -const std::string PROP_OUTPUT_SUBDIRS_PREFIX_UNIFORM_BANDS = - "OutputSubdirsPrefixUniformBands"; -const std::string PROP_OUTPUT_SUBDIRS_PREFIX_INDEX_BANDS = - "OutputSubdirsPrefixIndexBands"; -const std::string PROP_OUTPUT_SUBDIRS_PREFIX_TOF_BANDS = - "OutputSubdirsPrefixToFBands"; -const std::string PROP_INPUT_IMAGE_FORMAT = "InputImageFormat"; -const std::string PROP_OUTPUT_IMAGE_FORMAT = "OutputImageFormat"; -const std::string PROP_OUTPUT_BIT_DEPTH = "OutputBitDepth"; - -// just to compare two Poco::Path objects, used for std algorithms -struct PocoPathComp - : public std::binary_function<Poco::Path, Poco::Path, bool> { - bool operator()(const Poco::Path &lhs, const Poco::Path &rhs) const { - return lhs.toString() < rhs.toString(); - } -}; -} - -//---------------------------------------------------------------------------------------------- -/** Initialize the algorithm's properties. - */ -void ImggAggregateWavelengths::init() { - declareProperty(Mantid::Kernel::make_unique<API::FileProperty>( - PROP_INPUT_PATH, "", API::FileProperty::Directory), - "The path (directory) to the input image files. It must " - "contain image files (radiography) or subdirectories " - "containing image files (radiography, one directory per " - "projection angle)"); - - declareProperty( - Kernel::make_unique<API::FileProperty>(PROP_OUTPUT_PATH, "", - API::FileProperty::Directory), - "The path (directory) where to generate the output image(s)."); - - auto positive = boost::make_shared<Kernel::BoundedValidator<int>>(); - positive->setLower(0); - declareProperty( - PROP_UNIFORM_BANDS, 1, positive, - "The number of output bands. The input bands are divided into uniform " - "non-overlapping blocks and each of the output bands correspond to one " - "block. This is a convenience particular case of the property " + - PROP_INDEX_RANGES, - Direction::Input); - - declareProperty( - PROP_INDEX_RANGES, "", - "A comma separated list of ranges of indices, where the " - "indices refer to the input images, counting from 1. For " - "example: 1-100, 101-200, 201-300. The number of ranges " - "given will set the number of output bands. If you just need a " - "certain" - "number of bands split uniformly you can alternatively use " - "the simple property " + - PROP_UNIFORM_BANDS); - - // TODO: for later, when we have the required headers to do this - declareProperty( - PROP_TOF_RANGES, "", - "A comma separated list of time-of-flight ranges given as for example " - "5000-10000. These will be the boundaries in ToF that delimit the output " - "bands. The units are as specified in the input images headers or " - "metainformation (normally units of microseconds). The algorithm will " - "produce as many output bands as ranges are " - "given in this property. The ranges can overlap"); - - declareProperty(PROP_NUM_PROJECTIONS_PROCESSED, 0, - "The number of projections (subdirectories with images) " - "found in the input path and successfully processed", - Direction::Output); - - declareProperty(PROP_NUM_BANDS_PROCESSED, 0, - "The number of wavelength or energy bands found in the " - "inputs and successfully processed (aggregated) into the " - "output(s)", - Direction::Output); - - const std::string grpPrefixes = "Naming (prefixes for the outputs)"; - declareProperty( - PROP_OUTPUT_PREFIX_PROJECTIONS, outPrefixProjections, - Kernel::make_unique<Kernel::MandatoryValidator<std::string>>(), - "This prefix is added in the output file names to precede the projection " - "sequence number (or angle, or simply the input directory index). The " - "names of the output files then look like: " + - outPrefixProjections + outPrefixBands + indexRangesPrefix + "1_1200" + - ", as in addition to this prefix, another prefix is added with the " - "indices of the input images included (see option " + - PROP_OUTPUT_PREFIX_BANDS, - Direction::Input); - - declareProperty( - PROP_OUTPUT_PREFIX_BANDS, outPrefixBands, - Kernel::make_unique<Kernel::MandatoryValidator<std::string>>(), - "This prefix is used for the output file names in addition to the prefix " - "that specifies the projection or input " - "directory sequence number, (" + - PROP_OUTPUT_PREFIX_PROJECTIONS + - "). " - "The output bands will be written into subdirectories with names " - "where the prefix is prepended. In addition to this prefix, a second " - "prefix that specifies whether the input bands were aggregated by " - "indices or by time of flight is also appended. For example when " - "running this algorithm using the property " + - PROP_UNIFORM_BANDS + " or " + PROP_INDEX_RANGES + - " the output subdirectoy names will look like '" + - outPrefixProjections + outPrefixBands + indexRangesPrefix + - "1_1200' (where the 1 and 1200 derive from the " - "division into uniform non-overlaping blocks of " - "input bands, or the index ranges given. When " - "running the algorithm using the property " + - PROP_TOF_RANGES + " the output names will look like '" + - outPrefixBands + tofRangesPrefix + - "10000_50000' (where the 10000 and 50000 are the time of flight " - "boundaries of the output band, using the same units as in the image " - "headers).", - Direction::Input); - - declareProperty(PROP_OUTPUT_SUBDIRS_PREFIX_UNIFORM_BANDS, - outSubdirsPrefixUniformBands, - "This prefix will be " - "used for the name of the output subdirectories of every " - "output band when producing uniform output bands (property " + - PROP_UNIFORM_BANDS + ")", - Direction::Input); - - declareProperty( - PROP_OUTPUT_SUBDIRS_PREFIX_INDEX_BANDS, outSubdirsPrefixIndexBands, - "This prefix will be " - "used for the name of the output subdirectories of every " - "output band when producing output bands using index ranges (property " + - PROP_INDEX_RANGES + ")", - Direction::Input); - - declareProperty( - PROP_OUTPUT_SUBDIRS_PREFIX_TOF_BANDS, outSubdirsPrefixToFBands, - "This prefix will be " - "used for the name of the output subdirectories of every " - "output band when producing output bands using ToF ranges (property " + - PROP_TOF_RANGES + ")", - Direction::Input); - - setPropertyGroup(PROP_OUTPUT_PREFIX_PROJECTIONS, grpPrefixes); - setPropertyGroup(PROP_OUTPUT_PREFIX_BANDS, grpPrefixes); - setPropertyGroup(PROP_OUTPUT_SUBDIRS_PREFIX_UNIFORM_BANDS, grpPrefixes); - setPropertyGroup(PROP_OUTPUT_SUBDIRS_PREFIX_INDEX_BANDS, grpPrefixes); - setPropertyGroup(PROP_OUTPUT_SUBDIRS_PREFIX_TOF_BANDS, grpPrefixes); - - const std::string grpImgFormat = "Image format"; - - std::vector<std::string> imgFormat{"FITS"}; - declareProperty( - PROP_INPUT_IMAGE_FORMAT, "FITS", "From the input directory(ies) use " - "images in this format and ignore any " - "other files", - boost::make_shared<Mantid::Kernel::StringListValidator>(imgFormat), - Direction::Input); - - declareProperty( - PROP_OUTPUT_IMAGE_FORMAT, "FITS", "Produce output images in this format", - boost::make_shared<Mantid::Kernel::StringListValidator>(imgFormat), - Direction::Input); - - const std::vector<int> bitDepths{16}; - declareProperty(PROP_OUTPUT_BIT_DEPTH, 16, - boost::make_shared<Kernel::ListValidator<int>>(bitDepths), - "The bit depth or number of bits per pixel to use for the " - "output image(s). Only 16 bits is supported at the " - "moment.", - Direction::Input); - - setPropertyGroup(PROP_INPUT_IMAGE_FORMAT, grpImgFormat); - setPropertyGroup(PROP_OUTPUT_IMAGE_FORMAT, grpImgFormat); - setPropertyGroup(PROP_OUTPUT_BIT_DEPTH, grpImgFormat); -} - -std::map<std::string, std::string> ImggAggregateWavelengths::validateInputs() { - std::map<std::string, std::string> result; - - size_t optCount = 0; - const int uniformBands = getProperty(PROP_UNIFORM_BANDS); - if (uniformBands > 0) - optCount++; - const std::string indexRanges = getPropertyValue(PROP_INDEX_RANGES); - if (!indexRanges.empty()) - optCount++; - const std::string tofRanges = getPropertyValue(PROP_TOF_RANGES); - if (!tofRanges.empty()) - optCount++; - - // Prevent for now. When we enable this option, remove this if - if (!tofRanges.empty()) - result[PROP_TOF_RANGES] = - "This property is not supported in this version of the algorithm"; - - if (1 != optCount) { - result[PROP_UNIFORM_BANDS] = "One and only one of the options " + - PROP_UNIFORM_BANDS + ", " + PROP_INDEX_RANGES + - ", " + PROP_TOF_RANGES + " has to be set."; - } - - const std::string inputPath = getPropertyValue(PROP_INPUT_PATH); - const std::string outputPath = getPropertyValue(PROP_OUTPUT_PATH); - if (inputPath == outputPath) - result[PROP_INPUT_PATH] = "The input and output paths should be different."; - - return result; -} - -//---------------------------------------------------------------------------------------------- -/** Execute the algorithm. - */ -void ImggAggregateWavelengths::exec() { - const std::string inputPath = getPropertyValue(PROP_INPUT_PATH); - const std::string outputPath = getPropertyValue(PROP_OUTPUT_PATH); - const std::string indexRanges = getPropertyValue(PROP_INDEX_RANGES); - const std::string tofRanges = getPropertyValue(PROP_TOF_RANGES); - const int uniformBands = getProperty(PROP_UNIFORM_BANDS); - - if (uniformBands > 0) - aggUniformBands(inputPath, outputPath, uniformBands); - else if (!indexRanges.empty()) - aggIndexBands(inputPath, outputPath, indexRanges); - else if (!tofRanges.empty()) - aggToFBands(inputPath, outputPath, tofRanges); - - g_log.notice() << "Saved output aggregated images into: " << outputPath - << ". They are now ready for further processing. \n"; -} - -void ImggAggregateWavelengths::aggUniformBands(const std::string &inputPath, - const std::string &outputPath, - size_t bands) { - - Poco::Path path(inputPath); - auto inputSubDirs = findInputSubdirs(path); - - if (inputSubDirs.empty()) { - g_log.warning() << "Could not find any input files or directories in " - << inputPath - << " when trying to split the input bands into a uniform " - "number of output bands. Nothing will be produced in " - "the output path.\n"; - } - - auto outputSubdirs = - buildOutputSubdirNamesFromUniformBands(inputSubDirs, bands); - - size_t count = 0; - for (const auto &subdir : inputSubDirs) { - processDirectory(subdir, bands, outputPath, outputSubdirs, outPrefixBands, - count++); - } - setProperty(PROP_NUM_PROJECTIONS_PROCESSED, static_cast<int>(count)); -} - -void ImggAggregateWavelengths::aggIndexBands(const std::string &inputPath, - const std::string &outputPath, - const std::string &rangesSpec) { - - Poco::Path path(inputPath); - auto inputSubDirs = findInputSubdirs(path); - - if (inputSubDirs.empty()) { - g_log.warning() << "Could not find any input files or directories in " - << inputPath << " when looking for input bands. Nothing " - "will be produced in the output path.\n"; - } - - auto outRanges = rangesFromStringProperty(rangesSpec, PROP_INDEX_RANGES); - - auto outputSubdirs = buildOutputSubdirNamesFromIndexRangesBands(outRanges); - - size_t count = 0; - for (const auto &subdir : inputSubDirs) { - processDirectory(subdir, outRanges, outputPath, outputSubdirs, - outPrefixBands, count++); - } - setProperty(PROP_NUM_PROJECTIONS_PROCESSED, static_cast<int>(count)); -} - -void ImggAggregateWavelengths::aggToFBands(const std::string & /*inputPath*/, - const std::string & /*outputPath*/, - const std::string & /*ranges*/) { - - throw std::runtime_error("The property " + PROP_TOF_RANGES + - "is not supported at the moment"); -} - -/** - * Aggregate the images found in an input directory (can be all the - * images from a radiography experiment, or all the images - * corresponding to a single projection angle from a tomography - * experiment). This is the version that processed the "UniformBands" - * property, splitting the input images into uniform bands or blocks - * (as many as given in the property). - * - * @param inDir where to find the input images. - * - * @param bands number of output bands, or number of bands into - * which the input bands should be aggregated, non-overlapping and - * uniformly distributed. - * - * @param outDir where to write the output image(s). - * - * @param outSubdirs subdirectories for every output range (given in the - * input parameter rages) - * - * @param prefix prefix for the image names. The indices will be - * appended to the prefix - * - * @param outImgIndex index of the directory/angle/projection, for - * file naming purposes - */ -void ImggAggregateWavelengths::processDirectory( - const Poco::Path &inDir, size_t bands, const std::string &outDir, - const std::vector<std::string> &outSubdirs, const std::string &prefix, - size_t outImgIndex) { - Mantid::API::MatrixWorkspace_sptr aggImg; - - auto images = findInputImages(inDir); - - if (images.empty()) { - g_log.warning() - << "Could not find any input image files in the subdirectory '" - << inDir.toString() << "'. It will be ignored.\n"; - return; - } - - auto ranges = splitSizeIntoRanges(images.size(), bands); - - processDirectory(inDir, ranges, outDir, outSubdirs, prefix, outImgIndex); -} - -/** - * Produces the output images (bands) from a directory. The directory - * may hold the images for radiography data, or one projection angle - * from tomography data. Multiple output bands (images) can be - * produced as specified in ranges. - * - * This passes through the images one by one (only once), but every - * images can be aggregated into multiple output bands (as the bands - * or min-max ranges can overlap) - * - * @param inDir where to load images from - * @param ranges min-max pairs that define the limits of the output bands - * @param prefix to prepend to all the file names - * @param outDir where to write the output images/bands - * - * @param outSubdirs subdirectories for every output range (given in the - * input parameter rages) - * - * @param outImgIndex an index in the sequence of directories being - * processed - */ -void ImggAggregateWavelengths::processDirectory( - const Poco::Path &inDir, - const std::vector<std::pair<size_t, size_t>> &ranges, - const std::string outDir, const std::vector<std::string> &outSubdirs, - const std::string &prefix, size_t outImgIndex) { - - auto imgFiles = findInputImages(inDir); - - const size_t maxProgress = imgFiles.size() + 1; - API::Progress prog(this, 0, 1, maxProgress); - - const std::string wsName = "__ImggAggregateWavelengths_fits_seq"; - const std::string wsNameFirst = wsName + "_first"; - - prog.report(0, "Loading first input image file"); - auto it = std::begin(imgFiles); - std::vector<API::MatrixWorkspace_sptr> outAccums; - outAccums.resize(ranges.size()); - outAccums[0] = loadFITS(*it, wsNameFirst); - - prog.report(1, "Preparing workspaces for the output images"); - for (size_t idx = 1; idx < ranges.size(); ++idx) { - outAccums[idx] = outAccums[0]->clone(); - } - ++it; - - prog.report(1, "Loading input image files"); - size_t inputIdx = 1; - for (auto end = std::end(imgFiles); it != end; ++it, ++inputIdx) { - // load one more - const API::MatrixWorkspace_sptr img = loadFITS(*it, wsName); - - // add into output - for (size_t idx = 0; idx < outAccums.size(); ++idx) { - if (idx >= ranges[idx].first && idx <= ranges[idx].second) { - aggImage(outAccums[idx], img); - } - } - - // clear image/workspace. TODO: This is a big waste of - // allocations/deallocations - Mantid::API::AnalysisDataService::Instance().remove(wsName); - prog.reportIncrement(1); - } - - prog.report("Saving output image file(s)"); - for (size_t idx = 0; idx < outAccums.size(); ++idx) { - // call the file like: bands_idx_0_1000... - const std::string indicesName = indexRangesPrefix + - std::to_string(ranges[idx].first) + "_to_" + - std::to_string(ranges[idx].second); - - Poco::Path outPath(outDir); - outPath.append(outSubdirs[idx]); - Poco::File fileOutDir(outPath); - if (!fileOutDir.exists()) { - fileOutDir.createDirectory(); - } - - const std::string extendedPrefix = prefix + indicesName; - saveAggImage(outAccums[idx], outPath.toString(), extendedPrefix, - outImgIndex); - } - Mantid::API::AnalysisDataService::Instance().remove(wsNameFirst); - - // output just the number of bands founds for the first subdirectory - int nBands = getProperty(PROP_NUM_BANDS_PROCESSED); - if (0 == nBands) { - setProperty(PROP_NUM_BANDS_PROCESSED, static_cast<int>(imgFiles.size())); - } - prog.reportIncrement(1, "Finished processing input subdirectory/projection"); -} - -std::vector<std::pair<size_t, size_t>> -ImggAggregateWavelengths::rangesFromStringProperty( - const std::string &rangesSpec, const std::string &propName) { - Mantid::Kernel::StringTokenizer rangeTokens( - rangesSpec, ",", Mantid::Kernel::StringTokenizer::TOK_IGNORE_EMPTY | - Mantid::Kernel::StringTokenizer::TOK_TRIM); - - if (rangeTokens.count() <= 0) { - throw std::invalid_argument( - "Could not find any valid range of values in the property " + propName); - } - - std::vector<std::pair<size_t, size_t>> ranges; - for (const auto &str : rangeTokens) { - const std::string sep = "-"; - Mantid::Kernel::StringTokenizer minMaxTokens( - str, sep, Mantid::Kernel::StringTokenizer::TOK_IGNORE_EMPTY | - Mantid::Kernel::StringTokenizer::TOK_TRIM); - if (2 != minMaxTokens.count()) { - throw std::invalid_argument( - std::string( - "Could not parse a minimum and maximum value separated by '") - .append(sep) - .append("' from the string: ") - .append(str)); - } - - try { - ranges.emplace_back(boost::lexical_cast<size_t>(minMaxTokens[0]), - boost::lexical_cast<size_t>(minMaxTokens[1])); - } catch (std::runtime_error &rexc) { - throw std::runtime_error("Failed to parse this index range: " + str + - " . Details: " + std::string(rexc.what())); - } - } - - return ranges; -} - -/** - * Find the (sub)directories that need processing. Each subdirectory - * would normally correspond to a projection (angle). If an - * (apparently) image file is found in the input path, it is assumed - * that the input path is the only that needs processing (it should - * contain images from a radiography or single projection) and - * subdirectories are then ignored. Other files (for example .txt - * files) are ignored in any case. - * - * @param path input path which may contain subdirectories - * - * @return subdirectories of the input path to process (or the input - * path itself if it is the only one that will b processed). - */ -std::vector<Poco::Path> -ImggAggregateWavelengths::findInputSubdirs(const Poco::Path &path) { - // Note: sorted directory iterators available only in poco >= 1.5.2 - std::vector<Poco::Path> dirsFound; - - Poco::File dir(path); - if (!dir.isDirectory() || !dir.exists()) - return dirsFound; - - // could also use Poco::Glob to find the files as an alternative - Poco::DirectoryIterator it(dir); - Poco::DirectoryIterator end; - while (it != end) { - - // there is at least one image file: take just the first level directory - if (it->isFile()) { - const std::string &name = it.name(); - const std::string extShort = name.substr(name.size() - 3); - const std::string extLong = name.substr(name.size() - 4); - - if (isSupportedExtension(extShort, extLong)) { - // the input path contiains image files, take it - dirsFound = {path}; - break; - } - } - - if (it->isDirectory()) { - dirsFound.push_back(it.path()); - } - - ++it; - } - - // this assumes the usual sorting of images of a stack (directory): a prefix, - // and a sequence number (with a fixed number of digits). - std::sort(dirsFound.begin(), dirsFound.end(), PocoPathComp()); - - return dirsFound; -} - -/** - * Find images in a directory. It takes the (image) files that have - * the expected/supported extension. Anything else (other files, - * directories) is ignored. - * - * @param path directory where to look for images - */ -std::vector<Poco::Path> -ImggAggregateWavelengths::findInputImages(const Poco::Path &path) { - // Note: sorted directory iterators available only in poco >= 1.5.2 - std::vector<Poco::Path> imgsFound; - - Poco::File dir(path); - if (!dir.isDirectory() || !dir.exists()) - return imgsFound; - - Poco::DirectoryIterator it(dir); - Poco::DirectoryIterator end; - while (it != end) { - - if (it->isFile()) { - const std::string summedSkipStr = "_SummedImg."; - const std::string name = it.name(); - if (std::string::npos != name.find(summedSkipStr)) { - ++it; - continue; - } - - const std::string extShort = name.substr(name.size() - 3); - const std::string extLong = name.substr(name.size() - 4); - if (isSupportedExtension(extShort, extLong)) { - imgsFound.emplace_back(it.path()); - } - } - - if (it->isDirectory()) { - imgsFound.push_back(it.path()); - } - - ++it; - } - - // this assumes the usual sorting of images of a stack (directory): a prefix, - // and a sequence number (with a fixed number of digits). - std::sort(imgsFound.begin(), imgsFound.end(), PocoPathComp()); - - return imgsFound; -} - -/** - * Split into uniform blocks, for when producing multiple output bands - * from the input images/bands. If the division is not exact, a few - * images at the end will be ignored, so the number of input bands - * that will go into every output band is the same for all of - * them. For example, if 1000 input images/bands are aggregated into 3 - * output bands, From 1000/3: 333 (output band 1), 333 (output band - * 2), 333 (output band 3), and 1 last image is not considered. - * - * @param availableCount how many input elements there are @param - * bands into how many uniform blocks they should be split - * - * @returns pairs of min-max for the output blocks - */ -std::vector<std::pair<size_t, size_t>> -ImggAggregateWavelengths::splitSizeIntoRanges(size_t availableCount, - size_t bands) { - std::vector<std::pair<size_t, size_t>> ranges; - size_t inc = availableCount / bands; - if (inc < 1) { - throw std::runtime_error( - "The number of output bands requested (" + std::to_string(bands) + - ") is bigger than the number of available input images (" + - std::to_string(availableCount) + - "). It should be equal or smaller, and " - "normally it is much smaller. Please " - "check that you are providing the " - "correct input parameters"); - } - - for (size_t count = 0; count < availableCount; count += inc) { - size_t max = - ((count + inc) > availableCount) ? availableCount : count + inc; - ranges.emplace_back(count, max); - } - - return ranges; -} - -/** - * Builds the names of the output subdirectories (bands) given the - * input subdirectories, when splitting the input bands/images into - * uniform blocks. It has to look for the number of available input - * images from the first input subdirectory that has any images. - * - * @param inputSubDirs input subdirectories (one or more) - * @param bands how many output bands will be produced - * - * @returns list of names that can be used to create subdirectories - * for the outputs, derived from the ranges that split the input bands - * into uniform blocks. For example - */ -std::vector<std::string> -ImggAggregateWavelengths::buildOutputSubdirNamesFromUniformBands( - const std::vector<Poco::Path> &inputSubDirs, size_t bands) { - std::vector<std::string> outputSubdirs; - // get number of available images from first effective subdirectory - std::vector<Poco::Path> images; - for (size_t idx = 0; idx < inputSubDirs.size() && images.empty(); ++idx) { - images = findInputImages(inputSubDirs[idx]); - } - auto outRanges = splitSizeIntoRanges(images.size(), bands); - - const std::string subdirsPrefix = - getProperty(PROP_OUTPUT_SUBDIRS_PREFIX_UNIFORM_BANDS); - for (const auto &range : outRanges) { - // one different subdirectory for every output band - outputSubdirs.emplace_back(subdirsPrefix + indexRangesPrefix + - std::to_string(range.first) + "_to_" + - std::to_string(range.second)); - } - - return outputSubdirs; -} - -/** - * Builds the names of the output subdirectories (bands) given a - * sequence of image index ranges, when splitting the input - * bands/images into a sequence of ranges. It has to look for the - * number of available input images from the first input subdirectory - * that has any images. - * - * @param outRanges min-max pairs with ranges of image indices to use - * for the output bands - * - * @returns list of names that can be used to create subdirectories - * for the outputs, derived from the ranges - */ -std::vector<std::string> -ImggAggregateWavelengths::buildOutputSubdirNamesFromIndexRangesBands( - const std::vector<std::pair<size_t, size_t>> &outRanges) { - std::vector<std::string> outputSubdirs; - const std::string subdirsPrefix = - getProperty(PROP_OUTPUT_SUBDIRS_PREFIX_INDEX_BANDS); - for (const auto &range : outRanges) { - // one different subdirectory for every output band - outputSubdirs.emplace_back(subdirsPrefix + indexRangesPrefix + - std::to_string(range.first) + "_to_" + - std::to_string(range.second)); - } - - return outputSubdirs; -} - -bool ImggAggregateWavelengths::isSupportedExtension( - const std::string &extShort, const std::string &extLong) { - const std::vector<std::string> formatExtensionsShort{"fit"}; - const std::vector<std::string> formatExtensionsLong{"fits"}; - - bool found = (formatExtensionsShort.cend() != - std::find(formatExtensionsShort.cbegin(), - formatExtensionsShort.cend(), extShort)) || - (formatExtensionsLong.cend() != - std::find(formatExtensionsLong.cbegin(), - formatExtensionsLong.cend(), extLong)); - return found; -} - -/** - * Add a workspace into an accumulator workspace ('toAdd' into - * 'accum'). This method blatantly ignores the X values and the E - * (error) values. We're only interested in the Y values (pixels, - * counts). - * - * @param accum workspace where to add a new workspace - * @param toAdd workspace to add - */ -void ImggAggregateWavelengths::aggImage(API::MatrixWorkspace_sptr accum, - const API::MatrixWorkspace_sptr toAdd) { - const size_t sizeX = accum->blocksize(); - const size_t sizeY = accum->getNumberHistograms(); - - const size_t sizeXIn = accum->blocksize(); - const size_t sizeYIn = accum->getNumberHistograms(); - - if (sizeX != sizeXIn || sizeY != sizeYIn) { - throw std::runtime_error( - "Cannot add images of different dimensions. The first image has " - "dimensions " + - std::to_string(sizeY) + " rows by " + std::to_string(sizeX) + - " columns whereas the second image has dimensions " + - std::to_string(sizeYIn) + " rows by " + std::to_string(sizeXIn) + - " columns."); - } - - for (size_t row = 0; row < sizeY; row++) { - accum->mutableY(row) += toAdd->y(row); - } -} - -/** - * Save an image workspace into an image file. - * - * @param accum workspace with image data - * @param outDir where the file goes - * @param prefix prefix to use in the file name - * @param outImgIndex index of the directory/angle/projection which - * will be used in the filename - */ -void ImggAggregateWavelengths::saveAggImage( - const API::MatrixWorkspace_sptr accum, const std::string &outDir, - const std::string &prefix, size_t outImgIndex) { - // for example 'sum_projection_00003_bands_indices_0_1000' - std::ostringstream sstr; - sstr << std::setw(5) << std::setfill('0') << outImgIndex; - const std::string outName = outPrefixProjections + sstr.str() + "_" + prefix; - - Poco::Path outPath(outDir); - Poco::File dirFile(outPath); - if (!dirFile.isDirectory() || !dirFile.exists()) { - g_log.information() << "Cannot save output image into '" - << outPath.toString() - << "'. It is not an existing directory.\n"; - return; - } - - outPath.append(outName); - std::string fullName = outPath.toString(); - // only FITS support for now - fullName += ".fits"; - saveFITS(accum, fullName); - g_log.information() << "Saved output aggregated image into: " << fullName - << '\n'; -} - -API::MatrixWorkspace_sptr -ImggAggregateWavelengths::loadFITS(const Poco::Path &imgPath, - const std::string &outName) { - - auto loader = - Mantid::API::AlgorithmManager::Instance().createUnmanaged("LoadFITS"); - try { - loader->initialize(); - loader->setChild(true); - loader->setPropertyValue("Filename", imgPath.toString()); - loader->setProperty("OutputWorkspace", outName); - // this is way faster when loading into a MatrixWorkspace - loader->setProperty("LoadAsRectImg", true); - } catch (std::exception &e) { - throw std::runtime_error("Failed to initialize the algorithm to " - "load images. Error description: " + - std::string(e.what())); - } - - try { - loader->execute(); - } catch (std::exception &e) { - throw std::runtime_error( - "Failed to load image. Could not load this file as a " - "FITS image: " + - std::string(e.what())); - } - - if (!loader->isExecuted()) { - throw std::runtime_error( - "Failed to load image correctly. Note that even though " - "the image file has been loaded it seems to contain errors."); - } - - API::MatrixWorkspace_sptr ws; - try { - API::Workspace_sptr outWS = loader->getProperty("OutputWorkspace"); - API::WorkspaceGroup_sptr wsg = - boost::dynamic_pointer_cast<API::WorkspaceGroup>(outWS); - ws = boost::dynamic_pointer_cast<API::MatrixWorkspace>( - wsg->getItem(wsg->size() - 1)); - } catch (std::exception &e) { - throw std::runtime_error( - "Could not load image contents for file '" + imgPath.toString() + - "'. An unrecoverable error " - "happened when trying to load the image contents. Cannot " - "display it. Error details: " + - std::string(e.what())); - } - - return ws; -} - -void ImggAggregateWavelengths::saveFITS(const API::MatrixWorkspace_sptr accum, - const std::string &filename) { - auto writer = - Mantid::API::AlgorithmManager::Instance().createUnmanaged("SaveFITS"); - try { - writer->initialize(); - writer->setChild(true); - writer->setPropertyValue("Filename", filename); - writer->setProperty("InputWorkspace", accum); - // this is way faster when loading into a MatrixWorkspace - writer->setProperty("BitDepth", 16); - } catch (std::exception &e) { - throw std::runtime_error("Failed to initialize the algorithm to " - "save images in FITS format. Error description: " + - std::string(e.what())); - } - - try { - writer->execute(); - } catch (std::exception &e) { - throw std::runtime_error( - "Failed to write image. Could not write this file as a" - "FITS image: " + - std::string(e.what())); - } -} - -} // namespace DataHandling -} // namespace Mantid diff --git a/Framework/DataHandling/src/LoadSavuTomoConfig.cpp b/Framework/DataHandling/src/LoadSavuTomoConfig.cpp deleted file mode 100644 index 6b75a28a3de..00000000000 --- a/Framework/DataHandling/src/LoadSavuTomoConfig.cpp +++ /dev/null @@ -1,206 +0,0 @@ -#include "MantidAPI/FileProperty.h" -#include "MantidAPI/ITableWorkspace.h" -#include "MantidAPI/TableRow.h" -#include "MantidAPI/WorkspaceProperty.h" -#include "MantidAPI/WorkspaceFactory.h" -#include "MantidDataHandling/LoadSavuTomoConfig.h" -#include "MantidKernel/PropertyWithValue.h" - -#include <nexus/NeXusException.hpp> - -namespace Mantid { -namespace DataHandling { - -// Register the algorithm into the algorithm factory -DECLARE_ALGORITHM(LoadSavuTomoConfig) - -using namespace Mantid::API; - -/** - * Standard Initialisation method. Declares properties. - */ -void LoadSavuTomoConfig::init() { - // Required input properties - const std::vector<std::string> exts{".nxs", ".nx5", ".xml"}; - declareProperty( - Kernel::make_unique<FileProperty>("Filename", "", FileProperty::Load, - exts), - "The name of the Nexus parameterization file to read, as a full " - "or relative path."); - - declareProperty(Kernel::make_unique<WorkspaceProperty<ITableWorkspace>>( - "OutputWorkspace", "savuTomoConfig", - Kernel::Direction::Output, PropertyMode::Mandatory), - "The name of the workspace to be created as output of " - "the algorithm, a workspace with this name will be created " - "and stored in the Analysis Data Service."); -} - -/** - * Executes the algorithm: reads in the parameters file and creates - * and fills the output workspace - * - * @throw runtime_error Thrown if execution fails - */ -void LoadSavuTomoConfig::exec() { - progress(0, "Opening file..."); - - // Will throw an approriate exception if there is a problem with the - // properties - std::string fname = getPropertyValue("Filename"); - std::string wsName = getPropertyValue("OutputWorkspace"); - - ITableWorkspace_sptr ws; - try { - // Do the real load. Throws exception if issues found - ws = loadFile(fname, wsName); - if (ws) { - setProperty("OutputWorkspace", ws); - } - } catch (std::exception &e) { - g_log.error() << "Failed to load savu tomography reconstruction " - "parameterization file: " << e.what() << '\n'; - return; - } - - progress(1.0, "Loading finished."); -} - -/** - * Can it be openend in the expected format, and does it seem to have - * sensible contents? - * - * @param fname name of file - * @param f nexus file object, created if file is fine - * - * @return true if everything seems fine, false otherwise - */ -bool LoadSavuTomoConfig::checkOpenFile(std::string fname, - boost::shared_ptr<NeXus::File> &f) { - try { - f = boost::make_shared<NeXus::File>(fname); - if (f) - f->getEntries(); - } catch (NeXus::Exception &e) { - g_log.error() << "Failed to open as a NeXus file: '" << fname - << "', error description: " << e.what() << '\n'; - return false; - } - return true; -} - -/** - * Loads a tomography parameterization file into a newly created table - * workspace. The file must have the following syntax: - * - * @verbatim - <NXentry name="entry1"> - <NXprocess name="processing"> - <NXnote name="id"> - <values id="ID VALUE" params="..." name="..." cite="..."> - </values> - </NXnote> - </NXprocess> - </NXentry> -@endverbatim - * - * @param fname name of the parameterization file - * @param wsName name of workspace where to load the file data - * - * @return table workspace with parameters (plugins) found in the - * loaded file - */ -ITableWorkspace_sptr LoadSavuTomoConfig::loadFile(std::string &fname, - std::string &wsName) { - // Throws an exception if there is a problem with file access - // Mantid::NeXus::NXRoot root(fname); - boost::shared_ptr<NeXus::File> f; - if (!checkOpenFile(fname, f)) { - throw std::runtime_error( - "Failed to recognize this file as a NeXus file, cannot continue."); - } - - ITableWorkspace_sptr ws = API::WorkspaceFactory::Instance().createTable(); - if (!ws) - throw std::runtime_error("Could not create TableWorkspace for " - "workspace with name '" + - wsName + "'"); - - // init workspace - ws->setTitle("Table with tomography parameters from file " + fname); - ws->addColumn("str", "ID"); - ws->addColumn("str", "Parameters"); - ws->addColumn("str", "Name"); - ws->addColumn("str", "Cite"); - - // a bit of file consistency check, check at least there's a - // 'entry1' - // it could be more strict and demand entries.size()==1 - std::map<std::string, std::string> entries = f->getEntries(); - std::string mainEntryName = "entry"; - auto it = entries.find(mainEntryName); - if (entries.end() == it) { - throw std::runtime_error( - "Could not find the '" + mainEntryName + - "' " - "entry. Even though this file looks like a valid NeXus file, it is " - "not in the correct format for tomography reconstruction " - "parameterization files."); - } - - // go through the input file plugin entries - f->openGroup(mainEntryName, "NXentry"); - f->openGroup("process", "NXprocess"); - size_t pluginsLen = f->getEntries().size(); - for (size_t j = 0; j < pluginsLen; j++) { - API::TableRow table = ws->appendRow(); - - std::string entryIdx = std::to_string(j); - try { - f->openGroup(entryIdx, "NXnote"); - } catch (NeXus::Exception &e) { - // detailed NeXus error message and throw... - g_log.error() << "Failed to load plugin '" << j - << "' from" - "NeXus file. Error description: " << e.what() << '\n'; - throw std::runtime_error( - "Could not load one or more plugin " - "entries from the tomographic reconstruction parameterization " - "file. Please check that the file is correct."); - } - - // TODO: check final 'schema', get these 4 fields from the file - std::string id; - std::string params; - std::string name; - std::string cite; - try { - f->readData("data", params); - f->readData("id", id); - f->readData("name", name); - // cite not available for now - // f->readData("cite", cite); - // This might be extended to an NXcite group that would be included - // not here but inside an "intermediate" NXcollection group. That - // NXcite would have 4 arrays: description, doi, endnote, bibtex. - // But this is what we have so far. - cite = "Not available"; - } catch (NeXus::Exception &e) { - // permissive, just error message but carry on - g_log.warning() - << "Failed to read some fields in tomographic " - "reconstruction plugin line. The file seems to be wrong. Error " - "description: " << e.what() << '\n'; - } - - table << id << params << name << cite; - f->closeGroup(); - progress(static_cast<double>(j) / static_cast<double>(pluginsLen)); - } - f->close(); - - return ws; -} - -} // namespace DataHandling -} // namespace Mantid diff --git a/Framework/DataHandling/src/SaveSavuTomoConfig.cpp b/Framework/DataHandling/src/SaveSavuTomoConfig.cpp deleted file mode 100644 index 80c331018d6..00000000000 --- a/Framework/DataHandling/src/SaveSavuTomoConfig.cpp +++ /dev/null @@ -1,206 +0,0 @@ -#include "MantidAPI/AnalysisDataService.h" -#include "MantidAPI/FileProperty.h" -#include "MantidAPI/ITableWorkspace.h" -#include "MantidDataHandling/SaveSavuTomoConfig.h" -#include "MantidKernel/ArrayProperty.h" -#include "MantidKernel/MandatoryValidator.h" - -#include <nexus/NeXusFile.hpp> -#include <Poco/File.h> - -namespace Mantid { -namespace DataHandling { -// Register the algorithm into the algorithm factory -DECLARE_ALGORITHM(SaveSavuTomoConfig) - -using namespace Kernel; -using namespace API; - -SaveSavuTomoConfig::SaveSavuTomoConfig() - : API::Algorithm(), m_pluginInfoCount(4) {} - -/** - * Initialise the algorithm - */ -void SaveSavuTomoConfig::init() { - // Get a list of table workspaces which contain the plugin information - declareProperty( - Kernel::make_unique<ArrayProperty<std::string>>( - "InputWorkspaces", - boost::make_shared<MandatoryValidator<std::vector<std::string>>>()), - "The names of the table workspaces containing plugin information."); - - declareProperty(Kernel::make_unique<API::FileProperty>( - "Filename", "", FileProperty::Save, - std::vector<std::string>(1, ".nxs")), - "The name of the tomographic config file to write, as a full " - "or relative path. This will overwrite existing files."); -} - -/** - * Execute the algorithm - */ -void SaveSavuTomoConfig::exec() { - // Prepare properties for writing to file - std::string fileName = getPropertyValue("Filename"); - - progress(0, "Checking workspace (tables)..."); - - std::vector<ITableWorkspace_sptr> wss = - checkTables(getProperty("InputWorkspaces")); - - try { - saveFile(fileName, wss); - } catch (std::exception &e) { - g_log.error() - << "Failed to save savu tomography reconstruction parameterization " - "file, error description: " << e.what() << '\n'; - return; - } - - progress(0, "File saved."); -} - -/** - * Do a basic check that the table seems to be what we need to save a - * savu configuration file. - * - * @param tws Table workspace that should contain plugin/processing - * steps information (a savu configuration) - * - * @return True if the table passed seems to be a savu configuration table - */ -bool SaveSavuTomoConfig::tableLooksGenuine(const ITableWorkspace_sptr &tws) { - // note that more columns might be added in the relatively near future - if (!(tws->columnCount() >= m_pluginInfoCount)) - return false; - - std::vector<std::string> names = tws->getColumnNames(); - return (4 <= names.size() && "ID" == names[0] && "Parameters" == names[1] && - "Name" == names[2] && "Cite" == names[3]); -} - -/** - * Check that the list of workspace names identifies table workspaces - * with (approximately) the expected information (4 columns), and - * return the corresponding (table) workspace objects. - * - * @param workspaces Table workspace names that should contain plugin/processing - * steps information - * - * @return Table workspaces retrieved from the ADS, corresponding to - * the names passed - */ -std::vector<ITableWorkspace_sptr> -SaveSavuTomoConfig::checkTables(const std::vector<std::string> &workspaces) { - std::vector<ITableWorkspace_sptr> wss; - for (const auto &workspace : workspaces) { - if (AnalysisDataService::Instance().doesExist(workspace)) { - ITableWorkspace_sptr table = - AnalysisDataService::Instance().retrieveWS<ITableWorkspace>( - workspace); - // Check it's valid. Very permissive check for the time being - if (table && tableLooksGenuine(table)) { - wss.push_back(table); - } else { - throw std::runtime_error("Invalid workspace provided: " + workspace + - ". This algorithm requires a table " - "workspace with correct savu plugin/ " - "pipeline process information."); - } - } else { - throw std::runtime_error( - "One or more specified table workspaces don't exist. I could not " - "find this one: " + - workspace); - } - } - return wss; -} - -/** - * Check that the list of workspace names identifies table workspaces - * with (approximately) the expected information (4 columns), and - * return the corresponding (table) workspace objects. - * - * @param fname Destination file name (can be ammended if needed and that - * will be logged) - * @param wss Table workspaces that apparently contain plugin/processing - * steps information - */ -void SaveSavuTomoConfig::saveFile( - const std::string fname, const std::vector<ITableWorkspace_sptr> &wss) { - // Ensure it has a .nxs extension - std::string fileName = fname; - if (!boost::ends_with(fileName, ".nxs")) { - const std::string ext = ".nxs"; - g_log.notice() << "Adding extension '" << ext - << "' to the output " - "file name given (it is a NeXus file). \n"; - fileName = fileName + ".nxs"; - } - - // If file exists, delete it. - Poco::File f(fileName); - if (f.exists()) { - g_log.notice() << "Overwriting existing file: '" << fileName << "'\n"; - f.remove(); - } else { - g_log.notice() << "Creating file: '" << fileName << ";\n"; - } - - // Create the file handle - NXhandle fileHandle; - NXstatus status = NXopen(fileName.c_str(), NXACC_CREATE5, &fileHandle); - - if (status == NX_ERROR) - throw std::runtime_error("Unable to create file."); - - NeXus::File nxFile(fileHandle); - - std::string topLevelEntry = "entry"; - nxFile.makeGroup(topLevelEntry, "NXentry", true); - - const std::string processingEntry = "processing"; - nxFile.makeGroup(processingEntry, "NXprocess", true); - - // Iterate through all plugin entries (number sub groups 0....n-1) - size_t procCount = 0; - for (const auto &w : wss) { - // Concatenate table contents, putting pipeline processing steps in the same - // sequence - // as they come in the seq of table workspaces - for (size_t ti = 0; ti < w->rowCount(); ++ti) { - // Column info order is [ID / Params {as json string} / name {description} - // / - // citation info] - std::string id = w->cell<std::string>(ti, 0); - std::string params = w->cell<std::string>(ti, 1); - std::string name = w->cell<std::string>(ti, 2); - // Unused for now, until file format is finalized/documented. - // std::string cite = w->cell<std::string>(ti, 3); - - // but in the file it goes as: data (params), id, name - nxFile.makeGroup(std::to_string(procCount++), "NXnote", true); - nxFile.writeData("data", params); - nxFile.writeData("id", id); - nxFile.writeData("name", name); - // Ignore citation information for now. Format not fixed yet. - // nxFile.writeData("cite", cite); - nxFile.closeGroup(); // close NXnote - } - } - - nxFile.closeGroup(); // processing NXprocess - - // This seems to be required for certain extensions that can be appended - // to these files. Not fixed for now. - nxFile.makeGroup("intermediate", "NXcollection", false); - - nxFile.closeGroup(); // Top level entry (NXentry) - - nxFile.close(); -} - -} // namespace DataHandling -} // namespace Mantid diff --git a/Framework/DataHandling/test/LoadSavuTomoConfigTest.h b/Framework/DataHandling/test/LoadSavuTomoConfigTest.h deleted file mode 100644 index 013669f1ae6..00000000000 --- a/Framework/DataHandling/test/LoadSavuTomoConfigTest.h +++ /dev/null @@ -1,189 +0,0 @@ -#ifndef LOADSAVUTOMOCONFIGTEST_H_ -#define LOADSAVUTOMOCONFIGTEST_H_ - -#include <cxxtest/TestSuite.h> - -#include "MantidAPI/AlgorithmManager.h" -#include "MantidAPI/AnalysisDataService.h" -#include "MantidAPI/ITableWorkspace.h" -#include "MantidDataHandling/LoadSavuTomoConfig.h" - -using namespace Mantid::API; -using Mantid::DataHandling::LoadSavuTomoConfig; - -class LoadSavuTomoConfigTest : public CxxTest::TestSuite { -public: - // This pair of boilerplate methods prevent the suite being created statically - // This means the constructor isn't called when running other tests - static LoadSavuTomoConfigTest *createSuite() { - return new LoadSavuTomoConfigTest(); - } - static void destroySuite(LoadSavuTomoConfigTest *suite) { delete suite; } - - /// Tests casting, general algorithm properties: name, version, etc. - void test_algorithm() { - testAlg = Mantid::API::AlgorithmManager::Instance().create( - "LoadSavuTomoConfig" /*, 1*/); - TS_ASSERT(testAlg); - TS_ASSERT_EQUALS(testAlg->name(), "LoadSavuTomoConfig"); - TS_ASSERT_EQUALS(testAlg->version(), 1); - } - - void test_init() { - if (!testAlg->isInitialized()) - testAlg->initialize(); - - TS_ASSERT_THROWS_NOTHING(testAlg->initialize()); - TS_ASSERT(testAlg->isInitialized()); - } - - void test_wrongExec() { - IAlgorithm_sptr testFail = Mantid::API::AlgorithmManager::Instance().create( - "LoadSavuTomoConfig" /*, 1*/); - TS_ASSERT(testFail); - TS_ASSERT_THROWS_NOTHING(testFail->initialize()); - // exec without Filename property set -> should throw - TS_ASSERT_THROWS(testFail->execute(), std::runtime_error); - // try to set empty filename - TS_ASSERT_THROWS(testFail->setPropertyValue("Filename", ""), - std::invalid_argument); - TS_ASSERT(!testFail->isExecuted()); - - // exec with Filename but empty OutputWorkspace -> should throw - IAlgorithm_sptr fail2 = Mantid::API::AlgorithmManager::Instance().create( - "LoadSavuTomoConfig" /*, 1*/); - TS_ASSERT_THROWS_NOTHING(fail2->initialize()); - TS_ASSERT_THROWS_NOTHING(fail2->setPropertyValue("Filename", testFilename)); - TS_ASSERT_THROWS(fail2->setPropertyValue("OutputWorkspace", ""), - std::invalid_argument); - TS_ASSERT_THROWS(fail2->execute(), std::runtime_error); - TS_ASSERT(!fail2->isExecuted()); - - // exec with Filename but no OutputWorkspace -> should not finish - IAlgorithm_sptr fail3 = Mantid::API::AlgorithmManager::Instance().create( - "LoadSavuTomoConfig" /*, 1*/); - TS_ASSERT_THROWS_NOTHING(fail3->initialize()); - TS_ASSERT_THROWS_NOTHING(fail3->setPropertyValue("Filename", testFilename)); - TS_ASSERT_THROWS_NOTHING(fail3->execute()); - TS_ASSERT(!fail2->isExecuted()); - } - - // one file with errors/unrecognized content - void test_wrongContentsFile() { - // TODO: wait until we have a final spec of the format, then try to fool - // the loader here - } - - // one example file that should load fine - void test_loadOK() { - // Uses examples from the savu repository: - // https://github.com/DiamondLightSource/Savu/tree/master/test_data - - // TODO: At the moment load just one file to test basic - // functionality. Probably more files should be added here as we - // have more certainty about the format - std::string inWSName = "LoadSavuTomoConfig_test_ws"; - // Load examples from - // https://github.com/DiamondLightSource/Savu/tree/master/test_data - TS_ASSERT_THROWS_NOTHING( - testAlg->setPropertyValue("Filename", testFilename)); - TS_ASSERT_THROWS_NOTHING( - testAlg->setPropertyValue("OutputWorkspace", inWSName)); - - if (!testAlg->isInitialized()) - testAlg->initialize(); - TS_ASSERT(testAlg->isInitialized()); - - TS_ASSERT_THROWS_NOTHING(testAlg->execute()); - TS_ASSERT(testAlg->isExecuted()); - - AnalysisDataServiceImpl &ads = AnalysisDataService::Instance(); - - TS_ASSERT(ads.doesExist(inWSName)); - ITableWorkspace_sptr ws; - TS_ASSERT_THROWS_NOTHING(ws = ads.retrieveWS<ITableWorkspace>(inWSName)); - - // general format: 3 columns (data, id, name) - TS_ASSERT_EQUALS(ws->columnCount(), 4); - TS_ASSERT_EQUALS(ws->rowCount(), 3); - - checkColumns(ws); - -#if (defined __APPLE__ && defined __INTEL_COMPILER) - // This is a horror, an exception needed for osx 10.8 where lib nexus does - // not behave - // Bug in NeXus strings: the last character is trimmed - // TODO: remove this when osx 10.8 extinguishes (theres a ticket being - // created for that). - // ID - TS_ASSERT_EQUALS(ws->cell<std::string>(0, 0), - "savu.plugins.timeseries_field_correction"); - TS_ASSERT_EQUALS(ws->cell<std::string>(1, 0), "savu.plugins.median_filte"); - TS_ASSERT_EQUALS(ws->cell<std::string>(2, 0), "savu.plugins.simple_reco"); - - // data entry in NeXus file (Params column) - TS_ASSERT_EQUALS(ws->cell<std::string>(0, 1), "{"); - TS_ASSERT_EQUALS(ws->cell<std::string>(1, 1), - "{\"kernel_size\": [1, 3, 3]"); - TS_ASSERT_EQUALS(ws->cell<std::string>(2, 1), - "{\"center_of_rotation\": 86"); - - // name entry in NeXus file - TS_ASSERT_EQUALS(ws->cell<std::string>(0, 2), - "Timeseries Field Correction"); - TS_ASSERT_EQUALS(ws->cell<std::string>(1, 2), "Median Filte"); - TS_ASSERT_EQUALS(ws->cell<std::string>(2, 2), "Simple Reconstructio"); - -#else - // this example has 3 plugins: savu.plugins.timeseries_fields_corrections, - // savu.median_filter, - // savu.plugins.simple_recon - // ID - TS_ASSERT_EQUALS(ws->cell<std::string>(0, 0), - "savu.plugins.timeseries_field_corrections"); - TS_ASSERT_EQUALS(ws->cell<std::string>(1, 0), "savu.plugins.median_filter"); - TS_ASSERT_EQUALS(ws->cell<std::string>(2, 0), "savu.plugins.simple_recon"); - - // data entry in NeXus file (Params column) - TS_ASSERT_EQUALS(ws->cell<std::string>(0, 1), "{}"); - TS_ASSERT_EQUALS(ws->cell<std::string>(1, 1), - "{\"kernel_size\": [1, 3, 3]}"); - TS_ASSERT_EQUALS(ws->cell<std::string>(2, 1), - "{\"center_of_rotation\": 86}"); - - // name entry in NeXus file - TS_ASSERT_EQUALS(ws->cell<std::string>(0, 2), - "Timeseries Field Corrections"); - TS_ASSERT_EQUALS(ws->cell<std::string>(1, 2), "Median Filter"); - TS_ASSERT_EQUALS(ws->cell<std::string>(2, 2), "Simple Reconstruction"); -#endif - - // cite information, not presently available in example files - for (size_t i = 0; i < nRows; i++) { - TS_ASSERT_EQUALS(ws->cell<std::string>(i, 3), "Not available"); - } - } - -private: - void checkColumns(ITableWorkspace_sptr &table) { - // each row of the workspace should have: ID, Params, Name, Cite - std::vector<std::string> names = table->getColumnNames(); - TS_ASSERT_EQUALS(names.size(), 4); - TS_ASSERT_EQUALS(names[0], "ID"); - TS_ASSERT_EQUALS(names[1], "Parameters"); - TS_ASSERT_EQUALS(names[2], "Name"); - TS_ASSERT_EQUALS(names[3], "Cite"); - } - - IAlgorithm_sptr testAlg; - static const size_t nRows; - static const size_t nCols; - static const std::string testFilename; -}; - -const size_t LoadSavuTomoConfigTest::nRows = 3; -const size_t LoadSavuTomoConfigTest::nCols = 4; -const std::string LoadSavuTomoConfigTest::testFilename = - "savu_test_data_process03.nxs"; - -#endif /* LOADSAVUTOMOCONFIGTEST_H__*/ diff --git a/Framework/DataHandling/test/SaveSavuTomoConfigTest.h b/Framework/DataHandling/test/SaveSavuTomoConfigTest.h deleted file mode 100644 index c3f301f5033..00000000000 --- a/Framework/DataHandling/test/SaveSavuTomoConfigTest.h +++ /dev/null @@ -1,177 +0,0 @@ -#ifndef SAVESAVUTOMOCONFIGTEST_H_ -#define SAVESAVUTOMOCONFIGTEST_H_ - -#include <cxxtest/TestSuite.h> - -#include "MantidAPI/AlgorithmManager.h" -#include "MantidAPI/AnalysisDataService.h" -#include "MantidAPI/ITableWorkspace.h" -#include "MantidAPI/TableRow.h" -#include "MantidAPI/WorkspaceFactory.h" -#include "MantidDataHandling/SaveSavuTomoConfig.h" - -#include <Poco/File.h> - -using namespace Mantid::API; -using namespace Mantid::DataHandling; - -class SaveSavuTomoConfigTest : public CxxTest::TestSuite { -public: - // This pair of boilerplate methods prevent the suite being created statically - // This means the constructor isn't called when running other tests - static SaveSavuTomoConfigTest *createSuite() { - return new SaveSavuTomoConfigTest(); - } - static void destroySuite(SaveSavuTomoConfigTest *suite) { delete suite; } - - /// Tests casting, general algorithm properties: name, version, etc. - void test_algorithm() { - testSave = Mantid::API::AlgorithmManager::Instance().create( - "SaveSavuTomoConfig" /*, 1*/); - TS_ASSERT(testSave); - TS_ASSERT_EQUALS(testSave->name(), "SaveSavuTomoConfig"); - TS_ASSERT_EQUALS(testSave->version(), 1); - } - - void test_init() { - if (!testSave->isInitialized()) - testSave->initialize(); - - TS_ASSERT_THROWS_NOTHING(testSave->initialize()); - TS_ASSERT(testSave->isInitialized()); - } - - /// this is the first test that uses the good workspace (wsName) so it creates - /// it - void test_wrongExec() { - ITableWorkspace_sptr ws = makeTableWorkspace(wsName); - - IAlgorithm_sptr testFail = Mantid::API::AlgorithmManager::Instance().create( - "SaveSavuTomoConfig" /*, 1*/); - TS_ASSERT(testFail); - TS_ASSERT_THROWS_NOTHING(testFail->initialize()); - // exec without InputWorkspaces property set -> should throw - TS_ASSERT_THROWS(testFail->execute(), std::runtime_error); - // try to set empty InputWorkspaces - TS_ASSERT_THROWS(testFail->setPropertyValue("InputWorkspaces", ""), - std::invalid_argument); - TS_ASSERT(!testFail->isExecuted()); - - // exec with InputWorkspaces but empty Filename -> should throw - IAlgorithm_sptr fail2 = Mantid::API::AlgorithmManager::Instance().create( - "SaveSavuTomoConfig" /*, 1*/); - TS_ASSERT_THROWS_NOTHING(fail2->initialize()); - TS_ASSERT_THROWS_NOTHING( - fail2->setPropertyValue("InputWorkspaces", wsName)); - TS_ASSERT_THROWS(fail2->setPropertyValue("Filename", ""), - std::invalid_argument); - TS_ASSERT_THROWS(fail2->execute(), std::runtime_error); - TS_ASSERT(!fail2->isExecuted()); - - // exec with InputWorkspaces but no Filename -> should throw - IAlgorithm_sptr fail3 = Mantid::API::AlgorithmManager::Instance().create( - "SaveSavuTomoConfig" /*, 1*/); - TS_ASSERT_THROWS_NOTHING(fail3->initialize()); - TS_ASSERT_THROWS_NOTHING( - fail3->setPropertyValue("InputWorkspaces", wsName)); - TS_ASSERT_THROWS(fail3->execute(), std::runtime_error); - } - - void test_wrongTableFormat() { - std::string badWSName = "bad_table"; - ITableWorkspace_sptr ws = makeWrongTableWorkspace(badWSName); - - // using wrong table: should fail - IAlgorithm_sptr fail = Mantid::API::AlgorithmManager::Instance().create( - "SaveSavuTomoConfig" /*, 1*/); - TS_ASSERT_THROWS_NOTHING(fail->initialize()); - TS_ASSERT_THROWS_NOTHING( - fail->setPropertyValue("InputWorkspaces", badWSName)); - TS_ASSERT_THROWS_NOTHING(fail->setPropertyValue("Filename", outFilename)); - TS_ASSERT_THROWS_NOTHING(fail->execute()); - TS_ASSERT(!fail->isExecuted()); - - AnalysisDataService::Instance().remove(badWSName); - } - - /// this is the last test that uses the good workspace (wsName) so it removes - /// it from teh ADS - void test_saveOK() { - TS_ASSERT(testSave->isInitialized()); - TS_ASSERT_THROWS_NOTHING( - testSave->setPropertyValue("InputWorkspaces", wsName)); - TS_ASSERT_THROWS_NOTHING( - testSave->setPropertyValue("Filename", outFilename)); - TS_ASSERT_THROWS_NOTHING(testSave->execute()); - TS_ASSERT(testSave->isExecuted()); - - // very basic test, to do more than this use the sibling LoadSavuTomo - // algorithm - TS_ASSERT(Poco::File(outFilename).exists()); - boost::shared_ptr<NeXus::File> file; - // can open as NeXus and find one of the entries - TS_ASSERT_THROWS_NOTHING(file = - boost::make_shared<NeXus::File>(outFilename)); - TS_ASSERT_THROWS_NOTHING(file->openPath("/entry/processing/0")); - TS_ASSERT_THROWS_NOTHING(file->close()); - - cleanup(); - } - -private: - /// removes the output file and the input workspace - void cleanup() { - TS_ASSERT_THROWS_NOTHING(Poco::File(outFilename).remove()); - TS_ASSERT_THROWS_NOTHING(AnalysisDataService::Instance().remove(wsName)); - } - - /// helper: specific table format here for savu pipeline configurations - ITableWorkspace_sptr makeTableWorkspace(const std::string &name) { - ITableWorkspace_sptr ws = WorkspaceFactory::Instance().createTable(); - AnalysisDataService::Instance().addOrReplace(name, ws); - ws->addColumn("str", "ID"); - ws->addColumn("str", "Parameters"); - ws->addColumn("str", "Name"); - ws->addColumn("str", "Cite"); - - Mantid::API::TableRow row = ws->appendRow(); - row << "savu.id1" - << "{\"param1\": val1}" - << "name 1" - << "cite 1"; - row = ws->appendRow(); - row << "savu.id2" - << "{\"param2\": val2}" - << "name 2" - << "cite 2"; - - return ws; - } - - // helper to build a bad table: intentionally forgets to add some columns - ITableWorkspace_sptr makeWrongTableWorkspace(const std::string &name) { - ITableWorkspace_sptr ws = WorkspaceFactory::Instance().createTable(); - AnalysisDataService::Instance().addOrReplace(name, ws); - ws->addColumn("str", "ID"); - ws->addColumn("str", "Name"); - - Mantid::API::TableRow row = ws->appendRow(); - row << "savu.id1" - << "{\"param1\": val1}"; - row = ws->appendRow(); - row << "savu.id2" - << "{\"param2\": val2}"; - - return ws; - } - - IAlgorithm_sptr testSave; - static const std::string outFilename; - static const std::string wsName; -}; - -const std::string SaveSavuTomoConfigTest::wsName = "simple_table"; -const std::string SaveSavuTomoConfigTest::outFilename = - "savu_tomo_save_test.nxs"; - -#endif /* SAVESAVUTOMOCONFIGTEST_H */ diff --git a/Framework/RemoteAlgorithms/src/SCARFTomoReconstruction.cpp b/Framework/RemoteAlgorithms/src/SCARFTomoReconstruction.cpp deleted file mode 100644 index 78c7e4df572..00000000000 --- a/Framework/RemoteAlgorithms/src/SCARFTomoReconstruction.cpp +++ /dev/null @@ -1,1498 +0,0 @@ -#include <fstream> - -#include "MantidAPI/FileProperty.h" -#include "MantidAPI/WorkspaceFactory.h" -#include "MantidAPI/WorkspaceProperty.h" -#include "MantidKernel/ArrayProperty.h" -#include "MantidKernel/ConfigService.h" -#include "MantidKernel/FacilityInfo.h" -#include "MantidKernel/InternetHelper.h" -#include "MantidKernel/ListValidator.h" -#include "MantidKernel/MandatoryValidator.h" -#include "MantidKernel/MaskedProperty.h" -#include "MantidKernel/NullValidator.h" -#include "MantidKernel/RemoteJobManager.h" -#include "MantidKernel/VisibleWhenProperty.h" -#include "MantidRemoteAlgorithms/SCARFTomoReconstruction.h" - -#include <Poco/File.h> -#include <Poco/DOM/Document.h> -#include <Poco/DOM/DOMParser.h> -#include <Poco/DOM/Element.h> -#include <Poco/DOM/NodeList.h> -#include <Poco/Net/HTTPRequest.h> -#include <Poco/StreamCopier.h> - -#include <boost/algorithm/string/replace.hpp> - -namespace Mantid { -namespace RemoteAlgorithms { - -// Register the algorithm into the AlgorithmFactory -DECLARE_ALGORITHM(SCARFTomoReconstruction) - -using namespace Mantid::Kernel; - -std::map<std::string, SCARFTomoReconstruction::Token> - SCARFTomoReconstruction::m_tokenStash; - -std::string SCARFTomoReconstruction::m_acceptType = - "text/plain,application/xml,text/xml"; - -const std::string SCARFTomoReconstruction::m_SCARFComputeResource = - "SCARF@STFC"; - -int SCARFTomoReconstruction::m_jobSeq = 1; - -SCARFTomoReconstruction::SCARFTomoReconstruction() - : Mantid::API::Algorithm(), m_action() {} - -void SCARFTomoReconstruction::init() { - // list of all actions - std::vector<std::string> actions{"LogIn", "LogOut", "Ping", - "Upload", "SubmitJob", "JobStatus", - "JobStatusByID", "Download", "CancelJob"}; - - auto listValue = boost::make_shared<StringListValidator>(actions); - auto nullV = boost::make_shared<Kernel::NullValidator>(); - - // Username always visible, it doesn't hurt and it is required to know the - // web service base URL for most LSF commands - auto requireStrValue = boost::make_shared<MandatoryValidator<std::string>>(); - declareProperty("UserName", "", requireStrValue, - "Name of the user to authenticate as", Direction::Input); - - // Action to perform - declareProperty("Action", "LogIn", listValue, - "Choose the operation to perform " - "on the compute resource " + - m_SCARFComputeResource, - Direction::Input); - - // - Action: login - declareProperty(make_unique<MaskedProperty<std::string>>("Password", "", - Direction::Input), - "The password for the user"); - setPropertySettings("Password", make_unique<VisibleWhenProperty>( - "Action", IS_EQUAL_TO, "LogIn")); - - // - Action: submit - declareProperty(make_unique<PropertyWithValue<std::string>>( - "RunnablePath", - "/work/imat/webservice_test/tomopy/imat_recon_FBP.py", - Direction::Input), - "The path (on the remote compute resource) of a file to run " - "(example: shell or python script)"); - setPropertySettings("RunnablePath", make_unique<VisibleWhenProperty>( - "Action", IS_EQUAL_TO, "SubmitJob")); - - declareProperty( - make_unique<PropertyWithValue<std::string>>( - "JobOptions", "/work/imat/webservice_test/remote_output/test_", - Direction::Input), - "Options for the job command line, application dependent. It " - "can include for example the NXTomo input file when using savu " - "for tomographic reconstruction."); - setPropertySettings("JobOptions", make_unique<VisibleWhenProperty>( - "Action", IS_EQUAL_TO, "SubmitJob")); - - declareProperty( - "JobName", "", nullV, - "Optional name for the job, if not given then a " - "name will be generated internally or at the compute resource", - Direction::Input); - setPropertySettings("JobName", make_unique<VisibleWhenProperty>( - "Action", IS_EQUAL_TO, "SubmitJob")); - - // - Action: upload file - declareProperty( - make_unique<API::FileProperty>("FileToUpload", "", - API::FileProperty::OptionalLoad, "", - Direction::Input), - "Name of the file (local, full path) to upload to the compute " - "resource/server "); - setPropertySettings("FileToUpload", make_unique<VisibleWhenProperty>( - "Action", IS_EQUAL_TO, "Upload")); - - declareProperty( - make_unique<PropertyWithValue<std::string>>( - "DestinationDirectory", "/work/imat", Direction::Input), - "Path where to upload the file on the compute resource/server"); - setPropertySettings( - "DestinationDirectory", - make_unique<VisibleWhenProperty>("Action", IS_EQUAL_TO, "Upload")); - - // - Action: query status and info (of implicitly all jobs) - declareProperty(make_unique<ArrayProperty<std::string>>("RemoteJobsID", - Direction::Output), - "ID strings for the jobs"); - declareProperty(make_unique<ArrayProperty<std::string>>("RemoteJobsNames", - Direction::Output), - "Names of the jobs"); - declareProperty(make_unique<ArrayProperty<std::string>>("RemoteJobsStatus", - Direction::Output), - "Strings describing the current status of the jobs"); - declareProperty(make_unique<ArrayProperty<std::string>>("RemoteJobsCommands", - Direction::Output), - "Strings with the command line run for the jobs"); - - // - Action: query status and info by ID - declareProperty( - make_unique<PropertyWithValue<int>>("JobID", 0, Direction::Input), - "The ID of a job currently running or recently run on the " - "compute resource"); - setPropertySettings("JobID", make_unique<VisibleWhenProperty>( - "Action", IS_EQUAL_TO, "JobStatusByID")); - - declareProperty("RemoteJobName", "", nullV, "Name of the remote job", - Direction::Output); - declareProperty("RemoteJobStatus", "", nullV, "Current status of the job " - "(running, exited, etc.)", - Direction::Output); - declareProperty("RemoteJobCommand", "", nullV, "Command line run remotely " - "for this job ", - Direction::Output); - - // - Action: download file - declareProperty( - make_unique<PropertyWithValue<std::string>>("RemoteJobFilename", "", - Direction::Input), - "Name of the job file to download - you can give an empty name " - "to download all the files of this job."); - setPropertySettings( - "RemoteJobFilename", - make_unique<VisibleWhenProperty>("Action", IS_EQUAL_TO, "Download")); - - declareProperty( - make_unique<API::FileProperty>("LocalDirectory", "", - API::FileProperty::OptionalDirectory, "", - Direction::Input), - "Path to a local directory/folder where to download files from " - "the compute resource/server"); - setPropertySettings("LocalDirectory", make_unique<VisibleWhenProperty>( - "Action", IS_EQUAL_TO, "Download")); - - declareProperty( - make_unique<PropertyWithValue<int>>("DownloadJobID", 0, Direction::Input), - "ID of the job for which to download files. A job with this ID " - "must be running or have been run on the compute resource."); - setPropertySettings("DownloadJobID", make_unique<VisibleWhenProperty>( - "Action", IS_EQUAL_TO, "Download")); - - // - Action: cancel job by ID - declareProperty( - make_unique<PropertyWithValue<int>>("CancelJobID", 0, Direction::Input), - "The ID for a currently running job on " + m_SCARFComputeResource); - setPropertySettings("CancelJobID", make_unique<VisibleWhenProperty>( - "Action", IS_EQUAL_TO, "CancelJob")); -} - -/** - * Execute algorithm: check what action/command has to be run and call - * specific methods. - * - * The implementation of the more specific methods is based on: - * Mantid::Kernel::InternetHelper. - */ -void SCARFTomoReconstruction::exec() { - - m_action = getAction(); - - g_log.information("Running SCARFTomoReconstruction"); - - // only action that doesn't require any credentials - if (Action::PING == m_action) { - doPing(); - return; - } - - // otherwise, check first username and then action-specific parameters - std::string username; - try { - username = getPropertyValue("UserName"); - } catch (std::runtime_error & /*e*/) { - g_log.error() - << "To use this algorithm to perform the requested action " - "you need to give a valid username on the compute resource" + - m_SCARFComputeResource << '\n'; - throw; - } - // all actions that require at least a username - if (Action::LOGIN == m_action) { - std::string password; - try { - password = getPropertyValue("Password"); - } catch (std::runtime_error & /*e*/) { - g_log.error() << "To log in using this algorithm you need to give a " - "valid username and password on the compute resource " - << m_SCARFComputeResource << ".\n"; - throw; - } - if (password.empty()) { - throw std::runtime_error("You have given an empty password but the " - "current login mechanism on " + - m_SCARFComputeResource + - " does not support " - "this. This may change in the future. For the " - "time being you need to provide a password."); - } - doLogin(username, password); - } else if (Action::LOGOUT == m_action) { - doLogout(username); - } else if (Action::SUBMIT == m_action) { - doSubmit(username); - } else if (Action::QUERYSTATUS == m_action) { - doQueryStatus(username); - } else if (Action::QUERYSTATUSBYID == m_action) { - std::string jobId; - try { - jobId = getPropertyValue("JobID"); - } catch (std::runtime_error & /*e*/) { - g_log.error() << "To query the detailed status of a job by its ID you " - "need to give the ID of a job running on " - << m_SCARFComputeResource << ".\n"; - throw; - } - doQueryStatusById(username, jobId); - } else if (Action::CANCEL == m_action) { - std::string jobId; - try { - jobId = getPropertyValue("CancelJobID"); - } catch (std::runtime_error & /*e*/) { - g_log.error() << "To cancel a job you need to give the ID of a job " - "running on " << m_SCARFComputeResource << ".\n"; - throw; - } - doCancel(username, jobId); - } else if (Action::UPLOAD == m_action) { - std::string filename, destDir; - try { - filename = getPropertyValue("FileToUpload"); - } catch (std::runtime_error & /*e*/) { - g_log.error() << "To upload a file you need to provide an existing " - "local file.\n"; - throw; - } - try { - destDir = getPropertyValue("DestinationDirectory"); - } catch (std::runtime_error & /*e*/) { - g_log.error() << "To upload a file you need to provide a destination " - "directory on " << m_SCARFComputeResource << ".\n"; - throw; - } - doUploadFile(username, destDir, filename); - } else if (Action::DOWNLOAD == m_action) { - std::string jobId, fname, localDir; - try { - jobId = getPropertyValue("DownloadJobID"); - } catch (std::runtime_error & /*e*/) { - g_log.error() << "To download a file you need to give the ID of a job " - "running on " << m_SCARFComputeResource << ".\n"; - throw; - } - try { - fname = getPropertyValue("RemoteJobFilename"); - } catch (std::runtime_error & /*e*/) { - g_log.error() << "To download a file you need to provide the name of a " - "file from the remote job.\n"; - throw; - } - try { - localDir = getPropertyValue("LocalDirectory"); - } catch (std::runtime_error & /*e*/) { - g_log.error() << "To download a file you need to provide a destination " - "(local) directory.\n"; - throw; - } - doDownload(username, jobId, fname, localDir); - } -} - -/** - * Log into SCARF. If it goes well, it will produce a token that can - * be reused for a while in subsequent queries. Internally it relies - * on the InternetHelper to send an HTTP request and obtain the - * response. - * - * @param username normally an STFC federal ID - * @param password user password - */ -void SCARFTomoReconstruction::doLogin(const std::string &username, - const std::string &password) { - // log into "https://portal.scarf.rl.ac.uk/cgi-bin/token.py"; - - // this should go away and obtained from 'computeResourceInfo' (like - // a very simple InstrumentInfo) or similar. What we need here is - // computeResourceInfo::baseURL() - const std::string SCARFLoginBaseURL = "https://portal.scarf.rl.ac.uk/"; - const std::string SCARFLoginPath = "/cgi-bin/token.py"; - - std::vector<std::string> res = - ConfigService::Instance().getFacility().computeResources(); - auto it = std::find(res.begin(), res.end(), m_SCARFComputeResource); - if (res.end() == it) - throw std::runtime_error( - std::string("Failed to find a compute resource " - "for " + - m_SCARFComputeResource + " (facility: " + - ConfigService::Instance().getFacility().name() + ").")); - - std::string httpsURL = SCARFLoginBaseURL + SCARFLoginPath + "?username=" + - username + "&password=" + password; - int code; - std::stringstream ss; - try { - code = doSendRequestGetResponse(httpsURL, ss); - } catch (Kernel::Exception::InternetError &ie) { - throw std::runtime_error("Error while sending HTTP request to authenticate " - "(log in): " + - std::string(ie.what())); - } - // We would check (Poco::Net::HTTPResponse::HTTP_OK == code) but the SCARF - // login script (token.py) seems to return 200 whatever happens, as far as the - // request is well formed. So this is how to know if authentication succeeded: - const std::string expectedSubstr = "https://portal.scarf.rl.ac.uk"; - std::string resp = ss.str(); - if (InternetHelper::HTTP_OK == code && - resp.find(expectedSubstr) != std::string::npos) { - // it went fine, stash cookie/token which looks like this (2 lines): - // https://portal.scarf.rl.ac.uk:8443/platform/ - // scarf362"2015-02-10T18:50:00Z"Mv2ncX8Z0TpH0lZHxMyXNVCb7ucT6jHNOx... - std::string url, token_str; - std::getline(ss, url); - std::getline(ss, token_str); - // note that the token needs a substring replace and a prefix, like this: - boost::replace_all(token_str, "\"", "#quote#"); - token_str = "platform_token=" + token_str; - // insert in the token stash - UsernameToken tok(username, Token(url, token_str)); - m_tokenStash.insert(tok); // the password is never stored - g_log.notice() << "Got authentication token. You are now logged into " - << m_SCARFComputeResource << '\n'; - } else { - throw std::runtime_error("Login failed. Please check your username and " - "password. Got this response: " + - resp); - } -} - -/** - * Log out from SCARF. In practice, it trashes the cookie (if we were - * successfully logged in). - * - * @param username Username to use (should have authenticated before) - */ -void SCARFTomoReconstruction::doLogout(const std::string &username) { - auto it = m_tokenStash.find(username); - if (m_tokenStash.end() == it) { - throw std::runtime_error( - "Logout failed. You do not seem to be logged in. " - "I do not remember this username. Please check your " - "username."); - } - - // logout query, needs headers = {'Content-Type': 'text/plain', 'Cookie': - // token, - // 'Accept': 'text/plain,application/xml,text/xml'} - const std::string logoutPath = "webservice/pacclient/logout/"; - const std::string baseURL = it->second.m_url; - const std::string token = it->second.m_token_str; - - std::string httpsURL = baseURL + logoutPath; - std::map<std::string, std::string> headers{{"Content-Type", "text/plain"}, - {"Cookie", token}, - {"Accept", m_acceptType}}; - int code; - std::stringstream ss; - try { - code = doSendRequestGetResponse(httpsURL, ss, headers); - } catch (Kernel::Exception::InternetError &ie) { - throw std::runtime_error("Error while sending HTTP request to log out: " + - std::string(ie.what())); - } - if (Poco::Net::HTTPResponse::HTTP_OK == code) { - g_log.notice() << "Logged out.\n"; - g_log.debug() << "Response from server: " << ss.str() << '\n'; - } else { - throw std::runtime_error("Failed to logout from the web service at: " + - httpsURL + ". Please check your username."); - } - - // successfully logged out, forget the token - m_tokenStash.erase(it); -} - -/** - * Submits a job to SCARF. The different ways jobs could be submitted - * (supported toolkits, LSF PAC submission forms, launcher scripts, - * supported options, etc.) are not well defined at the moment. - * - * @param username Username to use (should have authenticated before) - */ -void SCARFTomoReconstruction::doSubmit(const std::string &username) { - auto it = m_tokenStash.find(username); - if (m_tokenStash.end() == it) { - throw std::runtime_error( - "Job submission failed. You do not seem to be logged " - "in. I do not remember this username. Please check " - "your username."); - } - - // Not sure at this point if there could be commands without options - // For the time being it's possible. - std::string jobOptions; - try { - jobOptions = getPropertyValue("JobOptions"); - } catch (std::runtime_error & /*e*/) { - g_log.warning() << "You did not specify any options for the job. Maybe you " - "forgot to pass the options?\n"; - m_jobOptions = ""; - } - - std::string runnablePath; - try { - runnablePath = getPropertyValue("RunnablePath"); - } catch (std::runtime_error & /*e*/) { - g_log.error() << "You did not specify a the path to the parameter file " - "which is required to create a new reconstruction job. " - "Please provide " - "a valid tomography reconstruction parameter file\n"; - throw; - } - - std::string jobName; - try { - jobName = getPropertyValue("JobName"); - } catch (std::runtime_error & /*e*/) { - jobName = ""; - } - - progress(0, "Starting job..."); - - // Job submit query, requires specific parameters for LSF submit - // Example params passed to python submit utility: - // $ pacclient.py submit --app TOMOPY_0_0_3 --param "INPUT_FILE= - // /work/imat/webservice_test/tomopy/imat_recon_FBP.py;INPUT_ARGS= - // /work/imat/scripts/test_;JOB_NAME=01_test_job;OUTPUT_FILE=%J.output;ERROR_FILE= - // %J.error" - - // Two applications are for now registered on SCARF: - // TOMOPY_0_0_3, PYASTRATOOLBOX_1_1 - old versions - // TOMOPY_0_1_9, PYASTRATOOLBOX_1_6 - newer versions (Dec 2015) - std::string appName = "TOMOPY_0_1_9"; - // Basic attempt at guessing the app that we might really need. This - // is not fixed/unstable at the moment - if (runnablePath.find("--tool astra") != std::string::npos || - runnablePath.find("--tool=astra") != std::string::npos) { - appName = "PYASTRATOOLBOX_1_6"; - } - - // this gets executed (for example via 'exec' or 'python', depending on the - // appName - const std::string boundary = "bqJky99mlBWa-ZuqjC53mG6EzbmlxB"; - const std::string &body = - buildSubmitBody(appName, boundary, runnablePath, jobOptions, jobName); - - // Job submit, needs these headers: - // headers = {'Content-Type': 'multipart/mixed; boundary='+boundary, - // 'Accept': 'text/xml,application/xml;', 'Cookie': token, - // 'Content-Length': str(len(body))} - // Content-Length is added by InternetHelper/Poco HTTP request - const std::string submitPath = "webservice/pacclient/submitapp"; - const std::string baseURL = it->second.m_url; - const std::string token = it->second.m_token_str; - - std::string httpsURL = baseURL + submitPath; - std::map<std::string, std::string> headers{ - {"Content-Type", "multipart/mixed; boundary=" + boundary}, - {"Accept", m_acceptType}, - {"Cookie", token}}; - int code; - std::stringstream ss; - try { - code = doSendRequestGetResponse(httpsURL, ss, headers, - Poco::Net::HTTPRequest::HTTP_POST, body); - } catch (Kernel::Exception::InternetError &ie) { - throw std::runtime_error( - "Error while sending HTTP request to submit a job: " + - std::string(ie.what())); - } - if (Poco::Net::HTTPResponse::HTTP_OK == code) { - std::string resp = ss.str(); - if (std::string::npos != resp.find("<errMsg>")) { - g_log.warning() - << "Submitted job but got a a response that seems to contain " - "an error message from " << m_SCARFComputeResource << ": " - << extractPACErrMsg(ss.str()) << '\n'; - } else { - g_log.notice() << "Submitted job successfully.\n"; - g_log.debug() << "Response from server: " << resp << '\n'; - } - } else { - throw std::runtime_error( - "Failed to submit a job through the web service at:" + httpsURL + - ". Please check your username, credentials, " - "and parameters."); - } - - progress(1.0, "Job started on " + m_SCARFComputeResource); -} - -/** - * Query the status of jobs running (if successful will return info on - * jobs running for our user) - * - * @param username Username to use (should have authenticated before) - */ -void SCARFTomoReconstruction::doQueryStatus(const std::string &username) { - auto it = m_tokenStash.find(username); - if (m_tokenStash.end() == it) { - throw std::runtime_error( - "Job status query failed. You do not seem to be logged " - "in. I do not remember this username. Please check " - "your username."); - } - - progress(0, "Checking the status of jobs..."); - - // Job query status, needs these headers: - // headers = {'Content-Type': 'application/xml', 'Cookie': token, - // 'Accept': ACCEPT_TYPE} - const std::string jobStatusPath = "webservice/pacclient/jobs?"; - const std::string baseURL = it->second.m_url; - const std::string token = it->second.m_token_str; - - std::string httpsURL = baseURL + jobStatusPath; - std::map<std::string, std::string> headers{ - {"Content-Type", "application/xml"}, - {"Accept", m_acceptType}, - {"Cookie", token}}; - int code; - std::stringstream ss; - try { - code = doSendRequestGetResponse(httpsURL, ss, headers); - } catch (Kernel::Exception::InternetError &ie) { - throw std::runtime_error( - "Error while sending HTTP request to query the status " - "of jobs: " + - std::string(ie.what())); - } - if (Poco::Net::HTTPResponse::HTTP_OK == code) { - std::string resp = ss.str(); - if (std::string::npos != resp.find("<Jobs>") && - std::string::npos != resp.find("<extStatus>")) { - genOutputStatusInfo(resp); - g_log.notice() << "Queried the status of jobs and stored the " - "information in output properties.\n"; - } else { - g_log.warning() << "Queried the status of jobs but got what looks " - "like an error message as response: " << resp << '\n'; - } - g_log.notice() << "Queried job status successfully.\n"; - g_log.debug() << "Response from server: " << resp << '\n'; - } else { - throw std::runtime_error( - "Failed to obtain job status information through the " - "web service at:" + - httpsURL + ". Please check your " - "username, credentials, and parameters."); - } - - progress(1.0, "Status of jobs retrived."); -} - -/** - * Query the status of jobs running (if successful will return info on - * jobs running for our user) - * - * @param username Username to use (should have authenticated before) - * @param jobId Identifier of a job as used by the job scheduler (integer - *number) - */ -void SCARFTomoReconstruction::doQueryStatusById(const std::string &username, - const std::string &jobId) { - auto it = m_tokenStash.find(username); - if (m_tokenStash.end() == it) { - throw std::runtime_error( - "Job status query failed. You do not seem to be logged " - "in. I do not remember this username. Please check " - "your username."); - } - - progress(0, "Checking the status of job with Id " + jobId); - - // Job query status, needs these headers: - // headers = {'Content-Type': 'application/xml', 'Cookie': token, - // 'Accept': ACCEPT_TYPE} - const std::string jobIdStatusPath = "webservice/pacclient/jobs/"; - const std::string baseURL = it->second.m_url; - const std::string token = it->second.m_token_str; - - std::string httpsURL = baseURL + jobIdStatusPath; - std::map<std::string, std::string> headers{ - {"Content-Type", "application/xml"}, - {"Accept", m_acceptType}, - {"Cookie", token}}; - int code; - std::stringstream ss; - try { - code = doSendRequestGetResponse(httpsURL, ss, headers); - } catch (Kernel::Exception::InternetError &ie) { - throw std::runtime_error( - "Error while sending HTTP request to query the status " - "of a job: " + - std::string(ie.what())); - } - if (Poco::Net::HTTPResponse::HTTP_OK == code) { - std::string resp = ss.str(); - if (std::string::npos != resp.find("<Jobs>") && - std::string::npos != resp.find("<extStatus>")) { - genOutputStatusInfo(resp, jobId); - g_log.notice() << "Queried job status (Id " << jobId - << ") and stored " - "information into output properties.\n"; - g_log.debug() << "Response from server: " << resp << '\n'; - } else { - g_log.warning() << "Queried job status (Id " << jobId - << " ) but got what " - "looks like an error message as response: " << resp - << '\n'; - } - } else { - throw std::runtime_error("Failed to obtain job (Id:" + jobId + - " ) status " - "information through the web service at:" + - httpsURL + - ". Please check your username, credentials, and " - "parameters."); - } - - progress(1.0, "Status of job " + jobId + "retrived."); -} - -/** - * Ping the server to see if the web service is active/available. - * - * @return true if the web service responds. - */ -bool SCARFTomoReconstruction::doPing() { - progress(0, "Pinging compute resource " + m_SCARFComputeResource); - - // Job ping, needs these headers: - // headers = {'Content-Type': 'application/xml', 'Accept': ACCEPT_TYPE} - const std::string pingPath = "platform/webservice/pacclient/ping/"; - // This could be retrieved from facilities or similar - // (like SCARFLoginBaseURL above) - TODO: clarify that in Facilities.xml - // the port number is known only after logging in - const std::string baseURL = "https://portal.scarf.rl.ac.uk:8443/"; - - std::string httpsURL = baseURL + pingPath; - std::map<std::string, std::string> headers{ - {"Content-Type", "application/xml"}, {"Accept", m_acceptType}}; - int code; - std::stringstream ss; - try { - code = doSendRequestGetResponse(httpsURL, ss, headers); - } catch (Kernel::Exception::InternetError &ie) { - throw std::runtime_error("Error while sending HTTP request to ping the " - "server " + - std::string(ie.what())); - } - bool ok = false; - if (Poco::Net::HTTPResponse::HTTP_OK == code) { - std::string resp = ss.str(); - if (std::string::npos != resp.find("Web Services are ready")) { - g_log.notice() - << "Pinged compute resource with apparently good response: " << resp - << '\n'; - ok = true; - } else { - g_log.warning() << "Pinged compute resource but got what looks like an " - "error message: " << resp << '\n'; - } - } else { - throw std::runtime_error( - "Failed to ping the web service at: " + httpsURL + - ". Please check your parameters, software version, " - "etc."); - } - - progress(1.0, "Ping compute resource " + m_SCARFComputeResource + " done."); - - return ok; -} - -/** - * Cancel a submitted job, identified by its ID in the job queue. - * - * @param username Username to use (should have authenticated before) - * @param jobId Identifier of a job as used by the job scheduler (integer - *number) - */ -void SCARFTomoReconstruction::doCancel(const std::string &username, - const std::string &jobId) { - auto it = m_tokenStash.find(username); - if (m_tokenStash.end() == it) { - throw std::runtime_error( - "Job status query failed. You do not seem to be logged " - "in. I do not remember this username. Please check " - "your username."); - } - - progress(0, "Cancelling/killing job " + jobId); - - // Job kill, needs these headers: - // headers = {'Content-Type': 'text/plain', 'Cookie': token, 'Accept': - // ACCEPT_TYPE} - const std::string killPath = - "webservice/pacclient/jobOperation/kill/" + jobId; - const std::string baseURL = it->second.m_url; - const std::string token = it->second.m_token_str; - - std::string httpsURL = baseURL + killPath; - std::map<std::string, std::string> headers{ - {"Content-Type", "application/xml"}, - {"Cookie", token}, - {"Accept", m_acceptType}}; - int code; - std::stringstream ss; - try { - code = doSendRequestGetResponse(httpsURL, ss, headers); - } catch (Kernel::Exception::InternetError &ie) { - throw std::runtime_error( - "Error while sending HTTP request to cancel a job: " + - std::string(ie.what())); - } - if (Poco::Net::HTTPResponse::HTTP_OK == code) { - std::string resp = ss.str(); - if (std::string::npos != resp.find("<errMsg>")) { - g_log.warning() << "Killed job with Id" << jobId - << " but got what looks like an " - "error message as response: " << extractPACErrMsg(resp) - << '\n'; - } else if (std::string::npos != resp.find("<actionMsg>")) { - g_log.notice() << "Killed job with Id" << jobId << ".\n"; - g_log.debug() << "Response from server: " << resp << '\n'; - } else { - g_log.warning() << "Killed job with Id" << jobId - << " but got what a response " - "that I do not recognize: " << resp << '\n'; - } - } else { - throw std::runtime_error( - "Failed to kill job (Id: " + jobId + " ) through the web " - "service at:" + - httpsURL + ". Please check your " - "existing jobs, username, and parameters."); - } - - progress(1.0, "Killed job with Id " + jobId + "."); -} - -/** - * Upload a file to a directory on the server. - * - * @param username Username to use (should have authenticated before) - * @param destDir Destination directory on the server - * @param filename File name of the local file to upload - */ -void SCARFTomoReconstruction::doUploadFile(const std::string &username, - const std::string &destDir, - const std::string &filename) { - auto it = m_tokenStash.find(username); - if (m_tokenStash.end() == it) { - throw std::runtime_error( - "File upload failed. You do not seem to be logged " - "in. I do not remember this username. Please check " - "your username."); - } - - progress(0, "Uploading file: " + filename); - - // File upload, needs these headers: - // headers = {'Content-Type': 'multipart/mixed; boundary='+boundary, - // 'Accept': 'text/plain;', 'Cookie': token, - // 'Content-Length': str(len(body))} - // Content-Length is added by InternetHelper/Poco HTTP request - // The 0 at the end of the upload path is 'jobId' 0, if a jobId is given the - // upload goes to a path relative to the job path. - const std::string uploadPath = "webservice/pacclient/upfile/0"; - const std::string boundary = "4k89ogja023oh1-gkdfk903jf9wngmujfs95m"; - const std::string baseURL = it->second.m_url; - const std::string token = it->second.m_token_str; - - InternetHelper session; - std::string httpsURL = baseURL + uploadPath; - std::map<std::string, std::string> headers{ - {"Content-Type", "multipart/mixed; boundary=" + boundary}, - {"Accept", m_acceptType}, - {"Cookie", token}}; - - const std::string &body = buildUploadBody(boundary, destDir, filename); - int code; - std::stringstream ss; - try { - code = doSendRequestGetResponse(httpsURL, ss, headers, - Poco::Net::HTTPRequest::HTTP_POST, body); - } catch (Kernel::Exception::InternetError &ie) { - throw std::runtime_error( - "Error while sending HTTP request to upload a file: " + - std::string(ie.what())); - } - if (Poco::Net::HTTPResponse::HTTP_OK == code) { - std::string resp = ss.str(); - g_log.notice() << "Uploaded file, response from server: " << resp << '\n'; - } else { - throw std::runtime_error( - "Failed to upload file through the web service at:" + httpsURL + - ". Please check your username, credentials, " - "and parameters."); - } - - progress(1.0, "File uploaded to " + m_SCARFComputeResource); -} - -/** - * Download a file or a set of files from a remote job into a local - * directory. Note that this download as supported by LSF at SCARF is - * job-specific: you download a file from a job and not a file in the - * file system in general. When downloading multiple files this action - * requires two steps: one first HTTP request to get the remote - * path(s) for all the job file(s), and a second request or series of - * requests to actually download the file(s). - * - * @param username Username to use (should have authenticated before) - * @param jobId Identifier of a job as used by the job scheduler (integer - *number) - * @param fname File name (of a job file on the compute resource). If no name is - * given then all the job files are downloaded into localDir - * @param localDir Local directory where to download the file(s) - */ -void SCARFTomoReconstruction::doDownload(const std::string &username, - const std::string &jobId, - const std::string &fname, - const std::string &localDir) { - auto it = m_tokenStash.find(username); - if (m_tokenStash.end() == it) { - throw std::runtime_error( - "File upload failed. You do not seem to be logged " - "in. I do not remember this username. Please check " - "your username."); - } - - progress(0, "Downloading file: " + fname + " in " + localDir); - - if (fname.empty()) { - // no/empty name implies we want all the files of a remote job - getAllJobFiles(jobId, localDir, it->second); - } else { - // name given, so we directly download this single file - getOneJobFile(jobId, fname, localDir, it->second); - } -} - -/** - * Send the HHTP(S) request required to perform one of the actions. - * - * @param url Full URL, including request string - * @param rss Response body stream - * @param headers HTTP headers given as key-value pairs - * @param method By default GET (Poco::Net::HTTPRequest::HTTP_POST), also - *accepts - * POST (Poco::Net::HTTPRequest::HTTP_POST) - * @param body HTTP message body - * - * @return HTTP(S) response code - */ -int SCARFTomoReconstruction::doSendRequestGetResponse( - const std::string &url, std::ostream &rss, const StringToStringMap &headers, - const std::string &method, const std::string &body) { - InternetHelper session; - - std::string ContTypeName = "Content-Type"; - auto it = headers.find(ContTypeName); - if (headers.end() != it) { - session.setContentType(it->second); - } - session.headers() = headers; - if (!method.empty()) - session.setMethod(method); - if (!body.empty()) { - session.setBody(body); - // beware, the inet helper will set method=POST if body not empty! - // But here, for example to download, we need a GET with non-empty body - if (Poco::Net::HTTPRequest::HTTP_GET == method) { - session.setMethod(method); - } - } - return session.sendRequest(url, rss); -} - -/** - * Adds one param to a submit request body (first argument). This is - * part of a multipart body content. - * - * @param body Body string being built for an HTTP request - * @param boundary Boundary string between parameters, for request encoding - * @param paramName Name of a parameter, for example INPUT_FILE - * @param paramVal Value of the parameter - */ -void SCARFTomoReconstruction::encodeParam(std::string &body, - const std::string &boundary, - const std::string ¶mName, - const std::string ¶mVal) { - body += "--" + boundary + "\r\n"; - body += "Content-Disposition: form-data; name=\"" + paramName + "\"\r\n"; - body += "Content-Type: application/xml; charset=US-ASCII\r\n"; - body += "Content-Transfer-Encoding: 8bit\r\n"; - body += "\r\n"; - body += "<AppParam><id>" + paramName + "</id><value>" + paramVal + - "</value><type></type></AppParam>\r\n"; -} - -/** - * Tiny helper to generate an integer sequence number for the job - * names. - */ -int SCARFTomoReconstruction::jobSeqNo() { return m_jobSeq++; } - -/** - * Helper method to do the somewhat ugly encoding of parameters for - * submit requests. - * - * @param appName A registered app name/form form SCARF, example: TOMOPY_0_0_3 - * @param boundary Boundary string between parts of the multi-part body - * @param inputFile Input file parameter, this file will be run - * @param inputArgs Arguments to the command (application specific) - * @param jobName Name passed by the user (can be empty == no preference) - * - * @return A string ready to be used as body of a 'job submit' HTTP request - */ -std::string SCARFTomoReconstruction::buildSubmitBody( - const std::string &appName, const std::string &boundary, - const std::string &inputFile, const std::string &inputArgs, - const std::string &jobName) { - // BLOCK: start and encode app name like this: - // --bqJky99mlBWa-ZuqjC53mG6EzbmlxB - // Content-Disposition: form-data; name="AppName" - // Content-ID: <AppName> - // - // TOMOPY_0_0_3 - std::string body = "--" + boundary + "\r\n"; - body += "Content-Disposition: form-data; name=\"AppName\"\r\n" - "Content-ID: <AppName>\r\n" - "\r\n" + - appName + "\r\n"; - - // BLOCK: encode params head like this: - // --bqJky99mlBWa-ZuqjC53mG6EzbmlxB - // Content-Disposition: form-data; name="data" - // Content-Type: multipart/mixed; boundary=_Part_1_701508.1145579811786 - // Content-ID: <data> - // - body += "--" + boundary + "\r\n"; - const std::string boundaryInner = "_Part_1_701508.1145579811786"; - body += "Content-Disposition: form-data; name=\"data\"\r\n"; - body += "Content-Type: multipart/mixed; boundary=" + boundaryInner + "\r\n"; - body += "Content-ID: <data>\r\n"; - body += "\r\n"; - - // BLOCKS: encode params like this: - { - // BLOCK: encode INPUT_ARGS like this: - // --_Part_1_701508.1145579811786 - // Content-Disposition: form-data; name="INPUT_ARGS" - // Content-Type: application/xml; charset=US-ASCII - // Content-Transfer-Encoding: 8bit - // <AppParam><id>INPUT_ARGS</id><value> - // /work/imat/scripts/test_</value><type></type></AppParam> - encodeParam(body, boundaryInner, "INPUT_ARGS", inputArgs); - } - { - // BLOCK: encode OUTPUT_FILE like this: - // --_Part_1_701508.1145579811786 - // Content-Disposition: form-data; name="OUTPUT_FILE" - // Content-Type: application/xml; charset=US-ASCII - // Content-Transfer-Encoding: 8bit - // <AppParam><id>OUTPUT_FILE</id><value>%J.output</value> - // <type></type></AppParam> - encodeParam(body, boundaryInner, "OUTPUT_FILE", "%J.output"); - } - { - // BLOCK: encode ERROR_FILE like this: - // --_Part_1_701508.1145579811786 - // Content-Disposition: form-data; name="ERROR_FILE" - // Content-Type: application/xml; charset=US-ASCII - // Content-Transfer-Encoding: 8bit - // <AppParam><id>ERROR_FILE</id><value>%J.error</value> - // <type></type></AppParam> - encodeParam(body, boundaryInner, "ERROR_FILE", "%J.error"); - } - { - // BLOCK: encode JOB_NAME like this: - // --_Part_1_701508.1145579811786 - // Content-Disposition: form-data; name="JOB_NAME" - // Content-Type: application/xml; charset=US-ASCII - // Content-Transfer-Encoding: 8bit - // <AppParam><id>JOB_NAME</id><value>foo</value><type></type></AppParam> - std::string name; - if (jobName.empty()) { - name = "Mantid_tomography_" + std::to_string(jobSeqNo()); - } else { - name = jobName; - } - encodeParam(body, boundaryInner, "JOB_NAME", name); - } - { - // BLOCK: encode INPUT_FILE (this is what will be run, - // if appName=TOMOPY_0_0_3) like this: - // --_Part_1_701508.1145579811786 - // Content-Disposition: form-data; name="INPUT_FILE" - // Content-Type: application/xml; charset=US-ASCII - // Content-Transfer-Encoding: 8bit - // <AppParam><id>INPUT_FILE</id><value> - // /work/imat/webservice_test/tomopy/imat_recon_FBP.py</value> - // <type></type></AppParam> - encodeParam(body, boundaryInner, "INPUT_FILE", inputFile); - } - // BLOCK: params end like this: - // --_Part_1_701508.1145579811786-- - // - body += "--" + boundaryInner + "--\r\n\r\n"; - - // BLOCK: end like this: - body += "--" + boundary + "--\r\n\r\n"; - - return body; -} - -/** - * Helper method to encode the body of file upload requests. - * - * @param boundary Boundary string between parts of the multi-part body - * @param destDir Path where to upload the file on the remote compute - *resource/server - * @param filename Name (path) of the local file to upload - * - * @return A string ready to be used as body of a 'file upload' HTTP request - */ -std::string -SCARFTomoReconstruction::buildUploadBody(const std::string &boundary, - const std::string &destDir, - const std::string &filename) { - // build file name as given in the request body - std::string upName = filename; - std::replace(upName.begin(), upName.end(), '\\', '/'); - // discard up to last / (path) - upName = upName.substr(upName.rfind('/') + 1); - - // BLOCK: start and encode destination directory like this: - // --4k89ogja023oh1-gkdfk903jf9wngmujfs95m - // Content-Disposition: form-data; name="DirName" - // Content-ID: <DirName> - // - // /work/imat/foo_test - std::string body = "--" + boundary + "\r\n"; - body += "Content-Disposition: form-data; name=\"DirName\"\r\n" - "Content-ID: <DirName>\r\n" - "\r\n" + - destDir + "\r\n"; - - // BLOCK: encode file like this (could be repeated for multi-file uploads): - // --4k89ogja023oh1-gkdfk903jf9wngmujfs95m - // Content-Disposition: form-data; name="bar.txt"; filename=bar.txt - // Content-Type: application/octet-stream - // Content-ID: <bar.txt> - // - body += "--" + boundary + "\r\n"; - body += "Content-Disposition: form-data; name=\"" + upName + "\"\r\n"; - body += "Content-Type: application/octet-stream \r\n"; - body += "Content-Transfer-Encoding: UTF-8\r\n"; - body += "Content-ID: <" + upName + ">\r\n"; - body += "\r\n"; - - // BLOCK: the file - std::ifstream fileStream(filename.c_str(), - std::ios_base::binary | std::ios_base::in); - Poco::StreamCopier::copyToString(fileStream, body); - - // BLOCK: end like this: - body += "--" + boundary + "--" + "\r\n\r\n"; - - return body; -} - -/** - * Fills in a table workspace with job status information from an LSC - * PAC response in ~xml format. Assumes that the workspace passed is - * empty and ready to be filled. This guarantees that a non-null (I) - * table workspace object is returned. - * - * @param resp Body of an HHTP response to a status query - * @param jobIDFilter ID of one job (empty string immplies all jobs) - */ -void SCARFTomoReconstruction::genOutputStatusInfo( - const std::string &resp, const std::string &jobIDFilter) { - Poco::XML::DOMParser parser; - Poco::AutoPtr<Poco::XML::Document> doc; - try { - doc = parser.parseString(resp); - } catch (Poco::Exception &e) { - throw std::runtime_error("Unable to parse response in XML format: " + - e.displayText()); - } catch (std::exception &e) { - throw std::runtime_error("Unable to parse response in XML format: " + - std::string(e.what())); - } - - Poco::XML::Element *pRootElem = doc->documentElement(); - if (!pRootElem || !pRootElem->hasChildNodes()) { - g_log.error("XML response from compute resouce contains no root element."); - throw std::runtime_error("No root element was found in XML response, " - "cannot parse it."); - } - - Poco::AutoPtr<Poco::XML::NodeList> jobs = - pRootElem->getElementsByTagName("Job"); - if (!jobs) { - g_log.error("XML response from compute resouce contains no root element."); - throw std::runtime_error("No root element was found in XML response, " - "cannot parse it."); - } - - size_t n = jobs->length(); - if (0 == jobs->length()) { - g_log.notice() << "Got information about 0 jobs. You may not have any jobs " - "currently running on the compute resource. The output " - "workspace will not " - "have any rows/information"; - } - - // This is the information that is usually available for running/recently - // run jobs - std::vector<std::string> jobIds; - std::vector<std::string> jobNames; - std::vector<std::string> jobStatus; - std::vector<std::string> jobCommands; - for (size_t i = 0; i < n; i++) { - Poco::XML::Element *el = static_cast<Poco::XML::Element *>( - jobs->item(static_cast<unsigned long>(i))); - if (!el) - throw std::runtime_error("Error while trying to parse job with index " + - std::to_string(i) + - "could not produce a complete table workspace."); - - Poco::XML::Element *id = el->getChildElement("id"); - if (id) { - const std::string &IdStr = id->innerText(); - if (!jobIDFilter.empty() && IdStr != jobIDFilter) - continue; - - jobIds.push_back(IdStr); - } - - Poco::XML::Element *name = el->getChildElement("name"); - if (name) { - jobNames.push_back(name->innerText()); - } else { - jobNames.emplace_back("Unknown!"); - } - - Poco::XML::Element *status = el->getChildElement("status"); - if (status) { - jobStatus.push_back(status->innerText()); - } else { - jobStatus.emplace_back("Unknown!"); - } - - Poco::XML::Element *cmd = el->getChildElement("cmd"); - if (cmd) { - jobCommands.push_back(cmd->innerText()); - } else { - jobCommands.emplace_back("Unknown!"); - } - } - - if (jobIds.size() != jobNames.size() || jobIds.size() != jobStatus.size() || - jobIds.size() != jobCommands.size()) { - throw std::runtime_error( - "There was an unexpected error while filling output " - "properties the information retrieved from the remote " - "compute resource. Failed to assign properties."); - } - if (jobIDFilter.empty()) { - // multi-job query - setProperty("RemoteJobsID", jobIds); - setProperty("RemoteJobsNames", jobNames); - setProperty("RemoteJobsStatus", jobStatus); - setProperty("RemoteJobsCommands", jobCommands); - } else { - // Single job query. Here the job ID is an input - if (jobIds.empty()) { - setProperty("RemoteJobName", "Unknown!"); - setProperty("RemoteJobStatus", "Unknown!"); - setProperty("RemoteJobCommand", "Unknown!"); - } else { - setProperty("RemoteJobName", jobNames.front()); - setProperty("RemoteJobStatus", jobStatus.front()); - setProperty("RemoteJobCommand", jobCommands.front()); - } - } -} - -/** - * Gets action code in m_action, if input argument is valid. Otherwise - * show error message and get undefined action. - * - * @return A valid action code (including 'undefined' code, if action - * not known). - */ -SCARFTomoReconstruction::Action::Type SCARFTomoReconstruction::getAction() { - std::string par = getPropertyValue("Action"); - Action::Type act = Action::UNDEF; - if (par == "LogIn") { - act = Action::LOGIN; - } else if (par == "LogOut") { - act = Action::LOGOUT; - } else if (par == "SubmitJob") { - act = Action::SUBMIT; - } else if (par == "JobStatus") { - act = Action::QUERYSTATUS; - } else if (par == "JobStatusByID") { - act = Action::QUERYSTATUSBYID; - } else if (par == "Ping") { - act = Action::PING; - } else if (par == "CancelJob") { - act = Action::CANCEL; - } else if (par == "Upload") { - act = Action::UPLOAD; - } else if (par == "Download") { - act = Action::DOWNLOAD; - } else { - g_log.error() << "Unknown action specified: '" << m_action - << "', ignoring it."; - } - return act; -} - -/** - * Helper to check if it's possible to write an output file and give - * informative messages. - * - * @param localPath Destination directory - * @param fname Name of the file being downloaded - * - * @return The full patch checked - */ -const std::string SCARFTomoReconstruction::checkDownloadOutputFile( - const std::string &localPath, const std::string &fname) const { - std::string outName = localPath + "/" + fname; - Poco::File f(outName); - if (f.exists()) { - if (f.canWrite()) { - g_log.notice() << "Overwriting output file: " << outName << '\n'; - } else { - g_log.warning() << "It is not possible to write into the output file: " - << outName << ", you may not have the required " - "permissions. Please check.\n"; - } - } - return f.path(); -} - -/** - * Turns the esoteric name used in LSF PAC web service into a normal - * filename (as a basename + extention, discarding the path to - * it). For example, this method translates: - * 'PAC Server* /home/isisg/scarf362/../scarf362/ - * Mantid_tomography_1_1423743450375PtlPj/417666.error*FILE*281*true' - * into '417666.error'. - * - * @param PACName A file name specification as returned by PAC LSF - * when downloading multiple files from jobs - * - * @return A filename ready to be used to save the file locally. Empty - * string if fails. - */ -const std::string -SCARFTomoReconstruction::filterPACFilename(const std::string PACName) const { - // discard up to last / (path) - std::string name = PACName.substr(PACName.rfind('/') + 1); - // remove trailing parameters - size_t ast = name.find('*'); - name.replace(ast, std::string::npos, ""); - return name; -} - -/** - * Download a job file once we have obtained the remote path. - * - * @param jobId Identifier of a job as used by the job scheduler (integer - *number) - * @param remotePath File name (of a job file on the compute resource) - * @param localPath Local path where to download the file (already checked) - * @param t Authentication token/cookie including url+string - */ -void SCARFTomoReconstruction::getOneJobFile(const std::string &jobId, - const std::string &remotePath, - const std::string &localPath, - const Token &t) { - // Job download (one) file once we know the remote path, needs these headers: - // headers = {'Content-Type': 'text/plain', 'Cookie': token, 'Accept': - // ACCEPT_TYPE} - // - and as request body the name of the file - const std::string downloadOnePath = "webservice/pacclient/file/" + jobId; - const std::string baseURL = t.m_url; - const std::string token = t.m_token_str; - - std::string httpsURL = baseURL + downloadOnePath; - - std::map<std::string, std::string> headers{ - {"Content-Type", "application/xml"}, - {"Cookie", token}, - {"Accept", m_acceptType}}; - int code; - std::stringstream ss; - try { - code = doSendRequestGetResponse( - httpsURL, ss, headers, Poco::Net::HTTPRequest::HTTP_GET, remotePath); - } catch (Kernel::Exception::InternetError &ie) { - throw std::runtime_error( - "Error while sending HTTP request to download a file: " + - std::string(ie.what())); - } - if (Poco::Net::HTTPResponse::HTTP_OK == code) { - // this is what indicates success/failure: response content empty/not empty - if (ss.rdbuf()->in_avail() > 0) { - // check file is writeable and inform user - // get basename from 'PAC' name - std::string name = filterPACFilename(remotePath); - if (name.empty()) { - g_log.notice() << "Could not download remote file " << remotePath - << " into " << localPath - << ", a problem with its name was found\n"; - } - std::string outName = checkDownloadOutputFile(localPath, name); - std::ofstream file(outName.c_str(), - std::ios_base::binary | std::ios_base::out); - Poco::StreamCopier::copyStream(ss, file); - g_log.notice() << "Downloaded remote file " << outName << " into " - << localPath << ".\n"; - // do this only if you want to log the file contents! - // g_log.debug() << "Response from server: " << ss.str() << '\n'; - } else { - // log an error but potentially continue with other files - g_log.error() - << "Download failed. You may not have the required permissions " - "or the file may not be available on " << m_SCARFComputeResource - << ": " << remotePath << '\n'; - } - } else { - throw std::runtime_error( - "Failed to download a file for job Id:" + jobId + - " through the web service at:" + httpsURL + - ". Please " - "check your existing jobs, username, and parameters."); - } -} - -/** - * Download all files for a remote job. - * - * @param jobId Identifier of a job as used by the job scheduler (integer - *number) - * @param localDir Local directory where to download the file (already checked) - * @param t Authentication token/cookie including url+string - */ -void SCARFTomoReconstruction::getAllJobFiles(const std::string &jobId, - const std::string &localDir, - const Token &t) { - // Job download (multiple) files, needs these headers: - // headers = {'Content-Type': 'text/plain', 'Cookie': token, 'Accept': - // ACCEPT_TYPE} - const std::string downloadPath = "webservice/pacclient/jobfiles/" + jobId; - const std::string baseURL = t.m_url; - const std::string token = t.m_token_str; - - std::string httpsURL = baseURL + downloadPath; - std::map<std::string, std::string> headers{ - {"Content-Type", "application/xml"}, - {"Cookie", token}, - {"Accept", m_acceptType}}; - int code; - std::stringstream ss; - try { - code = doSendRequestGetResponse(httpsURL, ss, headers); - } catch (Kernel::Exception::InternetError &ie) { - throw std::runtime_error( - "Error while sending HTTP request to download files: " + - std::string(ie.what())); - } - // what you get in this response is one line with text like this: - // 'PAC Server*/home/isisg/scarf362/../scarf362/ - // Mantid_tomography_1_1423743450375PtlPj/417666.error*FILE*281*true;PAC - // Server*/ - // home/isisg/scarf362/../scarf362/ - // Mantid_tomography_1_1423743450375PtlPj/417666.output*FILE*1145*true;' - // (the number between *FILE* and *true is the size in bytes) - std::vector<std::string> filePACNames; - if (Poco::Net::HTTPResponse::HTTP_OK == code) { - std::string resp = ss.str(); - // this is what indicates success/failure: presence of '/' or '\' - if (std::string::npos != resp.find('/') || - std::string::npos != resp.find('\\')) { - // you can get multiple files, as remote file names listed separated by - // ';' - std::string PACname; - while (std::getline(ss, PACname, ';')) { - filePACNames.push_back(PACname); - } - for (auto &filePACName : filePACNames) { - getOneJobFile(jobId, filePACName, localDir, t); - } - } - } else { - throw std::runtime_error( - "Failed to download job files (Id:" + jobId + " ) through " - "the web service at:" + - httpsURL + ". Please check your " - "existing jobs, username, and parameters."); - } - - progress(1.0, "Download of " + std::to_string(filePACNames.size()) + - " file(s) completed in " + localDir); -} - -/** - * Gets the error message from a more or less xml response body. Sometimes these - *error - * responses may read like this: - * <?xml version="1.0" encoding="UTF-8" standalone="yes"?><Job> - * <errMsg>Job <417940>: Job has already finished</errMsg><id>0</id></Job> - * - * @param response Body of an HHTP response that apparently contains some error - *message - * - * @return Part of the response that seems to contain the specific error message - */ -std::string -SCARFTomoReconstruction::extractPACErrMsg(const std::string &response) const { - // discard up to last errMsg start tag - const std::string openTag = "<errMsg>"; - std::string msg = response.substr(response.rfind(openTag) + openTag.size()); - if (msg.empty()) - return response; - - // remove close tags - size_t tags = msg.rfind("</errMsg>"); - msg.replace(tags, std::string::npos, ""); - - // avoid/translate common entities - boost::replace_all(msg, "<", "<"); - boost::replace_all(msg, ">", ">"); - - return msg; -} - -} // end namespace RemoteAlgorithms -} // end namespace Mantid diff --git a/Framework/RemoteAlgorithms/test/SCARFTomoReconstructionTest.h b/Framework/RemoteAlgorithms/test/SCARFTomoReconstructionTest.h deleted file mode 100644 index 207592a1dcd..00000000000 --- a/Framework/RemoteAlgorithms/test/SCARFTomoReconstructionTest.h +++ /dev/null @@ -1,683 +0,0 @@ -#ifndef MANTID_REMOTEALGORITHMS_SCARFTOMORECONSTRUCTION_H_ -#define MANTID_REMOTEALGORITHMS_SCARFTOMORECONSTRUCTION_H_ - -#include <cxxtest/TestSuite.h> - -#include "MantidAPI/ITableWorkspace.h" -#include "MantidKernel/ConfigService.h" -#include "MantidKernel/FacilityInfo.h" -#include "MantidRemoteAlgorithms/SCARFTomoReconstruction.h" - -using namespace Mantid::RemoteAlgorithms; - -/** - * Very crude mock up for the interaction with the remote compute - * resource (in real life, through the PAC web service of the LSF job - * scheduler on SCARF). This one returns 200 OK and a simple response - * string. - */ -class MockedSCARFTomo : public SCARFTomoReconstruction { -protected: - int doSendRequestGetResponse( - const std::string &url, std::ostream &response, - const StringToStringMap &headers = StringToStringMap(), - const std::string &method = std::string(), - const std::string &body = "") override { - UNUSED_ARG(url); - UNUSED_ARG(headers); - UNUSED_ARG(method); - UNUSED_ARG(body); - - response << "response OK - mocked up"; - return 200; - } -}; - -/** - * One more crude mock up for the interaction with the remote compute - * resource. This one returns an error (the connection is fine, but - * the response from the server is an error; example: wrong path, - * server bug, etc.). - */ -class MockedErrorResponse_SCARFTomo : public SCARFTomoReconstruction { -protected: - int doSendRequestGetResponse( - const std::string &url, std::ostream &response, - const StringToStringMap &headers = StringToStringMap(), - const std::string &method = std::string(), - const std::string &body = "") override { - UNUSED_ARG(url); - UNUSED_ARG(response); - UNUSED_ARG(headers); - UNUSED_ARG(method); - UNUSED_ARG(body); - - response << "Error response - mocked up"; - return 404; - } -}; - -/** - * One more crude mock up for the interaction with the remote compute - * resource. This one raises an exception as if the (underlying) - * InternetHelper had found a connection issue. - */ -class MockedConnectionError_SCARFTomo : public SCARFTomoReconstruction { -protected: - int doSendRequestGetResponse( - const std::string &url, std::ostream &response, - const StringToStringMap &headers = StringToStringMap(), - const std::string &method = std::string(), - const std::string &body = "") override { - UNUSED_ARG(url); - UNUSED_ARG(response); - UNUSED_ARG(headers); - UNUSED_ARG(method); - UNUSED_ARG(body); - - // throw as if there was a connection error - throw Mantid::Kernel::Exception::InternetError( - "Mocked up exception - connection error"); - } -}; - -/** - * One more crude mock up for the interaction with the remote compute - * resource. This one returns an OK code and a string that reads like - * what we expect when doing a successful login request. - */ -class MockedGoodLoginResponse_SCARFTomo : public SCARFTomoReconstruction { -protected: - int doSendRequestGetResponse( - const std::string &url, std::ostream &response, - const StringToStringMap &headers = StringToStringMap(), - const std::string &method = std::string(), - const std::string &body = "") override { - UNUSED_ARG(url); - UNUSED_ARG(response); - UNUSED_ARG(headers); - UNUSED_ARG(method); - UNUSED_ARG(body); - - response << "https://portal.scarf.rl.ac.uk - response OK and login " - "successful - mocked up"; - return 200; - } -}; - -/** - * One more crude mock up for the interaction with the remote compute - * resource. This one returns an OK code and a string that reads like - * a response with basic job status information. - */ -class MockedGoodJobStatus_SCARFTomo : public SCARFTomoReconstruction { -public: - MockedGoodJobStatus_SCARFTomo(const std::string &id) - : SCARFTomoReconstruction(), jobID(id){}; - -protected: - int doSendRequestGetResponse( - const std::string &url, std::ostream &response, - const StringToStringMap &headers = StringToStringMap(), - const std::string &method = std::string(), - const std::string &body = "") override { - UNUSED_ARG(url); - UNUSED_ARG(response); - UNUSED_ARG(headers); - UNUSED_ARG(method); - UNUSED_ARG(body); - - response - << "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>" - "<Jobs><Job><cmd>python /work/imat/webservice_test/test.py.py " - "/work/imat/webservice_test/test_out/</cmd><extStatus>-</extStatus>" - "<id>" << jobID - << "</id><name>Mantid_tomography_1</name><status>Running</status>" - "</Job></Jobs>"; - return 200; - } - -private: - std::string jobID; -}; - -class SCARFTomoReconstructionTest : public CxxTest::TestSuite { -public: - // This pair of boilerplate methods prevent the suite being created statically - // This means the constructor isn't called when running other tests - static SCARFTomoReconstructionTest *createSuite() { - return new SCARFTomoReconstructionTest(); - } - - static void destroySuite(SCARFTomoReconstructionTest *suite) { delete suite; } - - void setUp() override { - const Mantid::Kernel::FacilityInfo &fac = - Mantid::Kernel::ConfigService::Instance().getFacility(); - m_facility = fac.name(); - } - - void test_castAlgorithm() { - // can create - boost::shared_ptr<MockedSCARFTomo> a; - TS_ASSERT(a = boost::make_shared<MockedSCARFTomo>()); - // can cast to inherited interfaces and base classes - - MockedSCARFTomo alg; - TS_ASSERT(dynamic_cast<Mantid::RemoteAlgorithms::SCARFTomoReconstruction *>( - &alg)); - TS_ASSERT(dynamic_cast<Mantid::API::Algorithm *>(&alg)); - TS_ASSERT(dynamic_cast<Mantid::Kernel::PropertyManagerOwner *>(&alg)); - TS_ASSERT(dynamic_cast<Mantid::API::IAlgorithm *>(&alg)); - TS_ASSERT(dynamic_cast<Mantid::Kernel::IPropertyManager *>(&alg)); - } - - void test_initAlgorithm() { - MockedSCARFTomo tomo; - TS_ASSERT_THROWS_NOTHING(tomo.initialize()); - } - - void test_propertiesMissing() { - MockedSCARFTomo alg1; - TS_ASSERT_THROWS_NOTHING(alg1.initialize()); - // password missing - TS_ASSERT_THROWS_NOTHING(alg1.setPropertyValue("UserName", "anything")); - TS_ASSERT_THROWS_NOTHING(alg1.setPropertyValue("Action", "LogIn")); - - TS_ASSERT_THROWS_NOTHING(alg1.execute()); - TS_ASSERT(!alg1.isExecuted()); - - MockedSCARFTomo alg2; - TS_ASSERT_THROWS_NOTHING(alg2.initialize()); - // username missing - TS_ASSERT_THROWS_NOTHING(alg2.setPropertyValue("Password", "whatever")); - TS_ASSERT_THROWS_NOTHING(alg2.setPropertyValue("Action", "LogIn")); - - TS_ASSERT_THROWS(alg2.execute(), std::runtime_error); - TS_ASSERT(!alg2.isExecuted()); - - MockedSCARFTomo alg3; - TS_ASSERT_THROWS_NOTHING(alg3.initialize()); - // mispellings... - // these try to set inexistent propeties => runtime_error - TS_ASSERT_THROWS(alg3.setPropertyValue("sername", "anything"), - std::runtime_error); - TS_ASSERT_THROWS(alg3.setPropertyValue("Passw", "anything"), - std::runtime_error); - // these try to set wrong values for valid properties => invalid_argument - TS_ASSERT_THROWS(alg3.setPropertyValue("Action", "Loggin"), - std::invalid_argument); - TS_ASSERT_THROWS(alg3.setProperty("Action", "unknown_opt"), - std::invalid_argument); - TS_ASSERT_THROWS(alg3.setPropertyValue("JobID", "strings_not_allowed"), - std::invalid_argument); - } - - void test_actionWithoutUsernameBeforeLogin() { - MockedSCARFTomo alg; - TS_ASSERT_THROWS_NOTHING(alg.initialize()); - - // Forget the username and you should get an exception - // alg.setProperty("UserName", "foo_user")); - TS_ASSERT_THROWS_NOTHING(alg.setProperty("Action", "JobStatus")); - - TS_ASSERT_THROWS(alg.execute(), std::runtime_error); - TS_ASSERT(!alg.isExecuted()); - - MockedSCARFTomo tomo; - TS_ASSERT_THROWS_NOTHING(tomo.initialize()); - TS_ASSERT_THROWS_NOTHING(tomo.setProperty("Action", "SubmitJob")); - - TS_ASSERT_THROWS(tomo.execute(), std::runtime_error); - TS_ASSERT(!tomo.isExecuted()); - } - - void test_actionWithoutLogin() { - MockedSCARFTomo alg; - - // Even if you provide all required params, you should get an exception - // if not logged in - TS_ASSERT_THROWS_NOTHING(alg.initialize()); - TS_ASSERT_THROWS_NOTHING(alg.setProperty("Action", "JobStatus")); - - TS_ASSERT_THROWS(alg.execute(), std::runtime_error); - TS_ASSERT(!alg.isExecuted()); - - MockedSCARFTomo tomo; - TS_ASSERT_THROWS_NOTHING(tomo.initialize()); - TS_ASSERT_THROWS_NOTHING(tomo.setProperty("UserName", "anyone")); - TS_ASSERT_THROWS_NOTHING(tomo.setProperty("Action", "SubmitJob")); - TS_ASSERT_THROWS_NOTHING(tomo.setProperty("RunnablePath", "/foo/bar.sh")); - TS_ASSERT_THROWS_NOTHING(tomo.setProperty("JobOptions", "--test --baz")); - - TS_ASSERT_THROWS_NOTHING(tomo.execute()); - TS_ASSERT(!tomo.isExecuted()); - } - - /// Login is required before running the other actions (except ping) - // The good username is: foo_user - void test_login() { - m_goodUsername = "foo_user"; - m_goodPassword = "foo_password"; - - // severe (connection) error - MockedConnectionError_SCARFTomo err; - TS_ASSERT_THROWS_NOTHING(err.initialize()); - TS_ASSERT_THROWS_NOTHING(err.setProperty("UserName", m_goodUsername)); - TS_ASSERT_THROWS_NOTHING(err.setProperty("Password", m_goodPassword)); - TS_ASSERT_THROWS_NOTHING(err.setProperty("Action", "LogIn")); - - TS_ASSERT_THROWS_NOTHING(err.execute()); - TS_ASSERT(!err.isExecuted()); - - // standard mocked response: looks like an unsuccessful login attempt - MockedSCARFTomo tomo; - TS_ASSERT_THROWS_NOTHING(tomo.initialize()); - TS_ASSERT_THROWS_NOTHING(tomo.setProperty("UserName", m_goodUsername)); - TS_ASSERT_THROWS_NOTHING(tomo.setProperty("Password", m_goodPassword)); - TS_ASSERT_THROWS_NOTHING(tomo.setProperty("Action", "LogIn")); - - TS_ASSERT_THROWS_NOTHING(tomo.execute()); - TS_ASSERT(!tomo.isExecuted()); - - // successful login attempt - MockedGoodLoginResponse_SCARFTomo login; - TS_ASSERT_THROWS_NOTHING(login.initialize()); - TS_ASSERT_THROWS_NOTHING(login.setProperty("UserName", m_goodUsername)); - TS_ASSERT_THROWS_NOTHING(login.setProperty("Password", m_goodPassword)); - TS_ASSERT_THROWS_NOTHING(login.setProperty("Action", "LogIn")); - - TS_ASSERT_THROWS_NOTHING(login.execute()); - - if (g_supportedFacility != m_facility) { - TSM_ASSERT( - "This algorithm / login should fail when the facility is not " + - g_supportedFacility, - !login.isExecuted()); - return; - } - - TS_ASSERT(login.isExecuted()); - } - - void test_actionWithoutUsernameAfterLogin() { - MockedSCARFTomo alg; - TS_ASSERT_THROWS_NOTHING(alg.initialize()); - - TS_ASSERT_THROWS_NOTHING(alg.setProperty("Action", "JobStatus")); - - TS_ASSERT_THROWS(alg.execute(), std::runtime_error); - TS_ASSERT(!alg.isExecuted()); - - MockedSCARFTomo tomo; - TS_ASSERT_THROWS_NOTHING(tomo.initialize()); - // Forget this and you should get an exception - // tomo.setProperty("UserName", 3)); - TS_ASSERT_THROWS_NOTHING(tomo.setProperty("Action", "SubmitJob")); - - TS_ASSERT_THROWS(tomo.execute(), std::runtime_error); - TS_ASSERT(!tomo.isExecuted()); - } - - void test_actionWrongUsername() { - // Once you log out all actions should produce an exception - MockedSCARFTomo tomo; - TS_ASSERT_THROWS_NOTHING(tomo.initialize()); - TS_ASSERT_THROWS_NOTHING( - tomo.setProperty("UserName", "fail_" + m_goodUsername)); - TS_ASSERT_THROWS_NOTHING(tomo.setProperty("Action", "JobStatus")); - TS_ASSERT_THROWS_NOTHING(tomo.setProperty("RunnablePath", "/foo/bar.sh")); - TS_ASSERT_THROWS_NOTHING(tomo.setProperty("JobOptions", "--test --baz")); - - TS_ASSERT_THROWS_NOTHING(tomo.execute()); - TS_ASSERT(!tomo.isExecuted()); - } - - void test_wrongExec() { - MockedSCARFTomo alg; - TS_ASSERT_THROWS_NOTHING(alg.initialize()); - TS_ASSERT_THROWS(alg.setProperty("RandomName", 32), std::runtime_error); - - TS_ASSERT_THROWS(alg.execute(), std::runtime_error); - TS_ASSERT(!alg.isExecuted()); - } - - void test_ping() { - MockedSCARFTomo alg; - TS_ASSERT_THROWS_NOTHING(alg.initialize()); - TS_ASSERT_THROWS_NOTHING(alg.setPropertyValue("Action", "Ping")); - TS_ASSERT_THROWS_NOTHING(alg.setPropertyValue("Username", m_goodUsername)); - - TS_ASSERT_THROWS_NOTHING(alg.execute()); - TS_ASSERT(alg.isExecuted()); - } - - void test_submit() { - MockedSCARFTomo alg; - TS_ASSERT_THROWS_NOTHING(alg.initialize()); - TS_ASSERT_THROWS_NOTHING(alg.setProperty("UserName", m_goodUsername)); - TS_ASSERT_THROWS_NOTHING(alg.setProperty("Action", "SubmitJob")); - TS_ASSERT_THROWS_NOTHING(alg.setProperty("RunnablePath", "/foo/bar.sh")); - TS_ASSERT_THROWS_NOTHING(alg.setProperty("JobOptions", "--test --baz")); - - TS_ASSERT_THROWS_NOTHING(alg.execute()); - - if (g_supportedFacility != m_facility) { - TSM_ASSERT( - "This algorithm / submit should fail when the facility is not " + - g_supportedFacility, - !alg.isExecuted()); - return; - } - - TS_ASSERT(alg.isExecuted()); - - // second submit in a row - MockedSCARFTomo tomo; - TS_ASSERT_THROWS_NOTHING(tomo.initialize()); - TS_ASSERT_THROWS_NOTHING(tomo.setProperty("UserName", m_goodUsername)); - TS_ASSERT_THROWS_NOTHING(tomo.setProperty("Action", "SubmitJob")); - TS_ASSERT_THROWS_NOTHING(tomo.setProperty("RunnablePath", "/foo/bar.sh")); - TS_ASSERT_THROWS_NOTHING(tomo.setProperty("JobOptions", "--random --baz")); - - TS_ASSERT_THROWS_NOTHING(tomo.execute()); - TS_ASSERT(tomo.isExecuted()); - } - - void test_queryStatus() { - // this one is the basic mock up which doesn't provide the response content - // that we need - MockedSCARFTomo err; - TS_ASSERT_THROWS_NOTHING(err.initialize()); - TS_ASSERT_THROWS_NOTHING(err.setProperty("UserName", m_goodUsername)); - TS_ASSERT_THROWS_NOTHING(err.setProperty("Action", "JobStatus")); - - TS_ASSERT_THROWS_NOTHING(err.execute()); - - if (g_supportedFacility != m_facility) { - TSM_ASSERT( - "This algorithm / queryStatus should fail when the facility is not " + - g_supportedFacility, - !err.isExecuted()); - return; - } - - TS_ASSERT(err.isExecuted()); - - std::vector<std::string> vec; - TS_ASSERT_THROWS_NOTHING(vec = err.getProperty("RemoteJobsID")); - TS_ASSERT_EQUALS(vec.size(), 0); - TS_ASSERT_THROWS_NOTHING(vec = err.getProperty("RemoteJobsNames")); - TS_ASSERT_EQUALS(vec.size(), 0); - TS_ASSERT_THROWS_NOTHING(vec = err.getProperty("RemoteJobsStatus")); - TS_ASSERT_EQUALS(vec.size(), 0); - TS_ASSERT_THROWS_NOTHING(vec = err.getProperty("RemoteJobsCommands")); - TS_ASSERT_EQUALS(vec.size(), 0); - - // this one gives a basic/sufficient response with job status information - MockedGoodJobStatus_SCARFTomo alg("wrong id"); - TS_ASSERT_THROWS_NOTHING(alg.initialize()); - TS_ASSERT_THROWS_NOTHING(alg.setProperty("UserName", m_goodUsername)); - TS_ASSERT_THROWS_NOTHING(alg.setProperty("Action", "JobStatus")); - - TS_ASSERT_THROWS_NOTHING(alg.execute()); - - if (g_supportedFacility != m_facility) { - TSM_ASSERT( - "This algorithm / queryStatus should fail when the facility is not " + - g_supportedFacility, - !alg.isExecuted()); - return; - } - - TS_ASSERT(alg.isExecuted()); - - // the mock produces info on one job - TS_ASSERT_THROWS_NOTHING(vec = alg.getProperty("RemoteJobsID")); - TS_ASSERT_EQUALS(vec.size(), 1); - TS_ASSERT(vec.size() > 0 && !vec.front().empty()); - TS_ASSERT_THROWS_NOTHING(vec = alg.getProperty("RemoteJobsNames")); - TS_ASSERT_EQUALS(vec.size(), 1); - TS_ASSERT(vec.size() > 0 && !vec.front().empty()); - TS_ASSERT_THROWS_NOTHING(vec = alg.getProperty("RemoteJobsStatus")); - TS_ASSERT_EQUALS(vec.size(), 1); - TS_ASSERT(vec.size() > 0 && !vec.front().empty()); - TS_ASSERT_THROWS_NOTHING(vec = alg.getProperty("RemoteJobsCommands")); - TS_ASSERT_EQUALS(vec.size(), 1); - TS_ASSERT(vec.size() > 0 && !vec.front().empty()); - } - - void test_queryStatusByID() { - // this one is the basic mockup: doesn't provide the response content that - // we need - MockedSCARFTomo err; - TS_ASSERT_THROWS_NOTHING(err.initialize()); - TS_ASSERT_THROWS_NOTHING(err.setProperty("UserName", m_goodUsername)); - TS_ASSERT_THROWS_NOTHING(err.setProperty("Action", "JobStatusByID")); - TS_ASSERT_THROWS_NOTHING(err.setProperty("JobID", 123456789)); - - TS_ASSERT_THROWS_NOTHING(err.execute()); - - if (g_supportedFacility != m_facility) { - TSM_ASSERT("This algorithm / queryStatusByID should fail when the " - "facility is not " + - g_supportedFacility, - !err.isExecuted()); - return; - } - - TS_ASSERT(err.isExecuted()); - - std::string tmp; - TS_ASSERT_THROWS_NOTHING(tmp = err.getPropertyValue("RemoteJobName")); - TS_ASSERT(tmp.empty()); - TS_ASSERT_THROWS_NOTHING(tmp = err.getPropertyValue("RemoteJobStatus")); - TS_ASSERT(tmp.empty()); - TS_ASSERT_THROWS_NOTHING(tmp = err.getPropertyValue("RemoteJobsCommands")); - TS_ASSERT(tmp.empty()); - - // this one gives a basic/sufficient response with job status information - std::string jobID = "444449"; - MockedGoodJobStatus_SCARFTomo alg(jobID); - TS_ASSERT_THROWS_NOTHING(alg.initialize()); - TS_ASSERT_THROWS_NOTHING(alg.setProperty("UserName", m_goodUsername)); - TS_ASSERT_THROWS_NOTHING(alg.setProperty("Action", "JobStatusByID")); - TS_ASSERT_THROWS_NOTHING(alg.setProperty("JobID", jobID)); - - TS_ASSERT_THROWS_NOTHING(alg.execute()); - - if (g_supportedFacility != m_facility) { - TSM_ASSERT("This algorithm / queryStatusByID should fail when the " - "facility is not " + - g_supportedFacility, - !alg.isExecuted()); - return; - } - - TS_ASSERT(alg.isExecuted()); - - // It could also check that it gets the names, etc. that the mock-up - // produces - TS_ASSERT_THROWS_NOTHING(tmp = alg.getPropertyValue("RemoteJobName")); - TS_ASSERT(!tmp.empty()); - TS_ASSERT_THROWS_NOTHING(tmp = alg.getPropertyValue("RemoteJobStatus")); - TS_ASSERT(!tmp.empty()); - TS_ASSERT_THROWS_NOTHING(tmp = alg.getPropertyValue("RemoteJobCommand")); - TS_ASSERT(!tmp.empty()); - } - - void test_cancel() { - MockedSCARFTomo alg; - TS_ASSERT_THROWS_NOTHING(alg.initialize()); - TS_ASSERT_THROWS_NOTHING(alg.setProperty("UserName", m_goodUsername)); - TS_ASSERT_THROWS_NOTHING(alg.setProperty("Action", "CancelJob")); - TS_ASSERT_THROWS_NOTHING(alg.setProperty("CancelJobID", 123456789)); - - TS_ASSERT_THROWS_NOTHING(alg.execute()); - - if (g_supportedFacility != m_facility) { - TSM_ASSERT( - "This algorithm / cancel should fail when the facility is not " + - g_supportedFacility, - !alg.isExecuted()); - return; - } - - TS_ASSERT(alg.isExecuted()); - } - - void test_upload() { - MockedSCARFTomo alg; - TS_ASSERT_THROWS_NOTHING(alg.initialize()); - TS_ASSERT_THROWS_NOTHING(alg.setProperty("Username", m_goodUsername)); - TS_ASSERT_THROWS_NOTHING(alg.setProperty("Action", "Upload")); - TS_ASSERT_THROWS_NOTHING(alg.setProperty("FileToUpload", "random_file")); - TS_ASSERT_THROWS_NOTHING( - alg.setProperty("DestinationDirectory", "random_path/")); - - TS_ASSERT_THROWS_NOTHING(alg.execute()); - - if (g_supportedFacility != m_facility) { - TSM_ASSERT( - "This algorithm / upload should fail when the facility is not " + - g_supportedFacility, - !alg.isExecuted()); - return; - } - - TS_ASSERT(alg.isExecuted()); - } - - void test_download() { - MockedSCARFTomo alg; - TS_ASSERT_THROWS_NOTHING(alg.initialize()); - - // Download with empty filename (get all files) - TS_ASSERT_THROWS_NOTHING(alg.setProperty("UserName", m_goodUsername)); - TS_ASSERT_THROWS_NOTHING(alg.setProperty("Action", "Download")); - TS_ASSERT_THROWS_NOTHING(alg.setProperty("DownloadJobID", 12345)); - TS_ASSERT_THROWS_NOTHING(alg.setProperty("RemoteJobFilename", "")); - TS_ASSERT_THROWS_NOTHING(alg.setProperty("LocalDirectory", "/tmp/foo")); - TS_ASSERT_THROWS_NOTHING(alg.execute()); - - if (g_supportedFacility != m_facility) { - TSM_ASSERT( - "This algorithm / download should fail when the facility is not " + - g_supportedFacility, - !alg.isExecuted()); - return; - } - - TS_ASSERT(alg.isExecuted()); - - MockedSCARFTomo alg2; - TS_ASSERT_THROWS_NOTHING(alg2.initialize()); - - // Download a single file (giving its name) - TS_ASSERT_THROWS_NOTHING(alg2.setProperty("UserName", m_goodUsername)); - TS_ASSERT_THROWS_NOTHING(alg2.setProperty("Action", "Download")); - TS_ASSERT_THROWS_NOTHING(alg2.setProperty("DownloadJobID", 12345)); - TS_ASSERT_THROWS_NOTHING( - alg2.setProperty("RemoteJobFilename", "inexistent_test_name.nxs.foo")); - TS_ASSERT_THROWS_NOTHING(alg2.setProperty("LocalDirectory", "/tmp/foo")); - TS_ASSERT_THROWS_NOTHING(alg2.execute()); - TS_ASSERT(!alg2.isExecuted()); - } - - void test_errorResponseFromServer() { - MockedErrorResponse_SCARFTomo err; - TS_ASSERT_THROWS_NOTHING(err.initialize()); - TS_ASSERT_THROWS_NOTHING(err.setPropertyValue("Username", m_goodUsername)); - TS_ASSERT_THROWS_NOTHING(err.setPropertyValue("Action", "JobStatus")); - - TS_ASSERT_THROWS_NOTHING(err.execute()); - TS_ASSERT(!err.isExecuted()); - } - - // logout must run after all the (positive) tests - void test_logout() { - MockedSCARFTomo alg; - TS_ASSERT_THROWS_NOTHING(alg.initialize()); - TS_ASSERT_THROWS_NOTHING(alg.setProperty("UserName", m_goodUsername)); - TS_ASSERT_THROWS_NOTHING(alg.setProperty("Action", "LogOut")); - - TS_ASSERT_THROWS_NOTHING(alg.execute()); - - if (g_supportedFacility != m_facility) { - TSM_ASSERT( - "This algorithm / logout should fail when the facility is not " + - g_supportedFacility, - !alg.isExecuted()); - return; - } - - TS_ASSERT(alg.isExecuted()); - } - - void test_actionAfterLogout() { - MockedSCARFTomo alg; - // Once you log out all actions should produce an exception, regardless of - // the username given - TS_ASSERT_THROWS_NOTHING(alg.initialize()); - TS_ASSERT_THROWS_NOTHING( - alg.setProperty("UserName", "fail_" + m_goodUsername)); - TS_ASSERT_THROWS_NOTHING(alg.setProperty("Action", "JobStatus")); - TS_ASSERT_THROWS_NOTHING(alg.setProperty("RunnablePath", "/foo/bar.sh")); - TS_ASSERT_THROWS_NOTHING(alg.setProperty("JobOptions", "--test --baz")); - - TS_ASSERT_THROWS_NOTHING(alg.execute()); - TS_ASSERT(!alg.isExecuted()); - - MockedSCARFTomo alg2; - TS_ASSERT_THROWS_NOTHING(alg2.initialize()); - TS_ASSERT_THROWS_NOTHING(alg2.setProperty("UserName", m_goodUsername)); - TS_ASSERT_THROWS_NOTHING(alg2.setProperty("Action", "JobStatus")); - TS_ASSERT_THROWS_NOTHING(alg2.setProperty("RunnablePath", "/foo/bar.sh")); - TS_ASSERT_THROWS_NOTHING(alg2.setProperty("JobOptions", "--test --baz")); - - TS_ASSERT_THROWS_NOTHING(alg2.execute()); - TS_ASSERT(!alg2.isExecuted()); - } - - void test_failConnect() { - MockedConnectionError_SCARFTomo fail; - TS_ASSERT_THROWS_NOTHING(fail.initialize()); - TS_ASSERT_THROWS_NOTHING(fail.setPropertyValue("Action", "Ping")); - - TS_ASSERT_THROWS(fail.execute(), std::runtime_error); - TS_ASSERT(!fail.isExecuted()); - - MockedConnectionError_SCARFTomo fail2; - TS_ASSERT_THROWS_NOTHING(fail2.initialize()); - // username missing - TS_ASSERT_THROWS_NOTHING(fail2.setPropertyValue("Username", "uname")); - TS_ASSERT_THROWS_NOTHING(fail2.setPropertyValue("Password", "whatever")); - TS_ASSERT_THROWS_NOTHING(fail2.setPropertyValue("Action", "LogIn")); - - TS_ASSERT_THROWS_NOTHING(fail2.execute()); - TS_ASSERT(!fail2.isExecuted()); - } - - void test_errorResponseFromServerAfterLogout() { - MockedErrorResponse_SCARFTomo err; - TS_ASSERT_THROWS_NOTHING(err.initialize()); - TS_ASSERT_THROWS_NOTHING(err.setPropertyValue("Username", "foo")); - TS_ASSERT_THROWS_NOTHING(err.setPropertyValue("Action", "Ping")); - - TS_ASSERT_THROWS_NOTHING(err.execute()); - TS_ASSERT(!err.isExecuted()); - } - -private: - std::string m_goodUsername; - std::string m_goodPassword; - std::string m_facility; - static const std::string g_supportedFacility; - static const std::string g_SCARFName; -}; - -const std::string SCARFTomoReconstructionTest::g_SCARFName = "SCARF@STFC"; -// This algorithm work only for ISIS -const std::string SCARFTomoReconstructionTest::g_supportedFacility = "ISIS"; - -#endif // MANTID_REMOTEALGORITHMS_SCARFTOMORECONSTRUCTION_H_ diff --git a/MantidQt/CustomInterfaces/CMakeLists.txt b/MantidQt/CustomInterfaces/CMakeLists.txt index ef32f9a65cb..a4ecfad17c0 100644 --- a/MantidQt/CustomInterfaces/CMakeLists.txt +++ b/MantidQt/CustomInterfaces/CMakeLists.txt @@ -123,29 +123,6 @@ set ( SRC_FILES src/SANSRunWindow.cpp src/SampleTransmission.cpp src/StepScan.cpp - src/Tomography/EnergyBandsViewQtGUI.cpp - src/Tomography/TomographyROIPresenter.cpp - src/Tomography/TomographyROIViewQtWidget.cpp - src/Tomography/ImageStackPreParams.cpp - src/Tomography/ImggFormats.cpp - src/Tomography/ImggFormatsConvertPresenter.cpp - src/Tomography/ImggFormatsConvertViewQtWidget.cpp - src/Tomography/StackOfImagesDirs.cpp - src/Tomography/TomoPathsConfig.cpp - src/Tomography/TomoReconPostprocSettings.cpp - src/Tomography/TomoReconPreprocSettings.cpp - src/Tomography/TomoSystemSettings.cpp - src/Tomography/TomoSystemSettingsLocal.cpp - src/Tomography/TomoSystemSettingsRemote.cpp - src/Tomography/TomoToolConfigDialogBase.cpp - src/Tomography/TomoToolConfigDialogTomoPy.cpp - src/Tomography/TomoToolConfigDialogCustom.cpp - src/Tomography/TomoToolConfigDialogSavu.cpp - src/Tomography/TomoToolConfigDialogAstra.cpp - src/Tomography/TomographyIfaceModel.cpp - src/Tomography/TomographyIfacePresenter.cpp - src/Tomography/TomographyIfaceViewQtGUI.cpp - src/Tomography/ToolConfig.cpp src/UserInputValidator.cpp src/background.cpp src/deltaECalc.cpp @@ -300,40 +277,6 @@ set ( INC_FILES inc/MantidQtCustomInterfaces/SANSRunWindow.h inc/MantidQtCustomInterfaces/SampleTransmission.h inc/MantidQtCustomInterfaces/StepScan.h - inc/MantidQtCustomInterfaces/Tomography/ITomographyROIPresenter.h - inc/MantidQtCustomInterfaces/Tomography/ITomographyROIView.h - inc/MantidQtCustomInterfaces/Tomography/IImggFormatsConvertPresenter.h - inc/MantidQtCustomInterfaces/Tomography/IImggFormatsConvertView.h - inc/MantidQtCustomInterfaces/Tomography/ITomographyIfacePresenter.h - inc/MantidQtCustomInterfaces/Tomography/ITomographyIfaceView.h - inc/MantidQtCustomInterfaces/Tomography/TomographyROIPresenter.h - inc/MantidQtCustomInterfaces/Tomography/TomographyROIViewQtWidget.h - inc/MantidQtCustomInterfaces/Tomography/ImageStackPreParams.h - inc/MantidQtCustomInterfaces/Tomography/ImggFormats.h - inc/MantidQtCustomInterfaces/Tomography/ImggFormatsConvertPresenter.h - inc/MantidQtCustomInterfaces/Tomography/ImggFormatsConvertViewQtWidget.h - inc/MantidQtCustomInterfaces/Tomography/StackOfImagesDirs.h - inc/MantidQtCustomInterfaces/Tomography/TomoPathsConfig.h - inc/MantidQtCustomInterfaces/Tomography/TomoRecToolConfig.h - inc/MantidQtCustomInterfaces/Tomography/TomoReconPostprocSettings.h - inc/MantidQtCustomInterfaces/Tomography/TomoReconPreprocSettings.h - inc/MantidQtCustomInterfaces/Tomography/TomoReconToolsUserSettings.h - inc/MantidQtCustomInterfaces/Tomography/TomoSystemSettings.h - inc/MantidQtCustomInterfaces/Tomography/TomoSystemSettingsLocal.h - inc/MantidQtCustomInterfaces/Tomography/TomoSystemSettingsRemote.h - inc/MantidQtCustomInterfaces/Tomography/TomoToolConfigDialogBase.h - inc/MantidQtCustomInterfaces/Tomography/TomoToolConfigDialogTomoPy.h - inc/MantidQtCustomInterfaces/Tomography/TomoToolConfigDialogCustom.h - inc/MantidQtCustomInterfaces/Tomography/TomoToolConfigDialogSavu.h - inc/MantidQtCustomInterfaces/Tomography/TomoToolConfigDialogAstra.h - inc/MantidQtCustomInterfaces/Tomography/TomographyIfaceModel.h - inc/MantidQtCustomInterfaces/Tomography/TomographyIfacePresenter.h - inc/MantidQtCustomInterfaces/Tomography/TomographyIfaceViewQtGUI.h - inc/MantidQtCustomInterfaces/Tomography/TomographyThread.h - inc/MantidQtCustomInterfaces/Tomography/TomographyProcess.h - inc/MantidQtCustomInterfaces/Tomography/ToolConfigAstraToolbox.h - inc/MantidQtCustomInterfaces/Tomography/ToolConfigCustom.h - inc/MantidQtCustomInterfaces/Tomography/ToolConfigTomoPy.h inc/MantidQtCustomInterfaces/Updateable.h inc/MantidQtCustomInterfaces/UserInputValidator.h inc/MantidQtCustomInterfaces/deltaECalc.h @@ -441,14 +384,6 @@ set ( MOC_FILES inc/MantidQtCustomInterfaces/Background.h inc/MantidQtCustomInterfaces/SANSEventSlicing.h inc/MantidQtCustomInterfaces/SANSDiagnostics.h inc/MantidQtCustomInterfaces/StepScan.h - inc/MantidQtCustomInterfaces/Tomography/TomographyROIViewQtWidget.h - inc/MantidQtCustomInterfaces/Tomography/TomographyROIPresenter.h - inc/MantidQtCustomInterfaces/Tomography/ImggFormatsConvertViewQtWidget.h - inc/MantidQtCustomInterfaces/Tomography/TomographyIfacePresenter.h - inc/MantidQtCustomInterfaces/Tomography/TomographyIfaceViewQtGUI.h - inc/MantidQtCustomInterfaces/Tomography/TomoToolConfigDialogSavu.h - inc/MantidQtCustomInterfaces/Tomography/TomographyProcess.h - inc/MantidQtCustomInterfaces/Tomography/TomographyThread.h ) set ( UI_FILES inc/MantidQtCustomInterfaces/DataComparison.ui diff --git a/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/IImggFormatsConvertPresenter.h b/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/IImggFormatsConvertPresenter.h deleted file mode 100644 index 7fc3ea532d5..00000000000 --- a/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/IImggFormatsConvertPresenter.h +++ /dev/null @@ -1,60 +0,0 @@ -#ifndef MANTIDQTCUSTOMINTERFACES_TOMOGRAPHY_IIMGGFORMATSCONVERTPRESENTER_H_ -#define MANTIDQTCUSTOMINTERFACES_TOMOGRAPHY_IIMGGFORMATSCONVERTPRESENTER_H_ - -namespace MantidQt { -namespace CustomInterfaces { - -/** -Presenter for the widget to convert images and stacks of images -between different formats. - -Copyright © 2016 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 IImggFormatsConvertPresenter { - -public: - IImggFormatsConvertPresenter(){}; - virtual ~IImggFormatsConvertPresenter(){}; - - /// These are user actions, triggered from the (passive) view, that need - /// handling by the presenter - enum Notification { - Init, ///< interface is initing (reload settings, set defaults, etc.) - Convert, ///< User starts a conversion - ShutDown ///< The widget is being closed/destroyed - }; - - /** - * Notifications sent through the presenter when an (smart) action - * is required to respond to user requests or something changes in - * the view. This plays the role of signals emitted by the view to - * this presenter. - * - * @param notif Type of notification to process. - */ - virtual void notify(IImggFormatsConvertPresenter::Notification notif) = 0; -}; - -} // namespace CustomInterfaces -} // namespace MantidQt - -#endif // MANTIDQTCUSTOMINTERFACES_TOMOGRAPHY_IIMGGFORMATSCONVERTPRESENTER_H_ diff --git a/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/IImggFormatsConvertView.h b/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/IImggFormatsConvertView.h deleted file mode 100644 index 31d34f7ab0a..00000000000 --- a/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/IImggFormatsConvertView.h +++ /dev/null @@ -1,183 +0,0 @@ -#ifndef MANTIDQTCUSTOMINTERFACES_TOMOGRAPHY_IIMGGFORMATSCONVERTVIEW_H_ -#define MANTIDQTCUSTOMINTERFACES_TOMOGRAPHY_IIMGGFORMATSCONVERTVIEW_H_ - -#include "MantidAPI/MatrixWorkspace_fwd.h" - -#include <string> -#include <vector> - -namespace MantidQt { -namespace CustomInterfaces { - -/** -Widget to convert images and stacks of images between different image -formats. - -Copyright © 2016 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 IImggFormatsConvertView { - -public: - IImggFormatsConvertView() {} - - virtual ~IImggFormatsConvertView() {} - - /** - * Display a warning to the user (normally as a pop-up). - * - * @param warn warning title, should be short and would normally be - * shown as the title of the window or a big banner. - * - * @param description longer, free form and human readable - * description of the issue. - */ - virtual void userWarning(const std::string &warn, - const std::string &description) = 0; - - /** - * Display a visible error message (normally as a pop-up). - * - * @param err error title, should be short and would normally be - * shown as the title of the pop-up window or a big banner. - * - * @param description longer, free form description of the issue, as - * user-understandable and detailed as posssible. - */ - virtual void userError(const std::string &err, - const std::string &description) = 0; - - /** - * Set the list of formats that should be shown to the user - * - * @param fmts list of formats (identified by a (short) name). - * - * @param enableLoad (optional) whether to enable the loading of - * each of the formats. If not given all of them will be enabled. - * - * @param enableSave (optional) whether to enable saving of - * each of the formats. If not given all of them will be enabled. - */ - virtual void setFormats(const std::vector<std::string> &fmts, - const std::vector<bool> &enableLoad = {}, - const std::vector<bool> &enableSave = {}) = 0; - - /** - * The input path to the files to convert, as selected by the user - * - * @return path as a string / validation is not done here - */ - virtual std::string inputPath() const = 0; - - /** - * Name of the format selected to pick input files. - * - * @return format name as a string - */ - virtual std::string inputFormatName() const = 0; - - /** - * The output / destination path for the converted files, as - * selected by the user - * - * @return path as a string / validation is not done here - */ - virtual std::string outputPath() const = 0; - - /** - * Name of the output format selected. - * - * @return format name as a string - */ - virtual std::string outputFormatName() const = 0; - - /** - * User preference as to whether to compress the output images/data - * files. - * - * @return compress or not - */ - virtual bool compressHint() const = 0; - - /** - * Maximum depth (subdirectories) to search for file from the input path. - * - * @return maximum depth set by the user - */ - virtual size_t maxSearchDepth() const = 0; - - /** - * Convert image (format A) to image (format B) when both formats - * are only supported via Qt QImage and related classes. TODO: This - * should not be here. Move to presenter when we have the - * Load/SaveImage algorithm: - * https://github.com/mantidproject/mantid/issues/6843 - * - * @param inputName name of a readable image file(assuming Qt format - * guess by header probing + extension) - * - * @param inputFormat image format to read - * - * @param outputName name of an output image file (assuming Qt - * format guessing by suffix/extension) - * - * @param outputFormat image format to write - */ - virtual void convert(const std::string &inputName, - const std::string &inputFormat, - const std::string &outputName, - const std::string &outputFormat) const = 0; - - /** - * Write an image that has been loaded in a matrix workspace. As - * with convert(), move out of here when we have a Load/SaveImage - * algorithm. - * - * @param inWks workspace holding image data - * @param outputName name for the output file - * @param outFormat image format - */ - virtual void writeImg(Mantid::API::MatrixWorkspace_sptr inWks, - const std::string &outputName, - const std::string &outFormat) const = 0; - - /** - * Load an image in a matrix workspace. As with convert(), move out - * of here when we have a Load/SaveImage algorithm. - * - * @param inputName name for the output file - * @param inFormat image format - * - * @return a workspace with image data loaded from file - */ - virtual Mantid::API::MatrixWorkspace_sptr - loadImg(const std::string &inputName, const std::string &inFormat) const = 0; - - /** - * Save this widget settings (when closing this widget). - */ - virtual void saveSettings() const = 0; -}; - -} // namespace CustomInterfaces -} // namespace MantidQt - -#endif // MANTIDQTCUSTOMINTERFACES_TOMOGRAPHY_IIMGGFORMATSCONVERTVIEW_H_ diff --git a/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/ITomographyIfacePresenter.h b/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/ITomographyIfacePresenter.h deleted file mode 100644 index a97f414c83f..00000000000 --- a/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/ITomographyIfacePresenter.h +++ /dev/null @@ -1,73 +0,0 @@ -#ifndef MANTIDQTCUSTOMINTERFACES_TOMOGRAPHY_ITOMOGRAPHYIFACEPRESENTER_H_ -#define MANTIDQTCUSTOMINTERFACES_TOMOGRAPHY_ITOMOGRAPHYIFACEPRESENTER_H_ - -namespace MantidQt { -namespace CustomInterfaces { - -/** -Interface for what the presenter of the tomography GUI needs to -implement. Here the term presenter is used as in the MVP -(Model-View-Presenter) pattern. The (passive) view will use this. - -Copyright © 2014-2016 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 ITomographyIfacePresenter { -public: - virtual ~ITomographyIfacePresenter() {} - - /// These are user actions, triggered from the (passive) view, that need - /// handling by the presenter - enum Notification { - SystemSettingsUpdated, ///< Change in the system settings (local or remote) - SetupResourcesAndTools, ///< Setup what are available, normally at startup - CompResourceChanged, ///< 'current' compute resource changed - ToolChanged, ///< 'current' tomographic reconstruction tool changed - TomoPathsChanged, ///< user selects tomography data paths - TomoPathsEditedByUser, ///< user edits manually paths that may modify other - /// paths - LogInRequested, ///< user hits 'log in' or similar - LogOutRequested, ///< user hits 'log out' or similar - SetupReconTool, ///< To start the setup (open dialog, etc.) - RunReconstruct, ///< user hits 'reconstruct' or similar - RunExternalProcess, /// M run external process using the cached parameters - RefreshJobs, ///< get updated jobs info in the table/tree - CancelJobFromTable, ///< cancel one job from the list - VisualizeJobFromTable, ///< open visualization window for one job - AggregateEnergyBands, ///< run aggregate bands (in the background) - LogMsg, ///< need to send a message to the Mantid log system - ShutDown ///< closing the interface - }; - - /** - * Notifications sent through the presenter when something changes - * in the view. This plays the role of signals emitted by the view - * to this presenter. - * - * @param notif Type of notification to process. - */ - virtual void notify(ITomographyIfacePresenter::Notification notif) = 0; -}; - -} // namespace CustomInterfaces -} // namespace MantidQt - -#endif // MANTIDQTCUSTOMINTERFACES_TOMOGRAPHY_ITOMOGRAPHYIFACEPRESENTER_H_ \ No newline at end of file diff --git a/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/ITomographyIfaceView.h b/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/ITomographyIfaceView.h deleted file mode 100644 index 4cf862a8713..00000000000 --- a/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/ITomographyIfaceView.h +++ /dev/null @@ -1,323 +0,0 @@ -#ifndef MANTIDQTCUSTOMINTERFACES_TOMOGRAPHY_ITOMOGRAPHYIFACEVIEW_H_ -#define MANTIDQTCUSTOMINTERFACES_TOMOGRAPHY_ITOMOGRAPHYIFACEVIEW_H_ - -#include "MantidAPI/IAlgorithm_fwd.h" -#include "MantidAPI/IRemoteJobManager.h" -#include "MantidAPI/MatrixWorkspace_fwd.h" -#include "MantidQtCustomInterfaces/Tomography/ImageStackPreParams.h" -#include "MantidQtCustomInterfaces/Tomography/TomoPathsConfig.h" -#include "MantidQtCustomInterfaces/Tomography/TomoReconFiltersSettings.h" -#include "MantidQtCustomInterfaces/Tomography/TomoReconToolsUserSettings.h" -#include "MantidQtCustomInterfaces/Tomography/TomoSystemSettings.h" - -#include "MantidQtCustomInterfaces/Tomography/TomoToolConfigDialogBase.h" - -#include <QString> - -namespace MantidQt { -namespace CustomInterfaces { - -/** -Tomography GUI. Base class / interface for the view of the tomo GUI -(view in the sense of the MVP pattern). This class is Qt-free. Qt -specific functionality/dependencies are added in a class derived from -this. - -Copyright © 2014-2016 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 ITomographyIfaceView { - -public: - ITomographyIfaceView(){}; - virtual ~ITomographyIfaceView(){}; - - /** - * Display a warning to the user (for example as a pop-up window). - * - * @param warn warning title, should be short and would normally be - * shown as the title of the window or a big banner. - * - * @param description longer, free form description of the issue. - */ - virtual void userWarning(const std::string &warn, - const std::string &description) = 0; - - /** - * Display an error message (for example as a pop-up window). - * - * @param err Error title, should be short and would normally be - * shown as the title of the window or a big banner. - * - * @param description longer, free form description of the issue. - */ - virtual void userError(const std::string &err, - const std::string &description) = 0; - - /** - * Set the compute resources available (remote and/or local). Note - * that the order of the list is/can be important. - * - * @param resources identifiers for the resources (their display names - * normally). Order matters - * - * @param enabled tell if the resources are enabled or usable (which - * should have an effect on how they are displayed and if they can be - * used (for example, selected) in the interface. - */ - virtual void setComputeResources(const std::vector<std::string> &resources, - const std::vector<bool> &enabled) = 0; - - /** - * Set the tools available on a compute resource. - * - * @param tools identifiers of the tools that can or could be run. - * Order matters - * - * @param enabled tells if the tools are actually usable (which - * should have an effect on how they are displayed and if they can - * be used in the GUI (for example, if they can be selected at all). - */ - virtual void setReconstructionTools(const std::vector<std::string> &tools, - const std::vector<bool> &enabled) = 0; - - /** - * Gives messages that this View wants to send to the logging - * system. - * - * @return list of messages to log, one by one. - */ - virtual std::vector<std::string> logMsgs() const = 0; - - /** - * Reference or ID of the experiment entered/selected by the - * user. The ID is effectively the RBNumber (defined at ISIS as the - * "experiment reference number from the proposal"). The RBNumber - * identifies one experiment or a set of experiments from an - * approved experiment proposal. See for example: - * www.isis.stfc.ac.uk/groups/computing/data/problems-finding-your-data11691.html - * - * @return identifier as a string - */ - virtual std::string experimentReference() const = 0; - - /** - * Username entered by the user - * - * @return username to log in to the compute resource - */ - virtual std::string getUsername() const = 0; - - /** - * Password entered by the user - * - * @return password to authenticate / log in to the compute resource - */ - virtual std::string getPassword() const = 0; - - virtual std::vector<std::string> processingJobsIDs() const = 0; - - /** - * Get the current system settings. This includes several - * parameters. Most of them are paths or path components them, but - * there are also some naming conventions and other parameters. - * - * @return Settings with current values (possibly modified by the - * user). - */ - virtual TomoSystemSettings systemSettings() const = 0; - - /** - * The filters settings defined by the user. These options are - * general pre-/post-processing options. - * - * @return Pre-/post-processing filters settings - */ - virtual TomoReconFiltersSettings prePostProcSettings() const = 0; - - /** - * Gets the compute resource that is currently selected by the user. - * This calls a validation method that can throw in case of - * inconsistencies. - * - * @return Name of the compute resource as a string. - */ - virtual std::string currentComputeResource() const = 0; - - /** - * What's the reconstruction tool currently used and/or set up by - * the user. - * - * @return name of the tool as a human readable string - */ - virtual std::string currentReconTool() const = 0; - - /** - * Updates buttons and banners related to the current login - * status. For example, when we are logged in, the 'log in' button - * should be disabled, but some other widget may be enabled or some - * way displaying the 'in' status. - * - * @param loggedIn if we're logged in. - */ - virtual void updateLoginControls(bool loggedIn) = 0; - - /** - * To enable/disable the actions that require being logged in. This - * can include for example: submit jobs, get or refresh status of - * jobs, setup parameters for the remote compute resource, logout, - * etc. - * - * @param enable True to enable, or allow the user to use buttons - * and widgets to trigger those actions. - */ - virtual void enableLoggedActions(bool enable) = 0; - - /** - * Whether to enable (allow the user to open or use) the tool - * specific configuration dialog. - * - * @param on enable the button or mechanism to open the dialog - */ - virtual void enableConfigTool(bool on) = 0; - - /** - * Set the state of the 'reconstruct' button or similar to start - * reconstruction jobs. - * - * @param on whether to enable / allow the user to run it - */ - virtual void enableRunReconstruct(bool on) = 0; - - /** - * Paths to the sample, open beam, etc. data (image) files. - * - * @return paths configuration object - */ - virtual TomoPathsConfig currentPathsConfig() const = 0; - - /** - * Takes paths produces programmatically and displays them to the - * user. This can be used for example when modifying the paths based - * on some logic/consistency checks outside of this view. - * - * @param cfg configuration to use from now on - */ - virtual void updatePathsConfig(const TomoPathsConfig &cfg) = 0; - - /** - * Regions and center of rotation, normally defined by the user with - * a graphical rectangle selection tool. - * - * @return current user selection of regions - */ - virtual ImageStackPreParams currentROIEtcParams() const = 0; - - /** - * Show a tool specific configuration dialog for the user to set it up - * - * @param dialog The pointer to the current dialog - */ - virtual void showToolConfig(TomoToolConfigDialogBase &dialog) = 0; - - /** - * Refresh the table, tree etc. that displays info on the running/finished - *jobs. - * - * @param status Job information, as produced for example by the - * Mantid remote algorithms. - * - * @param localStatus similar information but for local runs - */ - virtual void updateJobsInfoDisplay( - const std::vector<Mantid::API::IRemoteJobManager::RemoteJobInfo> &status, - const std::vector<Mantid::API::IRemoteJobManager::RemoteJobInfo> & - localStatus) = 0; - - /** - * Save settings (normally when closing the interface). This refers - * to purely GUI settings, such as window max/min status and geometry, - * preferences and niceties of the user interface. - */ - virtual void saveSettings() const = 0; - - /** - * If using the keep alive mechanism, what's the period for the - * query to the remote compute resources? 0 == disabled (by default) - * - * @return period (in seconds) for the keep alive mechanism, when - * using it; 0 otherwise. - */ - virtual int keepAlivePeriod() { return 0; } - - /** - * Get parameters for wavelength/energy bands aggregation. Provides - * all the parameters needed to run the aggregation algorithm. - * - * @return parameters for an algorithm, as key-value strings - * for every required parameter and optinal parameter set to - * non-default values. - */ - virtual std::map<std::string, std::string> - currentAggregateBandsParams() const = 0; - - /** - * Run the wavelength/energy bands aggregation algorithm in the - * background. - * - * @param alg algorithm initialized and ready to run. - */ - virtual void runAggregateBands(Mantid::API::IAlgorithm_sptr alg) = 0; - - /** - * Prompts the user for confirmation with a yes/no dialogue. - * The body can use HTML formatting. - * - * @param title The title that the message has - * @param body The body that the message has. This CAN use HTML formatting - */ - virtual bool userConfirmation(const std::string &title, - const std::string &body) = 0; - - /** - * Returns the cached executable string. This will be cached by calls from the - * tabs, and allow the execution of any external program - */ - virtual std::string getCachedExecutable() const = 0; - - /** - * Returns the cached arguments string. This will be cached by calls from the - * tabs, and allow the execution of any external program - */ - virtual std::vector<std::string> getCachedArguments() const = 0; - - /** - * Emit the external process output signal so that it can be processed by it's - * receivers. The signals are connected inside the View's concrete class' - * @param str the output string of the process - */ - virtual void emitExternalProcessFinished(const QString &str) = 0; -}; - -} // namespace CustomInterfaces -} // namespace MantidQt - -#endif // MANTIDQTCUSTOMINTERFACES_TOMOGRAPHY_ITOMOGRAPHYIFACEVIEW_H_ diff --git a/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/ITomographyROIPresenter.h b/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/ITomographyROIPresenter.h deleted file mode 100644 index c34bb28324d..00000000000 --- a/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/ITomographyROIPresenter.h +++ /dev/null @@ -1,85 +0,0 @@ -#ifndef MANTIDQTCUSTOMINTERFACES_TOMOGRAPHY_ITOMOGRAPHYROIPRESENTER_H_ -#define MANTIDQTCUSTOMINTERFACES_TOMOGRAPHY_ITOMOGRAPHYROIPRESENTER_H_ - -namespace MantidQt { -namespace CustomInterfaces { - -/** -Presenter for the widget that handles the selection of the center of -rotation, region of interest, region for normalization, etc. from an -image or stack of images. This is the abstract base class / interface -for the presenter (in the sense of the MVP pattern). The name -ImageROI refers to the Center-of-Rotation, which is the most basic -parameter that users can select via this widget. This class is -QtGUI-free as it uses the interface of the view. The model is simply -the ImageStackPreParams class which holds coordinates selected by the -user. - -Copyright © 2015 ISIS Rutherford Appleton Laboratory, NScD -Oak Ridge National Laboratory & European Spallation Source - -This file is part of Mantid. - -Mantid is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 3 of the License, or -(at your option) any later version. - -Mantid is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see <http://www.gnu.org/licenses/>. - -File change history is stored at: <https://github.com/mantidproject/mantid> -Code Documentation is available at: <http://doxygen.mantidproject.org> -*/ -class ITomographyROIPresenter { - -public: - ITomographyROIPresenter(){}; - virtual ~ITomographyROIPresenter(){}; - - /// These are user actions, triggered from the (passive) view, that need - /// handling by the presenter - enum Notification { - Init, ///< interface is initing (set, defaults, etc.) - BrowseImage, ///< User browses for a single image file - BrowseStack, ///< User browses for a stack (with - ///< possibly many files) - ChangeImageType, ///< Change between sample/flat/dark images - ChangeRotation, ///< Modify the rotation in the images displayed - UpdateImgIndex, ///< Sliding/scrolling through the stack - PlayStartStop, ///< User starts or stops the "play images" - UpdateColorMap, ///< When the user wants to change the - ///< image colormap - ColorRangeUpdated, ///< The uses changes the values or options of the - ///< color range - SelectCoR, ///< Start picking of the center of rotation - SelectROI, ///< Start selection of the region of interest - SelectNormalization, ///< Start selection of the normalization region - FinishedCoR, ///< A CoR has been picked - FinishedROI, ///< The ROI is selected - FinishedNormalization, ///< The normalization region is selected - ResetCoR, ///< Reset CoR to default/none/middle - ResetROI, ///< Reset ROI to default/empty - ResetNormalization, ///< Reet the normalization region to default/empty - ShutDown ///< The widget is being closed/destroyed - }; - - /** - * Notifications sent through the presenter when something changes - * in the view. This plays the role of signals emitted by the view - * to this presenter. - * - * @param notif Type of notification to process. - */ - virtual void notify(ITomographyROIPresenter::Notification notif) = 0; -}; - -} // namespace CustomInterfaces -} // namespace MantidQt - -#endif // MANTIDQTCUSTOMINTERFACES_TOMOGRAPHY_ITOMOGRAPHYROIPRESENTER_H_ diff --git a/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/ITomographyROIView.h b/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/ITomographyROIView.h deleted file mode 100644 index 447661f4a8d..00000000000 --- a/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/ITomographyROIView.h +++ /dev/null @@ -1,290 +0,0 @@ -#ifndef MANTIDQTCUSTOMINTERFACES_TOMOGRAPHY_ITOMOGRAPHYROIVIEW_H_ -#define MANTIDQTCUSTOMINTERFACES_TOMOGRAPHY_ITOMOGRAPHYROIVIEW_H_ - -#include "MantidAPI/WorkspaceGroup_fwd.h" -#include "MantidQtCustomInterfaces/Tomography/ImageStackPreParams.h" - -namespace MantidQt { -namespace CustomInterfaces { - -/** -Widget to handle the selection of the center of rotation, region of -interest, region for normalization, etc. from an image or stack of -images. This is the abstract base class / interface for the view of -this widget (in the sense of the MVP pattern). The name ImageROI -refers to the Center-of-Rotation, which is the most basic parameter -that users can select via this widget. This class is Qt-free. Qt -specific functionality and dependencies are added in a class derived -from this. - -Copyright © 2015 ISIS Rutherford Appleton Laboratory, NScD -Oak Ridge National Laboratory & European Spallation Source - -This file is part of Mantid. - -Mantid is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 3 of the License, or -(at your option) any later version. - -Mantid is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see <http://www.gnu.org/licenses/>. - -File change history is stored at: <https://github.com/mantidproject/mantid> -Code Documentation is available at: <http://doxygen.mantidproject.org> -*/ -class ITomographyROIView { - -public: - ITomographyROIView(){}; - virtual ~ITomographyROIView(){}; - - // Selection states - enum SelectionState { - SelectNone, ///< Init, or after any reset - SelectCoR, - SelectROIFirst, - SelectROISecond, - SelectNormAreaFirst, - SelectNormAreaSecond - }; - - /** - * Sets the user selection. This should guarantee that all widgets - * are updated (including spin boxes, image, slider through the - * image stack, etc. - * - * @param params all user-modifyable parameters (coordinates for the - * CoR, ROI and area for normalization). - * - */ - virtual void setParams(ImageStackPreParams ¶ms) = 0; - - /** - * Provides the current user selection. - * - * @return parameters as set/edited by the user. - */ - virtual ImageStackPreParams userSelection() const = 0; - - /** - * The current selection state. For example: nothin/initialized, - * selecting CoR, selecting second corner of the normalization area, - * selecting first corner of the ROI. - * - * @return current state - */ - virtual SelectionState selectionState() const = 0; - - /** - * Update to a new state (for example select CoR). - * - * @param state new state we're transitioning into. - */ - virtual void changeSelectionState(const SelectionState &state) = 0; - - /** - * Display a special case of stack of images: individual image, from - * a path to a recognized directory structure (sample/dark/white) or - * image format. Here recognized format means something that is - * supported natively by the widgets library, in practice - * Qt. Normally you can expect that .tiff and .png images are - * supported. - * - * @param path path to the stack (directory) or individual image file. - */ - virtual void showStack(const std::string &path) = 0; - - /** - * Display a stack of images (or individual image as a particular - * case), from a workspace group containing matrix workspaces. It - * assumes that the workspace contains an image in the form in which - * LoadFITS loads FITS images (or spectrum per row, all of them with - * the same number of data points (columns)). - * - * @param wsg Workspace group where every workspace is a FITS or - * similar image that has been loaded with LoadFITS or similar - * algorithm. This holds the sample images. - * - * @param wsgFlats Workspace group with flat (open beam) images. - * - * @param wsgDarks Workspace group with dark images. - */ - virtual void showStack(const Mantid::API::WorkspaceGroup_sptr &wsg, - const Mantid::API::WorkspaceGroup_sptr &wsgFlats, - const Mantid::API::WorkspaceGroup_sptr &wsgDarks) = 0; - - /** - * Get the stack of (sample) images currently being displayed (it - * has been shown using showStack()), as a workspace group. - * - * @return workspace group containing the individual images, which - * can be empty if no stack has been loaded. - */ - virtual const Mantid::API::WorkspaceGroup_sptr stackSamples() const = 0; - - /** - * Normally one image (projection for tomography stacks) will be - * shown on a 2D display. Show there a particular projection from a - * stack contained in a workspace group. - * - * @param wsg workspace holding a stack of images - * - * @param idx index (in the group) of the image to show - * - */ - virtual void showProjection(const Mantid::API::WorkspaceGroup_sptr &wsg, - size_t idx) = 0; - - /** - * Display a warning to the user (for example as a pop-up window). - * - * @param warn warning title, should be short and would normally be - * shown as the title of the window or a big banner. - * - * @param description longer, free form description of the issue. - */ - virtual void userWarning(const std::string &warn, - const std::string &description) = 0; - - /** - * Display an error message (for example as a pop-up window). - * - * @param err Error title, should be short and would normally be - * shown as the title of the window or a big banner. - * - * @param description longer, free form description of the issue. - */ - virtual void userError(const std::string &err, - const std::string &description) = 0; - - /** - * To enable/disable all actions in the view. Useful when it is - * necessary to prevent the user from requesting actions. For - * example, during a lenghty execution of a process, drawing, etc. - * - * @param enable whether to enable or disable actions. - */ - virtual void enableActions(bool enable) = 0; - - /** - * The images of the type selected by the user (samples/flats/darks). - * - * @return a workspace group with the images of the current type - */ - virtual Mantid::API::WorkspaceGroup_sptr currentImageTypeStack() const = 0; - - /** - * Sets the type of image (sample/flat/dark). - * - * @param wsg workspace group that contains the type of image - */ - virtual void updateImageType(const Mantid::API::WorkspaceGroup_sptr wsg) = 0; - - /** - * The index of the image currently shown (from the current stack if there's - * any). - * - * @return index from 0 to the total number of images in the - * stack-1, as used for example when indexing workspaces in - * workspacegroups - */ - virtual size_t currentImgIndex() const = 0; - - /** - * Display now this image (idx) from the stack. - * - * @param idx index of the image to display. - */ - virtual void updateImgWithIndex(size_t idx) = 0; - - /** - * Start to play/animate the stack currently displayed. - */ - virtual void playStart() = 0; - - /** - * Stop playing/animating the stack currently displayed, and goes - * back to the default status. - */ - virtual void playStop() = 0; - - /** - * The rotation angle selected. - * - * @return angle in degrees. - */ - virtual float currentRotationAngle() const = 0; - - /** - * Modify the rotation angle selection and update the image display - * to match the new rotation. - * - * @param angle rotation angle in degrees - */ - virtual void updateRotationAngle(float angle) = 0; - - /** - * Get the WHOLE path/location of a single image file. This includes the - * filename and the whole path of directories to it. If you want only the - * directories the filename must be trimmed. - * - * @return location as a string - */ - virtual std::string - askImagePath(const std::string &windowTitle = "Open image") = 0; - - /** - * Get the path of a color map file from the user. - * - * @return path as a string (empty if the selection is canceled or - * fails otherwise) - */ - virtual std::string askColorMapFile() = 0; - - /** - * Update the current color map (and refresh the image with it). - * - * @param filename name of a color map file - */ - virtual void updateColorMap(const std::string &filename) = 0; - - /** - * Save settings (normally when closing this widget). - */ - virtual void saveSettings() const = 0; - - /** - * Forget the current center-of-rotation selection and set to - * default. - */ - virtual void resetCoR() = 0; - - /** - * Forget the current region-of-interest selection and set to - * default (all). - */ - virtual void resetROI() = 0; - - /** - * Forget the current selection of region-for-normalization and set - * to default (none). - */ - virtual void resetNormArea() = 0; - - /** - * Notifies the main view that an image has been loaded, so that it can update - * the paths - */ - virtual void imageOrStackLoaded(const std::string &path) = 0; -}; - -} // namespace CustomInterfaces -} // namespace MantidQt - -#endif // MANTIDQTCUSTOMINTERFACES_TOMOGRAPHY_ITOMOGRAPHYROIVIEW_H_ diff --git a/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/ImageSelectCoRAndRegions.ui b/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/ImageSelectCoRAndRegions.ui deleted file mode 100644 index 4dc019ab85e..00000000000 --- a/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/ImageSelectCoRAndRegions.ui +++ /dev/null @@ -1,933 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<ui version="4.0"> - <class>ImageSelectCoRAndRegions</class> - <widget class="QWidget" name="ImageSelectCoRAndRegions"> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>800</width> - <height>600</height> - </rect> - </property> - <property name="sizePolicy"> - <sizepolicy hsizetype="Preferred" vsizetype="Expanding"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="windowTitle"> - <string>Form</string> - </property> - <layout class="QGridLayout" name="gridLayout_8"> - <item row="0" column="0"> - <widget class="QSplitter" name="splitter_main_horiz"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <widget class="QSplitter" name="splitter_img_vertical"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Preferred" vsizetype="Expanding"> - <horstretch>2</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="orientation"> - <enum>Qt::Vertical</enum> - </property> - <widget class="QWidget" name="layoutWidget"> - <layout class="QGridLayout" name="gridLayout_5"> - <property name="sizeConstraint"> - <enum>QLayout::SetMinimumSize</enum> - </property> - <item row="0" column="4"> - <widget class="QPushButton" name="pushButton_browse_stack"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Minimum" vsizetype="Fixed"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="minimumSize"> - <size> - <width>0</width> - <height>28</height> - </size> - </property> - <property name="maximumSize"> - <size> - <width>16777215</width> - <height>28</height> - </size> - </property> - <property name="text"> - <string>Stack...</string> - </property> - </widget> - </item> - <item row="0" column="0"> - <widget class="QLabel" name="label_img_seq"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="minimumSize"> - <size> - <width>0</width> - <height>28</height> - </size> - </property> - <property name="maximumSize"> - <size> - <width>16777215</width> - <height>28</height> - </size> - </property> - <property name="text"> - <string>Image:</string> - </property> - </widget> - </item> - <item row="0" column="2"> - <widget class="QLabel" name="label_img_name"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> - <horstretch>1</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="minimumSize"> - <size> - <width>0</width> - <height>28</height> - </size> - </property> - <property name="maximumSize"> - <size> - <width>16777215</width> - <height>28</height> - </size> - </property> - <property name="text"> - <string>none</string> - </property> - </widget> - </item> - <item row="0" column="1"> - <widget class="QLineEdit" name="lineEdit_img_seq"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="minimumSize"> - <size> - <width>100</width> - <height>28</height> - </size> - </property> - <property name="maximumSize"> - <size> - <width>100</width> - <height>28</height> - </size> - </property> - <property name="text"> - <string>0/0</string> - </property> - <property name="alignment"> - <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> - </property> - <property name="readOnly"> - <bool>true</bool> - </property> - </widget> - </item> - <item row="0" column="3"> - <widget class="QPushButton" name="pushButton_browse_img"> - <property name="text"> - <string>Image...</string> - </property> - </widget> - </item> - </layout> - </widget> - <widget class="QWidget" name="layoutWidget1"> - <layout class="QGridLayout" name="gridLayout_7" rowstretch="0,0"> - <property name="sizeConstraint"> - <enum>QLayout::SetMaximumSize</enum> - </property> - <property name="spacing"> - <number>3</number> - </property> - <item row="0" column="0"> - <widget class="QScrollArea" name="scrollArea"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> - <horstretch>2</horstretch> - <verstretch>2</verstretch> - </sizepolicy> - </property> - <property name="widgetResizable"> - <bool>true</bool> - </property> - <widget class="QWidget" name="scrollAreaWidgetContents"> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>496</width> - <height>412</height> - </rect> - </property> - <property name="sizePolicy"> - <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> - <horstretch>2</horstretch> - <verstretch>2</verstretch> - </sizepolicy> - </property> - <layout class="QGridLayout" name="gridLayout" rowstretch="0" columnstretch="0"> - <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> - <property name="spacing"> - <number>1</number> - </property> - <item row="0" column="0"> - <widget class="QLabel" name="label_img"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> - <horstretch>3</horstretch> - <verstretch>3</verstretch> - </sizepolicy> - </property> - <property name="text"> - <string/> - </property> - </widget> - </item> - </layout> - </widget> - </widget> - </item> - <item row="1" column="0"> - <widget class="QScrollBar" name="horizontalScrollBar_img_stack"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> - <horstretch>2</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="invertedControls"> - <bool>true</bool> - </property> - </widget> - </item> - </layout> - </widget> - </widget> - <widget class="QSplitter" name="splitter_right_horiz"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <widget class="QWidget" name="layoutWidget_2"> - <layout class="QGridLayout" name="gridLayout_6"> - <property name="sizeConstraint"> - <enum>QLayout::SetDefaultConstraint</enum> - </property> - <property name="spacing"> - <number>4</number> - </property> - <item row="3" column="0"> - <spacer name="verticalSpacer_2"> - <property name="orientation"> - <enum>Qt::Vertical</enum> - </property> - <property name="sizeType"> - <enum>QSizePolicy::Minimum</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>20</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item row="2" column="0"> - <widget class="QGroupBox" name="groupBox_cor"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Minimum"> - <horstretch>1</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="maximumSize"> - <size> - <width>250</width> - <height>16777215</height> - </size> - </property> - <property name="title"> - <string>Center of rotation</string> - </property> - <layout class="QGridLayout" name="gridLayout_2"> - <property name="leftMargin"> - <number>3</number> - </property> - <property name="topMargin"> - <number>3</number> - </property> - <property name="rightMargin"> - <number>3</number> - </property> - <property name="bottomMargin"> - <number>3</number> - </property> - <property name="spacing"> - <number>4</number> - </property> - <item row="1" column="0"> - <layout class="QHBoxLayout" name="horizontalLayout"> - <item> - <widget class="QLabel" name="label_3"> - <property name="text"> - <string>Column:</string> - </property> - </widget> - </item> - <item> - <widget class="QSpinBox" name="spinBox_cor_x"> - <property name="maximum"> - <number>9999</number> - </property> - <property name="value"> - <number>9999</number> - </property> - </widget> - </item> - <item> - <widget class="QLabel" name="label_2"> - <property name="text"> - <string>Row:</string> - </property> - </widget> - </item> - <item> - <widget class="QSpinBox" name="spinBox_cor_y"> - <property name="maximum"> - <number>9999</number> - </property> - <property name="value"> - <number>9999</number> - </property> - </widget> - </item> - </layout> - </item> - <item row="2" column="0"> - <layout class="QHBoxLayout" name="horizontalLayout_2"> - <item> - <widget class="QPushButton" name="pushButton_cor"> - <property name="toolTip"> - <string>After pushing this button, click on the image to select</string> - </property> - <property name="text"> - <string>Select</string> - </property> - </widget> - </item> - <item> - <spacer name="horizontalSpacer_3"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>108</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item> - <widget class="QPushButton" name="pushButton_cor_reset"> - <property name="text"> - <string>Reset</string> - </property> - </widget> - </item> - </layout> - </item> - <item row="0" column="0"> - <layout class="QHBoxLayout" name="horizontalLayout_5"> - <item> - <spacer name="horizontalSpacer_4"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>78</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item> - <widget class="QPushButton" name="pushButton_center_find"> - <property name="enabled"> - <bool>false</bool> - </property> - <property name="text"> - <string>Auto-find</string> - </property> - </widget> - </item> - <item> - <widget class="QComboBox" name="comboBox_center_method"> - <property name="enabled"> - <bool>false</bool> - </property> - <item> - <property name="text"> - <string>TomoPy</string> - </property> - </item> - </widget> - </item> - </layout> - </item> - </layout> - </widget> - </item> - <item row="5" column="0"> - <spacer name="verticalSpacer_3"> - <property name="orientation"> - <enum>Qt::Vertical</enum> - </property> - <property name="sizeType"> - <enum>QSizePolicy::Minimum</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>20</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item row="7" column="0"> - <spacer name="verticalSpacer"> - <property name="orientation"> - <enum>Qt::Vertical</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>20</width> - <height>68</height> - </size> - </property> - </spacer> - </item> - <item row="0" column="0"> - <layout class="QHBoxLayout" name="horizontalLayout_4"> - <item> - <widget class="QPushButton" name="pushButton_play"> - <property name="enabled"> - <bool>false</bool> - </property> - <property name="text"> - <string>Play</string> - </property> - </widget> - </item> - <item> - <spacer name="horizontalSpacer_5"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>20</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item> - <widget class="QLabel" name="label_image_type"> - <property name="text"> - <string>Display:</string> - </property> - </widget> - </item> - <item> - <widget class="QComboBox" name="comboBox_image_type"> - <property name="enabled"> - <bool>false</bool> - </property> - <item> - <property name="text"> - <string>Samples</string> - </property> - </item> - <item> - <property name="text"> - <string>Flat</string> - </property> - </item> - <item> - <property name="text"> - <string>Dark</string> - </property> - </item> - </widget> - </item> - </layout> - </item> - <item row="1" column="0"> - <layout class="QHBoxLayout" name="horizontalLayout_6"> - <item> - <spacer name="horizontalSpacer_6"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>80</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item> - <widget class="QLabel" name="label_rotation"> - <property name="text"> - <string>Rotate (clockwise):</string> - </property> - </widget> - </item> - <item> - <widget class="QComboBox" name="comboBox_rotation"> - <property name="enabled"> - <bool>false</bool> - </property> - <property name="editable"> - <bool>false</bool> - </property> - <property name="minimumContentsLength"> - <number>3</number> - </property> - <item> - <property name="text"> - <string>0°</string> - </property> - </item> - <item> - <property name="text"> - <string>90°</string> - </property> - </item> - <item> - <property name="text"> - <string>180°</string> - </property> - </item> - <item> - <property name="text"> - <string>270°</string> - </property> - </item> - </widget> - </item> - </layout> - </item> - <item row="4" column="0"> - <widget class="QGroupBox" name="groupBox_roi"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Minimum"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="minimumSize"> - <size> - <width>250</width> - <height>0</height> - </size> - </property> - <property name="maximumSize"> - <size> - <width>250</width> - <height>16777215</height> - </size> - </property> - <property name="title"> - <string>Region of interest:</string> - </property> - <layout class="QGridLayout" name="gridLayout_3"> - <property name="leftMargin"> - <number>3</number> - </property> - <property name="topMargin"> - <number>3</number> - </property> - <property name="rightMargin"> - <number>3</number> - </property> - <property name="bottomMargin"> - <number>3</number> - </property> - <property name="spacing"> - <number>2</number> - </property> - <item row="0" column="0"> - <widget class="QLabel" name="spinbox_roi_left_label"> - <property name="text"> - <string> Left</string> - </property> - </widget> - </item> - <item row="0" column="1"> - <widget class="QLabel" name="spinbox_roi_top_label"> - <property name="text"> - <string> Top</string> - </property> - </widget> - </item> - <item row="0" column="2"> - <widget class="QLabel" name="spinbox_roi_right_label"> - <property name="text"> - <string> Right</string> - </property> - </widget> - </item> - <item row="0" column="3"> - <widget class="QLabel" name="spinbox_roi_bottom_label"> - <property name="text"> - <string> Bottom</string> - </property> - </widget> - </item> - <item row="1" column="0"> - <widget class="QSpinBox" name="spinBox_roi_left"> - <property name="minimumSize"> - <size> - <width>50</width> - <height>0</height> - </size> - </property> - <property name="maximum"> - <number>9999</number> - </property> - <property name="value"> - <number>9999</number> - </property> - </widget> - </item> - <item row="1" column="1"> - <widget class="QSpinBox" name="spinBox_roi_top"> - <property name="minimumSize"> - <size> - <width>50</width> - <height>0</height> - </size> - </property> - <property name="maximum"> - <number>9999</number> - </property> - <property name="value"> - <number>9999</number> - </property> - </widget> - </item> - <item row="1" column="2"> - <widget class="QSpinBox" name="spinBox_roi_right"> - <property name="minimumSize"> - <size> - <width>50</width> - <height>0</height> - </size> - </property> - <property name="maximum"> - <number>9999</number> - </property> - <property name="value"> - <number>9999</number> - </property> - </widget> - </item> - <item row="1" column="3"> - <widget class="QSpinBox" name="spinBox_roi_bottom"> - <property name="minimumSize"> - <size> - <width>50</width> - <height>4</height> - </size> - </property> - <property name="maximum"> - <number>9999</number> - </property> - <property name="value"> - <number>9999</number> - </property> - </widget> - </item> - <item row="7" column="0" colspan="4"> - <layout class="QHBoxLayout" name="horizontalLayout_3"> - <item> - <widget class="QPushButton" name="pushButton_roi"> - <property name="toolTip"> - <string>After pushing this button, click and drag on the image to select</string> - </property> - <property name="text"> - <string>Select</string> - </property> - </widget> - </item> - <item> - <spacer name="horizontalSpacer_2"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>80</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item> - <widget class="QPushButton" name="pushButton_roi_reset"> - <property name="toolTip"> - <string>Reset to the whole field of view</string> - </property> - <property name="text"> - <string>Reset</string> - </property> - </widget> - </item> - </layout> - </item> - </layout> - </widget> - </item> - <item row="6" column="0"> - <widget class="QGroupBox" name="groupBox_norm"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Minimum"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="minimumSize"> - <size> - <width>250</width> - <height>0</height> - </size> - </property> - <property name="maximumSize"> - <size> - <width>250</width> - <height>16777215</height> - </size> - </property> - <property name="title"> - <string>Area for normalization:</string> - </property> - <layout class="QGridLayout" name="gridLayout_4"> - <property name="leftMargin"> - <number>3</number> - </property> - <property name="topMargin"> - <number>3</number> - </property> - <property name="rightMargin"> - <number>3</number> - </property> - <property name="bottomMargin"> - <number>3</number> - </property> - <property name="spacing"> - <number>2</number> - </property> - <item row="0" column="0"> - <widget class="QLabel" name="spinbox_norm_left_label"> - <property name="text"> - <string> Left</string> - </property> - </widget> - </item> - <item row="0" column="1"> - <widget class="QLabel" name="spinbox_norm_top_label"> - <property name="text"> - <string> Top</string> - </property> - </widget> - </item> - <item row="0" column="2"> - <widget class="QLabel" name="spinbox_norm_right_label"> - <property name="text"> - <string> Right</string> - </property> - </widget> - </item> - <item row="0" column="3"> - <widget class="QLabel" name="spinbox_norm_bottom_label"> - <property name="text"> - <string> Bottom</string> - </property> - </widget> - </item> - <item row="1" column="0"> - <widget class="QSpinBox" name="spinBox_norm_left"> - <property name="minimumSize"> - <size> - <width>50</width> - <height>0</height> - </size> - </property> - <property name="maximum"> - <number>9999</number> - </property> - <property name="value"> - <number>9999</number> - </property> - </widget> - </item> - <item row="1" column="1"> - <widget class="QSpinBox" name="spinBox_norm_top"> - <property name="minimumSize"> - <size> - <width>50</width> - <height>0</height> - </size> - </property> - <property name="maximum"> - <number>9999</number> - </property> - <property name="value"> - <number>9999</number> - </property> - </widget> - </item> - <item row="1" column="2"> - <widget class="QSpinBox" name="spinBox_norm_right"> - <property name="minimumSize"> - <size> - <width>50</width> - <height>0</height> - </size> - </property> - <property name="maximum"> - <number>9999</number> - </property> - <property name="value"> - <number>9999</number> - </property> - </widget> - </item> - <item row="1" column="3"> - <widget class="QSpinBox" name="spinBox_norm_bottom"> - <property name="minimumSize"> - <size> - <width>50</width> - <height>0</height> - </size> - </property> - <property name="maximum"> - <number>9999</number> - </property> - <property name="value"> - <number>9999</number> - </property> - </widget> - </item> - <item row="3" column="0" colspan="4"> - <layout class="QHBoxLayout" name="horizontalLayout_8"> - <item> - <widget class="QPushButton" name="pushButton_norm_area"> - <property name="toolTip"> - <string>After pushing this button, click and drag on the image to select</string> - </property> - <property name="text"> - <string>Select</string> - </property> - </widget> - </item> - <item> - <spacer name="horizontalSpacer"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>80</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item> - <widget class="QPushButton" name="pushButton_norm_area_reset"> - <property name="toolTip"> - <string>Reset to empty/none</string> - </property> - <property name="text"> - <string>Reset</string> - </property> - </widget> - </item> - </layout> - </item> - </layout> - </widget> - </item> - </layout> - </widget> - <widget class="QWidget" name="layoutWidget_10"> - <layout class="QVBoxLayout" name="verticalLayout"> - <item> - <widget class="MantidQt::MantidWidgets::ColorBarWidget" name="colorBarWidget" native="true"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Preferred" vsizetype="Expanding"> - <horstretch>0</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> - </widget> - </item> - </layout> - </widget> - </widget> - </widget> - </item> - </layout> - </widget> - <customwidgets> - <customwidget> - <class>MantidQt::MantidWidgets::ColorBarWidget</class> - <extends>QWidget</extends> - <header>MantidQtMantidWidgets/ColorBarWidget.h</header> - </customwidget> - </customwidgets> - <resources/> - <connections/> -</ui> diff --git a/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/ImageStackPreParams.h b/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/ImageStackPreParams.h deleted file mode 100644 index 8b966e60183..00000000000 --- a/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/ImageStackPreParams.h +++ /dev/null @@ -1,62 +0,0 @@ -#ifndef MANTIDQTCUSTOMINTERFACES_TOMOGRAPHY_IMAGESTACKPREPARAMS_H_ -#define MANTIDQTCUSTOMINTERFACES_TOMOGRAPHY_IMAGESTACKPREPARAMS_H_ - -#include "MantidQtCustomInterfaces/DllConfig.h" -#include "MantidKernel/V2D.h" - -#include <utility> - -namespace MantidQt { -namespace CustomInterfaces { - -/** -This holds parameters for pre-processing images or stacks of images -for tomographic reconstruction. These parameters are used in different -pre-processing steps in the tomographic reconstruction pipeline, and -also for the reconstruction algorithms (iternative methods, FBP, -etc.). - -The parameters include: -- center of rotation -- region of interest (clip from original or raw images) -- region for normalization (where the beam is not blocked by any sample - object throughout the stack of images) other parameters describing - the stack of images: - -Copyright © 2014,2015 ISIS Rutherford Appleton Laboratory, NScD -Oak Ridge National Laboratory & European Spallation Source - -This file is part of Mantid. - -Mantid is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 3 of the License, or -(at your option) any later version. - -Mantid is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see <http://www.gnu.org/licenses/>. - -File change history is stored at: <https://github.com/mantidproject/mantid> -Code Documentation is available at: <http://doxygen.mantidproject.org> -*/ -class MANTIDQT_CUSTOMINTERFACES_DLL ImageStackPreParams { -public: - ImageStackPreParams(); - - typedef std::pair<Mantid::Kernel::V2D, Mantid::Kernel::V2D> Box2D; - - Mantid::Kernel::V2D cor; - Box2D roi; - Box2D normalizationRegion; //< also known as 'air' region - float rotation; //< rotation angle in degrees -}; - -} // namespace CustomInterfaces -} // namespace MantidQt - -#endif // MANTIDQTCUSTOMINTERFACES_TOMOGRAPHY_IMAGESTACKPREPARAMS_H_ diff --git a/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/ImggFormats.h b/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/ImggFormats.h deleted file mode 100644 index 50061993400..00000000000 --- a/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/ImggFormats.h +++ /dev/null @@ -1,55 +0,0 @@ -#ifndef MANTIDQTCUSTOMINTERFACES_TOMOGRAPHY_IMGGFORMATS_H_ -#define MANTIDQTCUSTOMINTERFACES_TOMOGRAPHY_IMGGFORMATS_H_ - -#include <string> -#include <vector> - -namespace MantidQt { -namespace CustomInterfaces { - -/** -File formats used to store imaging data (image file formats and -generic imaging formats such as NXTomo -http://download.nexusformat.org/sphinx/classes/applications/NXtomo.html). - -Copyright © 2016 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> -*/ -namespace ImggFormats { -enum Format { FITS = 0, TIFF = 1, PNG = 2, JPG = 3, NXTomo = 4 }; - -std::string shortName(Format fmt); - -std::vector<std::string> fileExtension(Format fmt); - -std::string fileExtension(const std::string &format); - -bool isFileExtension(const std::string &extension, - const std::string &shortName); - -std::string description(Format fmt); - -} // namespace ImggFormats - -} // namespace CustomInterfaces -} // namespace MantidQt - -#endif // MANTIDQTCUSTOMINTERFACES_TOMOGRAPHY_IMGGFORMATS_H_ diff --git a/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/ImggFormatsConvert.ui b/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/ImggFormatsConvert.ui deleted file mode 100644 index da24f8a5c46..00000000000 --- a/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/ImggFormatsConvert.ui +++ /dev/null @@ -1,350 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<ui version="4.0"> - <class>ImggFormatsConvert</class> - <widget class="QWidget" name="ImggFormatsConvert"> - <property name="enabled"> - <bool>true</bool> - </property> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>654</width> - <height>426</height> - </rect> - </property> - <property name="windowTitle"> - <string>ImgFormatsConversion</string> - </property> - <layout class="QGridLayout" name="gridLayout_3"> - <item row="0" column="0"> - <widget class="QGroupBox" name="groupBox"> - <property name="enabled"> - <bool>true</bool> - </property> - <property name="title"> - <string>Input:</string> - </property> - <layout class="QGridLayout" name="gridLayout"> - <item row="1" column="3"> - <widget class="QPushButton" name="pushButton_browse_input"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="text"> - <string>Browse</string> - </property> - </widget> - </item> - <item row="1" column="0"> - <widget class="QLabel" name="label_2"> - <property name="text"> - <string>Path:</string> - </property> - </widget> - </item> - <item row="0" column="2" colspan="2"> - <spacer name="horizontalSpacer_2"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeType"> - <enum>QSizePolicy::Expanding</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>268</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item row="0" column="0"> - <widget class="QLabel" name="label_3"> - <property name="text"> - <string>Pick format:</string> - </property> - </widget> - </item> - <item row="0" column="1"> - <widget class="QComboBox" name="comboBox_input_format"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <item> - <property name="text"> - <string>FITS</string> - </property> - </item> - <item> - <property name="text"> - <string>TIFF</string> - </property> - </item> - <item> - <property name="text"> - <string>PNG</string> - </property> - </item> - <item> - <property name="text"> - <string>NXTomo</string> - </property> - </item> - </widget> - </item> - <item row="1" column="1" colspan="2"> - <widget class="QLineEdit" name="lineEdit_input_path"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> - <horstretch>2</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="readOnly"> - <bool>true</bool> - </property> - </widget> - </item> - </layout> - </widget> - </item> - <item row="1" column="0"> - <widget class="QGroupBox" name="groupBox_2"> - <property name="enabled"> - <bool>true</bool> - </property> - <property name="title"> - <string>Output</string> - </property> - <layout class="QGridLayout" name="gridLayout_2"> - <item row="1" column="0"> - <widget class="QLabel" name="label"> - <property name="text"> - <string>Pixel bit-depth in outputs:</string> - </property> - </widget> - </item> - <item row="0" column="1"> - <widget class="QComboBox" name="comboBox_output_format"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <item> - <property name="text"> - <string>PNG</string> - </property> - </item> - <item> - <property name="text"> - <string>TIFF</string> - </property> - </item> - <item> - <property name="text"> - <string>FITS</string> - </property> - </item> - <item> - <property name="text"> - <string>NXTomo</string> - </property> - </item> - </widget> - </item> - <item row="2" column="0"> - <widget class="QLabel" name="label_6"> - <property name="text"> - <string>Compression:</string> - </property> - </widget> - </item> - <item row="2" column="1"> - <widget class="QComboBox" name="comboBox_compression"> - <item> - <property name="text"> - <string>Enable</string> - </property> - </item> - <item> - <property name="text"> - <string>Disable</string> - </property> - </item> - </widget> - </item> - <item row="2" column="2"> - <spacer name="horizontalSpacer_4"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>362</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item row="4" column="0" colspan="3"> - <layout class="QHBoxLayout" name="horizontalLayout"> - <item> - <widget class="QLabel" name="label_5"> - <property name="text"> - <string>Path:</string> - </property> - </widget> - </item> - <item> - <widget class="QLineEdit" name="lineEdit_output_path"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> - <horstretch>2</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="readOnly"> - <bool>true</bool> - </property> - </widget> - </item> - <item> - <widget class="QPushButton" name="pushButton_browse_output"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="text"> - <string>Browse</string> - </property> - </widget> - </item> - </layout> - </item> - <item row="0" column="0"> - <widget class="QLabel" name="label_4"> - <property name="text"> - <string>Format:</string> - </property> - </widget> - </item> - <item row="1" column="1"> - <widget class="QComboBox" name="comboBox_bit_depth"> - <item> - <property name="text"> - <string>16 bits</string> - </property> - </item> - </widget> - </item> - <item row="1" column="2"> - <spacer name="horizontalSpacer"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>362</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item row="0" column="2"> - <spacer name="horizontalSpacer_3"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeType"> - <enum>QSizePolicy::Expanding</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>362</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item row="3" column="0"> - <widget class="QLabel" name="label_7"> - <property name="text"> - <string>Maximum search depth:</string> - </property> - </widget> - </item> - <item row="3" column="1"> - <widget class="QSpinBox" name="spinBox_max_search_depth"> - <property name="toolTip"> - <string>How many subdirectory levels should be processed at most</string> - </property> - <property name="minimum"> - <number>1</number> - </property> - <property name="maximum"> - <number>10</number> - </property> - <property name="value"> - <number>3</number> - </property> - </widget> - </item> - </layout> - </widget> - </item> - <item row="2" column="0"> - <layout class="QHBoxLayout" name="horizontalLayout_2"> - <item> - <spacer name="horizontalSpacer_5"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>278</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item> - <widget class="QPushButton" name="pushButton_convert"> - <property name="enabled"> - <bool>true</bool> - </property> - <property name="text"> - <string>Convert</string> - </property> - </widget> - </item> - </layout> - </item> - <item row="3" column="0"> - <spacer name="verticalSpacer"> - <property name="orientation"> - <enum>Qt::Vertical</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>20</width> - <height>40</height> - </size> - </property> - </spacer> - </item> - </layout> - </widget> - <resources/> - <connections/> -</ui> diff --git a/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/ImggFormatsConvertPresenter.h b/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/ImggFormatsConvertPresenter.h deleted file mode 100644 index c18a91663b2..00000000000 --- a/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/ImggFormatsConvertPresenter.h +++ /dev/null @@ -1,105 +0,0 @@ -#ifndef MANTIDQTCUSTOMINTERFACES_TOMOGRAPHY_IMGGFORMATSCONVERTPRESENTER_H_ -#define MANTIDQTCUSTOMINTERFACES_TOMOGRAPHY_IMGGFORMATSCONVERTPRESENTER_H_ - -#include "MantidQtCustomInterfaces/DllConfig.h" -#include "MantidQtCustomInterfaces/Tomography/IImggFormatsConvertPresenter.h" -#include "MantidQtCustomInterfaces/Tomography/IImggFormatsConvertView.h" -#include "MantidAPI/MatrixWorkspace_fwd.h" - -// forward declarations for Poco classes -namespace Poco { -class File; -class Path; -} - -namespace MantidQt { - -namespace API { -class BatchAlgorithmRunner; -} - -namespace CustomInterfaces { - -/** -Presenter for the widget to convert images and stacks of images -between formats. - -Copyright © 2016 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 MANTIDQT_CUSTOMINTERFACES_DLL ImggFormatsConvertPresenter - : public IImggFormatsConvertPresenter { - -public: - /// Default constructor - normally used from the concrete view - ImggFormatsConvertPresenter(IImggFormatsConvertView *view); - ~ImggFormatsConvertPresenter() override; - - void notify(IImggFormatsConvertPresenter::Notification notif) override; - -protected: - void initialize(); - - /// clean shut down of model, view, etc. - void cleanup(); - - // Methods that process notifications from view->presenter - void processInit(); - void processConvert(); - void processShutDown(); - -private: - size_t goThroughDirRecur(const Poco::File &inFilePath, - const std::string &inFormat, - const Poco::File &outFilePath, - const std::string &outExt, size_t depth); - - void convert(const std::string &inputName, const std::string &inFormat, - const std::string &outputName, - const std::string &outFormat) const; - - void convertToFITS(const std::string &inputName, const std::string &inFormat, - const std::string &outputName) const; - - void convertToNXTomo(const std::string &inputName, - const std::string &inFormat, - const std::string &outputName) const; - - Mantid::API::MatrixWorkspace_sptr loadImg(const std::string &inputName, - const std::string inFormat) const; - - Mantid::API::MatrixWorkspace_sptr - loadFITS(const std::string &inputName) const; - - void saveFITS(Mantid::API::MatrixWorkspace_sptr image, - const std::string &outputName) const; - - void saveNXTomo(Mantid::API::MatrixWorkspace_sptr image, - const std::string &outputName) const; - - /// Associated view for this presenter (MVP pattern) - IImggFormatsConvertView *const m_view; -}; - -} // namespace CustomInterfaces -} // namespace MantidQt - -#endif // MANTIDQTCUSTOMINTERFACES_TOMOGRAPHY_IMGGGFORMATSCONVERTPRESENTER_H_ diff --git a/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/ImggFormatsConvertViewQtWidget.h b/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/ImggFormatsConvertViewQtWidget.h deleted file mode 100644 index 3d1dbd7d746..00000000000 --- a/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/ImggFormatsConvertViewQtWidget.h +++ /dev/null @@ -1,129 +0,0 @@ -#ifndef MANTIDQTCUSTOMINTERFACES_TOMOGRAPHY_IMGGFORMATSCONVERTVIEWQTWIDGET_H_ -#define MANTIDQTCUSTOMINTERFACES_TOMOGRAPHY_IMGGFORMATSCONVERTVIEWQTWIDGET_H_ - -#include "MantidAPI/MatrixWorkspace_fwd.h" -#include "MantidQtCustomInterfaces/DllConfig.h" -#include "MantidQtCustomInterfaces/Tomography/IImggFormatsConvertPresenter.h" -#include "MantidQtCustomInterfaces/Tomography/IImggFormatsConvertView.h" - -#include "ui_ImggFormatsConvert.h" - -#include <QWidget> - -// forward declarations for Qt -class QComboBox; -class QImage; - -namespace MantidQt { -namespace CustomInterfaces { - -/** -Qt view of a widget to convert images and stacks of images between -different formats. - -Copyright © 2016 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 MANTIDQT_CUSTOMINTERFACES_DLL ImggFormatsConvertViewQtWidget - : public QWidget, - public IImggFormatsConvertView { - Q_OBJECT - -public: - ImggFormatsConvertViewQtWidget(QWidget *parent = 0); - - ~ImggFormatsConvertViewQtWidget() override; - - void userWarning(const std::string &err, - const std::string &description) override; - - void userError(const std::string &err, - const std::string &description) override; - - void setFormats(const std::vector<std::string> &fmts, - const std::vector<bool> &enableLoad, - const std::vector<bool> &enableSave) override; - - std::string inputPath() const override; - std::string inputFormatName() const override; - - std::string outputPath() const override; - std::string outputFormatName() const override; - - bool compressHint() const override; - - size_t maxSearchDepth() const override; - - void convert(const std::string &inputName, const std::string &inputFormat, - const std::string &outputName, - const std::string &outputFormat) const override; - - void writeImg(Mantid::API::MatrixWorkspace_sptr inWks, - const std::string &outputName, - const std::string &outFormat) const override; - - Mantid::API::MatrixWorkspace_sptr - loadImg(const std::string &inputName, - const std::string &inFormat) const override; - -protected: - void initLayout(); - - void saveSettings() const override; - void readSettings(); - void setup(); - -private slots: - void browseImgInputConvertClicked(); - void browseImgOutputConvertClicked(); - void convertClicked(); - -private: - void writeImgFile(const QImage &img, const std::string &outputName, - const std::string &outFormat) const; - - QImage loadImgFile(const std::string &inputName, - const std::string inFormat) const; - - void setFormatsCombo(QComboBox *cbox, const std::vector<std::string> &fmts, - const std::vector<bool> &enable); - - std::string - grabUserBrowseDir(QLineEdit *le, - const std::string &userMsg = "Open directory/folder", - bool remember = true); - std::string askImgOrStackPath(); - - void closeEvent(QCloseEvent *event) override; - - Ui::ImggFormatsConvert m_ui; - - // path name for persistent settings - const static std::string m_settingsGroup; - - // presenter as in the model-view-presenter - std::unique_ptr<IImggFormatsConvertPresenter> m_presenter; -}; - -} // namespace CustomInterfaces -} // namespace MantidQt - -#endif // MANTIDQTCUSTOMINTERFACES_TOMOGRAPHY_IMGGFORMATSCONVERTVIEWQTWIDGET_H_ diff --git a/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/StackOfImagesDirs.h b/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/StackOfImagesDirs.h deleted file mode 100644 index 9aa221bdfcf..00000000000 --- a/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/StackOfImagesDirs.h +++ /dev/null @@ -1,102 +0,0 @@ -#ifndef MANTIDQTCUSTOMINTERFACES_TOMOGRAPHY_STACKOFIMAGESDIR_H_ -#define MANTIDQTCUSTOMINTERFACES_TOMOGRAPHY_STACKOFIMAGESDIR_H_ - -#include "MantidKernel/System.h" - -#include <string> -#include <vector> - -// forward declarations -namespace Poco { -class File; -} - -namespace MantidQt { -namespace CustomInterfaces { - -/** -Represents the structure of directories where a stack of images is -stored on disk: data/flat/dark + processed + pre_filtered, etc. - -Copyright © 2015 ISIS Rutherford Appleton Laboratory, NScD -Oak Ridge National Laboratory & European Spallation Source - -This file is part of Mantid. - -Mantid is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 3 of the License, or -(at your option) any later version. - -Mantid is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see <http://www.gnu.org/licenses/>. - -File change history is stored at: <https://github.com/mantidproject/mantid> -Code Documentation is available at: <http://doxygen.mantidproject.org> -*/ -class DLLExport StackOfImagesDirs { -public: - /// constructor from a path (to a directory) - StackOfImagesDirs(const std::string &path, bool allowSimpleLayout = true); - - /// The current (simple) concept of valid is: there at least a - /// sample/data directory with at least one file in it. - bool isValid() const { return m_valid; } - - // human readable description of the expected structure of directories - std::string description() const; - - // string that describes the status/error message about this directory - std::string status() const; - - std::string sampleImagesDir() const { return m_sampleDir; }; - std::string flatImagesDir() const { return m_flatDir; }; - std::string darkImagesDir() const { return m_darkDir; }; - - std::vector<std::string> sampleFiles() const; - std::vector<std::string> flatFiles() const; - std::vector<std::string> darkFiles() const; - -private: - /// tries to find the expected data_/dark_/flat_ directories - void findStackDirs(const std::string &path, bool allowSimpleLayout); - - /// simple version: just files (sample data) - bool findStackFilesSimple(Poco::File &dir); - - /// complex version: sample (data), flat, and dark - bool findStackDirsComplex(Poco::File &dir); - - /// finds images in a directory - std::vector<std::string> findImgFiles(const std::string &path) const; - - /// passes basic validity checks - bool m_valid; - /// string with informative messages specially when not valid - std::string m_statusDescStr; - - std::string m_sampleDir; - std::string m_flatDir; - std::string m_darkDir; - - std::string m_descr; - - static const std::string g_descrComplex; - static const std::string g_descrSimple; - static const std::string g_descrBoth; - static const std::string g_sampleNamePrefix; - static const std::string g_flatNamePrefix; - static const std::string g_darkNamePrefix; - static const std::string g_processedNamePrefix; - static const std::string g_prefilteredNamePrefix; -}; - -} // namespace CustomInterfaces -} // namespace MantidQt - -#endif // MANTIDQTCUSTOMINTERFACES_TOMOGRAPHY_STACKOFIMAGESDIR_H_ diff --git a/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomoPathsConfig.h b/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomoPathsConfig.h deleted file mode 100644 index 4c079cf53e8..00000000000 --- a/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomoPathsConfig.h +++ /dev/null @@ -1,145 +0,0 @@ -#ifndef MANTIDQTCUSTOMINTERFACES_TOMOGRAPHY_TOMOPATHSCONFIG_H_ -#define MANTIDQTCUSTOMINTERFACES_TOMOGRAPHY_TOMOPATHSCONFIG_H_ - -#include "MantidQtCustomInterfaces/DllConfig.h" -#include "MantidQtCustomInterfaces/Tomography/ToolConfigAstraToolbox.h" -#include "MantidQtCustomInterfaces/Tomography/ToolConfigCustom.h" -#include "MantidQtCustomInterfaces/Tomography/ToolConfigTomoPy.h" - -#include <string> - -namespace MantidQt { -namespace CustomInterfaces { - -/** -Represents one particular configuration of paths for tomography -jobs. These paths point to sample, open bean, flat etc. data (images) -that define where the data for a particular dataset can be found, and -that are normally required to run reconstruction tools but also pre- -and post- processing steps. - -Copyright © 2015,2016 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 MANTIDQT_CUSTOMINTERFACES_DLL TomoPathsConfig { -public: - /** - * Default constructor, makes a paths configuration which probably - * needs additional input from the user before being usable (see - * validate()). - */ - TomoPathsConfig(); - - /** - * If the result of this validation is true, that must be - * interpreted as: "this is ready to be used to run reconstruction - * or other types of tools." Answers the question: is it non-empty - * and apparently correct and usable? This will be false if it is - * not initialized or any inconsistency can be detected. - * - * @return whether this configuration seems to be ready to be used. - */ - bool validate() const; - - /** - * Path to the sample files (sample images, typically FITS files) - * - * @return path (full or relative) as a string. - */ - std::string pathSamples() const { return m_pathFITS; } - - void updatePathSamples(const std::string &p) { m_pathFITS = p; } - - /** - * Path to the open beam / flat file(s) (sample images, typically - * FITS files) Note: open bean a.k.a. 'flat' or 'white' - * - * @return path (full or relative, directory or file) as a string. - */ - std::string pathOpenBeam() const { return m_pathFlat; } - - /** - * Set a new path to open beam/flat images, and whether it is - * enabled. - * - * @param p new path string - * - * @param enable whether to effectively use the path for the - * "normalize by flats" option with the current setup - */ - void updatePathOpenBeam(const std::string &p, bool enable) { - m_pathFlat = p; - m_pathOpenBeamEnabled = enable; - } - - /** - * Path to the dark image file(s) - * - * @return path (full or relative, directory or file) as a string. - */ - std::string pathDarks() const { return m_pathDark; } - - /** - * Set a new path to dark images, and whether it is - * enabled. - * - * @param p new path string - * - * @param enable whether to effectively use the path for the - * "normalize by dark images" option with the current setup - */ - void updatePathDarks(const std::string &p, bool enable) { - m_pathDark = p; - m_pathDarkEnabled = enable; - } - - /** - * Path to a base directory (for data usually). All other paths - * could be absolute or relative to this one. - * - * @return path (full, directory) as a string. - */ - std::string pathBase() const { return m_pathBase; } - - void updatePathBase(const std::string &p) { m_pathBase = p; } - - std::string pathSavuConfig() const; - - /// Whether the flat/open beam option is enabled by the user - bool m_pathOpenBeamEnabled; - /// Whether the "use dark images" option is enabled for this setup - bool m_pathDarkEnabled; - -private: - /// file paths, base dir on scarf - std::string m_pathBase; - /// path to fits file (sample data) - std::string m_pathFITS; - /// path to flat/open beam/bright image - std::string m_pathFlat; - /// path to dark image - std::string m_pathDark; -}; - -} // namespace CustomInterfaces -} // namespace MantidQt - -#endif // MANTIDQTCUSTOMINTERFACES_TOMOGRAPHY_TOMOPATHSCONFIG_H_ diff --git a/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomoRecToolConfig.h b/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomoRecToolConfig.h deleted file mode 100644 index 485e585d3a6..00000000000 --- a/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomoRecToolConfig.h +++ /dev/null @@ -1,121 +0,0 @@ -#ifndef MANTIDQTCUSTOMINTERFACES_TOMOGRAPHY_TOMORECTOOLCONFIG_H_ -#define MANTIDQTCUSTOMINTERFACES_TOMOGRAPHY_TOMORECTOOLCONFIG_H_ - -#include <string> -#include <vector> - -namespace MantidQt { -namespace CustomInterfaces { - -/** -Configuration of a third party tomographic reconstruction tool. This -is under development, and as it is not necessarily related to custom -interfaces this class and some derived ones might be moved out of -here. - -Copyright © 2014,2015 ISIS Rutherford Appleton Laboratory, NScD -Oak Ridge National Laboratory & European Spallation Source - -This file is part of Mantid. - -Mantid is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 3 of the License, or -(at your option) any later version. - -Mantid is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see <http://www.gnu.org/licenses/>. - -File change history is stored at: <https://github.com/mantidproject/mantid> -Code Documentation is available at: <http://doxygen.mantidproject.org> -*/ - -/** - * General tomographic reconstruction tool configuration. This class - * represents the configuration (or run options/settings) of a third - * party or external tool/program/module/etc. that Mantid would run - * either locally or on a remote computer. The purpose here is to - * produce the command line or similar that will run the third party - * tool for certain user requirements/settings/options/preferences. - * - * TODO: a related class to represent third party tools should be - * added that would take care of platform specificities, tool - * availability, execute permissions, etc. - */ -class TomoRecToolConfig { -public: - /** - * Construct a config object, given a 'runnable', which can be an - * application, executable, script, etc. - the access point to a - * third party tool. If this class is developed to be smart enough, - * and with the help of the additional '3rd party tool' class, it - * should be able to translate application names into binary paths - * and similar internally. - * - * @param runnable name of the runnable object (application, executable, - * etc.). This can be a full path, an application name, etc. At - * present it is used in its simplest form: platform and machine - * dependent full path to an execuatable or script. - */ - TomoRecToolConfig(const std::string &runnable = "") : m_runnable(runnable) {} - - virtual ~TomoRecToolConfig() {} - - /** - * validate that it is possible to produce a sensible command line - * from this config object. - * - * @return the tool and its config are consistent and it looks - * like it should be possible to run it. - */ - virtual bool valid() const { return true; } - - /// A vector of tomographic reconstruction algorithms described by a - /// name-in-tool and a human-readable-name - typedef std::vector<std::pair<std::string, std::string>> TomoReconAlgs; - - virtual TomoReconAlgs algorithmsAvailable() const { return m_algs; }; - - virtual void appendOptions(std::string &opts) { - m_appendix = m_appendix + " " + opts; - }; - - /** - * Produce a command line to run this tool with this configuration. - * - * @return command line ready to run on a certain platform - */ - virtual std::string toCommand() const { - return makeExecutable() + " " + makeCmdLineOptions(); - } - - /** - * Produces a string with the command line options derived from the - * different options set. - * - * @return command line options string - */ - virtual std::string makeCmdLineOptions() const = 0; - - /** - * Produces an string that describes the executable, ready to run - * as a binary, python or other type of scripts, etc. Normally you - * append command line options to this. - */ - virtual std::string makeExecutable() const = 0; - -protected: - std::string m_runnable; - std::string m_appendix; - TomoReconAlgs m_algs; -}; - -} // namespace CustomInterfaces -} // namespace MantidQt - -#endif // MANTIDQTCUSTOMINTERFACES_TOMOGRAPHY_TOMORECTOOLCONFIG_H_ diff --git a/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomoReconFiltersSettings.h b/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomoReconFiltersSettings.h deleted file mode 100644 index 2097585aff5..00000000000 --- a/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomoReconFiltersSettings.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef MANTIDQTCUSTOMINTERFACES_TOMOGRAPHY_TOMORECONFILTERSETTINGS_H_ -#define MANTIDQTCUSTOMINTERFACES_TOMOGRAPHY_TOMORECONFILTERSETTINGS_H_ - -#include "MantidQtCustomInterfaces/Tomography/TomoReconPreprocSettings.h" -#include "MantidQtCustomInterfaces/Tomography/TomoReconPostprocSettings.h" - -#include "MantidQtCustomInterfaces/DllConfig.h" - -namespace MantidQt { -namespace CustomInterfaces { - -/** -Settings for pre-/post-/other-processing filters to run a -reconstruction jobs. Note this has been defined as general processing -steps, not tied to any particular tool. - -Copyright © 2015 ISIS Rutherford Appleton Laboratory, NScD -Oak Ridge National Laboratory & European Spallation Source - -This file is part of Mantid. - -Mantid is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 3 of the License, or -(at your option) any later version. - -Mantid is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see <http://www.gnu.org/licenses/>. - -File change history is stored at: <https://github.com/mantidproject/mantid> -Code Documentation is available at: <http://doxygen.mantidproject.org> -*/ -struct MANTIDQT_CUSTOMINTERFACES_DLL TomoReconFiltersSettings { - MantidQt::CustomInterfaces::TomoReconPreprocSettings prep; - MantidQt::CustomInterfaces::TomoReconPostprocSettings postp; - - /// whether to write pre-processed images in addition to the output - /// reconstructed volume (slices/images) - bool outputPreprocImages; - - TomoReconFiltersSettings() : prep(), postp(), outputPreprocImages(true) {} -}; - -} // namespace CustomInterfaces -} // namespace MantidQt - -#endif // MANTIDQTCUSTOMINTERFACES_TOMOGRAPHY_TOMORECONFILTERSETTINGS_H_ diff --git a/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomoReconPostprocSettings.h b/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomoReconPostprocSettings.h deleted file mode 100644 index 9fa1122258f..00000000000 --- a/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomoReconPostprocSettings.h +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef MANTIDQTCUSTOMINTERFACES_TOMOGRAPHY_TOMORECONPOSTPROCSETTINGS_H_ -#define MANTIDQTCUSTOMINTERFACES_TOMOGRAPHY_TOMORECONPOSTPROCSETTINGS_H_ - -#include "MantidQtCustomInterfaces/DllConfig.h" - -namespace MantidQt { -namespace CustomInterfaces { - -/** -Settings for post-processing a reconstructed volume. -Note this is in principle not tied to any particular tool. - -Copyright © 2015 ISIS Rutherford Appleton Laboratory, NScD -Oak Ridge National Laboratory & European Spallation Source - -This file is part of Mantid. - -Mantid is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 3 of the License, or -(at your option) any later version. - -Mantid is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see <http://www.gnu.org/licenses/>. - -File change history is stored at: <https://github.com/mantidproject/mantid> -Code Documentation is available at: <http://doxygen.mantidproject.org> -*/ -struct MANTIDQT_CUSTOMINTERFACES_DLL TomoReconPostprocSettings { - double circMaskRadius; - double cutOffLevel; - - TomoReconPostprocSettings(); -}; - -} // namespace CustomInterfaces -} // namespace MantidQt - -#endif // MANTIDQTCUSTOMINTERFACES_TOMOGRAPHY_TOMORECONPOSTPROCSETTINGS_H_ diff --git a/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomoReconPreprocSettings.h b/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomoReconPreprocSettings.h deleted file mode 100644 index f201d2c76d0..00000000000 --- a/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomoReconPreprocSettings.h +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef MANTIDQTCUSTOMINTERFACES_TOMOGRAPHY_TOMORECONPREPROCSETTINGS_H_ -#define MANTIDQTCUSTOMINTERFACES_TOMOGRAPHY_TOMORECONPREPROCSETTINGS_H_ - -#include "MantidQtCustomInterfaces/DllConfig.h" - -#include <cstddef> - -namespace MantidQt { -namespace CustomInterfaces { - -/** -Settings for pre-processing of the raw input images before -reconstructing a volume. Note this is in principle not tied to any -particular tool. - -Copyright © 2015,2016 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> -*/ -struct MANTIDQT_CUSTOMINTERFACES_DLL TomoReconPreprocSettings { - bool normalizeByAirRegion; - bool normalizeByProtonCharge; - bool normalizeByFlats; - bool normalizeByDarks; - - // block-size in pixels - size_t medianFilterWidth; - // rotation to correct raw images, in degrees. Only multiples of 90 - int rotation; - // maximum angle, in degrees - double maxAngle; - // block size in pixels - size_t scaleDownFactor; - - TomoReconPreprocSettings(); -}; - -} // namespace CustomInterfaces -} // namespace MantidQt - -#endif // MANTIDQTCUSTOMINTERFACES_TOMOGRAPHY_TOMORECONPREPROCSETTINGS_H_ diff --git a/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomoReconToolsUserSettings.h b/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomoReconToolsUserSettings.h deleted file mode 100644 index 4466cad265e..00000000000 --- a/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomoReconToolsUserSettings.h +++ /dev/null @@ -1,55 +0,0 @@ -#ifndef MANTIDQTCUSTOMINTERFACES_TOMOGRAPHY_TOMORECONTOOLSUSERSETTINGS_H_ -#define MANTIDQTCUSTOMINTERFACES_TOMOGRAPHY_TOMORECONTOOLSUSERSETTINGS_H_ - -#include "MantidQtCustomInterfaces/Tomography/ToolConfigAstraToolbox.h" -#include "MantidQtCustomInterfaces/Tomography/ToolConfigCustom.h" -#include "MantidQtCustomInterfaces/Tomography/ToolConfigTomoPy.h" - -#include <string> - -namespace MantidQt { -namespace CustomInterfaces { - -/** -Settings for a set of tomographic reconstruction tools supported. - -Copyright © 2014,2015 ISIS Rutherford Appleton Laboratory, NScD -Oak Ridge National Laboratory & European Spallation Source - -This file is part of Mantid. - -Mantid is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 3 of the License, or -(at your option) any later version. - -Mantid is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see <http://www.gnu.org/licenses/>. - -File change history is stored at: <https://github.com/mantidproject/mantid> -Code Documentation is available at: <http://doxygen.mantidproject.org> -*/ -struct TomoReconToolsUserSettings { - // This is just too basic at the moment. We probably want to store - // here the real settings objects for all the tools, and rather than - // this horror have a dictionary of tools-settings or - // similar. Waiting to see what happens with Savu and others. - MantidQt::CustomInterfaces::ToolConfigTomoPy tomoPy; - MantidQt::CustomInterfaces::ToolConfigAstraToolbox astra; - MantidQt::CustomInterfaces::ToolConfigCustom custom; - - // savu not ready - std::string savu; - // CCPi not ready - std::string CCPi; -}; - -} // namespace CustomInterfaces -} // namespace MantidQt - -#endif // MANTIDQTCUSTOMINTERFACES_TOMOGRAPHY_TOMORECONTOOLSUSERSETTINGS_H_ diff --git a/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomoSystemSettings.h b/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomoSystemSettings.h deleted file mode 100644 index ee1ce8ecf66..00000000000 --- a/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomoSystemSettings.h +++ /dev/null @@ -1,75 +0,0 @@ -#ifndef MANTIDQTCUSTOMINTERFACES_TOMOGRAPHY_TOMOSYSTEMSETTINGS_H_ -#define MANTIDQTCUSTOMINTERFACES_TOMOGRAPHY_TOMOSYSTEMSETTINGS_H_ - -#include "MantidQtCustomInterfaces/Tomography/TomoSystemSettingsLocal.h" -#include "MantidQtCustomInterfaces/Tomography/TomoSystemSettingsRemote.h" - -#include "MantidQtCustomInterfaces/DllConfig.h" - -#include <string> -#include <vector> - -namespace MantidQt { -namespace CustomInterfaces { - -/** -Settings for the paths on the local and remote machines, path -components, and related parameters. Most of these options could be -hardcoded but it is convenient to be able to manipulate them, for -flexibility and for testing purposes. Consists of "local" and "remote" -parameters as well as other parameters that are global. - -Copyright © 2016 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> -*/ -struct MANTIDQT_CUSTOMINTERFACES_DLL TomoSystemSettings { - // TODO use dictionary(es) for the string settings when they settle down - TomoSystemSettingsLocal m_local; - TomoSystemSettingsRemote m_remote; - - std::vector<std::string> m_pathComponents; - - std::string m_samplesDirPrefix; - std::string m_flatsDirPrefix; - std::string m_darksDirPrefix; - - /// path component for the pre-processed file (outputs) - std::string m_outputPathCompPreProcessed; - /// path component for the reconstructed files (outputs) - std::string m_outputPathCompReconst; - - /// experiment reference from the Run tab - std::string m_experimentReference; - - static const std::string g_defSamplesDirPrefix; - static const std::string g_defFlatsDirPrefix; - static const std::string g_defDarksDirPrefix; - - static const std::string g_defOutputPathCompPreProcessed; - static const std::string g_defOutputPathCompReconst; - - TomoSystemSettings(); -}; - -} // namespace CustomInterfaces -} // namespace MantidQt - -#endif // MANTIDQTCUSTOMINTERFACES_TOMOGRAPHY_TOMOSYSTEMSETTINGS_H_ diff --git a/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomoSystemSettingsLocal.h b/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomoSystemSettingsLocal.h deleted file mode 100644 index 9842f517f93..00000000000 --- a/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomoSystemSettingsLocal.h +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef MANTIDQTCUSTOMINTERFACES_TOMOGRAPHY_TOMOSYSTEMSETTINGSLOCAL_H_ -#define MANTIDQTCUSTOMINTERFACES_TOMOGRAPHY_TOMOSYSTEMSETTINGSLOCAL_H_ - -#include "MantidQtCustomInterfaces/DllConfig.h" - -#include <string> - -namespace MantidQt { -namespace CustomInterfaces { - -/** -Settings for the paths and other parameters on the local machine. Most -of these options could be hardcoded but it is convenient to be able to -manipulate them, for flexibility and for testing/commissioning. - -Copyright © 2016 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> -*/ -struct MANTIDQT_CUSTOMINTERFACES_DLL TomoSystemSettingsLocal { - std::string m_basePathTomoData; - std::string m_remoteDriveOrMountPoint; - - std::string m_reconScriptsPath; - std::string m_externalInterpreterPath; - - int m_processes; - int m_cores; - - static const std::string g_defBasePathTomoData; - static const std::string g_defRemoteDriveOrMountPoint; - static const std::string g_defReconScriptsPath; - static const std::string g_defExternalInterpreterPath; - - TomoSystemSettingsLocal(); -}; - -} // namespace CustomInterfaces -} // namespace MantidQt - -#endif // MANTIDQTCUSTOMINTERFACES_TOMOGRAPHY_TOMOSYSTEMSETTINGSLOCAL_H_ diff --git a/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomoSystemSettingsRemote.h b/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomoSystemSettingsRemote.h deleted file mode 100644 index d86778deb7e..00000000000 --- a/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomoSystemSettingsRemote.h +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef MANTIDQTCUSTOMINTERFACES_TOMOGRAPHY_TOMOSYSTEMSETTINGSREMOTE_H_ -#define MANTIDQTCUSTOMINTERFACES_TOMOGRAPHY_TOMOSYSTEMSETTINGSREMOTE_H_ - -#include "MantidQtCustomInterfaces/DllConfig.h" - -#include <string> - -namespace MantidQt { -namespace CustomInterfaces { - -/** -Settings for the paths and other parameters on the remote -machine/compute resource/cluster. Some of these options could be -hardcoded but it is convenient to be able to manipulate them, for -flexibility and for testing/commissioning. - -Copyright © 2016 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> -*/ -struct MANTIDQT_CUSTOMINTERFACES_DLL TomoSystemSettingsRemote { - std::string m_basePathTomoData; - std::string m_basePathReconScripts; - int m_nodes; - int m_cores; - - static const std::string g_defBasePathTomoData; - static const std::string g_defBasePathReconScripts; - - TomoSystemSettingsRemote(); -}; - -} // namespace CustomInterfaces -} // namespace MantidQt - -#endif // MANTIDQTCUSTOMINTERFACES_TOMOGRAPHY_TOMOSYSTEMSETTINGSREMOTE_H_ diff --git a/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomoToolConfigAstra.ui b/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomoToolConfigAstra.ui deleted file mode 100644 index 6a279bfe7ca..00000000000 --- a/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomoToolConfigAstra.ui +++ /dev/null @@ -1,206 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<ui version="4.0"> - <class>TomoToolConfigAstra</class> - <widget class="QDialog" name="TomoToolConfigAstra"> - <property name="windowModality"> - <enum>Qt::WindowModal</enum> - </property> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>545</width> - <height>179</height> - </rect> - </property> - <property name="windowTitle"> - <string>Astra Toolbox Configuration</string> - </property> - <layout class="QVBoxLayout" name="verticalLayout"> - <item> - <layout class="QHBoxLayout" name="horizontalLayout_2"> - <item> - <widget class="QLabel" name="label_method"> - <property name="text"> - <string>Method:</string> - </property> - </widget> - </item> - <item> - <widget class="QComboBox" name="comboBox_method"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> - <horstretch>1</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <item> - <property name="text"> - <string>FBP: filtered back propagation</string> - </property> - </item> - <item> - <property name="text"> - <string>SIRT: statistical image reconstruction</string> - </property> - </item> - </widget> - </item> - </layout> - </item> - <item> - <widget class="QGroupBox" name="groupBox"> - <property name="title"> - <string>Advanced options</string> - </property> - <property name="checkable"> - <bool>true</bool> - </property> - <property name="checked"> - <bool>false</bool> - </property> - <layout class="QGridLayout" name="gridLayout"> - <item row="0" column="0"> - <widget class="QLabel" name="label_iter"> - <property name="text"> - <string>Iterations:</string> - </property> - </widget> - </item> - <item row="0" column="1"> - <widget class="QSpinBox" name="spinBox_iter"> - <property name="minimum"> - <number>1</number> - </property> - <property name="maximum"> - <number>999</number> - </property> - <property name="value"> - <number>5</number> - </property> - </widget> - </item> - <item row="0" column="2" colspan="2"> - <spacer name="horizontalSpacer_4"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>178</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item row="1" column="0"> - <widget class="QLabel" name="label_cli_options"> - <property name="text"> - <string>Regularization:</string> - </property> - </widget> - </item> - <item row="1" column="1" colspan="2"> - <widget class="QDoubleSpinBox" name="doubleSpinBox_regularization"> - <property name="decimals"> - <number>5</number> - </property> - <property name="maximum"> - <double>180.000000000000000</double> - </property> - </widget> - </item> - <item row="1" column="3"> - <spacer name="horizontalSpacer_5"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>305</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - </layout> - </widget> - </item> - <item> - <spacer name="verticalSpacer"> - <property name="orientation"> - <enum>Qt::Vertical</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>20</width> - <height>0</height> - </size> - </property> - </spacer> - </item> - <item> - <layout class="QHBoxLayout" name="horizontalLayout"> - <item> - <spacer name="horizontalSpacer"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>178</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item> - <widget class="QDialogButtonBox" name="buttonBox"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="standardButtons"> - <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> - </property> - </widget> - </item> - </layout> - </item> - </layout> - </widget> - <resources/> - <connections> - <connection> - <sender>buttonBox</sender> - <signal>accepted()</signal> - <receiver>TomoToolConfigAstra</receiver> - <slot>accept()</slot> - <hints> - <hint type="sourcelabel"> - <x>248</x> - <y>254</y> - </hint> - <hint type="destinationlabel"> - <x>157</x> - <y>274</y> - </hint> - </hints> - </connection> - <connection> - <sender>buttonBox</sender> - <signal>rejected()</signal> - <receiver>TomoToolConfigAstra</receiver> - <slot>reject()</slot> - <hints> - <hint type="sourcelabel"> - <x>316</x> - <y>260</y> - </hint> - <hint type="destinationlabel"> - <x>286</x> - <y>274</y> - </hint> - </hints> - </connection> - </connections> -</ui> diff --git a/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomoToolConfigCustom.ui b/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomoToolConfigCustom.ui deleted file mode 100644 index def36df933b..00000000000 --- a/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomoToolConfigCustom.ui +++ /dev/null @@ -1,135 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<ui version="4.0"> - <class>TomoToolConfigCustom</class> - <widget class="QDialog" name="TomoToolConfigCustom"> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>802</width> - <height>278</height> - </rect> - </property> - <property name="windowTitle"> - <string>Custom tool configuration</string> - </property> - <layout class="QGridLayout" name="gridLayout_2"> - <item row="0" column="0"> - <layout class="QGridLayout" name="gridLayout"> - <item row="0" column="0"> - <widget class="QLabel" name="label_runnable"> - <property name="text"> - <string>Runnable:</string> - </property> - </widget> - </item> - <item row="0" column="2"> - <widget class="QLineEdit" name="lineEdit_runnable"> - <property name="toolTip"> - <string>Script or binary that can run on the remote environment</string> - </property> - <property name="text"> - <string>/work/imat/phase_commissioning/scripts/Imaging/IMAT/tomo_reconstruct.py</string> - </property> - </widget> - </item> - <item row="1" column="0" colspan="2"> - <widget class="QLabel" name="label_cli_options"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="text"> - <string>Command line options:</string> - </property> - </widget> - </item> - <item row="1" column="2"> - <widget class="QTextEdit" name="textEdit_cl_opts"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Minimum" vsizetype="Fixed"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="toolTip"> - <string>Command line options to the script or binary</string> - </property> - <property name="html"> - <string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">--help</p></body></html></string> - </property> - </widget> - </item> - <item row="2" column="1" colspan="2"> - <layout class="QVBoxLayout" name="verticalLayout"> - <item> - <spacer name="verticalSpacer"> - <property name="orientation"> - <enum>Qt::Vertical</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>20</width> - <height>17</height> - </size> - </property> - </spacer> - </item> - <item> - <widget class="QDialogButtonBox" name="buttonBox"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="standardButtons"> - <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> - </property> - </widget> - </item> - </layout> - </item> - </layout> - </item> - </layout> - </widget> - <resources/> - <connections> - <connection> - <sender>buttonBox</sender> - <signal>accepted()</signal> - <receiver>TomoToolConfigCustom</receiver> - <slot>accept()</slot> - <hints> - <hint type="sourcelabel"> - <x>248</x> - <y>254</y> - </hint> - <hint type="destinationlabel"> - <x>157</x> - <y>274</y> - </hint> - </hints> - </connection> - <connection> - <sender>buttonBox</sender> - <signal>rejected()</signal> - <receiver>TomoToolConfigCustom</receiver> - <slot>reject()</slot> - <hints> - <hint type="sourcelabel"> - <x>316</x> - <y>260</y> - </hint> - <hint type="destinationlabel"> - <x>286</x> - <y>274</y> - </hint> - </hints> - </connection> - </connections> -</ui> diff --git a/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomoToolConfigDialogAstra.h b/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomoToolConfigDialogAstra.h deleted file mode 100644 index 34fa4233bd4..00000000000 --- a/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomoToolConfigDialogAstra.h +++ /dev/null @@ -1,38 +0,0 @@ -#ifndef MANTIDQTCUSTOMINTERFACES_TOMOTOOLCONFIGDIALOGASTRA_H_ -#define MANTIDQTCUSTOMINTERFACES_TOMOTOOLCONFIGDIALOGASTRA_H_ - -#include "ui_TomoToolConfigAstra.h" -#include "MantidQtCustomInterfaces/Tomography/TomoToolConfigDialogBase.h" - -namespace MantidQt { -namespace CustomInterfaces { -class TomoToolConfigDialogAstra : public TomoToolConfigDialogBase { -public: - TomoToolConfigDialogAstra() - : TomoToolConfigDialogBase(DEFAULT_TOOL_NAME, DEFAULT_TOOL_METHOD) {} - - ~TomoToolConfigDialogAstra() override { - if (m_dialog) { - delete m_dialog; - } - } - -private: - void initialiseDialog() override; - void setupMethodSelected() override; - void setupToolSettingsFromPaths() override; - void setupDialogUi() override; - int executeQt() override; - std::vector<std::pair<std::string, std::string>> getToolMethods() override; - - // initialised in .cpp file - static const std::string DEFAULT_TOOL_NAME; - static const std::string DEFAULT_TOOL_METHOD; - - QDialog *m_dialog = nullptr; - Ui::TomoToolConfigAstra m_astraUi; -}; - -} // CustomInterfaces -} // MantidQt -#endif // MANTIDQTCUSTOMINTERFACES_TOMOTOOLCONFIGDIALOGASTRA_H_ diff --git a/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomoToolConfigDialogBase.h b/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomoToolConfigDialogBase.h deleted file mode 100644 index 4933973efc7..00000000000 --- a/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomoToolConfigDialogBase.h +++ /dev/null @@ -1,153 +0,0 @@ -#ifndef MANTIDQTCUSTOMINTERFACES_TOMOTOOLCONFIGDIALOGBASE_H_ -#define MANTIDQTCUSTOMINTERFACES_TOMOTOOLCONFIGDIALOGBASE_H_ - -#include "MantidQtCustomInterfaces/Tomography/TomoPathsConfig.h" -#include "MantidQtCustomInterfaces/Tomography/TomoReconToolsUserSettings.h" - -#include <memory> - -namespace MantidQt { -namespace CustomInterfaces { - -/** -Third party tool configuration dialog(s) for the tomographic reconstruction -GUI. - -Copyright © 2014,2015 ISIS Rutherford Appleton Laboratory, NScD -Oak Ridge National Laboratory & European Spallation Source - -This file is part of Mantid. - -Mantid is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 3 of the License, or -(at your option) any later version. - -Mantid is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see <http://www.gnu.org/licenses/>. - -File change history is stored at: <https://github.com/mantidproject/mantid> -Code Documentation is available at: <http://doxygen.mantidproject.org> -*/ -class TomoToolConfigDialogBase { -public: - TomoToolConfigDialogBase(const std::string toolName = "", - const std::string toolMethod = "") - : m_toolName(toolName), m_toolMethod(toolMethod), m_isInitialised(false) { - } - virtual ~TomoToolConfigDialogBase() {} - - /// public static function accessor to create dialogues - static std::unique_ptr<TomoToolConfigDialogBase> - getToolDialogFor(const std::string &toolName); - - /// Sets up the dialogue settings, but does not initialise a QDialog - void setupDialog(const std::string &runPath, const TomoPathsConfig &paths, - const std::string &pathOut, - const std::string &localOutNameAppendix) { - - setupPaths(runPath, paths, pathOut, localOutNameAppendix); - setupToolSettingsFromPaths(); - } - - /// initialises a QDialog and handles the returns - virtual int initialiseGUIandExecute() { - if (!isInitialised()) { - // set up the tool's method on the first run - // this prevents from creating and destroying many dialogues if the user - // decides to scroll quickly, and the dialogue is only initialised if the - // user clicks the "Setup" button. If the tool is not setup the default - // settings will be provided if the user clicks Reconstruct - initialiseDialog(); - setupDialogUi(); - setupMethodSelected(); - - m_isInitialised = true; - } - - const int res = this->executeQt(); - this->handleDialogResult(res); - return res; - } - - virtual bool isInitialised() const { return m_isInitialised; } - - std::string getSelectedToolMethod() const { return m_toolMethod; } - - /// return pointer and transfer ownership - std::shared_ptr<TomoRecToolConfig> getSelectedToolSettings() const { - return m_toolSettings; - } - - std::string getSelectedToolName() const { return m_toolName; } - -protected: - virtual void initialiseDialog() = 0; - - virtual void handleDialogResult(const int result); - - virtual void setScriptRunPath(const std::string run) { m_runPath = run; } - - virtual void setTomoPathsConfig(const TomoPathsConfig paths) { - m_paths = paths; - } - - virtual void setPathOut(const std::string pathOut) { m_pathOut = pathOut; } - - virtual void setLocalOutNameAppendix(const std::string localOutNameAppendix) { - m_localOutNameAppendix = localOutNameAppendix; - } - - virtual void setupPaths(const std::string &runPath, - const TomoPathsConfig &paths, - const std::string &pathOut, - const std::string &localOutNameAppendix) { - this->setScriptRunPath(runPath); - this->setTomoPathsConfig(paths); - this->setPathOut(pathOut); - this->setLocalOutNameAppendix(localOutNameAppendix); - } - - virtual void setupDialogUi() = 0; - - /// setup the selected method member variable - virtual void setupMethodSelected() = 0; - - /// setup the tool config with the correct paths, must be called after the - /// paths have been set! - virtual void setupToolSettingsFromPaths() = 0; - - /// provided virtual function to add Qt execute behaviour as necessary - virtual int executeQt() = 0; // this class doesn't inherit from Qt and doesnt - // have this->exec() - - // empty function body as not all tools have methods - virtual std::vector<std::pair<std::string, std::string>> getToolMethods() { - return {}; - } - - std::shared_ptr<TomoRecToolConfig> m_toolSettings; - - const std::string m_toolName; - - std::string m_toolMethod; - - std::string m_runPath; - - std::string m_localOutNameAppendix; - - std::string m_pathOut; - - TomoPathsConfig m_paths; - - bool m_isInitialised; -}; -} -} - -#endif // MANTIDQTCUSTOMINTERFACES_TOMOTOOLCONFIGDIALOGBASE_H_ diff --git a/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomoToolConfigDialogCustom.h b/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomoToolConfigDialogCustom.h deleted file mode 100644 index 98f493470a0..00000000000 --- a/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomoToolConfigDialogCustom.h +++ /dev/null @@ -1,37 +0,0 @@ -#ifndef MANTIDQTCUSTOMINTERFACES_TOMOTOOLCONFIGDIALOGCUSTOM_H_ -#define MANTIDQTCUSTOMINTERFACES_TOMOTOOLCONFIGDIALOGCUSTOM_H_ - -#include "ui_TomoToolConfigCustom.h" -#include "MantidQtCustomInterfaces/Tomography/TomoToolConfigDialogBase.h" - -namespace MantidQt { -namespace CustomInterfaces { -class TomoToolConfigDialogCustom : public TomoToolConfigDialogBase { -public: - TomoToolConfigDialogCustom() - : TomoToolConfigDialogBase(DEFAULT_TOOL_NAME, DEFAULT_TOOL_METHOD) {} - ~TomoToolConfigDialogCustom() override { - if (m_dialog) { - delete m_dialog; - } - } - -private: - void initialiseDialog() override; - void setupMethodSelected() override; - void setupToolSettingsFromPaths() override; - void setupDialogUi() override; - void handleDialogResult(int result) override; - int executeQt() override; - - // initialised in .cpp file - static const std::string DEFAULT_TOOL_NAME; - static const std::string DEFAULT_TOOL_METHOD; - static std::string m_backupCommandLine; - - QDialog *m_dialog = nullptr; - Ui::TomoToolConfigCustom m_customUi; -}; -} // CustomInterfaces -} // MantidQt -#endif // MANTIDQTCUSTOMINTERFACES_TOMOTOOLCONFIGDIALOGCUSTOM_H_ diff --git a/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomoToolConfigDialogSavu.h b/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomoToolConfigDialogSavu.h deleted file mode 100644 index fc6f242f538..00000000000 --- a/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomoToolConfigDialogSavu.h +++ /dev/null @@ -1,71 +0,0 @@ -#ifndef MANTIDQTCUSTOMINTERFACES_TOMOTOOLCONFIGDIALOGSAVU_H_ -#define MANTIDQTCUSTOMINTERFACES_TOMOTOOLCONFIGDIALOGSAVU_H_ - -#include "ui_TomoToolConfigSavu.h" -#include "MantidQtCustomInterfaces/Tomography/TomoToolConfigDialogBase.h" -#include <MantidAPI/ITableWorkspace.h> - -namespace Mantid { -namespace API { -class TableRow; -} -} - -namespace MantidQt { -namespace CustomInterfaces { -class TomoToolConfigDialogSavu : public QMainWindow, - public TomoToolConfigDialogBase { - Q_OBJECT -public: - TomoToolConfigDialogSavu(QWidget *parent = 0); - -private: - void setupMethodSelected() override; - void setupToolSettingsFromPaths() override; - void setupDialogUi() override; - void initialiseDialog() override; - int executeQt() override; - - void initSavuWindow(); - void loadAvailablePlugins(); - void refreshAvailablePluginListUI(); - void refreshCurrentPluginListUI(); - void availablePluginSelected(); - - void createPluginTreeEntry(Mantid::API::TableRow &row); - void createPluginTreeEntries(Mantid::API::ITableWorkspace_sptr table); - void paramValModified(QTreeWidgetItem *item, int /*column*/); - void currentPluginSelected(); - std::string paramValStringFromArray(const Json::Value &jsonVal, - const std::string &name); - - std::string pluginParamValString(const Json::Value &jsonVal, - const std::string &name); - - void loadSavuTomoConfig(std::string &filePath, - Mantid::API::ITableWorkspace_sptr ¤tPlugins); - void moveUpClicked(); - void moveDownClicked(); - void removeClicked(); - void menuOpenClicked(); - void menuSaveClicked(); - void menuSaveAsClicked(); - QString tableWSRowToString(Mantid::API::ITableWorkspace_sptr table, size_t i); - void expandedItem(QTreeWidgetItem *item); - void transferClicked(); - std::string createUniqueNameHidden(); - - void userWarning(const std::string &err, const std::string &description); - void userError(const std::string &err, const std::string &description); - - static size_t g_nameSeqNo; - - Ui::TomoToolConfigSavu m_savuUi; - Mantid::API::ITableWorkspace_sptr m_availPlugins; - Mantid::API::ITableWorkspace_sptr m_currPlugins; - std::string m_currentParamPath; -}; - -} // CustomInterfaces -} // MantidQt -#endif // MANTIDQTCUSTOMINTERFACES_TOMOTOOLCONFIGDIALOGSAVU_H_ diff --git a/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomoToolConfigDialogTomoPy.h b/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomoToolConfigDialogTomoPy.h deleted file mode 100644 index bdd5b63e3aa..00000000000 --- a/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomoToolConfigDialogTomoPy.h +++ /dev/null @@ -1,37 +0,0 @@ -#ifndef MANTIDQTCUSTOMINTERFACES_TOMOTOOLCONFIGDIALOGTOMOPY_H_ -#define MANTIDQTCUSTOMINTERFACES_TOMOTOOLCONFIGDIALOGTOMOPY_H_ - -#include "ui_TomoToolConfigTomoPy.h" -#include "MantidQtCustomInterfaces/Tomography/TomoToolConfigDialogBase.h" - -namespace MantidQt { -namespace CustomInterfaces { -class TomoToolConfigDialogTomoPy : public TomoToolConfigDialogBase { - -public: - TomoToolConfigDialogTomoPy() - : TomoToolConfigDialogBase(DEFAULT_TOOL_NAME, DEFAULT_TOOL_METHOD) {} - - ~TomoToolConfigDialogTomoPy() override { - if (m_dialog) { - delete m_dialog; - } - } - -private: - void initialiseDialog() override; - void setupMethodSelected() override; - void setupToolSettingsFromPaths() override; - void setupDialogUi() override; - int executeQt() override; - std::vector<std::pair<std::string, std::string>> getToolMethods() override; - // initialised in .cpp file - static const std::string DEFAULT_TOOL_NAME; - static const std::string DEFAULT_TOOL_METHOD; - - QDialog *m_dialog = nullptr; - Ui::TomoToolConfigTomoPy m_tomoPyUi; -}; -} // CustomInterfaces -} // MantidQt -#endif // MANTIDQTCUSTOMINTERFACES_TOMOTOOLCONFIGDIALOGTOMOPY_H_ diff --git a/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomoToolConfigSavu.ui b/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomoToolConfigSavu.ui deleted file mode 100644 index 633f346ec3f..00000000000 --- a/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomoToolConfigSavu.ui +++ /dev/null @@ -1,392 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<ui version="4.0"> - <class>TomoToolConfigSavu</class> - <widget class="QMainWindow" name="MainWindow"> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>800</width> - <height>600</height> - </rect> - </property> - <property name="windowTitle"> - <string>Savu configuration</string> - </property> - <widget class="QWidget" name="savuConfigCentralWidget"> - <layout class="QGridLayout" name="gridLayout"> - <item row="0" column="0"> - <layout class="QVBoxLayout" name="verticalLayout"> - <item> - <layout class="QVBoxLayout" name="verticalLayout_2"> - <item> - <widget class="QMenuBar" name="menubar_2"> - <property name="maximumSize"> - <size> - <width>16777215</width> - <height>21</height> - </size> - </property> - <widget class="QMenu" name="menuFile"> - <property name="title"> - <string>File</string> - </property> - <addaction name="separator"/> - </widget> - <addaction name="menuFile"/> - </widget> - </item> - <item> - <widget class="QFrame" name="frame_2"> - <property name="frameShape"> - <enum>QFrame::Box</enum> - </property> - <property name="frameShadow"> - <enum>QFrame::Raised</enum> - </property> - <layout class="QVBoxLayout" name="verticalLayout_3"> - <property name="margin"> - <number>0</number> - </property> - <item> - <widget class="QSplitter" name="splitterPlugins"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <widget class="QFrame" name="frame_3"> - <property name="frameShape"> - <enum>QFrame::Box</enum> - </property> - <property name="frameShadow"> - <enum>QFrame::Raised</enum> - </property> - <layout class="QVBoxLayout" name="verticalLayout_4"> - <item> - <widget class="QFrame" name="pluginBar"> - <property name="minimumSize"> - <size> - <width>0</width> - <height>32</height> - </size> - </property> - <property name="maximumSize"> - <size> - <width>16777215</width> - <height>32</height> - </size> - </property> - <property name="baseSize"> - <size> - <width>0</width> - <height>32</height> - </size> - </property> - <property name="frameShape"> - <enum>QFrame::NoFrame</enum> - </property> - <property name="frameShadow"> - <enum>QFrame::Raised</enum> - </property> - <layout class="QHBoxLayout" name="horizontalLayout_2"> - <property name="margin"> - <number>0</number> - </property> - <item> - <widget class="QLabel" name="lblFilename"> - <property name="font"> - <font> - <pointsize>10</pointsize> - </font> - </property> - <property name="text"> - <string>Available Plugins:</string> - </property> - </widget> - </item> - <item> - <spacer name="horizontalSpacer"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>284</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item> - <widget class="QPushButton" name="btnTransfer"> - <property name="font"> - <font> - <pointsize>26</pointsize> - <weight>75</weight> - <bold>true</bold> - </font> - </property> - <property name="text"> - <string>→</string> - </property> - <property name="autoDefault"> - <bool>false</bool> - </property> - <property name="default"> - <bool>false</bool> - </property> - <property name="flat"> - <bool>true</bool> - </property> - </widget> - </item> - </layout> - </widget> - </item> - <item> - <widget class="QListWidget" name="listAvailablePlugins"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>0</horstretch> - <verstretch>3</verstretch> - </sizepolicy> - </property> - </widget> - </item> - <item> - <widget class="QTextBrowser" name="availablePluginDesc"> - <property name="maximumSize"> - <size> - <width>16777215</width> - <height>120</height> - </size> - </property> - <property name="baseSize"> - <size> - <width>0</width> - <height>120</height> - </size> - </property> - </widget> - </item> - </layout> - </widget> - <widget class="QFrame" name="frame_4"> - <property name="frameShape"> - <enum>QFrame::Box</enum> - </property> - <property name="frameShadow"> - <enum>QFrame::Raised</enum> - </property> - <layout class="QVBoxLayout" name="verticalLayout_5"> - <item> - <widget class="QFrame" name="currentBar"> - <property name="minimumSize"> - <size> - <width>0</width> - <height>32</height> - </size> - </property> - <property name="maximumSize"> - <size> - <width>16777215</width> - <height>32</height> - </size> - </property> - <property name="baseSize"> - <size> - <width>0</width> - <height>32</height> - </size> - </property> - <property name="frameShape"> - <enum>QFrame::NoFrame</enum> - </property> - <property name="frameShadow"> - <enum>QFrame::Raised</enum> - </property> - <layout class="QHBoxLayout" name="horizontalLayout_3"> - <property name="margin"> - <number>0</number> - </property> - <item> - <widget class="QLabel" name="label"> - <property name="font"> - <font> - <pointsize>10</pointsize> - </font> - </property> - <property name="text"> - <string>Current configuration</string> - </property> - </widget> - </item> - <item> - <spacer name="horizontalSpacer_2"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>239</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item> - <widget class="QPushButton" name="btnMoveUp"> - <property name="maximumSize"> - <size> - <width>45</width> - <height>16777215</height> - </size> - </property> - <property name="font"> - <font> - <pointsize>18</pointsize> - <weight>75</weight> - <italic>false</italic> - <bold>true</bold> - </font> - </property> - <property name="text"> - <string>â–²</string> - </property> - <property name="flat"> - <bool>true</bool> - </property> - </widget> - </item> - <item> - <widget class="QPushButton" name="btnMoveDown"> - <property name="maximumSize"> - <size> - <width>45</width> - <height>16777215</height> - </size> - </property> - <property name="font"> - <font> - <pointsize>18</pointsize> - <weight>75</weight> - <italic>false</italic> - <bold>true</bold> - </font> - </property> - <property name="text"> - <string>â–¼</string> - </property> - <property name="flat"> - <bool>true</bool> - </property> - </widget> - </item> - <item> - <widget class="QPushButton" name="btnRemove"> - <property name="maximumSize"> - <size> - <width>45</width> - <height>16777215</height> - </size> - </property> - <property name="font"> - <font> - <pointsize>16</pointsize> - <weight>75</weight> - <bold>true</bold> - </font> - </property> - <property name="text"> - <string>X</string> - </property> - <property name="flat"> - <bool>true</bool> - </property> - </widget> - </item> - </layout> - </widget> - </item> - <item> - <widget class="QTreeWidget" name="treeCurrentPlugins"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>1</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="toolTip"> - <string>Here you can modify the parameters of the plugins. -Double-click on them to modify their values.</string> - </property> - <column> - <property name="text"> - <string notr="true">1</string> - </property> - </column> - </widget> - </item> - <item> - <widget class="QTextBrowser" name="currentPluginDesc"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>1</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="maximumSize"> - <size> - <width>16777215</width> - <height>120</height> - </size> - </property> - </widget> - </item> - </layout> - </widget> - </widget> - </item> - </layout> - </widget> - </item> - </layout> - </item> - <item> - <layout class="QHBoxLayout" name="horizontalLayout"> - <item> - <widget class="QPushButton" name="pushButton_Help"> - <property name="maximumSize"> - <size> - <width>23</width> - <height>23</height> - </size> - </property> - <property name="text"> - <string>?</string> - </property> - </widget> - </item> - <item> - <spacer name="horizontalSpacer_3"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>728</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - </layout> - </item> - </layout> - </item> - </layout> - </widget> - <widget class="QStatusBar" name="statusbar"/> - </widget> - <resources/> - <connections/> -</ui> diff --git a/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomoToolConfigTomoPy.ui b/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomoToolConfigTomoPy.ui deleted file mode 100644 index c285f5b3791..00000000000 --- a/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomoToolConfigTomoPy.ui +++ /dev/null @@ -1,210 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<ui version="4.0"> - <class>TomoToolConfigTomoPy</class> - <widget class="QDialog" name="TomoToolConfigTomoPy"> - <property name="windowModality"> - <enum>Qt::WindowModal</enum> - </property> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>547</width> - <height>177</height> - </rect> - </property> - <property name="windowTitle"> - <string>TomoPy Configuration</string> - </property> - <layout class="QVBoxLayout" name="verticalLayout"> - <item> - <layout class="QHBoxLayout" name="horizontalLayout_2"> - <item> - <widget class="QLabel" name="label"> - <property name="text"> - <string>Method:</string> - </property> - </widget> - </item> - <item> - <widget class="QComboBox" name="comboBox_method"> - <item> - <property name="text"> - <string>gridrec: Fourier grid reconstruction</string> - </property> - </item> - <item> - <property name="text"> - <string>SIRT: Simultaneous algebraic reconstruction technique</string> - </property> - </item> - <item> - <property name="text"> - <string>FBP: filtered back-propagation</string> - </property> - </item> - <item> - <property name="text"> - <string>MLEM: Maximum-likelihood expectation maximization</string> - </property> - </item> - </widget> - </item> - </layout> - </item> - <item> - <widget class="QGroupBox" name="groupBox"> - <property name="title"> - <string>Advanced options</string> - </property> - <property name="checkable"> - <bool>true</bool> - </property> - <property name="checked"> - <bool>false</bool> - </property> - <layout class="QGridLayout" name="gridLayout"> - <item row="0" column="0"> - <widget class="QLabel" name="label_iter"> - <property name="text"> - <string>Iterations:</string> - </property> - </widget> - </item> - <item row="0" column="1"> - <widget class="QSpinBox" name="spinBox_iter"> - <property name="minimum"> - <number>1</number> - </property> - <property name="maximum"> - <number>999</number> - </property> - <property name="value"> - <number>5</number> - </property> - </widget> - </item> - <item row="0" column="2" colspan="2"> - <spacer name="horizontalSpacer_4"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>178</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item row="1" column="0"> - <widget class="QLabel" name="label_cli_options"> - <property name="text"> - <string>Regularization:</string> - </property> - </widget> - </item> - <item row="1" column="1" colspan="2"> - <widget class="QDoubleSpinBox" name="doubleSpinBox_regularization"> - <property name="decimals"> - <number>5</number> - </property> - <property name="maximum"> - <double>180.000000000000000</double> - </property> - </widget> - </item> - <item row="1" column="3"> - <spacer name="horizontalSpacer_5"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>305</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - </layout> - </widget> - </item> - <item> - <spacer name="verticalSpacer"> - <property name="orientation"> - <enum>Qt::Vertical</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>20</width> - <height>0</height> - </size> - </property> - </spacer> - </item> - <item> - <layout class="QHBoxLayout" name="horizontalLayout"> - <item> - <spacer name="horizontalSpacer"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>178</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item> - <widget class="QDialogButtonBox" name="buttonBox"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="standardButtons"> - <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> - </property> - </widget> - </item> - </layout> - </item> - </layout> - </widget> - <resources/> - <connections> - <connection> - <sender>buttonBox</sender> - <signal>accepted()</signal> - <receiver>TomoToolConfigTomoPy</receiver> - <slot>accept()</slot> - <hints> - <hint type="sourcelabel"> - <x>434</x> - <y>200</y> - </hint> - <hint type="destinationlabel"> - <x>291</x> - <y>111</y> - </hint> - </hints> - </connection> - <connection> - <sender>buttonBox</sender> - <signal>rejected()</signal> - <receiver>TomoToolConfigTomoPy</receiver> - <slot>reject()</slot> - <hints> - <hint type="sourcelabel"> - <x>434</x> - <y>200</y> - </hint> - <hint type="destinationlabel"> - <x>291</x> - <y>111</y> - </hint> - </hints> - </connection> - </connections> -</ui> diff --git a/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomographyIfaceModel.h b/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomographyIfaceModel.h deleted file mode 100644 index 7167c8ca59d..00000000000 --- a/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomographyIfaceModel.h +++ /dev/null @@ -1,330 +0,0 @@ -#ifndef MANTIDQTCUSTOMINTERFACES_TOMOGRAPHY_TOMOGRAPHYIFACEMODEL_H_ -#define MANTIDQTCUSTOMINTERFACES_TOMOGRAPHY_TOMOGRAPHYIFACEMODEL_H_ - -#include "MantidAPI/IRemoteJobManager.h" -#include "MantidAPI/ITableWorkspace_fwd.h" -#include "MantidAPI/WorkspaceGroup_fwd.h" -#include "MantidKernel/System.h" -#include "MantidQtCustomInterfaces/Tomography/ImageStackPreParams.h" -#include "MantidQtCustomInterfaces/Tomography/TomoPathsConfig.h" -#include "MantidQtCustomInterfaces/Tomography/TomoRecToolConfig.h" -#include "MantidQtCustomInterfaces/Tomography/TomoReconFiltersSettings.h" -#include "MantidQtCustomInterfaces/Tomography/TomoReconToolsUserSettings.h" -#include "MantidQtCustomInterfaces/Tomography/TomoSystemSettings.h" - -// Include instead of forward declare so we have definition of qint64 -#include <QMutex> - -namespace MantidQt { -namespace CustomInterfaces { - -class TomographyProcess; -class TomographyThread; -/** -Tomography GUI. Model for the interface (as in the MVP -(Model-View-Presenter) pattern). In principle, in a strict MVP setup, -signals from this model should always be handled through the presenter -and never go directly to the view. - -Copyright © 2014,2016 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 MANTIDQT_CUSTOMINTERFACES_DLL TomographyIfaceModel { - // For now, there is no need to make this a Q_OBJECT (and derive from - // QObject, but this class may become a "full" Q_OBJECT as soon as a Qt - // model (table, tree, etc.), with its signals, is used here - // Q_OBJECT - -public: - /// Default constructor - TomographyIfaceModel(); - virtual ~TomographyIfaceModel(); - - void setupComputeResource(); - void setupRunTool(const std::string &compRes); - - /// is the current facility supported? (only ISIS for now) - bool facilitySupported(); - - /// the compure resources supported and their status/availability - std::vector<std::string> computeResources() { return m_computeRes; } - std::vector<bool> computeResourcesStatus() { return m_computeResStatus; } - - /// the reconstruction tools supported and their status/availability - std::vector<std::string> reconTools() { return m_reconTools; } - std::vector<bool> reconToolsStatus() { return m_reconToolsStatus; } - - // Mantid::Kernel::Logger & logger() const; - - const std::vector<Mantid::API::IRemoteJobManager::RemoteJobInfo> - jobsStatus() const { - return m_jobsStatus; - } - - const std::vector<Mantid::API::IRemoteJobManager::RemoteJobInfo> - jobsStatusLocal() const { - return m_jobsStatusLocal; - } - - /// Username last logged in, if any. - std::string loggedIn() const { return m_loggedInUser; } - - // TODO: add companion currentComputeResource where LoggedIn() is in - //-------------------------------------------- - // Current tool Settings - //-------------------------------------------- - void usingTool(const std::string &tool) { m_currentToolName = tool; } - std::string usingTool() const { return m_currentToolName; } - - void setCurrentToolMethod(std::string toolMethod) { - m_currentToolMethod = toolMethod; - } - std::string getCurrentToolMethod() const { return m_currentToolMethod; } - - void setCurrentToolSettings(std::shared_ptr<TomoRecToolConfig> settings) { - m_currentToolSettings = settings; - } - - //-------------------------------------------- - // Access to the system settings information - //-------------------------------------------- - // get the remote scripts base dir from the system settings - std::string getCurrentRemoteScriptsBasePath() const { - return m_systemSettings.m_remote.m_basePathReconScripts; - } - - /// get the local paths from the system settings - std::string getCurrentLocalScriptsBasePath() const { - return m_systemSettings.m_local.m_reconScriptsPath; - } - - std::string getExeternalInterpreterPath() const { - return m_systemSettings.m_local.m_externalInterpreterPath; - } - - /// get the experiment reference currently selected - std::string getCurrentExperimentReference() const { - return m_systemSettings.m_experimentReference; - } - - /// returns the scripts folder, used for remote path - std::string getTomoScriptFolderPath() const { return g_tomoScriptFolderPath; } - - /// returns the tomo script location path inside the scripts folder - std::string getTomoScriptLocationPath() const { - return g_mainReconstructionScript; - } - - /// ping the (remote) compute resource - bool doPing(const std::string &compRes); - /// Log into the (remote or local) compute resource - void doLogin(const std::string &compRes, const std::string &user, - const std::string &pw); - /// Log out from the (remote or local) compute resource - void doLogout(const std::string &compRes, const std::string &username); - /// Query the status of running (and recent) jobs - void doQueryJobStatus(const std::string &compRes, - std::vector<std::string> &ids, - std::vector<std::string> &names, - std::vector<std::string> &status, - std::vector<std::string> &cmds); - /// Submit a new job to the (remote or local) compute resource - void prepareSubmissionArguments(const bool local, std::string &runnable, - std::vector<std::string> &args, - std::string &allOpts); - - void doLocalRunReconstructionJob( - const std::string &runnable, const std::vector<std::string> &args, - const std::string &allOpts, - MantidQt::CustomInterfaces::TomographyThread &thread, - MantidQt::CustomInterfaces::TomographyProcess &worker, - const std::string &workerName = "Mantid_Local"); - - void doRemoteRunReconstructionJob(const std::string &compRes, - const std::string &runnable, - const std::string &allOpts); - - /// Cancel a previously submitted job - void doCancelJobs(const std::string &compRes, - const std::vector<std::string> &id); - - void addJobToStatus(const qint64 pid, const std::string &runnable, - const std::string &allOpts, - const std::string &workerName); - /// Get fresh status information on running/recent jobs - void doRefreshJobsInfo(const std::string &compRes); - - void refreshLocalJobsInfo(); - - void setExperimentReference(const std::string ref) { m_experimentRef = ref; } - - /// Update to the current setings given by the user - void setSystemSettings(const TomoSystemSettings &settings) { - m_systemSettings = settings; - } - - void setPrePostProcSettings(const TomoReconFiltersSettings &filters) { - m_prePostProcSettings = filters; - } - - void setImageStackPreParams(const ImageStackPreParams &roiEtc) { - m_imageStackPreParams = roiEtc; - } - - /// loads an image/picture in FITS format - Mantid::API::WorkspaceGroup_sptr loadFITSImage(const std::string &path); - - /// Log this message through the system logging - void logMsg(const std::string &msg); - void logErrMsg(const std::string &msg); - - /// for clean destruction - void cleanup(); - - std::string localComputeResource() const { return g_LocalResourceName; } - - void setTomoPathsConfig(const TomoPathsConfig &tc) { m_pathsConfig = tc; } - void updateProcessInJobList(const qint64 pid, const int exitCode); - void terminateProcess(); - - // Names of reconstruction tools - static const std::string g_TomoPyTool; - static const std::string g_AstraTool; - static const std::string g_customCmdTool; - // not supported yet - static const std::string g_CCPiTool; - static const std::string g_SavuTool; - - // Name of the remote compute resource - static const std::string g_SCARFName; - static const std::string g_LocalResourceName; - - // The main tomo_reconstruct.py or similar script (as it is distributed with - // Mantid). This is the entry point for reconstruction jobs. - static const std::string g_mainReconstructionScript; - static const std::string g_tomoScriptFolderPath; - -protected: // protected to expose everything to testing - std::string - constructSingleStringFromVector(const std::vector<std::string> args) const; - - /// retrieve info from compute resource into status table - void getJobStatusInfo(const std::string &compRes); - - std::string validateCompResource(const std::string &res) const; - - bool checkIfToolIsSetupProperly(const std::string &tool, - const std::string &cmd, - const std::vector<std::string> &args) const; - - void makeTomoRecScriptOptions(const bool local, - std::vector<std::string> &opts) const; - - void filtersCfgToCmdOpts(const TomoReconFiltersSettings &filters, - const ImageStackPreParams &corRegions, - const bool local, - std::vector<std::string> &opts) const; - - void splitCmdLine(const std::string &cmd, std::string &runnable, - std::string &opts) const; - - /// process the tool name to be appropriate for the command line arg - std::string prepareToolNameForArgs(const std::string &toolName) const; - - void checkDataPathsSet() const; - - std::string adaptInputPathForExecution(const std::string &path, - const bool local) const; - - std::string buildOutReconstructionDir(const std::string &samplesDir, - bool) const; - - bool processIsRunning(qint64 pid) const; - - std::string - buildOutReconstructionDirFromSystemRoot(const std::string &samplesDir, - bool local) const; - - std::string - buildOutReconstructionDirFromSamplesDir(const std::string &samplesDir) const; - -private: - /// facility for the remote compute resource - const std::string m_facility; - - /// Experiment reference (RBNumber for example) - std::string m_experimentRef; - - /// username last logged in (empty if not in login status), from local - /// perspective - std::string m_loggedInUser; - std::string m_loggedInComp; - - /// compute resources suppoted by this GUI (remote ones, clusters, etc.) - std::vector<std::string> m_computeRes; - /// status of the compute resources: availalbe/unavailable or usable/unusable - std::vector<bool> m_computeResStatus; - /// identifiers of reconstruction tools supported, given a compute resource - std::vector<std::string> m_reconTools; - std::vector<bool> m_reconToolsStatus; - - // status of remote jobs - std::vector<Mantid::API::IRemoteJobManager::RemoteJobInfo> m_jobsStatus; - // status of local runs/jobs - std::vector<Mantid::API::IRemoteJobManager::RemoteJobInfo> m_jobsStatusLocal; - - /// reconstruction tools available on SCARF - std::vector<std::string> m_SCARFtools; - - // Paths for the sample, flat and dark images - TomoPathsConfig m_pathsConfig; - - // System settting including several paths and parameters (local and remote) - TomoSystemSettings m_systemSettings; - - //-------------------------------- - // Current tool variables - //-------------------------------- - - // current tool's name, updated from the presenter on change - std::string m_currentToolName; - - // the tool settings so we can use it for reconstruction params - std::shared_ptr<TomoRecToolConfig> m_currentToolSettings; - - // current tool's method, updated from the presenter on change - std::string m_currentToolMethod; - - // Settings for the pre-/post-processing filters - TomoReconFiltersSettings m_prePostProcSettings; - - // Parameters set for the ROI, normalization region, etc. - ImageStackPreParams m_imageStackPreParams; - - // mutex for the job status info update operations - // TODO: replace with std::mutex+std::lock_guard - QMutex *m_statusMutex; -}; - -} // namespace CustomInterfaces -} // namespace MantidQt - -#endif // MANTIDQTCUSTOMINTERFACES_TOMOGRAPHY_TOMOGRAPHYIFACEMODEL_H_ diff --git a/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomographyIfacePresenter.h b/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomographyIfacePresenter.h deleted file mode 100644 index 3a874640a08..00000000000 --- a/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomographyIfacePresenter.h +++ /dev/null @@ -1,185 +0,0 @@ -#ifndef MANTIDQTCUSTOMINTERFACES_TOMOGRAPHY_TOMOGRAPHYIFACEPRESENTER_H_ -#define MANTIDQTCUSTOMINTERFACES_TOMOGRAPHY_TOMOGRAPHYIFACEPRESENTER_H_ - -#include "MantidQtCustomInterfaces/DllConfig.h" -#include "MantidQtCustomInterfaces/Tomography/ITomographyIfacePresenter.h" -#include "MantidQtCustomInterfaces/Tomography/ITomographyIfaceView.h" -#include "MantidQtCustomInterfaces/Tomography/TomographyIfaceModel.h" - -#include <QMutex> -#include <QObject> -#include <boost/scoped_ptr.hpp> - -// Qt classes forward declarations -class QThread; -class QTimer; - -namespace MantidQt { -namespace CustomInterfaces { - -class TomoPathsConfig; -class TomoToolConfigDialogBase; - -/** -Tomography GUI. Presenter for the GUI (as in the MVP -(Model-View-Presenter) pattern). In principle, in a strict MVP setup, -signals from the model should always be handled through this presenter -and never go directly to the view, and viceversa. - -Copyright © 2014-2016 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 MANTIDQT_CUSTOMINTERFACES_DLL TomographyIfacePresenter - : public QObject, - public ITomographyIfacePresenter { - Q_OBJECT - -public: - /// Default constructor - normally used from the concrete view - TomographyIfacePresenter(ITomographyIfaceView *view); - ~TomographyIfacePresenter() override; - - void notify(ITomographyIfacePresenter::Notification notif) override; - -protected: - void initialize(); - - /// clean shut down of model, view, etc. - void cleanup(); - - // notification methods - void processSystemSettingsUpdated(); - void processSetupResourcesAndTools(); - void processCompResourceChanged(); - void processToolChanged(); - void processTomoPathsChanged(); - void processTomoPathsEditedByUser(); - void processRunExternalProcess(); - void processLogin(); - void processLogout(); - void processSetupReconTool(); - void processRunRecon(); - void processCancelJobs(); - void processVisualizeJobs(); - void processLogMsg(); - void processAggregateEnergyBands(); - void processShutDown(); - - void doVisualize(const std::vector<std::string> &ids); - - /// auto-guess additional directories when the user gives the samples path - void findFlatsDarksFromSampleGivenByUser(TomoPathsConfig &cfg); - - bool - usableEnergyBandsPaths(const std::map<std::string, std::string> &algParams); - - /// Starts a periodic query just to keep sessions alive when logged in - void startKeepAliveMechanism(int period); - - /// Stops/kills the periodic query (for example if the user logs out) - void killKeepAliveMechanism(); - - bool isLocalResourceSelected() const; -signals: - void terminated(); - -protected slots: - /// It may be run on user request, or periodically from a timer/thread - void processRefreshJobs(); - void readWorkerStdOut(const QString &workerString); - void readWorkerStdErr(const QString &workerString); - void addProcessToJobList(); - void reconProcessFailedToStart(); - void workerFinished(const qint64 pid, const int exitCode); - void emitExternalProcessOutput(const qint64 pid, const int exitCode); - -private: - /// Update the model's filter, COR and ROI/Area of norm settings - /// and build the runnable and arguments - void prepareSubmissionArguments(const bool local, std::string &runnable, - std::vector<std::string> &args, - std::string &allOpts); - /// Asks the user for permission to cancel the running reconstruction - bool userConfirmationToCancelRecon(); - void setupAndRunLocalReconstruction(const std::string &runnable, - const std::vector<std::string> &args, - const std::string &allOpts); - - void setupAndRunLocalExternalProcess(const std::string &runnable, - const std::vector<std::string> &args, - const std::string &allOpts); - /// creates the correct dialog pointer and sets it to the member variable - void createConfigDialogUsingToolName(const std::string &toolName); - - /// sets up the dialog and uses the settings to update the model - void - setupConfigDialogSettingsAndUpdateModel(TomoToolConfigDialogBase *dialog); - - /// configures up the dialog using the view - void setupConfigDialogSettings(TomoToolConfigDialogBase &dialog); - - /// does the actual path configuration for local resource - void setupConfigDialogSettingsForLocal(TomoToolConfigDialogBase &dialog); - - /// does the actual path configuration for remote resource - void setupConfigDialogSettingsForRemote(TomoToolConfigDialogBase &dialog); - - /// update all the model information after the tool's been changed - void updateModelAfterToolChanged(const TomoToolConfigDialogBase &dialog); - - /// update the model's current tool name using the dialog - void updateModelCurrentToolName(const TomoToolConfigDialogBase &dialog); - - /// update the model's current tool method using the dialog - void updateModelCurrentToolMethod(const TomoToolConfigDialogBase &dialog); - - /// update the model's current tool settings using the dialog - void updateModelCurrentToolSettings(const TomoToolConfigDialogBase &dialog); - - /// Associated view for this presenter (MVP pattern) - ITomographyIfaceView *const m_view; - - /// Associated model for this presenter (MVP pattern) - const boost::scoped_ptr<TomographyIfaceModel> m_model; - - // TODO: replace this with an std::mutex. Also below for threads. - // mutex for the job status info update operations on the view - QMutex *m_statusMutex; - - // for periodic update of the job status table/tree - QTimer *m_keepAliveTimer; - - std::unique_ptr<TomographyThread> m_workerThread; - QString m_workerOutputCache; - QString m_workerErrorCache; - - std::unique_ptr<TomoToolConfigDialogBase> m_configDialog; - - static const std::string g_defOutPathLocal; - static const std::string g_defOutPathRemote; - - bool m_reconRunning = false; -}; - -} // namespace CustomInterfaces -} // namespace MantidQt - -#endif // MANTIDQTCUSTOMINTERFACES_TOMOGRAPHY_TOMOGRAPHYIFACEPRESENTER_H_ diff --git a/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomographyIfaceQtGUI.ui b/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomographyIfaceQtGUI.ui deleted file mode 100644 index 0c3e4253364..00000000000 --- a/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomographyIfaceQtGUI.ui +++ /dev/null @@ -1,106 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<ui version="4.0"> - <class>TomographyIfaceQtGUI</class> - <widget class="QMainWindow" name="TomographyIfaceQtGUI"> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>1059</width> - <height>700</height> - </rect> - </property> - <property name="windowTitle"> - <string>IMAT Imaging and Tomography</string> - </property> - <widget class="QWidget" name="mainWidget"> - <layout class="QGridLayout" name="gridLayout_4"> - <property name="margin"> - <number>3</number> - </property> - <property name="spacing"> - <number>1</number> - </property> - <item row="1" column="0"> - <layout class="QHBoxLayout" name="horizontalLayout_3"> - <item> - <widget class="QPushButton" name="pushButton_help"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Minimum" vsizetype="Fixed"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="maximumSize"> - <size> - <width>25</width> - <height>25</height> - </size> - </property> - <property name="text"> - <string>?</string> - </property> - </widget> - </item> - <item> - <spacer name="horizontalSpacer"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>158</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item> - <widget class="QPushButton" name="pushButton_close"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Minimum" vsizetype="Fixed"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="text"> - <string>Close</string> - </property> - </widget> - </item> - </layout> - </item> - <item row="0" column="0"> - <widget class="QTabWidget" name="tabMain"> - <property name="toolTip"> - <string/> - </property> - <property name="currentIndex"> - <number>-1</number> - </property> - </widget> - </item> - </layout> - </widget> - <action name="actionOpen"> - <property name="text"> - <string>&Open...</string> - </property> - </action> - <action name="actionSave"> - <property name="text"> - <string>&Save</string> - </property> - </action> - <action name="actionSaveAs"> - <property name="text"> - <string>Save As</string> - </property> - </action> - </widget> - <tabstops> - <tabstop>tabMain</tabstop> - </tabstops> - <resources/> - <connections/> -</ui> diff --git a/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomographyIfaceQtTabEnergy.ui b/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomographyIfaceQtTabEnergy.ui deleted file mode 100644 index 2a250fefa8d..00000000000 --- a/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomographyIfaceQtTabEnergy.ui +++ /dev/null @@ -1,400 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<ui version="4.0"> - <class>TomographyIfaceQtTabEnergy</class> - <widget class="QWidget" name="TomographyIfaceQtTabEnergy"> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>822</width> - <height>574</height> - </rect> - </property> - <property name="windowTitle"> - <string>Form</string> - </property> - <layout class="QGridLayout" name="gridLayout_4"> - <item row="0" column="0"> - <layout class="QVBoxLayout" name="verticalLayout_3"> - <item> - <layout class="QVBoxLayout" name="verticalLayout_2"> - <item> - <widget class="QGroupBox" name="groupBox_inputs"> - <property name="enabled"> - <bool>true</bool> - </property> - <property name="title"> - <string>Input:</string> - </property> - <layout class="QGridLayout" name="gridLayout"> - <item row="1" column="3"> - <widget class="QPushButton" name="pushButton_browse_input"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="text"> - <string>Browse</string> - </property> - </widget> - </item> - <item row="1" column="0"> - <widget class="QLabel" name="label_2"> - <property name="text"> - <string>Path:</string> - </property> - </widget> - </item> - <item row="0" column="2" colspan="2"> - <spacer name="horizontalSpacer_2"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeType"> - <enum>QSizePolicy::Expanding</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>268</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item row="0" column="0"> - <widget class="QLabel" name="label_3"> - <property name="text"> - <string>Pick format:</string> - </property> - </widget> - </item> - <item row="0" column="1"> - <widget class="QComboBox" name="comboBox_input_format"> - <property name="enabled"> - <bool>false</bool> - </property> - <property name="sizePolicy"> - <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <item> - <property name="text"> - <string>FITS</string> - </property> - </item> - <item> - <property name="text"> - <string>TIFF</string> - </property> - </item> - <item> - <property name="text"> - <string>PNG</string> - </property> - </item> - </widget> - </item> - <item row="1" column="1" colspan="2"> - <widget class="QLineEdit" name="lineEdit_input_path"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> - <horstretch>2</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="readOnly"> - <bool>true</bool> - </property> - </widget> - </item> - </layout> - </widget> - </item> - <item> - <widget class="QGroupBox" name="groupBox_outputs"> - <property name="enabled"> - <bool>true</bool> - </property> - <property name="title"> - <string>Output:</string> - </property> - <layout class="QVBoxLayout" name="verticalLayout"> - <item> - <layout class="QGridLayout" name="gridLayout_3"> - <item row="0" column="0"> - <widget class="QRadioButton" name="radioButton_uniform_bands"> - <property name="text"> - <string>Uniform</string> - </property> - <property name="checked"> - <bool>true</bool> - </property> - </widget> - </item> - <item row="0" column="1" colspan="2"> - <widget class="QLabel" name="label"> - <property name="text"> - <string>Number of bands:</string> - </property> - </widget> - </item> - <item row="0" column="3"> - <widget class="QSpinBox" name="spinBox_uniform_bands"> - <property name="minimum"> - <number>1</number> - </property> - <property name="maximum"> - <number>1000</number> - </property> - </widget> - </item> - <item row="0" column="4"> - <spacer name="horizontalSpacer"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>326</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item row="1" column="0" colspan="2"> - <widget class="QRadioButton" name="radioButton_index_ranges"> - <property name="text"> - <string>Indices of boundaries:</string> - </property> - <property name="checked"> - <bool>false</bool> - </property> - </widget> - </item> - <item row="1" column="2" colspan="3"> - <widget class="QLineEdit" name="lineEdit_index_ranges"/> - </item> - <item row="2" column="0" colspan="2"> - <widget class="QRadioButton" name="radioButton_tof_ranges"> - <property name="enabled"> - <bool>false</bool> - </property> - <property name="text"> - <string>ToF boundaries:</string> - </property> - </widget> - </item> - <item row="2" column="2" colspan="3"> - <widget class="QLineEdit" name="lineEdit_tof_ranges"/> - </item> - </layout> - </item> - <item> - <layout class="QHBoxLayout" name="horizontalLayout_4"> - <item> - <widget class="QLabel" name="label_7"> - <property name="text"> - <string>Image format:</string> - </property> - </widget> - </item> - <item> - <widget class="QComboBox" name="comboBox_output_format"> - <property name="enabled"> - <bool>false</bool> - </property> - <property name="sizePolicy"> - <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <item> - <property name="text"> - <string>FITS</string> - </property> - </item> - <item> - <property name="text"> - <string>TIFF</string> - </property> - </item> - <item> - <property name="text"> - <string>PNG</string> - </property> - </item> - </widget> - </item> - <item> - <spacer name="horizontalSpacer_3"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>40</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - </layout> - </item> - <item> - <layout class="QHBoxLayout" name="horizontalLayout_5"> - <item> - <widget class="QLabel" name="label_6"> - <property name="text"> - <string>Path</string> - </property> - </widget> - </item> - <item> - <widget class="QLineEdit" name="lineEdit_output_path"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> - <horstretch>1</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="readOnly"> - <bool>true</bool> - </property> - </widget> - </item> - <item> - <widget class="QPushButton" name="pushButton_browse_output"> - <property name="text"> - <string>Browse</string> - </property> - </widget> - </item> - </layout> - </item> - </layout> - </widget> - </item> - <item> - <layout class="QHBoxLayout" name="horizontalLayout"> - <item> - <spacer name="horizontalSpacer_5"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>278</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item> - <widget class="QPushButton" name="pushButton_agg"> - <property name="enabled"> - <bool>true</bool> - </property> - <property name="text"> - <string>Aggregate</string> - </property> - </widget> - </item> - </layout> - </item> - </layout> - </item> - <item> - <spacer name="verticalSpacer"> - <property name="orientation"> - <enum>Qt::Vertical</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>20</width> - <height>88</height> - </size> - </property> - </spacer> - </item> - <item> - <widget class="QGroupBox" name="groupBox_config"> - <property name="title"> - <string>Configuration for remote:</string> - </property> - <property name="checkable"> - <bool>true</bool> - </property> - <property name="checked"> - <bool>false</bool> - </property> - <layout class="QGridLayout" name="gridLayout_2"> - <item row="0" column="0"> - <layout class="QHBoxLayout" name="horizontalLayout_2"> - <item> - <widget class="QLabel" name="label_4"> - <property name="text"> - <string>Path:</string> - </property> - </widget> - </item> - <item> - <widget class="QLineEdit" name="lineEdit_script"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> - <horstretch>2</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="text"> - <string>C:\MantidInstall\scrips\imaging\IMAT\agg_energy_bands.py</string> - </property> - </widget> - </item> - <item> - <widget class="QPushButton" name="pushButton_browse_script"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="text"> - <string>Browse</string> - </property> - </widget> - </item> - </layout> - </item> - </layout> - </widget> - </item> - </layout> - </item> - </layout> - </widget> - <tabstops> - <tabstop>comboBox_input_format</tabstop> - <tabstop>lineEdit_input_path</tabstop> - <tabstop>pushButton_browse_input</tabstop> - <tabstop>radioButton_uniform_bands</tabstop> - <tabstop>spinBox_uniform_bands</tabstop> - <tabstop>radioButton_index_ranges</tabstop> - <tabstop>lineEdit_index_ranges</tabstop> - <tabstop>radioButton_tof_ranges</tabstop> - <tabstop>lineEdit_tof_ranges</tabstop> - <tabstop>comboBox_output_format</tabstop> - <tabstop>lineEdit_output_path</tabstop> - <tabstop>pushButton_browse_output</tabstop> - <tabstop>pushButton_agg</tabstop> - <tabstop>groupBox_config</tabstop> - <tabstop>lineEdit_script</tabstop> - <tabstop>pushButton_browse_script</tabstop> - </tabstops> - <resources/> - <connections/> -</ui> diff --git a/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomographyIfaceQtTabFiltersSettings.ui b/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomographyIfaceQtTabFiltersSettings.ui deleted file mode 100644 index 639ba999b67..00000000000 --- a/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomographyIfaceQtTabFiltersSettings.ui +++ /dev/null @@ -1,604 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<ui version="4.0"> - <class>TomographyIfaceQtTabFiltersSettings</class> - <widget class="QWidget" name="TomographyIfaceQtTabFiltersSettings"> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>826</width> - <height>578</height> - </rect> - </property> - <property name="windowTitle"> - <string>Form</string> - </property> - <layout class="QGridLayout" name="gridLayout"> - <item row="0" column="0"> - <widget class="QScrollArea" name="scrollArea"> - <property name="widgetResizable"> - <bool>true</bool> - </property> - <widget class="QWidget" name="scrollAreaWidgetContents"> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>788</width> - <height>671</height> - </rect> - </property> - <layout class="QVBoxLayout" name="verticalLayout"> - <item> - <widget class="QGroupBox" name="groupBox"> - <property name="title"> - <string>Pre-processing (raw images)</string> - </property> - <layout class="QGridLayout" name="gridLayout_5"> - <item row="10" column="2"> - <widget class="QDoubleSpinBox" name="doubleSpinBox_prep_max_angle"> - <property name="toolTip"> - <string>Maximum angle to use for reconstruction</string> - </property> - <property name="decimals"> - <number>3</number> - </property> - <property name="minimum"> - <double>1.000000000000000</double> - </property> - <property name="maximum"> - <double>360.000000000000000</double> - </property> - <property name="value"> - <double>360.000000000000000</double> - </property> - </widget> - </item> - <item row="11" column="0"> - <widget class="QLabel" name="label_prep_scale_factor"> - <property name="text"> - <string>Scale down factor:</string> - </property> - </widget> - </item> - <item row="2" column="0"> - <widget class="QCheckBox" name="checkBox_normalize_by_flats"> - <property name="statusTip"> - <string>Normalize every image with respect to the reference flat and dark images, if available</string> - </property> - <property name="text"> - <string>Normalize by flat (open beam) mages</string> - </property> - <property name="checked"> - <bool>true</bool> - </property> - </widget> - </item> - <item row="5" column="1"> - <spacer name="horizontalSpacer_13"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>399</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item row="11" column="1"> - <spacer name="horizontalSpacer_14"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>399</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item row="10" column="1"> - <spacer name="horizontalSpacer_15"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>399</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item row="11" column="2"> - <widget class="QSpinBox" name="spinBox_prep_scale_factor"> - <property name="toolTip"> - <string>Sets the size of block to downscale. For example with 2, blocks of 2x2 pixels will be combined into a (median value) pixel</string> - </property> - <property name="minimum"> - <number>0</number> - </property> - <property name="maximum"> - <number>100</number> - </property> - <property name="value"> - <number>0</number> - </property> - </widget> - </item> - <item row="5" column="0"> - <widget class="QLabel" name="label_prep_median"> - <property name="text"> - <string>Dots removal (median filter width):</string> - </property> - </widget> - </item> - <item row="10" column="0"> - <widget class="QLabel" name="label_prep_max_angle"> - <property name="text"> - <string>Maximum angle:</string> - </property> - </widget> - </item> - <item row="5" column="2"> - <widget class="QSpinBox" name="spinBox_prep_median_filter_width"> - <property name="toolTip"> - <string>Set size of the blocks to calculate a median filter. Bigger size implies more smoothing.</string> - </property> - <property name="minimum"> - <number>1</number> - </property> - <property name="maximum"> - <number>1000</number> - </property> - </widget> - </item> - <item row="6" column="0" colspan="3"> - <layout class="QHBoxLayout" name="horizontalLayout_5"> - <item> - <widget class="QLabel" name="label_3"> - <property name="text"> - <string>Sinogram stripes removal / ring artifacts removal</string> - </property> - </widget> - </item> - <item> - <widget class="QComboBox" name="comboBox_3"> - <item> - <property name="text"> - <string>Wavelet-Fourier</string> - </property> - </item> - <item> - <property name="text"> - <string>None</string> - </property> - </item> - </widget> - </item> - </layout> - </item> - <item row="4" column="0"> - <widget class="QCheckBox" name="checkBox_corrections_MCP_detector"> - <property name="enabled"> - <bool>false</bool> - </property> - <property name="text"> - <string>Corrections for MCP detector</string> - </property> - </widget> - </item> - <item row="2" column="1"> - <widget class="QCheckBox" name="checkBox_normalize_by_darks"> - <property name="statusTip"> - <string>Normalize every image with respect to the reference flat and dark images, if available</string> - </property> - <property name="text"> - <string>Normalize by dark field images</string> - </property> - <property name="checked"> - <bool>true</bool> - </property> - </widget> - </item> - <item row="1" column="0"> - <widget class="QCheckBox" name="checkBox_normalize_by_air_region"> - <property name="statusTip"> - <string>Normalize every image by their relative proton charges</string> - </property> - <property name="text"> - <string>Normalize by air region / proton charge</string> - </property> - <property name="checked"> - <bool>true</bool> - </property> - </widget> - </item> - <item row="1" column="1"> - <widget class="QCheckBox" name="checkBox_normalize_by_proton_charge"> - <property name="enabled"> - <bool>false</bool> - </property> - <property name="text"> - <string>Normalize by proton charge</string> - </property> - </widget> - </item> - <item row="8" column="2"> - <widget class="QComboBox" name="comboBox_prep_rotation"> - <property name="toolTip"> - <string>Rotate all images in the input stacks by this angle</string> - </property> - <item> - <property name="text"> - <string>0</string> - </property> - </item> - <item> - <property name="text"> - <string>90</string> - </property> - </item> - <item> - <property name="text"> - <string>180</string> - </property> - </item> - <item> - <property name="text"> - <string>270</string> - </property> - </item> - </widget> - </item> - <item row="8" column="1"> - <spacer name="horizontalSpacer_12"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>399</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item row="8" column="0"> - <widget class="QLabel" name="label"> - <property name="text"> - <string>Rotation (°, clockwise)</string> - </property> - </widget> - </item> - </layout> - </widget> - </item> - <item> - <spacer name="verticalSpacer"> - <property name="orientation"> - <enum>Qt::Vertical</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>20</width> - <height>15</height> - </size> - </property> - </spacer> - </item> - <item> - <widget class="QGroupBox" name="groupBox_2"> - <property name="title"> - <string>Post-processing (reconstructed volume)</string> - </property> - <layout class="QGridLayout" name="gridLayout_4"> - <item row="0" column="0"> - <widget class="QLabel" name="label_post_cir_mask"> - <property name="text"> - <string>Circular mask radius [0,1]:</string> - </property> - </widget> - </item> - <item row="0" column="1"> - <spacer name="horizontalSpacer_9"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>487</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item row="0" column="2"> - <widget class="QDoubleSpinBox" name="doubleSpinBox_post_circ_mask"> - <property name="toolTip"> - <string>Set the radius (relative to the smaller edge of the images). All pixels outside the mask are zeroed.</string> - </property> - <property name="decimals"> - <number>3</number> - </property> - <property name="maximum"> - <double>1.000000000000000</double> - </property> - <property name="singleStep"> - <double>0.010000000000000</double> - </property> - <property name="value"> - <double>0.940000000000000</double> - </property> - </widget> - </item> - <item row="1" column="0"> - <widget class="QLabel" name="label_post_cutoff"> - <property name="text"> - <string>Cut-off level (%)</string> - </property> - </widget> - </item> - <item row="1" column="1"> - <spacer name="horizontalSpacer_10"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>487</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item row="1" column="2"> - <widget class="QDoubleSpinBox" name="doubleSpinBox_post_cutoff"> - <property name="toolTip"> - <string>Cut-off (zeroes) low pixel values, below this level</string> - </property> - <property name="singleStep"> - <double>0.010000000000000</double> - </property> - </widget> - </item> - </layout> - </widget> - </item> - <item> - <spacer name="verticalSpacer_3"> - <property name="orientation"> - <enum>Qt::Vertical</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>20</width> - <height>15</height> - </size> - </property> - </spacer> - </item> - <item> - <widget class="QGroupBox" name="groupBox_3"> - <property name="title"> - <string>Output options:</string> - </property> - <layout class="QVBoxLayout" name="verticalLayout_3"> - <item> - <layout class="QHBoxLayout" name="horizontalLayout"> - <item> - <widget class="QLabel" name="label_out_img_format"> - <property name="text"> - <string>Output image format:</string> - </property> - </widget> - </item> - <item> - <widget class="QComboBox" name="comboBox_out_img_format"> - <item> - <property name="text"> - <string>PNG</string> - </property> - </item> - </widget> - </item> - <item> - <spacer name="horizontalSpacer"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>40</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - </layout> - </item> - <item> - <layout class="QHBoxLayout" name="horizontalLayout_6"> - <item> - <widget class="QLabel" name="label_out_bit_depth"> - <property name="text"> - <string>Pixel bit-depth in outputs:</string> - </property> - </widget> - </item> - <item> - <widget class="QComboBox" name="comboBox_out_bit_depth"> - <item> - <property name="text"> - <string>16 bits</string> - </property> - </item> - </widget> - </item> - <item> - <spacer name="horizontalSpacer_16"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>40</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - </layout> - </item> - <item> - <widget class="QCheckBox" name="checkBox_out_preproc_images"> - <property name="enabled"> - <bool>true</bool> - </property> - <property name="toolTip"> - <string>Write pre-processed images in addition to reconstructed volume</string> - </property> - <property name="text"> - <string>Produce pre-processed images stack</string> - </property> - <property name="checked"> - <bool>true</bool> - </property> - </widget> - </item> - <item> - <widget class="QGroupBox" name="groupBox_out_intermediate_prep"> - <property name="enabled"> - <bool>false</bool> - </property> - <property name="title"> - <string>Produce intermediate pre-processed images</string> - </property> - <property name="checkable"> - <bool>true</bool> - </property> - <property name="checked"> - <bool>false</bool> - </property> - <layout class="QGridLayout" name="gridLayout_6"> - <item row="3" column="0"> - <widget class="QCheckBox" name="checkBox_output_dot_removal"> - <property name="text"> - <string>Dots removed (median filter)</string> - </property> - <property name="checked"> - <bool>true</bool> - </property> - </widget> - </item> - <item row="2" column="0"> - <widget class="QCheckBox" name="checkBox_output_normalized_flat_images"> - <property name="text"> - <string>Normalized - flat, dark images</string> - </property> - </widget> - </item> - <item row="1" column="0"> - <widget class="QCheckBox" name="checkBox_output_normalized_proton_images"> - <property name="text"> - <string>Normalized - proton charge</string> - </property> - </widget> - </item> - <item row="0" column="0"> - <widget class="QCheckBox" name="checkBox_output_cropped_images"> - <property name="text"> - <string>Cropped</string> - </property> - </widget> - </item> - <item row="4" column="0"> - <widget class="QCheckBox" name="checkBox_output_sinograms"> - <property name="text"> - <string>sinograms</string> - </property> - <property name="checked"> - <bool>true</bool> - </property> - </widget> - </item> - </layout> - </widget> - </item> - </layout> - </widget> - </item> - <item> - <spacer name="verticalSpacer_2"> - <property name="orientation"> - <enum>Qt::Vertical</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>20</width> - <height>14</height> - </size> - </property> - </spacer> - </item> - <item> - <layout class="QHBoxLayout" name="horizontalLayout_4"> - <item> - <spacer name="horizontalSpacer_11"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>608</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item> - <widget class="QPushButton" name="pushButton_reset"> - <property name="text"> - <string>Reset all</string> - </property> - </widget> - </item> - </layout> - </item> - </layout> - </widget> - </widget> - </item> - </layout> - </widget> - <tabstops> - <tabstop>scrollArea</tabstop> - <tabstop>checkBox_normalize_by_air_region</tabstop> - <tabstop>checkBox_normalize_by_proton_charge</tabstop> - <tabstop>checkBox_normalize_by_flats</tabstop> - <tabstop>checkBox_normalize_by_darks</tabstop> - <tabstop>checkBox_corrections_MCP_detector</tabstop> - <tabstop>spinBox_prep_median_filter_width</tabstop> - <tabstop>comboBox_3</tabstop> - <tabstop>comboBox_prep_rotation</tabstop> - <tabstop>doubleSpinBox_prep_max_angle</tabstop> - <tabstop>spinBox_prep_scale_factor</tabstop> - <tabstop>doubleSpinBox_post_circ_mask</tabstop> - <tabstop>doubleSpinBox_post_cutoff</tabstop> - <tabstop>comboBox_out_img_format</tabstop> - <tabstop>comboBox_out_bit_depth</tabstop> - <tabstop>checkBox_out_preproc_images</tabstop> - <tabstop>groupBox_out_intermediate_prep</tabstop> - <tabstop>checkBox_output_cropped_images</tabstop> - <tabstop>checkBox_output_normalized_proton_images</tabstop> - <tabstop>checkBox_output_normalized_flat_images</tabstop> - <tabstop>checkBox_output_dot_removal</tabstop> - <tabstop>checkBox_output_sinograms</tabstop> - <tabstop>pushButton_reset</tabstop> - </tabstops> - <resources/> - <connections/> -</ui> diff --git a/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomographyIfaceQtTabRun.ui b/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomographyIfaceQtTabRun.ui deleted file mode 100644 index 4d62147b85b..00000000000 --- a/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomographyIfaceQtTabRun.ui +++ /dev/null @@ -1,802 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<ui version="4.0"> - <class>TomographyIfaceQtTabRun</class> - <widget class="QWidget" name="TomographyIfaceQtTabRun"> - <property name="enabled"> - <bool>true</bool> - </property> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>965</width> - <height>764</height> - </rect> - </property> - <layout class="QGridLayout" name="gridLayout"> - <item row="0" column="0"> - <widget class="QSplitter" name="splitter_run_main_vertical"> - <property name="orientation"> - <enum>Qt::Vertical</enum> - </property> - <widget class="QSplitter" name="splitter_image_resource"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="minimumSize"> - <size> - <width>0</width> - <height>220</height> - </size> - </property> - <property name="maximumSize"> - <size> - <width>16777215</width> - <height>16777215</height> - </size> - </property> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="opaqueResize"> - <bool>true</bool> - </property> - <widget class="QWidget" name="layoutWidget_5"> - <layout class="QGridLayout" name="gridLayout_11"> - <property name="sizeConstraint"> - <enum>QLayout::SetMinimumSize</enum> - </property> - <item row="1" column="1"> - <layout class="QVBoxLayout" name="verticalLayout_2"> - <item> - <spacer name="verticalSpacer"> - <property name="orientation"> - <enum>Qt::Vertical</enum> - </property> - <property name="sizeType"> - <enum>QSizePolicy::Fixed</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>20</width> - <height>6</height> - </size> - </property> - </spacer> - </item> - <item> - <widget class="QGroupBox" name="experiment_reference"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="minimumSize"> - <size> - <width>400</width> - <height>49</height> - </size> - </property> - <property name="maximumSize"> - <size> - <width>400</width> - <height>79</height> - </size> - </property> - <property name="layoutDirection"> - <enum>Qt::LeftToRight</enum> - </property> - <property name="title"> - <string/> - </property> - <property name="flat"> - <bool>false</bool> - </property> - <property name="checkable"> - <bool>false</bool> - </property> - <widget class="QLabel" name="label_experiment_reference"> - <property name="geometry"> - <rect> - <x>10</x> - <y>20</y> - <width>141</width> - <height>40</height> - </rect> - </property> - <property name="minimumSize"> - <size> - <width>39</width> - <height>40</height> - </size> - </property> - <property name="maximumSize"> - <size> - <width>16777215</width> - <height>40</height> - </size> - </property> - <property name="text"> - <string>Exp. reference (RB number)</string> - </property> - </widget> - <widget class="QLineEdit" name="lineEdit_experiment_reference"> - <property name="enabled"> - <bool>true</bool> - </property> - <property name="geometry"> - <rect> - <x>160</x> - <y>30</y> - <width>221</width> - <height>20</height> - </rect> - </property> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> - <horstretch>1</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="text"> - <string>RB0000XXX</string> - </property> - </widget> - </widget> - </item> - <item> - <widget class="QGroupBox" name="compute_resource"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="minimumSize"> - <size> - <width>400</width> - <height>130</height> - </size> - </property> - <property name="maximumSize"> - <size> - <width>400</width> - <height>129</height> - </size> - </property> - <property name="title"> - <string>Compute resource</string> - </property> - <layout class="QGridLayout" name="gridLayout_15"> - <property name="sizeConstraint"> - <enum>QLayout::SetMinimumSize</enum> - </property> - <item row="1" column="0"> - <widget class="QComboBox" name="comboBox_run_compute_resource"> - <item> - <property name="text"> - <string>SCARF</string> - </property> - </item> - <item> - <property name="text"> - <string>Local</string> - </property> - </item> - </widget> - </item> - <item row="1" column="1"> - <layout class="QHBoxLayout" name="horizontalLayout_6"> - <item> - <widget class="QLabel" name="label_SCARF_username"> - <property name="minimumSize"> - <size> - <width>90</width> - <height>20</height> - </size> - </property> - <property name="text"> - <string>Username:</string> - </property> - </widget> - </item> - <item> - <widget class="QLineEdit" name="lineEdit_SCARF_username"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="minimumSize"> - <size> - <width>140</width> - <height>20</height> - </size> - </property> - <property name="toolTip"> - <string>Type your username on the remote compute resource</string> - </property> - <property name="text"> - <string/> - </property> - </widget> - </item> - </layout> - </item> - <item row="2" column="0"> - <layout class="QHBoxLayout" name="horizontalLayout_4"> - <item> - <spacer name="horizontalSpacer_8"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>40</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item> - <widget class="QLabel" name="remote_status"> - <property name="text"> - <string>Remote status:</string> - </property> - </widget> - </item> - <item> - <widget class="QPushButton" name="pushButton_remote_status"> - <property name="text"> - <string>Offline</string> - </property> - <property name="autoDefault"> - <bool>false</bool> - </property> - <property name="default"> - <bool>false</bool> - </property> - <property name="flat"> - <bool>true</bool> - </property> - </widget> - </item> - <item> - <spacer name="horizontalSpacer_9"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>40</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - </layout> - </item> - <item row="2" column="1"> - <layout class="QHBoxLayout" name="horizontalLayout_7"> - <item> - <widget class="QLabel" name="label_SCARF_password"> - <property name="minimumSize"> - <size> - <width>90</width> - <height>20</height> - </size> - </property> - <property name="text"> - <string>Password:</string> - </property> - </widget> - </item> - <item> - <widget class="QLineEdit" name="lineEdit_SCARF_password"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="minimumSize"> - <size> - <width>140</width> - <height>20</height> - </size> - </property> - <property name="toolTip"> - <string>Type your password. It will be used just for authentication. It won't be displayed or saved anywhere</string> - </property> - <property name="text"> - <string/> - </property> - <property name="echoMode"> - <enum>QLineEdit::Password</enum> - </property> - <property name="cursorPosition"> - <number>0</number> - </property> - </widget> - </item> - </layout> - </item> - <item row="3" column="1"> - <layout class="QHBoxLayout" name="horizontalLayout"> - <item> - <widget class="QPushButton" name="pushButton_SCARF_login"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Minimum" vsizetype="Preferred"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="minimumSize"> - <size> - <width>0</width> - <height>22</height> - </size> - </property> - <property name="maximumSize"> - <size> - <width>16777215</width> - <height>27</height> - </size> - </property> - <property name="text"> - <string>Log in</string> - </property> - </widget> - </item> - <item> - <widget class="QPushButton" name="pushButton_SCARF_logout"> - <property name="enabled"> - <bool>false</bool> - </property> - <property name="sizePolicy"> - <sizepolicy hsizetype="Minimum" vsizetype="Preferred"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="minimumSize"> - <size> - <width>0</width> - <height>22</height> - </size> - </property> - <property name="maximumSize"> - <size> - <width>16777215</width> - <height>27</height> - </size> - </property> - <property name="text"> - <string>Log out</string> - </property> - </widget> - </item> - </layout> - </item> - </layout> - </widget> - </item> - </layout> - </item> - <item row="1" column="0"> - <layout class="QVBoxLayout" name="verticalLayout"> - <item> - <widget class="QGroupBox" name="reconstruction_tool"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="minimumSize"> - <size> - <width>535</width> - <height>50</height> - </size> - </property> - <property name="maximumSize"> - <size> - <width>535</width> - <height>90</height> - </size> - </property> - <property name="title"> - <string>Reconstruction tool</string> - </property> - <layout class="QGridLayout" name="gridLayout_18"> - <property name="sizeConstraint"> - <enum>QLayout::SetMinimumSize</enum> - </property> - <item row="0" column="1"> - <widget class="QComboBox" name="comboBox_run_tool"> - <item> - <property name="text"> - <string>TomoPy</string> - </property> - </item> - <item> - <property name="text"> - <string>Astra</string> - </property> - </item> - <item> - <property name="text"> - <string>CCPi CGLS</string> - </property> - </item> - <item> - <property name="text"> - <string>Savu</string> - </property> - </item> - <item> - <property name="text"> - <string>Custom command</string> - </property> - </item> - </widget> - </item> - <item row="0" column="2"> - <widget class="QPushButton" name="pushButton_run_tool_setup"> - <property name="toolTip"> - <string>Define specific settings for the tool selected</string> - </property> - <property name="statusTip"> - <string/> - </property> - <property name="text"> - <string>Setup</string> - </property> - <property name="autoRepeat"> - <bool>false</bool> - </property> - <property name="autoExclusive"> - <bool>false</bool> - </property> - <property name="flat"> - <bool>false</bool> - </property> - </widget> - </item> - <item row="1" column="2"> - <widget class="QPushButton" name="pushButton_reconstruct"> - <property name="toolTip"> - <string/> - </property> - <property name="statusTip"> - <string/> - </property> - <property name="text"> - <string>Reconstruct</string> - </property> - </widget> - </item> - </layout> - </widget> - </item> - <item> - <widget class="QGroupBox" name="input_directories"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="minimumSize"> - <size> - <width>535</width> - <height>129</height> - </size> - </property> - <property name="maximumSize"> - <size> - <width>535</width> - <height>129</height> - </size> - </property> - <property name="title"> - <string>Directories/folders for the input images:</string> - </property> - <widget class="QWidget" name="horizontalLayoutWidget"> - <property name="geometry"> - <rect> - <x>10</x> - <y>20</y> - <width>521</width> - <height>31</height> - </rect> - </property> - <layout class="QHBoxLayout" name="sample_dir"> - <item> - <widget class="QLabel" name="label_samples"> - <property name="minimumSize"> - <size> - <width>120</width> - <height>0</height> - </size> - </property> - <property name="maximumSize"> - <size> - <width>101</width> - <height>16777215</height> - </size> - </property> - <property name="text"> - <string>Samples directory:</string> - </property> - </widget> - </item> - <item> - <widget class="QLineEdit" name="lineEdit_path_samples"> - <property name="text"> - <string>D:/data/RB000000/experiment1/sample</string> - </property> - </widget> - </item> - <item> - <widget class="QPushButton" name="pushButton_samples_dir"> - <property name="maximumSize"> - <size> - <width>75</width> - <height>16777215</height> - </size> - </property> - <property name="text"> - <string>Browse...</string> - </property> - </widget> - </item> - </layout> - </widget> - <widget class="QWidget" name="horizontalLayoutWidget_2"> - <property name="geometry"> - <rect> - <x>10</x> - <y>50</y> - <width>521</width> - <height>31</height> - </rect> - </property> - <layout class="QHBoxLayout" name="flat_dir"> - <property name="spacing"> - <number>6</number> - </property> - <item> - <widget class="QCheckBox" name="checkBox_path_flats"> - <property name="text"> - <string>Flat/open beam</string> - </property> - <property name="checked"> - <bool>true</bool> - </property> - </widget> - </item> - <item> - <widget class="QLineEdit" name="lineEdit_path_flats"> - <property name="text"> - <string>D:/data/RB000000/experiment1/flat</string> - </property> - </widget> - </item> - <item> - <widget class="QPushButton" name="pushButton_flats_dir"> - <property name="maximumSize"> - <size> - <width>75</width> - <height>16777215</height> - </size> - </property> - <property name="text"> - <string>Browse...</string> - </property> - </widget> - </item> - </layout> - </widget> - <widget class="QWidget" name="horizontalLayoutWidget_3"> - <property name="geometry"> - <rect> - <x>10</x> - <y>80</y> - <width>521</width> - <height>31</height> - </rect> - </property> - <layout class="QHBoxLayout" name="dark_dir"> - <item> - <widget class="QCheckBox" name="checkBox_path_darks"> - <property name="text"> - <string>Dark field:</string> - </property> - <property name="checked"> - <bool>true</bool> - </property> - </widget> - </item> - <item> - <widget class="QLineEdit" name="lineEdit_path_darks"> - <property name="text"> - <string>D:/data/RB000000/experiment1/dark</string> - </property> - </widget> - </item> - <item> - <widget class="QPushButton" name="pushButton_darks_dir"> - <property name="maximumSize"> - <size> - <width>75</width> - <height>16777215</height> - </size> - </property> - <property name="text"> - <string>Browse...</string> - </property> - </widget> - </item> - </layout> - </widget> - </widget> - </item> - </layout> - </item> - </layout> - </widget> - </widget> - <widget class="QWidget" name="layoutWidget_7"> - <layout class="QVBoxLayout" name="verticalLayout_7"> - <property name="sizeConstraint"> - <enum>QLayout::SetMaximumSize</enum> - </property> - <item> - <widget class="QLabel" name="label_11"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="text"> - <string>Reconstruction jobs:</string> - </property> - </widget> - </item> - <item> - <widget class="QSplitter" name="splitter_run_jobs"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <widget class="QTableWidget" name="tableWidget_run_jobs"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>1</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> - <property name="minimumSize"> - <size> - <width>0</width> - <height>500</height> - </size> - </property> - <property name="maximumSize"> - <size> - <width>16777215</width> - <height>16777215</height> - </size> - </property> - <property name="selectionBehavior"> - <enum>QAbstractItemView::SelectRows</enum> - </property> - <attribute name="horizontalHeaderStretchLastSection"> - <bool>true</bool> - </attribute> - <column> - <property name="text"> - <string>Running on</string> - </property> - </column> - <column> - <property name="text"> - <string>Name</string> - </property> - </column> - <column> - <property name="text"> - <string>ID</string> - </property> - </column> - <column> - <property name="text"> - <string>Status</string> - </property> - </column> - <column> - <property name="text"> - <string>Command line</string> - </property> - </column> - </widget> - <widget class="QWidget" name="layoutWidget_8"> - <layout class="QGridLayout" name="gridLayout_16"> - <item row="5" column="0"> - <widget class="QPushButton" name="pushButton_run_job_cancel"> - <property name="text"> - <string>Cancel</string> - </property> - </widget> - </item> - <item row="4" column="0"> - <spacer name="verticalSpacer_5"> - <property name="orientation"> - <enum>Qt::Vertical</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>20</width> - <height>40</height> - </size> - </property> - </spacer> - </item> - <item row="1" column="0"> - <widget class="QPushButton" name="pushButton_run_refresh"> - <property name="text"> - <string>Refresh</string> - </property> - </widget> - </item> - <item row="3" column="0"> - <widget class="QPushButton" name="pushButton_showProcessOutput"> - <property name="enabled"> - <bool>false</bool> - </property> - <property name="text"> - <string>Show Output</string> - </property> - </widget> - </item> - <item row="2" column="0"> - <widget class="QPushButton" name="pushButton_run_job_visualize"> - <property name="text"> - <string>Visualize</string> - </property> - </widget> - </item> - </layout> - </widget> - </widget> - </item> - </layout> - </widget> - </widget> - </item> - </layout> - </widget> - <tabstops> - <tabstop>comboBox_run_tool</tabstop> - <tabstop>pushButton_run_tool_setup</tabstop> - <tabstop>pushButton_reconstruct</tabstop> - <tabstop>lineEdit_experiment_reference</tabstop> - <tabstop>comboBox_run_compute_resource</tabstop> - <tabstop>lineEdit_SCARF_username</tabstop> - <tabstop>lineEdit_SCARF_password</tabstop> - <tabstop>pushButton_SCARF_login</tabstop> - <tabstop>pushButton_SCARF_logout</tabstop> - <tabstop>tableWidget_run_jobs</tabstop> <!-- not sure we want this--> - <tabstop>pushButton_run_refresh</tabstop> - <tabstop>pushButton_run_job_visualize</tabstop> - <tabstop>pushButton_run_job_cancel</tabstop> - </tabstops> - <resources/> - <connections/> -</ui> diff --git a/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomographyIfaceQtTabSystemSettings.ui b/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomographyIfaceQtTabSystemSettings.ui deleted file mode 100644 index 910e59df411..00000000000 --- a/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomographyIfaceQtTabSystemSettings.ui +++ /dev/null @@ -1,790 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<ui version="4.0"> - <class>TomographyIfaceQtTabSystemSettings</class> - <widget class="QWidget" name="TomographyIfaceQtTabSystemSettings"> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>738</width> - <height>571</height> - </rect> - </property> - <property name="windowTitle"> - <string>Form</string> - </property> - <layout class="QGridLayout" name="gridLayout_9"> - <item row="0" column="0"> - <widget class="QScrollArea" name="scrollArea"> - <property name="lineWidth"> - <number>0</number> - </property> - <property name="widgetResizable"> - <bool>true</bool> - </property> - <widget class="QWidget" name="scrollAreaWidgetContents"> - <property name="geometry"> - <rect> - <x>0</x> - <y>-161</y> - <width>700</width> - <height>710</height> - </rect> - </property> - <layout class="QGridLayout" name="gridLayout_8"> - <item row="1" column="0"> - <widget class="QGroupBox" name="groupBox_10"> - <property name="title"> - <string>Execution of reconstruction jobs:</string> - </property> - <property name="checkable"> - <bool>true</bool> - </property> - <property name="checked"> - <bool>false</bool> - </property> - <layout class="QGridLayout" name="gridLayout_6"> - <item row="0" column="0"> - <widget class="QGroupBox" name="groupBox_5"> - <property name="title"> - <string>Remote runs:</string> - </property> - <property name="checkable"> - <bool>true</bool> - </property> - <property name="checked"> - <bool>false</bool> - </property> - <layout class="QGridLayout" name="gridLayout_12"> - <item row="4" column="0"> - <spacer name="verticalSpacer_2"> - <property name="orientation"> - <enum>Qt::Vertical</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>20</width> - <height>51</height> - </size> - </property> - </spacer> - </item> - <item row="2" column="1"> - <widget class="QSpinBox" name="spinBox_remote_cores"> - <property name="enabled"> - <bool>false</bool> - </property> - <property name="minimumSize"> - <size> - <width>0</width> - <height>20</height> - </size> - </property> - <property name="minimum"> - <number>1</number> - </property> - <property name="maximum"> - <number>99</number> - </property> - <property name="value"> - <number>8</number> - </property> - </widget> - </item> - <item row="2" column="0"> - <widget class="QLabel" name="label_24"> - <property name="enabled"> - <bool>false</bool> - </property> - <property name="text"> - <string>Number of cores:</string> - </property> - </widget> - </item> - <item row="0" column="0"> - <widget class="QLabel" name="label_23"> - <property name="enabled"> - <bool>false</bool> - </property> - <property name="text"> - <string>Number of nodes:</string> - </property> - </widget> - </item> - <item row="0" column="1"> - <widget class="QSpinBox" name="spinBox_remote_nodes"> - <property name="enabled"> - <bool>false</bool> - </property> - <property name="minimumSize"> - <size> - <width>0</width> - <height>20</height> - </size> - </property> - <property name="minimum"> - <number>1</number> - </property> - <property name="maximum"> - <number>99</number> - </property> - <property name="value"> - <number>1</number> - </property> - </widget> - </item> - </layout> - </widget> - </item> - <item row="0" column="1"> - <widget class="QGroupBox" name="groupBox_4"> - <property name="title"> - <string>Local runs:</string> - </property> - <property name="checkable"> - <bool>true</bool> - </property> - <property name="checked"> - <bool>false</bool> - </property> - <layout class="QGridLayout" name="gridLayout_11"> - <item row="1" column="0" colspan="2"> - <layout class="QHBoxLayout" name="horizontalLayout_5"> - <item> - <widget class="QLabel" name="label_recon_scripts"> - <property name="text"> - <string>Reconstruction scripts:</string> - </property> - </widget> - </item> - <item> - <widget class="QLineEdit" name="lineEdit_local_recon_scripts"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> - <horstretch>2</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="text"> - <string>C:/MantidInstall/scripts/</string> - </property> - <property name="readOnly"> - <bool>true</bool> - </property> - </widget> - </item> - <item> - <widget class="QPushButton" name="pushButton_local_recon_scripts_dir"> - <property name="text"> - <string>Browse</string> - </property> - </widget> - </item> - </layout> - </item> - <item row="0" column="0"> - <layout class="QGridLayout" name="gridLayout_10"> - <item row="0" column="0"> - <widget class="QLabel" name="label_3"> - <property name="enabled"> - <bool>false</bool> - </property> - <property name="text"> - <string>Max. processes:</string> - </property> - </widget> - </item> - <item row="0" column="1"> - <widget class="QSpinBox" name="spinBox_local_processes"> - <property name="enabled"> - <bool>false</bool> - </property> - <property name="minimum"> - <number>1</number> - </property> - <property name="maximum"> - <number>10</number> - </property> - <property name="value"> - <number>4</number> - </property> - </widget> - </item> - <item row="1" column="0"> - <widget class="QLabel" name="label_25"> - <property name="enabled"> - <bool>false</bool> - </property> - <property name="text"> - <string>Number of cores:</string> - </property> - </widget> - </item> - <item row="1" column="1"> - <widget class="QSpinBox" name="spinBox_local_cores"> - <property name="enabled"> - <bool>false</bool> - </property> - <property name="minimumSize"> - <size> - <width>0</width> - <height>10</height> - </size> - </property> - <property name="maximum"> - <number>99</number> - </property> - <property name="value"> - <number>4</number> - </property> - </widget> - </item> - </layout> - </item> - <item row="0" column="1"> - <spacer name="horizontalSpacer_7"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>259</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item row="2" column="0" colspan="2"> - <layout class="QHBoxLayout" name="horizontalLayout_6"> - <item> - <widget class="QLabel" name="label_13_local_external_interpreter"> - <property name="text"> - <string>External interpreter:</string> - </property> - </widget> - </item> - <item> - <widget class="QLineEdit" name="lineEdit_local_external_interpreter"> - <property name="text"> - <string>C:\local\Anaconda\python.exe</string> - </property> - <property name="readOnly"> - <bool>true</bool> - </property> - </widget> - </item> - <item> - <widget class="QPushButton" name="pushButton_local_external_interpreter"> - <property name="text"> - <string>Browse</string> - </property> - </widget> - </item> - </layout> - </item> - </layout> - </widget> - </item> - </layout> - </widget> - </item> - <item row="0" column="0"> - <widget class="QGroupBox" name="groupBox"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> - <horstretch>0</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> - <property name="title"> - <string>File system and paths of the tomography system:</string> - </property> - <property name="checkable"> - <bool>true</bool> - </property> - <property name="checked"> - <bool>false</bool> - </property> - <layout class="QGridLayout" name="gridLayout_7"> - <item row="0" column="0"> - <widget class="QGroupBox" name="groupBox_2"> - <property name="title"> - <string>Path components of the inputs and outputs:</string> - </property> - <layout class="QGridLayout" name="gridLayout_5"> - <item row="0" column="0"> - <widget class="QLabel" name="label_4"> - <property name="text"> - <string>1st level:</string> - </property> - </widget> - </item> - <item row="0" column="1"> - <widget class="QLineEdit" name="lineEdit_path_comp_1st"> - <property name="text"> - <string>data</string> - </property> - </widget> - </item> - <item row="1" column="0"> - <widget class="QLabel" name="label_5"> - <property name="text"> - <string>2nd level:</string> - </property> - </widget> - </item> - <item row="1" column="1"> - <widget class="QComboBox" name="comboBox_path_comp_2nd"> - <item> - <property name="text"> - <string>Experiment Reference (RB number)</string> - </property> - </item> - </widget> - </item> - <item row="2" column="0"> - <widget class="QLabel" name="label_6"> - <property name="text"> - <string>3rd level:</string> - </property> - </widget> - </item> - <item row="2" column="1"> - <widget class="QComboBox" name="comboBox_path_comp_3rd"> - <item> - <property name="text"> - <string>Sample/experiment name (free form)</string> - </property> - </item> - </widget> - </item> - <item row="3" column="0"> - <widget class="QLabel" name="label_7"> - <property name="text"> - <string>4th level:</string> - </property> - </widget> - </item> - <item row="4" column="0" colspan="2"> - <layout class="QHBoxLayout" name="horizontalLayout_3"> - <item> - <widget class="QGroupBox" name="groupBox_7"> - <property name="title"> - <string>Path components (prefixes) of the inputs:</string> - </property> - <layout class="QGridLayout" name="gridLayout_4"> - <item row="2" column="1"> - <widget class="QLineEdit" name="lineEdit_path_comp_input_darks"> - <property name="text"> - <string>dark</string> - </property> - <property name="readOnly"> - <bool>true</bool> - </property> - </widget> - </item> - <item row="1" column="1"> - <widget class="QLineEdit" name="lineEdit_path_comp_input_flats"> - <property name="text"> - <string>flat</string> - </property> - <property name="readOnly"> - <bool>true</bool> - </property> - </widget> - </item> - <item row="2" column="0"> - <widget class="QLabel" name="label_11"> - <property name="text"> - <string>Dark images:</string> - </property> - </widget> - </item> - <item row="0" column="0"> - <widget class="QLabel" name="label_9"> - <property name="text"> - <string>Sample images</string> - </property> - </widget> - </item> - <item row="1" column="0"> - <widget class="QLabel" name="label_10"> - <property name="text"> - <string>Flat images:</string> - </property> - </widget> - </item> - <item row="0" column="1"> - <widget class="QLineEdit" name="lineEdit_path_comp_input_samples"> - <property name="text"> - <string>data</string> - </property> - <property name="readOnly"> - <bool>true</bool> - </property> - </widget> - </item> - <item row="1" column="2"> - <spacer name="horizontalSpacer_6"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>40</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - </layout> - </widget> - </item> - <item> - <layout class="QVBoxLayout" name="verticalLayout"> - <item> - <widget class="QGroupBox" name="groupBox_6"> - <property name="title"> - <string>Path components of the outputs:</string> - </property> - <layout class="QGridLayout" name="gridLayout_3"> - <item row="0" column="0"> - <widget class="QLabel" name="label_8"> - <property name="text"> - <string>Pre-processed data::</string> - </property> - </widget> - </item> - <item row="0" column="1"> - <widget class="QLineEdit" name="lineEdit_path_comp_out_preprocessed"> - <property name="text"> - <string>pre_processed</string> - </property> - <property name="readOnly"> - <bool>true</bool> - </property> - </widget> - </item> - <item row="0" column="2"> - <spacer name="horizontalSpacer_4"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>40</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item row="1" column="0"> - <widget class="QLabel" name="label_2"> - <property name="text"> - <string>Reconstructed data::</string> - </property> - </widget> - </item> - <item row="1" column="1"> - <widget class="QLineEdit" name="lineEdit_path_comp_out_processed"> - <property name="text"> - <string>processed</string> - </property> - <property name="readOnly"> - <bool>false</bool> - </property> - </widget> - </item> - <item row="1" column="2"> - <spacer name="horizontalSpacer_5"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>40</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - </layout> - </widget> - </item> - <item> - <spacer name="verticalSpacer"> - <property name="orientation"> - <enum>Qt::Vertical</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>20</width> - <height>18</height> - </size> - </property> - </spacer> - </item> - </layout> - </item> - </layout> - </item> - </layout> - </widget> - </item> - <item row="1" column="0"> - <widget class="QGroupBox" name="groupBox_3"> - <property name="title"> - <string>Paths on the remote (SCARF) file system</string> - </property> - <property name="checkable"> - <bool>true</bool> - </property> - <property name="checked"> - <bool>false</bool> - </property> - <layout class="QGridLayout" name="gridLayout_2"> - <item row="0" column="0"> - <layout class="QHBoxLayout" name="horizontalLayout_10"> - <item> - <widget class="QLabel" name="label_22"> - <property name="text"> - <string>Base path for tomography data:</string> - </property> - </widget> - </item> - <item> - <widget class="QLineEdit" name="lineEdit_remote_base_path_data"> - <property name="minimumSize"> - <size> - <width>0</width> - <height>20</height> - </size> - </property> - <property name="text"> - <string>/work/imat</string> - </property> - </widget> - </item> - <item> - <spacer name="horizontalSpacer_2"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>40</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - </layout> - </item> - <item row="1" column="0"> - <layout class="QHBoxLayout" name="horizontalLayout_2"> - <item> - <widget class="QLabel" name="label"> - <property name="text"> - <string>Base path for reconstruction tools/scripts:</string> - </property> - </widget> - </item> - <item> - <widget class="QLineEdit" name="lineEdit_remote_scripts_base_dir"> - <property name="text"> - <string>/work/imat/phase_commissioning</string> - </property> - </widget> - </item> - <item> - <widget class="QPushButton" name="pushButton_reset_scripts_base_dir_remote"> - <property name="text"> - <string>Reset</string> - </property> - </widget> - </item> - </layout> - </item> - </layout> - </widget> - </item> - <item row="2" column="0"> - <widget class="QGroupBox" name="groupBox_8"> - <property name="title"> - <string>Root paths on the local system</string> - </property> - <property name="checkable"> - <bool>true</bool> - </property> - <property name="checked"> - <bool>false</bool> - </property> - <layout class="QGridLayout" name="gridLayout"> - <item row="0" column="0"> - <layout class="QHBoxLayout" name="horizontalLayout_11"> - <item> - <widget class="QLabel" name="label_26"> - <property name="text"> - <string>Base drive / path for tomography data (in/out)::</string> - </property> - </widget> - </item> - <item> - <widget class="QLineEdit" name="lineEdit_on_local_data_drive_or_path"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> - <horstretch>1</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="minimumSize"> - <size> - <width>0</width> - <height>20</height> - </size> - </property> - <property name="text"> - <string>D:\</string> - </property> - <property name="readOnly"> - <bool>true</bool> - </property> - </widget> - </item> - <item> - <widget class="QPushButton" name="pushButton_on_local_data_drive_or_path"> - <property name="text"> - <string>Browse</string> - </property> - </widget> - </item> - <item> - <spacer name="horizontalSpacer"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>40</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - </layout> - </item> - <item row="1" column="0"> - <layout class="QHBoxLayout" name="horizontalLayout_4"> - <item> - <widget class="QLabel" name="label_12"> - <property name="text"> - <string>Network drive or mount point for the remote:</string> - </property> - </widget> - </item> - <item> - <widget class="QLineEdit" name="lineEdit_on_local_remote_data_drive_path"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> - <horstretch>1</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="text"> - <string>S:</string> - </property> - <property name="readOnly"> - <bool>true</bool> - </property> - </widget> - </item> - <item> - <widget class="QPushButton" name="pushButton_on_local_remote_data_drive_path"> - <property name="text"> - <string>Browse</string> - </property> - </widget> - </item> - <item> - <spacer name="horizontalSpacer_3"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>40</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - </layout> - </item> - </layout> - </widget> - </item> - </layout> - </widget> - </item> - <item row="2" column="0"> - <layout class="QHBoxLayout" name="horizontalLayout"> - <item> - <spacer name="horizontalSpacer_8"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>40</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item> - <widget class="QPushButton" name="pushButton_reset_all"> - <property name="text"> - <string>Reset all</string> - </property> - </widget> - </item> - </layout> - </item> - </layout> - </widget> - </widget> - </item> - </layout> - </widget> - <tabstops> - <tabstop>groupBox</tabstop> - <tabstop>lineEdit_path_comp_1st</tabstop> - <tabstop>comboBox_path_comp_2nd</tabstop> - <tabstop>comboBox_path_comp_3rd</tabstop> - <tabstop>lineEdit_path_comp_input_samples</tabstop> - <tabstop>lineEdit_path_comp_input_flats</tabstop> - <tabstop>lineEdit_path_comp_input_darks</tabstop> - <tabstop>lineEdit_path_comp_out_preprocessed</tabstop> - <tabstop>lineEdit_path_comp_out_processed</tabstop> - <tabstop>groupBox_3</tabstop> - <tabstop>lineEdit_remote_base_path_data</tabstop> - <tabstop>lineEdit_remote_scripts_base_dir</tabstop> - <tabstop>pushButton_reset_scripts_base_dir_remote</tabstop> - <tabstop>groupBox_8</tabstop> - <tabstop>lineEdit_on_local_data_drive_or_path</tabstop> - <tabstop>pushButton_on_local_data_drive_or_path</tabstop> - <tabstop>lineEdit_on_local_remote_data_drive_path</tabstop> - <tabstop>pushButton_on_local_remote_data_drive_path</tabstop> - <tabstop>groupBox_10</tabstop> - <tabstop>groupBox_5</tabstop> - <tabstop>spinBox_remote_cores</tabstop> - <tabstop>groupBox_4</tabstop> - <tabstop>spinBox_local_processes</tabstop> - <tabstop>spinBox_local_cores</tabstop> - <tabstop>lineEdit_local_recon_scripts</tabstop> - <tabstop>pushButton_local_recon_scripts_dir</tabstop> - <tabstop>scrollArea</tabstop> - </tabstops> - <resources/> - <connections/> -</ui> diff --git a/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomographyIfaceQtTabVisualize.ui b/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomographyIfaceQtTabVisualize.ui deleted file mode 100644 index 89b22407306..00000000000 --- a/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomographyIfaceQtTabVisualize.ui +++ /dev/null @@ -1,236 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<ui version="4.0"> - <class>TomographyIfaceQtTabVisualize</class> - <widget class="QWidget" name="TomographyIfaceQtTabVisualize"> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>733</width> - <height>569</height> - </rect> - </property> - <property name="windowTitle"> - <string>Form</string> - </property> - <layout class="QGridLayout" name="gridLayout_2"> - <item row="0" column="0"> - <widget class="QSplitter" name="splitter"> - <property name="orientation"> - <enum>Qt::Vertical</enum> - </property> - <widget class="QWidget" name="layoutWidget"> - <layout class="QHBoxLayout" name="horizontalLayout_4"> - <item> - <layout class="QVBoxLayout" name="verticalLayout" stretch="0,1"> - <item> - <layout class="QHBoxLayout" name="horizontalLayout_3"> - <item> - <widget class="QPushButton" name="pushButton_local_default_dir"> - <property name="text"> - <string>Local default</string> - </property> - </widget> - </item> - <item> - <widget class="QPushButton" name="pushButton_remote_default_dir"> - <property name="text"> - <string>Remote default</string> - </property> - </widget> - </item> - <item> - <spacer name="horizontalSpacer"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>40</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item> - <widget class="QPushButton" name="pushButton_browse_files"> - <property name="text"> - <string>Browse</string> - </property> - </widget> - </item> - </layout> - </item> - <item> - <widget class="QTreeView" name="treeView_files"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> - <horstretch>1</horstretch> - <verstretch>1</verstretch> - </sizepolicy> - </property> - </widget> - </item> - </layout> - </item> - <item> - <layout class="QVBoxLayout" name="verticalLayout_2"> - <item> - <spacer name="verticalSpacer_2"> - <property name="orientation"> - <enum>Qt::Vertical</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>20</width> - <height>40</height> - </size> - </property> - </spacer> - </item> - <item> - <widget class="QPushButton" name="pushButton_paraview"> - <property name="text"> - <string>>ParaView</string> - </property> - </widget> - </item> - <item> - <widget class="QPushButton" name="pushButton_octopus"> - <property name="text"> - <string>>Octopus Vis.</string> - </property> - </widget> - </item> - <item> - <widget class="QPushButton" name="pushButton_vgstudio"> - <property name="enabled"> - <bool>false</bool> - </property> - <property name="text"> - <string>>VGStudio</string> - </property> - </widget> - </item> - <item> - <spacer name="verticalSpacer"> - <property name="orientation"> - <enum>Qt::Vertical</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>20</width> - <height>148</height> - </size> - </property> - </spacer> - </item> - </layout> - </item> - </layout> - </widget> - <widget class="QGroupBox" name="groupBox"> - <property name="title"> - <string>Configuration</string> - </property> - <property name="checkable"> - <bool>true</bool> - </property> - <property name="checked"> - <bool>false</bool> - </property> - <layout class="QGridLayout" name="gridLayout" rowstretch="0,0" rowminimumheight="1,0"> - <property name="sizeConstraint"> - <enum>QLayout::SetMinimumSize</enum> - </property> - <property name="margin"> - <number>3</number> - </property> - <property name="spacing"> - <number>2</number> - </property> - <item row="0" column="0"> - <layout class="QHBoxLayout" name="horizontalLayout_2"> - <property name="spacing"> - <number>0</number> - </property> - <item> - <widget class="QLabel" name="label_2"> - <property name="text"> - <string>ParaView:</string> - </property> - </widget> - </item> - <item> - <widget class="QLineEdit" name="lineEdit_paraview_location"> - <property name="text"> - <string>C:\Program Files\ParaView</string> - </property> - </widget> - </item> - <item> - <widget class="QPushButton" name="pushButton_browse_paraview"> - <property name="text"> - <string>Browse</string> - </property> - </widget> - </item> - </layout> - </item> - <item row="1" column="0"> - <layout class="QHBoxLayout" name="horizontalLayout_5"> - <property name="spacing"> - <number>0</number> - </property> - <item> - <widget class="QLabel" name="label_3"> - <property name="text"> - <string>Octopus Vis.</string> - </property> - </widget> - </item> - <item> - <widget class="QLineEdit" name="lineEdit_octopus_vis_location"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> - <horstretch>1</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - <property name="text"> - <string>C:/Program Files/Octopus Imaging/Octopus Visualisation</string> - </property> - </widget> - </item> - <item> - <widget class="QPushButton" name="pushButton_browse_octopus"> - <property name="text"> - <string>Browse</string> - </property> - </widget> - </item> - </layout> - </item> - </layout> - </widget> - </widget> - </item> - </layout> - </widget> - <tabstops> - <tabstop>pushButton_local_default_dir</tabstop> - <tabstop>pushButton_remote_default_dir</tabstop> - <tabstop>pushButton_browse_files</tabstop> - <tabstop>treeView_files</tabstop> - <tabstop>pushButton_paraview</tabstop> - <tabstop>pushButton_octopus</tabstop> - <tabstop>pushButton_vgstudio</tabstop> - <tabstop>groupBox</tabstop> - <tabstop>lineEdit_paraview_location</tabstop> - <tabstop>pushButton_browse_paraview</tabstop> - <tabstop>lineEdit_octopus_vis_location</tabstop> - <tabstop>pushButton_browse_octopus</tabstop> - </tabstops> - <resources/> - <connections/> -</ui> diff --git a/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomographyIfaceViewQtGUI.h b/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomographyIfaceViewQtGUI.h deleted file mode 100644 index 446294d2ce7..00000000000 --- a/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomographyIfaceViewQtGUI.h +++ /dev/null @@ -1,402 +0,0 @@ -#ifndef MANTIDQTCUSTOMINTERFACES_TOMOGRAPHY_TOMOGRAPHYIFACEVIEWQTGUI_H_ -#define MANTIDQTCUSTOMINTERFACES_TOMOGRAPHY_TOMOGRAPHYIFACEVIEWQTGUI_H_ - -#include "MantidAPI/IRemoteJobManager.h" -#include "MantidAPI/ITableWorkspace_fwd.h" -#include "MantidAPI/MatrixWorkspace_fwd.h" -#include "MantidAPI/TableRow.h" -#include "MantidQtAPI/BatchAlgorithmRunner.h" -#include "MantidQtAPI/UserSubWindow.h" -#include "MantidQtCustomInterfaces/DllConfig.h" -#include "MantidQtCustomInterfaces/Tomography/ITomographyIfacePresenter.h" -#include "MantidQtCustomInterfaces/Tomography/ITomographyIfaceView.h" -#include "MantidQtCustomInterfaces/Tomography/ImggFormatsConvertViewQtWidget.h" -#include "MantidQtCustomInterfaces/Tomography/TomoSystemSettings.h" -#include "MantidQtCustomInterfaces/Tomography/TomographyROIViewQtWidget.h" - -#include "ui_ImageSelectCoRAndRegions.h" -#include "ui_TomographyIfaceQtGUI.h" -#include "ui_TomographyIfaceQtTabEnergy.h" -#include "ui_TomographyIfaceQtTabFiltersSettings.h" -#include "ui_TomographyIfaceQtTabRun.h" -#include "ui_TomographyIfaceQtTabSystemSettings.h" -#include "ui_TomographyIfaceQtTabVisualize.h" -#include <boost/scoped_ptr.hpp> -#include <json/json.h> - -// widgets used in this interface -class QMutex; - -namespace MantidQt { -namespace API { -class BatchAlgorithmRunner; -} -} -// Qt classes forward declarations - -namespace MantidQt { -namespace CustomInterfaces { - -/** -Qt-based view of the Tomography GUI. Provides a concrete view for the -graphical interface for tomography functionality in Mantid. This view -is Qt-based and it is probably the only one that will be implemented -in a foreseeable horizon. The interface of this class is given by -ITomographyIfaceView so that it fits in the MVP (Model-View-Presenter) -design of the tomography GUI. - -Copyright © 2014-2016 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 MANTIDQT_CUSTOMINTERFACES_DLL TomographyIfaceViewQtGUI - : public MantidQt::API::UserSubWindow, - public ITomographyIfaceView { - Q_OBJECT - -public: - /// Default Constructor - TomographyIfaceViewQtGUI(QWidget *parent = 0); - /// Destructor - ~TomographyIfaceViewQtGUI() override; - - /// Interface name - static std::string name() { return "Tomographic Reconstruction"; } - /// This interface's categories. - static QString categoryInfo() { return "Diffraction"; } - - void userWarning(const std::string &warn, - const std::string &description) override; - - void userError(const std::string &err, - const std::string &description) override; - - std::vector<std::string> logMsgs() const override { return m_logMsgs; } - - void setComputeResources(const std::vector<std::string> &resources, - const std::vector<bool> &enabled) override; - - void setReconstructionTools(const std::vector<std::string> &tools, - const std::vector<bool> &enabled) override; - - std::string experimentReference() const override { - return m_setupExperimentRef; - } - - std::string getUsername() const override; - - std::string getPassword() const override; - - void updateLoginControls(bool loggedIn) override; - - void enableLoggedActions(bool enable) override; - - /// possible for the user to define the configuration of a tool - void enableConfigTool(bool on) override; - - /// possible for the user to run / submit a job - void enableRunReconstruct(bool on) override; - - void updateCompResourceStatus(bool online); - - void updateJobsInfoDisplay( - const std::vector<Mantid::API::IRemoteJobManager::RemoteJobInfo> &status, - const std::vector<Mantid::API::IRemoteJobManager::RemoteJobInfo> & - localStatus) override; - - std::vector<std::string> processingJobsIDs() const override { - return m_processingJobsIDs; - } - - TomoSystemSettings systemSettings() const override; - - TomoReconFiltersSettings prePostProcSettings() const override; - - std::string currentComputeResource() const override { - return m_currentComputeRes; - } - std::string currentReconTool() const override { return m_currentReconTool; } - - int keepAlivePeriod() override { return m_settings.useKeepAlive; } - - TomoPathsConfig currentPathsConfig() const override { return m_pathsConfig; } - - ImageStackPreParams currentROIEtcParams() const override { - return m_tabROIWidget->userSelection(); - } - - std::map<std::string, std::string> - currentAggregateBandsParams() const override { - return grabCurrentAggParams(); - } - - void runAggregateBands(Mantid::API::IAlgorithm_sptr alg) override; - - bool userConfirmation(const std::string &title, - const std::string &body) override; - - std::string getCachedExecutable() const override { return m_extExec; } - - std::vector<std::string> getCachedArguments() const override { - return m_extArgs; - } - - void emitExternalProcessFinished(const QString &str) override; - -signals: - void externalProcessFinished(const QString &str); - -private slots: - void reconstructClicked(); - void toolSetupClicked(); - void runVisualizeClicked(); - void jobCancelClicked(); - void jobTableRefreshClicked(); - void updatedExperimentReference(); - - void compResourceIndexChanged(int); - void runToolIndexChanged(int); - void SCARFLoginClicked(); - void SCARFLogoutClicked(); - - void browseLocalInOutDirClicked(); - void browseLocalRemoteDriveOrPath(); - void browseLocalReconScriptsDirClicked(); - void browseLocalExternalInterpreterClicked(); - - void flatsPathCheckStatusChanged(int status); - void darksPathCheckStatusChanged(int status); - - void samplesPathBrowseClicked(); - void flatsPathBrowseClicked(); - void darksPathBrowseClicked(); - - void samplesPathEditedByUser(); - void flatsPathEditedByUser(); - void darksPathEditedByUser(); - - /// For the filters tab - void resetPrePostFilters(); - - /// open the MantidQT help window for this interface - void openHelpWin(); - - // visualization tools / short-cuts - void browseFilesToVisualizeClicked(); - void sendToParaviewClicked(); - void sendToOctopusVisClicked(); - void defaultDirLocalVisualizeClicked(); - void defaultDirRemoteVisualizeClicked(); - void browseVisToolParaviewClicked(); - void browseVisToolOctopusClicked(); - - // processing of energy bands - void browseEnergyInputClicked(); - void browseEnergyOutputClicked(); - - void systemSettingsEdited(); - void systemSettingsNumericEdited(); - - // part of the system / advanced settings - void resetRemoteSetup(); - - // reset all system / advanced settings - void resetSystemSettings(); - - // start aggregation of energy/wavelength bands - void pushButtonAggClicked(); - void browseAggScriptClicked(); - // aggregation run finished - void finishedAggBands(bool error); - - // If the exec string is empty then the executable will be the one from the - // system settings tab - void runExternalProcess(const std::string &exec, - const std::vector<std::string> &args); - - void imageOrStackLoadedInRoi(const std::string &path); - -private: - /// Setup the interface (tab UI) - void initLayout() override; - - void doSetupSectionRun(); - void doSetupSectionFilters(); - void doSetupSectionVisualize(); - void doSetupSectionEnergy(); - void doSetupSectionSystemSettings(); - void doSetupGeneralWidgets(); - void doSetupSectionRoi(); - - /// Load default interface settings for each tab, normally on startup - void readSettings(); - /// for the energy bands tab/widget - void readSettingsEnergy(); - /// save settings (before closing) - void saveSettings() const override; - /// for the energy bands tab/widget - void saveSettingsEnergy() const; - - void updateSystemSettingsTabFields(const TomoSystemSettings &setts); - - void updatePathsConfig(const TomoPathsConfig &cfg) override; - - void showToolConfig( - MantidQt::CustomInterfaces::TomoToolConfigDialogBase &dialog) override; - - void closeEvent(QCloseEvent *ev) override; - - void processPathBrowseClick(QLineEdit *le, std::string &data); - - void updateFlatsDarksFromSamplePath(const std::string &path); - - TomoSystemSettings grabSystemSettingsFromUser() const; - - TomoReconFiltersSettings grabPrePostProcSettings() const; - - void setPrePostProcSettings(const TomoReconFiltersSettings &opts); - - std::string - checkUserBrowseDir(QLineEdit *le, - const std::string &userMsg = "Open directory/folder", - bool remember = true); - - std::string checkUserBrowseFile(QLineEdit *le, - const std::string &userMsg = "Open file", - bool remember = true); - - std::string checkDefaultVisualizeDir(const std::string &basePath, - const std::string &appendComp); - - void sendToVisTool(const std::string &toolName, const std::string &pathString, - const std::string &appendBin); - - std::map<std::string, std::string> grabCurrentAggParams() const; - - void sendLog(const std::string &msg); - - static const std::string g_styleSheetOffline; - static const std::string g_styleSheetOnline; - - /// Interface definition with widgets for the main interface window - Ui::TomographyIfaceQtGUI m_ui; - // And its sections/tabs. Note that for compactness they're called simply - // 'tabs' but they could be separate dialogs, widgets, etc. combined in - // different ways. - Ui::TomographyIfaceQtTabRun m_uiTabRun; - Ui::TomographyIfaceQtTabFiltersSettings m_uiTabFilters; - Ui::ImageSelectCoRAndRegions m_uiTabCoR; - Ui::TomographyIfaceQtTabVisualize m_uiTabVisualize; - Ui::TomographyIfaceQtTabEnergy m_uiTabEnergy; - Ui::TomographyIfaceQtTabSystemSettings m_uiTabSystemSettings; - - TomographyROIViewQtWidget *m_tabROIWidget; - ImggFormatsConvertViewQtWidget *m_tabImggFormats; - - std::vector<std::string> m_processingJobsIDs; - - std::string m_currentComputeRes; - std::string m_currentReconTool; - - std::string m_imgPath; - - std::vector<Mantid::API::IRemoteJobManager::RemoteJobInfo> m_localJobsStatus; - - // Settings for external tools. where to find the system Python - static std::vector<std::string> g_defAddPathPython; - std::vector<std::string> m_defAddPathPython; - - static const std::string g_SCARFName; - // a general (all tools in principle) default output path - static const std::string g_defOutPathLocal; - static const std::string g_defOutPathRemote; - - TomoPathsConfig m_pathsConfig; - - // several paths or path components related to where the files are found - // (raw files, reconstructions, pre-post processed files, etc.) - // These are the defaults - static const std::string g_defPathComponentPhase; - static const std::string g_defExperimentRef; - // reconstruction scripts (external, but shipped with Mantid) - static const std::string g_defPathReconScripts; - // base dir for the reconstruction outputs - static const std::string g_defPathReconOut; - static const std::string g_defParaviewPath; - static const std::string g_defParaviewAppendPath; - static const std::string g_defOctopusVisPath; - static const std::string g_defOctopusAppendPath; - static const std::string g_defProcessedSubpath; - // And these are the paths set up - std::string m_setupPathComponentPhase; - std::string m_setupExperimentRef; - std::string m_setupParaviewPath; - std::string m_setupOctopusVisPath; - std::string m_setupProcessedSubpath; - - // here the view puts messages before notifying the presenter to show them - std::vector<std::string> m_logMsgs; - - /// The not-so-small set of paths, path compnents and related parameters for - /// the local and remote machines - TomoSystemSettings m_systemSettings; - - // Basic representation of user settings, read/written on startup/close. - // TODO: this could be done more sophisticated, with a class using - // QDataStream and in/out stream operators for example. Keeping - // it simple for now - struct UserSettings { - std::string SCARFBasePath; - int useKeepAlive; // use if >0, number of seconds for a periodic query - bool onCloseAskForConfirmation; - - UserSettings() - : SCARFBasePath("/work/imat/runs/test/"), useKeepAlive(60), - onCloseAskForConfirmation(false) {} - }; - UserSettings m_settings; - - // path name for persistent settings - std::string m_settingsGroup; - std::string m_settingsSubGroupEnergy; - - // To run aggregation of wavelength/energy bands - std::unique_ptr<MantidQt::API::BatchAlgorithmRunner> m_aggAlgRunner; - - // TODO? move to TomographyIfaceModel or TomographyIfaceSavuModel.h - // plugins for Savu config files - Mantid::API::ITableWorkspace_sptr m_availPlugins; - Mantid::API::ITableWorkspace_sptr m_currPlugins; - std::string m_currentParamPath; - - // presenter as in the model-view-presenter - boost::scoped_ptr<ITomographyIfacePresenter> m_presenter; - - // holders for the external process' arguments - // as the connection to the presenter is not done via Qt Signals we have no - // other way of transfering data between them - std::string m_extExec = ""; - std::vector<std::string> m_extArgs; -}; - -} // namespace CustomInterfaces -} // namespace MantidQt - -#endif // MANTIDQTCUSTOMINTERFACES_TOMOGRAPHY_TOMOGRAPHYIFACEVIEWQTGUI_H_ diff --git a/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomographyProcess.h b/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomographyProcess.h deleted file mode 100644 index 17311d6c905..00000000000 --- a/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomographyProcess.h +++ /dev/null @@ -1,105 +0,0 @@ -#ifndef MANTIDQTCUSTOMINTERFACES_TOMOGRAPHY_TOMOGRAPHYPROCESS_H_ -#define MANTIDQTCUSTOMINTERFACES_TOMOGRAPHY_TOMOGRAPHYPROCESS_H_ - -#include <QProcess> -#include <QString> -#include <QStringList> -#include <vector> - -namespace MantidQt { -namespace CustomInterfaces { - -/* -TomographyProcess class that run external processes and provides some helper -functions. This class was designed to be used with TomographyThread to run -external processes asyncronously to the main thread 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 TomographyProcess : public QProcess { - Q_OBJECT -public: - // we want a nullptr for parent so we can move it to a thread - TomographyProcess() : QProcess(nullptr) {} - - // intentionally copy the vector - void setup(const std::string &runnable, const std::vector<std::string> &args, - const std::string &allOpts, - const std::string &workerName = "Mantid_Local") { - m_runnable = QString::fromStdString(runnable); - m_args = buildArguments(args); - m_allArgs = allOpts; - m_workerName = workerName; - } - - std::string getRunnable() const { return m_runnable.toStdString(); } - std::string getArgs() const { return m_allArgs; } - std::string getName() const { return m_workerName; } - - /** - * This method must be called after the process has emitted started(). - * Otherwise the returned PID is wrong, as it has not been assigned - * a PID from the OS. - * - * The PID here is read after the process emits started() - * by a connection to addJobToStatus() by the Presenter. - */ - qint64 getPID() const { - auto pid = this->pid(); - - // qt connect could sometimes try to read the terminated process' PID - if (!pid) { - return 0; - } - -#ifdef _WIN32 - // windows gets a struct object with more info - auto actualpid = static_cast<qint64>(pid->dwProcessId); -#else - // linux just gets the PID - auto actualpid = static_cast<qint64>(pid); -#endif - return actualpid; - } - -public slots: - /** This method should be used to start the worker as it passes the setup - * runnable and args parameters into the base start method - */ - void startWorker() { start(m_runnable, m_args); } - -private: - QStringList buildArguments(const std::vector<std::string> &args) const { - QStringList list; - list.reserve(static_cast<int>(args.size())); - - for (const auto &arg : args) { - list << QString::fromStdString(arg); - } - - return list; - } - - QString m_runnable; - QStringList m_args; - - std::string m_allArgs; - std::string m_workerName; -}; -} // CustomInterfaces -} // MantidQt -#endif diff --git a/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomographyROIPresenter.h b/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomographyROIPresenter.h deleted file mode 100644 index 192ae80611f..00000000000 --- a/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomographyROIPresenter.h +++ /dev/null @@ -1,158 +0,0 @@ -#ifndef MANTIDQTCUSTOMINTERFACES_TOMOGRAPHY_TOMOGRAPHYROIPRESENTER_H_ -#define MANTIDQTCUSTOMINTERFACES_TOMOGRAPHY_TOMOGRAPHYROIPRESENTER_H_ - -#include "MantidAPI/WorkspaceGroup_fwd.h" -#include "MantidQtCustomInterfaces/Tomography/ITomographyROIPresenter.h" -#include "MantidQtCustomInterfaces/Tomography/ITomographyROIView.h" -#include "MantidQtCustomInterfaces/Tomography/ImageStackPreParams.h" -#include "MantidQtCustomInterfaces/Tomography/StackOfImagesDirs.h" -#include <memory> -#include <boost/scoped_ptr.hpp> - -#include <QObject> - -namespace MantidQt { - -namespace API { -class BatchAlgorithmRunner; -} - -namespace CustomInterfaces { -class TomographyThread; - -/** -Presenter for the image center of rotation (and other parameters) -selection widget. In principle, in a strict MVP setup, signals from -the model should always be handled through this presenter and never go -directly to the view, and viceversa. - -Copyright © 2015 ISIS Rutherford Appleton Laboratory, NScD -Oak Ridge National Laboratory & European Spallation Source - -This file is part of Mantid. - -Mantid is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 3 of the License, or -(at your option) any later version. - -Mantid is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see <http://www.gnu.org/licenses/>. - -File change history is stored at: <https://github.com/mantidproject/mantid> -Code Documentation is available at: <http://doxygen.mantidproject.org> -*/ -class MANTIDQT_CUSTOMINTERFACES_DLL TomographyROIPresenter - : public QObject, - public ITomographyROIPresenter { - // Q_OBJECT for the 'algorithm runner' signals - // TODO: move the AlgorithmRunner to the view? Have a different, non-Qt - // runner? - // Remove Q_OBJECT and take this file out out MOC_FILES in CMakeLists.txt - Q_OBJECT - -public: - /// Default constructor - normally used from the concrete view - TomographyROIPresenter(ITomographyROIView *view); - ~TomographyROIPresenter() override; - - void notify(ITomographyROIPresenter::Notification notif) override; - -protected: - void initialize(); - - /// clean shut down of model, view, etc. - void cleanup(); - - // Methods that process notifications from view->presenter - void processInit(); - - void processBrowseImage(); - void processBrowseStack(); - void processNewStack(bool singleImage); - void processLoadSingleImage(); - void processLoadStackOfImages(); - void processFindCoR(); - void setupAlgorithmRunnerAfterLoad(); - void processChangeImageType(); - void processChangeRotation(); - void processPlayStartStop(); - void processUpdateImgIndex(); - void processUpdateColorMap(); - void processColorRangeUpdated(); - - void processSelectCoR(); - void processSelectROI(); - void processSelectNormalization(); - void processFinishedCoR(); - void processFinishedROI(); - void processFinishedNormalization(); - void processResetCoR(); - void processResetROI(); - void processResetNormalization(); - - void processShutDown(); - -private slots: - void finishedLoadStack(bool error); - -private: - inline std::string trimFileNameFromPath(const std::string &path) { - return path.substr(0, path.find_last_of("/\\")); - } - - StackOfImagesDirs checkInputStack(const std::string &path); - - /// loads a list of images from a stack, from their individual paths - void loadFITSStack(const StackOfImagesDirs &soid, const std::string &wsgName, - const std::string &wsgFlatsName, - const std::string &wsgDarksName); - - void loadFITSList(const std::vector<std::string> &imgs, - const std::string &wsName); - - void loadFITSImage(const std::string &path, const std::string &wsName); - - std::string - filterImagePathsForFITSStack(const std::vector<std::string> &paths); - - /// the workspaces being visualized - Mantid::API::WorkspaceGroup_sptr m_stackSamples, m_stackFlats, m_stackDarks; - - /// whether 'playing' the current stack of images - bool m_playStatus; - - /// whether to show (potentially too many and too annoying) warning pop-ups or - /// messages - static bool g_warnIfUnexpectedFileExtensions; - - /// path to the image stack being visualized - std::string m_stackPath; - - /// To run sequences of algorithms in a separate thread - std::unique_ptr<MantidQt::API::BatchAlgorithmRunner> m_algRunner; - - /// Names used by the widget to store workspace groups - static const std::string g_wsgName; - static const std::string g_wsgFlatsName; - static const std::string g_wsgDarksName; - - /// Associated view for this presenter (MVP pattern) - ITomographyROIView *const m_view; - - /// Associated model for this presenter (MVP pattern). This is just - /// a set of coordinates - const boost::scoped_ptr<ImageStackPreParams> m_model; - - std::unique_ptr<TomographyThread> m_workerThread; -}; - -} // namespace CustomInterfaces -} // namespace MantidQt - -#endif // MANTIDQTCUSTOMINTERFACES_TOMOGRAPHY_TOMOGRAPHYROIPRESENTER_H_ diff --git a/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomographyROIViewQtWidget.h b/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomographyROIViewQtWidget.h deleted file mode 100644 index a42d94725d9..00000000000 --- a/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomographyROIViewQtWidget.h +++ /dev/null @@ -1,311 +0,0 @@ -#ifndef MANTIDQTCUSTOMINTERFACES_TOMOGRAPHY_TOMOGRAPHYROIVIEWQTWIDGET_H_ -#define MANTIDQTCUSTOMINTERFACES_TOMOGRAPHY_TOMOGRAPHYROIVIEWQTWIDGET_H_ - -#include "MantidAPI/MatrixWorkspace_fwd.h" -#include "MantidAPI/WorkspaceGroup_fwd.h" -#include "MantidQtCustomInterfaces/DllConfig.h" -#include "MantidQtCustomInterfaces/Tomography/ITomographyROIPresenter.h" -#include "MantidQtCustomInterfaces/Tomography/ITomographyROIView.h" - -#include "ui_ImageSelectCoRAndRegions.h" - -#include <boost/scoped_ptr.hpp> - -#include <QTimer> -// forward declarations for Qt -class QWidget; -class QPixmap; - -namespace Mantid { -namespace Kernel { -class V2D; -} -} - -namespace MantidQt { -namespace CustomInterfaces { - -/** -Qt-based view of the widget to handle the selection of the center of -rotation, region of interest, region for normalization, etc. from an -image or stack of images. Provides a concrete view for the graphical -interface for tomography functionality in Mantid. This view is -Qt-based and it is probably the only one that will be implemented in a -foreseeable horizon. The interface of this class is given by -ITomographyROIView so that it fits in the MVP (Model-View-Presenter) design -of the TomographyROI widget. - -Copyright © 2015-2016 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 MANTIDQT_CUSTOMINTERFACES_DLL TomographyROIViewQtWidget - : public QWidget, - public ITomographyROIView { - Q_OBJECT - -public: - TomographyROIViewQtWidget(QWidget *parent = 0); - ~TomographyROIViewQtWidget() override; - - void setParams(ImageStackPreParams ¶ms) override; - - ImageStackPreParams userSelection() const override; - - SelectionState selectionState() const override { return m_selectionState; } - - void changeSelectionState(const SelectionState &state) override; - - /// show a stack of images given the path to the files - void showStack(const std::string &path) override; - - /// show a (new) stack of images that have been loaded into groups of - /// workspaces (samples, flats, darks) - void showStack(const Mantid::API::WorkspaceGroup_sptr &wsg, - const Mantid::API::WorkspaceGroup_sptr &wsgFlats, - const Mantid::API::WorkspaceGroup_sptr &wsgDarks) override; - - const Mantid::API::WorkspaceGroup_sptr stackSamples() const override { - return m_stackSamples; - } - - void showProjection(const Mantid::API::WorkspaceGroup_sptr &wsg, - size_t idx) override; - - void userWarning(const std::string &warn, - const std::string &description) override; - - void userError(const std::string &err, - const std::string &description) override; - - void enableActions(bool enable) override; - - size_t currentImgIndex() const override; - - void updateImgWithIndex(size_t idx) override; - - void playStart() override; - - void playStop() override; - - float currentRotationAngle() const override; - - void updateRotationAngle(float angle) override; - - Mantid::API::WorkspaceGroup_sptr currentImageTypeStack() const override; - - void updateImageType(const Mantid::API::WorkspaceGroup_sptr wsg) override; - - std::string askImagePath(const std::string &windowTitle) override; - - std::string askColorMapFile() override; - - void updateColorMap(const std::string &filename) override; - - void saveSettings() const override; - void imageOrStackLoaded(const std::string &path) override; - -signals: - void findCORClickedSignal(const std::string &exec, - const std::vector<std::string> &args); - - void imageOrStackLoadedSignal(const std::string &path); - -public slots: - void readCoRFromProcessOutput(const QString &str); - -protected: - void initLayout(); - - void resetCoR() override; - void resetROI() override; - void resetNormArea() override; - - void resetWidgetsOnNewStack(); - - /// update coordinates from mouse event - void mouseUpdateCoR(const int x, const int y); - - // get the coordinates on the first click of selection - void mouseUpdateROICornersStartSelection(const int x, const int y); - // update the coordinates while dragging the mouse - void mouseUpdateROICornerContinuedSelection(const int x, const int y); - // notify the presenter that the user has stopped selection - void mouseFinishROI(const int x, const int y); - - // get the coordinates on the first click of selection - void mouseUpdateNormAreaCornersStartSelection(const int x, const int y); - // update the coordinates while dragging the mouse - void mouseUpdateNormAreaCornerContinuedSelection(const int x, const int y); - // notify the presenter that the user has stopped selection - void mouseFinishNormArea(const int x, const int y); - -private slots: - void browseImageClicked(); - void browseStackClicked(); - - void rotationUpdated(int idx); - void autoCoRToolChanged(int idx); - - void imageTypeUpdated(int idx); - - void loadColorMapRequest(); - void colorRangeChanged(); - - void corClicked(); - void corResetClicked(); - void roiClicked(); - void roiResetClicked(); - void normAreaClicked(); - void normAreaResetClicked(); - - void playClicked(); - void updatePlay(); - - void updateFromImagesSlider(int current); - - void valueUpdatedCoR(int v); - void valueUpdatedROI(int v); - void valueUpdatedNormArea(int v); - void findCORClicked(); - -private: - void setupConnections(); - - void readSettings(); - - /// enable types of images (sample, flat, dark) - /// depending on their - /// availability - void enableImageTypes(bool enableSamples, bool enableFlats, bool enableDarks); - - /// enable/disable the groups with spin boxes for the - /// center and corners - void enableParamWidgets(bool enable); - - // widget closing - void closeEvent(QCloseEvent *ev) override; - - /// initialize values to defaults and set max/min for - /// the spin boxes - void initParamWidgets(size_t maxWidth, size_t maxHeight); - - /// Set coordinates in the widgets from a params object - void setParamWidgets(ImageStackPreParams ¶ms); - - // shows the image in a widget - void showProjectionImage(const Mantid::API::WorkspaceGroup_sptr &wsg, - size_t idx, float rotationAngle = 0); - - void getCheckedDimensions(const Mantid::API::MatrixWorkspace_sptr ws, - size_t &width, size_t &height); - - void checkNewProjectionImage(const Mantid::API::WorkspaceGroup_sptr &wsg, - size_t idx, size_t &width, size_t &height, - Mantid::API::MatrixWorkspace_sptr &imgWS, - std::string &imgName); - - void getPixelMinMax(Mantid::API::MatrixWorkspace_sptr ws, double &min, - double &max); - - QPixmap transferWSImageToQPixmap(const Mantid::API::MatrixWorkspace_sptr ws, - size_t width, size_t height, - float rotationAngle); - - void grabCoRFromWidgets(); - void grabROIFromWidgets(); - void grabNormAreaFromWidgets(); - - void grabCoRFromMousePoint(int x, int y); - void grabROICorner1FromMousePoint(int x, int y); - void grabROICorner2FromMousePoint(int x, int y); - void grabNormAreaCorner1FromMousePoint(int x, int y); - void grabNormAreaCorner2FromMousePoint(int x, int y); - - /// repaint the image with new positions of points and - /// rectangles - void refreshImage(); - void refreshCoR(); - void refreshROI(); - void refreshNormArea(); - - /// draw a cross/target symbol - void drawCenterCrossSymbol(QPainter &painter, - const Mantid::Kernel::V2D ¢er) const; - - /// draw a rectangle/box to highlight the ROI: region of - /// interest - void drawBoxROI(QPainter &painter, const Mantid::Kernel::V2D &first, - const Mantid::Kernel::V2D &second) const; - - /// draw a rectangle/box to highlight the normalization - /// ("air") region - void drawBoxNormalizationRegion(QPainter &painter, - const Mantid::Kernel::V2D &first, - const Mantid::Kernel::V2D &second) const; - - bool eventFilter(QObject *obj, QEvent *event) override; - - struct RectangleXY { - int right; - int top; - } m_startOfRectangle; - - void updateValuesForSpinBoxes( - const int x, const int y, - const struct TomographyROIViewQtWidget::RectangleXY startPositions, - QSpinBox *spinLeft, QSpinBox *spinTop, QSpinBox *spinRight, - QSpinBox *spinBottom); - - Ui::ImageSelectCoRAndRegions m_ui; - - Mantid::API::WorkspaceGroup_sptr m_stackSamples, m_stackFlats, m_stackDarks; - - /// this holds the base image on top of which rectangles - /// and other - /// objects are drawn - boost::scoped_ptr<QPixmap> m_basePixmap; - - /// current color map used to visualize the image/slice - std::string m_colorMapFilename; - - /// persistent settings - static const std::string m_settingsGroup; - - /// parameters currently set by the user - ImageStackPreParams m_params; - - /// Timer for the "play" function - std::unique_ptr<QTimer> m_playTimer; - - /// max image size for the current stack - int m_imgWidth, m_imgHeight; - - /// are we picking the CoR, or the first point of the - /// ROI, etc. - SelectionState m_selectionState; - - // presenter as in the model-view-presenter - boost::scoped_ptr<ITomographyROIPresenter> m_presenter; -}; -} // namespace CustomInterfaces -} // namespace MantidQt - -#endif // MANTIDQTCUSTOMINTERFACES_TOMOGRAPHY_TOMOGRAPHYROIVIEWQTWIDGET_H_ diff --git a/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomographyThread.h b/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomographyThread.h deleted file mode 100644 index 97699ecc194..00000000000 --- a/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/TomographyThread.h +++ /dev/null @@ -1,115 +0,0 @@ -#ifndef MANTIDQTCUSTOMINTERFACES_TOMOGRAPHY_TOMOGRAPHYTHREAD_H_ -#define MANTIDQTCUSTOMINTERFACES_TOMOGRAPHY_TOMOGRAPHYTHREAD_H_ - -#include "MantidQtCustomInterfaces/Tomography/TomographyProcess.h" -#include <QString> -#include <QThread> - -namespace MantidQt { -namespace CustomInterfaces { -/* -TomographyThread class that can handle a single worker, and get all the standard -output and standard error content from the process. - -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 TomographyThread : public QThread { - Q_OBJECT -public: - TomographyThread(QObject *parent, TomographyProcess *worker) - : QThread(parent), m_worker(worker) { - // interactions between the thread and the worker are defined here - connect(this, SIGNAL(started()), worker, SLOT(startWorker())); - connect(this, SIGNAL(started()), this, SLOT(startWorker())); - - connect(worker, SIGNAL(readyReadStandardOutput()), this, - SLOT(readWorkerStdOut())); - connect(worker, SIGNAL(readyReadStandardError()), this, - SLOT(readWorkerStdErr())); - - connect(worker, SIGNAL(finished(int)), this, SLOT(finished(int))); - - connect(this, SIGNAL(finished()), this, SLOT(deleteLater()), - Qt::DirectConnection); - - connect(this, SIGNAL(terminated()), worker, SLOT(terminate())); - m_worker->moveToThread(this); - } - - ~TomographyThread() override { - // this will terminate the process if another reconstruction is started, - // thus not allowing to have multiple reconstructions running at the same - // time - emit terminated(); - - // this causes segfault in processRefreshJobs if the check isnt here - if (m_workerRunning || !m_worker) { - // emit that the worker has been forcefully closed, exit with error code 1 - // this is bad, find a way to notify without an explicit emit on thread - // destroy - emit workerFinished(m_workerPID, 1); - } - } - - /// this method is called after the worker's process has been successfully - /// initialised. It is necessary to do that after the initialisation of the - /// worker, because otherwise it does not have an assigned PID yet, as it is - /// not running on the OS - void setProcessPID(const qint64 pid) { m_workerPID = pid; } - - qint64 getProcessPID() const { return m_workerPID; } - -public slots: - void finished(const int exitCode) { - // queue up object deletion - m_worker->deleteLater(); - m_workerRunning = false; - // emit the exit code to the presenter so the process info can be updated - emit workerFinished(m_workerPID, exitCode); - } - - void readWorkerStdOut() const { - auto *worker = qobject_cast<TomographyProcess *>(sender()); - QString out(worker->readAllStandardOutput()); - if (!out.isEmpty()) - emit stdOutReady(out.trimmed()); - } - - void readWorkerStdErr() const { - auto *worker = qobject_cast<TomographyProcess *>(sender()); - QString out(worker->readAllStandardError()); - - if (!out.isEmpty()) - emit stdErrReady(out.trimmed()); - } - - void startWorker() { m_workerRunning = true; } - -signals: - void workerFinished(const qint64, const int); - void stdOutReady(const QString &) const; - void stdErrReady(const QString &) const; - -private: - bool m_workerRunning = false; - /// Holder for the current running process' PID - qint64 m_workerPID = 0; - TomographyProcess *const m_worker; -}; -} // CustomInterfaces -} // MantidQt -#endif diff --git a/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/ToolConfigAstraToolbox.h b/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/ToolConfigAstraToolbox.h deleted file mode 100644 index 233947c42c7..00000000000 --- a/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/ToolConfigAstraToolbox.h +++ /dev/null @@ -1,74 +0,0 @@ -#ifndef MANTIDQTCUSTOMINTERFACES_TOMOGRAPHY_TOOLCONFIGATRATOOLBOX_H_ -#define MANTIDQTCUSTOMINTERFACES_TOMOGRAPHY_TOOLCONFIGATRATOOLBOX_H_ - -#include <string> - -#include "MantidQtCustomInterfaces/DllConfig.h" -#include "MantidQtCustomInterfaces/Tomography/TomoRecToolConfig.h" - -namespace MantidQt { -namespace CustomInterfaces { - -/** - -Configuration of a third party tomographic reconstruction tool -specialized for the Astra Toolbox tomographic reconstruction tool -(C++, CUDA): Astra Toolbox <http://sourceforge.net/p/astra-toolbox/wiki/Home/ - -Copyright © 2014,2015 ISIS Rutherford Appleton Laboratory, NScD -Oak Ridge National Laboratory & European Spallation Source - -This file is part of Mantid. - -Mantid is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 3 of the License, or -(at your option) any later version. - -Mantid is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see <http://www.gnu.org/licenses/>. - -File change history is stored at: <https://github.com/mantidproject/mantid> -Code Documentation is available at: <http://doxygen.mantidproject.org> -*/ -class MANTIDQT_CUSTOMINTERFACES_DLL ToolConfigAstraToolbox - : public TomoRecToolConfig { -public: - ToolConfigAstraToolbox(); - - ToolConfigAstraToolbox(const std::string &runnable, - const std::string &pathOut, - const std::string &pathDark, - const std::string &pathOpen, - const std::string &pathSample); - - ~ToolConfigAstraToolbox() override {} - - // gives the list of methods (reconstruction algorithms) available - static const std::vector<std::pair<std::string, std::string>> methods() { - return g_astraMethods; - } - -protected: - std::string makeCmdLineOptions() const override; - - std::string makeExecutable() const override { return m_runnable; }; - -private: - static const std::vector<std::pair<std::string, std::string>> g_astraMethods; - - std::string m_pathOut; - std::string m_pathDark; - std::string m_pathOpen; - std::string m_pathSample; -}; - -} // namespace CustomInterfaces -} // namespace MantidQt - -#endif // MANTIDQTCUSTOMINTERFACES_TOMOGRAPHY_TOOLCONFIGATRATOOLBOX_H_ diff --git a/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/ToolConfigCustom.h b/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/ToolConfigCustom.h deleted file mode 100644 index e1409bb0fed..00000000000 --- a/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/ToolConfigCustom.h +++ /dev/null @@ -1,63 +0,0 @@ -#ifndef MANTIDQTCUSTOMINTERFACES_TOMOGRAPHY_TOOLCONFIGCUSTOM_H_ -#define MANTIDQTCUSTOMINTERFACES_TOMOGRAPHY_TOOLCONFIGCUSTOM_H_ - -#include <string> - -#include "MantidQtCustomInterfaces/Tomography/TomoRecToolConfig.h" - -namespace MantidQt { -namespace CustomInterfaces { - -/** -Configuration of a third party tomographic reconstruction tool as a -Custom command line. To run a reconstruction tool via a command of the -user's choice with free-form options. - -This is under development, and as it is not necessarily related to -custom interfaces might be moved out of here. Tools of other type -might be added, and then this should not be a sublcass of -TomoRecToolConfig but of a more general ToolConfig class. - -Copyright © 2014,2015 ISIS Rutherford Appleton Laboratory, NScD -Oak Ridge National Laboratory & European Spallation Source - -This file is part of Mantid. - -Mantid is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 3 of the License, or -(at your option) any later version. - -Mantid is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see <http://www.gnu.org/licenses/>. - -File change history is stored at: <https://github.com/mantidproject/mantid> -Code Documentation is available at: <http://doxygen.mantidproject.org> -*/ -class ToolConfigCustom : public TomoRecToolConfig { -public: - ToolConfigCustom() {} - - ToolConfigCustom(const std::string &runnable, const std::string &cmdOptions) - : TomoRecToolConfig(runnable), m_opts(cmdOptions) {} - - ~ToolConfigCustom() override {} - -protected: - std::string makeCmdLineOptions() const override { return m_opts; } - - std::string makeExecutable() const override { return m_runnable; }; - -private: - std::string m_opts; -}; - -} // namespace CustomInterfaces -} // namespace MantidQt - -#endif // MANTIDQTCUSTOMINTERFACES_TOMOGRAPHY_TOOLCONFIGCUSTOM_H_ diff --git a/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/ToolConfigTomoPy.h b/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/ToolConfigTomoPy.h deleted file mode 100644 index 1af2c729ff3..00000000000 --- a/MantidQt/CustomInterfaces/inc/MantidQtCustomInterfaces/Tomography/ToolConfigTomoPy.h +++ /dev/null @@ -1,69 +0,0 @@ -#ifndef MANTIDQTCUSTOMINTERFACES_TOMOGRAPHY_TOOLCONFIGTOMOPY_H_ -#define MANTIDQTCUSTOMINTERFACES_TOMOGRAPHY_TOOLCONFIGTOMOPY_H_ - -#include "MantidQtCustomInterfaces/Tomography/TomoRecToolConfig.h" -#include "MantidQtCustomInterfaces/DllConfig.h" - -namespace MantidQt { -namespace CustomInterfaces { - -/** -Third party tomographic reconstruction tool configuration class -specialized for TomoPy (Python + C++): -https://www1.aps.anl.gov/Science/Scientific-Software/TomoPy - -Copyright © 2014,2015 ISIS Rutherford Appleton Laboratory, NScD -Oak Ridge National Laboratory & European Spallation Source - -This file is part of Mantid. - -Mantid is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 3 of the License, or -(at your option) any later version. - -Mantid is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see <http://www.gnu.org/licenses/>. - -File change history is stored at: <https://github.com/mantidproject/mantid> -Code Documentation is available at: <http://doxygen.mantidproject.org> -*/ -class MANTIDQT_CUSTOMINTERFACES_DLL ToolConfigTomoPy - : public TomoRecToolConfig { -public: - ToolConfigTomoPy(); - - ToolConfigTomoPy(const std::string &runnable, const std::string &pathOut, - const std::string &pathDark, const std::string &pathOpen, - const std::string &pathSample); - - ~ToolConfigTomoPy() override {} - - // gives the list of methods (reconstruction algorithms) available - static const std::vector<std::pair<std::string, std::string>> methods() { - return g_tomopyMethods; - } - -protected: - std::string makeCmdLineOptions() const override; - - std::string makeExecutable() const override { return m_runnable; }; - -private: - static const std::vector<std::pair<std::string, std::string>> g_tomopyMethods; - - std::string m_pathOut; - std::string m_pathDark; - std::string m_pathOpen; - std::string m_pathSample; -}; - -} // namespace CustomInterfaces -} // namespace MantidQt - -#endif // MANTIDQTCUSTOMINTERFACES_TOMOGRAPHY_TOOLCONFIGTOMOPY_H_ diff --git a/MantidQt/CustomInterfaces/src/Tomography/EnergyBandsViewQtGUI.cpp b/MantidQt/CustomInterfaces/src/Tomography/EnergyBandsViewQtGUI.cpp deleted file mode 100644 index 80a2a433786..00000000000 --- a/MantidQt/CustomInterfaces/src/Tomography/EnergyBandsViewQtGUI.cpp +++ /dev/null @@ -1,163 +0,0 @@ -#include "MantidQtCustomInterfaces/Tomography/TomographyIfaceViewQtGUI.h" -#include "MantidAPI/AlgorithmManager.h" - -#include <QSettings> - -namespace MantidQt { -namespace CustomInterfaces { - -// Tomo GUI methods that process the energy bands tab. This -// could/should become a class of its own, as the tab evolves. - -void TomographyIfaceViewQtGUI::readSettingsEnergy() { - QSettings qs; - qs.beginGroup(QString::fromStdString(m_settingsSubGroupEnergy)); - - m_uiTabEnergy.lineEdit_input_path->setText( - qs.value("input-path", "").toString()); - - m_uiTabEnergy.lineEdit_output_path->setText( - qs.value("output-path", "").toString()); - - m_uiTabEnergy.radioButton_uniform_bands->setChecked( - qs.value("uniform-bands-on", true).toBool()); - m_uiTabEnergy.radioButton_index_ranges->setChecked( - qs.value("index-ranges-on", false).toBool()); - m_uiTabEnergy.radioButton_tof_ranges->setChecked( - qs.value("tof-ranges-on", false).toBool()); - - m_uiTabEnergy.spinBox_uniform_bands->setValue( - qs.value("uniform-bands-value", 1).toInt()); - m_uiTabEnergy.lineEdit_index_ranges->setText( - qs.value("index-ranges-value", "").toString()); - m_uiTabEnergy.lineEdit_tof_ranges->setText( - qs.value("tof-ranges-value", "").toString()); - - m_uiTabEnergy.comboBox_input_format->setCurrentIndex( - qs.value("input-image-format", 0).toInt()); - m_uiTabEnergy.comboBox_output_format->setCurrentIndex( - qs.value("output-image-format", 0).toInt()); - - qs.endGroup(); -} - -void TomographyIfaceViewQtGUI::saveSettingsEnergy() const { - QSettings qs; - qs.beginGroup(QString::fromStdString(m_settingsSubGroupEnergy)); - - qs.setValue("input-path", m_uiTabEnergy.lineEdit_input_path->text()); - qs.setValue("output-path", m_uiTabEnergy.lineEdit_output_path->text()); - - qs.setValue("uniform-bands-on", - m_uiTabEnergy.radioButton_uniform_bands->isChecked()); - qs.setValue("index-ranges-on", - m_uiTabEnergy.radioButton_index_ranges->isChecked()); - qs.setValue("tof-ranges-on", - m_uiTabEnergy.radioButton_tof_ranges->isChecked()); - - qs.setValue("uniform-bands-value", - m_uiTabEnergy.spinBox_uniform_bands->value()); - qs.setValue("index-ranges-value", - m_uiTabEnergy.lineEdit_index_ranges->text()); - qs.setValue("tof-ranges-value", m_uiTabEnergy.lineEdit_tof_ranges->text()); - - qs.setValue("input-image-format", - m_uiTabEnergy.comboBox_input_format->currentIndex()); - qs.setValue("output-image-format", - m_uiTabEnergy.comboBox_output_format->currentIndex()); - - qs.endGroup(); -} - -void TomographyIfaceViewQtGUI::doSetupSectionEnergy() { - m_aggAlgRunner = - Mantid::Kernel::make_unique<MantidQt::API::BatchAlgorithmRunner>(); - - connect(m_uiTabEnergy.pushButton_browse_input, SIGNAL(released()), this, - SLOT(browseEnergyInputClicked())); - - connect(m_uiTabEnergy.pushButton_browse_output, SIGNAL(released()), this, - SLOT(browseEnergyOutputClicked())); - - connect(m_uiTabEnergy.pushButton_agg, SIGNAL(released()), this, - SLOT(pushButtonAggClicked())); - - connect(m_uiTabEnergy.pushButton_browse_script, SIGNAL(released()), this, - SLOT(browseAggScriptClicked())); -} - -std::map<std::string, std::string> -TomographyIfaceViewQtGUI::grabCurrentAggParams() const { - std::map<std::string, std::string> params; - - params["InputPath"] = m_uiTabEnergy.lineEdit_input_path->text().toStdString(); - params["OutputPath"] = - m_uiTabEnergy.lineEdit_output_path->text().toStdString(); - - if (m_uiTabEnergy.radioButton_uniform_bands->isChecked()) { - params["UniformBands"] = - std::to_string(m_uiTabEnergy.spinBox_uniform_bands->value()); - } else if (m_uiTabEnergy.radioButton_index_ranges->isChecked()) { - params["IndexRanges"] = - m_uiTabEnergy.lineEdit_index_ranges->text().toStdString(); - } else if (m_uiTabEnergy.radioButton_tof_ranges->isChecked()) { - params["ToFRanges"] = - m_uiTabEnergy.lineEdit_tof_ranges->text().toStdString(); - } - - params["InputImageFormat"] = "FITS"; - params["OutputImageFormat"] = "FITS"; - - return params; -} - -void TomographyIfaceViewQtGUI::browseEnergyInputClicked() { - checkUserBrowseDir(m_uiTabEnergy.lineEdit_input_path); -} - -void TomographyIfaceViewQtGUI::browseEnergyOutputClicked() { - checkUserBrowseDir(m_uiTabEnergy.lineEdit_output_path); -} - -void TomographyIfaceViewQtGUI::pushButtonAggClicked() { - m_presenter->notify(ITomographyIfacePresenter::AggregateEnergyBands); -} - -void TomographyIfaceViewQtGUI::browseAggScriptClicked() { - checkUserBrowseFile( - m_uiTabEnergy.lineEdit_script, - "Select script to aggregate bands on the remote compute resource", false); -} - -void TomographyIfaceViewQtGUI::runAggregateBands( - Mantid::API::IAlgorithm_sptr alg) { - - // reset any previous connections - m_aggAlgRunner.get()->disconnect(); - connect(m_aggAlgRunner.get(), SIGNAL(batchComplete(bool)), this, - SLOT(finishedAggBands(bool)), Qt::QueuedConnection); - - m_aggAlgRunner->addAlgorithm(alg); - - // run lengthy I/O intensive algorithm async - m_uiTabEnergy.pushButton_agg->setEnabled(false); - m_aggAlgRunner->executeBatchAsync(); -} - -void TomographyIfaceViewQtGUI::finishedAggBands(bool error) { - if (error) { - userWarning("Process failed", "Could not run or finish the aggregation of " - "bands. Please check the log messages for " - "details."); - } else { - userWarning("Process finished", - "Aggregation of bands finished. The " - "results should now be available from the output path given. " - "You can check the logs for more information and (detailed " - "warning/error messages if there were any issues)."); - } - m_uiTabEnergy.pushButton_agg->setEnabled(true); -} - -} // namespace CustomInterfaces -} // namespace MantidQt diff --git a/MantidQt/CustomInterfaces/src/Tomography/ImageStackPreParams.cpp b/MantidQt/CustomInterfaces/src/Tomography/ImageStackPreParams.cpp deleted file mode 100644 index 784dc8ed98c..00000000000 --- a/MantidQt/CustomInterfaces/src/Tomography/ImageStackPreParams.cpp +++ /dev/null @@ -1,12 +0,0 @@ -#include "MantidQtCustomInterfaces/Tomography/ImageStackPreParams.h" - -using namespace MantidQt::CustomInterfaces; - -namespace MantidQt { -namespace CustomInterfaces { - -ImageStackPreParams::ImageStackPreParams() - : cor(), roi(), normalizationRegion(), rotation(-1.0f) {} - -} // namespace CustomInterfaces -} // namespace MantidQt diff --git a/MantidQt/CustomInterfaces/src/Tomography/ImggFormats.cpp b/MantidQt/CustomInterfaces/src/Tomography/ImggFormats.cpp deleted file mode 100644 index 45ba954d80b..00000000000 --- a/MantidQt/CustomInterfaces/src/Tomography/ImggFormats.cpp +++ /dev/null @@ -1,94 +0,0 @@ -#include "MantidQtCustomInterfaces/Tomography/ImggFormats.h" - -#include <algorithm> -#include <map> - -namespace MantidQt { -namespace CustomInterfaces { -namespace ImggFormats { - -// Names are often acronyms, so writing them uppercase -const static std::vector<std::string> shortNames{"FITS", "TIFF", "PNG", "JPEG", - "NXTomo"}; - -// Map format name to vector of accepted/recognized extensions -const static std::map<std::string, std::vector<std::string>> extensions{ - {"FITS", {"fits", "fit"}}, - {"TIFF", {"tiff", "tif"}}, - {"PNG", {"png"}}, - {"JPEG", {"jpg", "jpeg"}}, - {"NXTomo", {"nxs"}}}; - -const static std::vector<std::string> descriptions{ - "FITS: Flexible Image Transport System.", - "TIFF: - Tagged Image File Format", "PNG: Portable Network Graphics", - "JPEG: Joint Photographic Experts Group", - "NXTomo: NXTomo NeXus application definition"}; - -/** - * Possible common/accepted file extensions for a format - * - * @return extensions (without the dot, like "fits") in no particular - * order, lowercase - */ -std::string shortName(Format fmt) { return shortNames.at(fmt); } - -/** - * Get sequence number or ID of the format - * - * @param shortName short name of the format (example: "FITS") - * - * @return the format id number, -1 if it is unknown - */ -size_t formatID(const std::string &shortName) { - auto pos = std::find(shortNames.begin(), shortNames.end(), shortName); - - if (shortNames.end() == pos) { - return 0; - } - - return pos - shortNames.begin(); -} - -/** - * The first-choice file extension for a format (given by - * name). Example: FITS => fit - * - * @param format name of the format (short string) - * - * @return extension as a string, empty if the format is unknown. - */ -std::string fileExtension(const std::string &format) { - const auto &exts = extensions.at(format); - - return exts.front(); -} - -/** - * Find out whether this extension is one of the accepted format - * extensions. This is case insensitive - * - * @param extension a file name extension like .fits, or a filename - * @param shortName name of a file format - */ -bool isFileExtension(const std::string &extension, - const std::string &shortName) { - size_t pos = extension.find_last_of('.'); - std::string lowExt = extension.substr(pos + 1); - std::transform(lowExt.begin(), lowExt.end(), lowExt.begin(), ::tolower); - - const auto &valid = extensions.at(shortName); - return (valid.end() != std::find(valid.begin(), valid.end(), lowExt)); -} - -/** - * Human readable description / long name of the format - * - * @return description string to show in log messages, interfaces, - * etc. - */ -std::string description(Format fmt) { return descriptions.at(fmt); } - -} // namespace ImggFormats -} // namespace CustomInterfaces -} // namespace MantidQt diff --git a/MantidQt/CustomInterfaces/src/Tomography/ImggFormatsConvertPresenter.cpp b/MantidQt/CustomInterfaces/src/Tomography/ImggFormatsConvertPresenter.cpp deleted file mode 100644 index a4fb00fff43..00000000000 --- a/MantidQt/CustomInterfaces/src/Tomography/ImggFormatsConvertPresenter.cpp +++ /dev/null @@ -1,359 +0,0 @@ -#include "MantidQtCustomInterfaces/Tomography/ImggFormatsConvertPresenter.h" -#include "MantidAPI/AlgorithmManager.h" -#include "MantidAPI/AnalysisDataService.h" -#include "MantidAPI/MatrixWorkspace.h" -#include "MantidAPI/WorkspaceGroup.h" -#include "MantidQtCustomInterfaces/Tomography/IImggFormatsConvertView.h" -#include "MantidQtCustomInterfaces/Tomography/ImggFormats.h" - -#include <Poco/DirectoryIterator.h> -#include <Poco/File.h> -#include <Poco/Path.h> - -using namespace MantidQt::CustomInterfaces; - -namespace MantidQt { -namespace CustomInterfaces { - -namespace { -Mantid::Kernel::Logger g_log("ImggFormatsConvert"); -} - -ImggFormatsConvertPresenter::ImggFormatsConvertPresenter( - IImggFormatsConvertView *view) - : m_view(view) { - if (!m_view) { - throw std::runtime_error( - "Severe inconsistency found. Presenter created " - "with an empty/null view (formats conversion interface). " - "Cannot continue."); - } -} - -ImggFormatsConvertPresenter::~ImggFormatsConvertPresenter() { cleanup(); } - -void ImggFormatsConvertPresenter::cleanup() {} - -void ImggFormatsConvertPresenter::notify(Notification notif) { - - switch (notif) { - - case IImggFormatsConvertPresenter::Init: - processInit(); - break; - - case IImggFormatsConvertPresenter::Convert: - processConvert(); - break; - - case IImggFormatsConvertPresenter::ShutDown: - processShutDown(); - break; - } -} - -void ImggFormatsConvertPresenter::processInit() { - const std::vector<std::string> formats{ - shortName(ImggFormats::FITS), shortName(ImggFormats::TIFF), - shortName(ImggFormats::PNG), shortName(ImggFormats::JPG), - shortName(ImggFormats::NXTomo)}; - - const std::vector<bool> enableLoads{true, true, true, true, false}; - - m_view->setFormats(formats, enableLoads); -} - -void ImggFormatsConvertPresenter::processConvert() { - const std::string inPS = m_view->inputPath(); - const std::string outPS = m_view->outputPath(); - size_t depth = m_view->maxSearchDepth(); - - g_log.information() << "Trying to convert images from path: " << inPS - << " into " << outPS << ", with depth " << depth << '\n'; - - const std::string emptyMsg = "Please specify an input and and output path."; - if (inPS.empty()) { - m_view->userError("Empty imput path", emptyMsg); - return; - } - if (outPS.empty()) { - m_view->userError("Empty output path", emptyMsg); - return; - } - - Poco::File inFilePath(inPS); - if (!inFilePath.exists() || !inFilePath.isDirectory() || - !inFilePath.canRead()) { - m_view->userError( - "Cannot read from input path", - "Please check the input path given: " + inPS + - ". It must be an existing directory and it must be readable."); - return; - } - - Poco::File outFilePath(outPS); - if (!outFilePath.exists() || !outFilePath.isDirectory() || - !outFilePath.canWrite()) { - m_view->userError( - "Cannot write into the output path", - "Please check the output path given: " + outPS + - ". It must be an existing directory and it must be writeable."); - return; - } - - const std::string inFormat = m_view->inputFormatName(); - const std::string outFormat = m_view->outputFormatName(); - - try { - size_t count = goThroughDirRecur(inPS, inFormat, outPS, outFormat, depth); - if (count > 0) { - std::stringstream msg; - msg << "Finished converstion of images from path: " << inPS << " into " - << outPS << ", with depth " << depth << ". Converted " << count - << " images from format " << inFormat << " to format " << outFormat - << '\n'; - g_log.notice() << msg.str(); - m_view->userWarning("Conversion finished successfully", msg.str()); - } else { - std::stringstream msg; - msg << "No images could be found in input path: " << inPS - << " with format " << inFormat << ". 0 images converted.\n"; - g_log.notice() << msg.str(); - m_view->userWarning("No images could be found", msg.str()); - } - } catch (std::runtime_error &rexc) { - m_view->userError("Error while converting files", - "There was an error in the conversion process: " + - std::string(rexc.what())); - } -} - -void ImggFormatsConvertPresenter::processShutDown() { m_view->saveSettings(); } - -/** - * Search for images in the input path and transfers them to the - * output path in the output format. For subdirectories, it recurs - * through subdirectories "depth" levels. - * - * @param inFilePath input path where to search for image/stack files - * @param inFormat input format to consider - * @param outFilePath output path to write converted files - * @param outFormat format for the output images - * @param depth search depth remaining (for recursive calls). - * - * @return count of images processed/converted - */ -size_t ImggFormatsConvertPresenter::goThroughDirRecur( - const Poco::File &inFilePath, const std::string &inFormat, - const Poco::File &outFilePath, const std::string &outFormat, size_t depth) { - - const std::string outExt = ImggFormats::fileExtension(outFormat); - - size_t count = 0; - Poco::DirectoryIterator end; - for (Poco::DirectoryIterator it(inFilePath); it != end; ++it) { - if (it->isDirectory()) { - - if (1 == depth) - continue; - - // skip the output directory if it is nested in the input path! - if (it.path().toString() == outFilePath.path()) - continue; - - // append, to delve into subdirectory: - Poco::Path outPath(outFilePath.path()); - outPath.append(it.name()); - // create subdirectory in output path - Poco::File(outPath).createDirectory(); - - count += - goThroughDirRecur(it.path(), inFormat, outPath, outFormat, depth - 1); - } else if (it->isFile()) { - - const std::string fname = it.name(); - if (ImggFormats::isFileExtension(fname, inFormat)) { - // intentionally not removing source/original extension - Poco::Path path(outFilePath.path()); - path.append(it.name()); - const std::string outFilename = path.toString() + "." + outExt; - convert(it.path().toString(), inFormat, outFilename, outFormat); - ++count; - } - } - } - return count; -} - -/** - * Create an output image from an input image, converting - * formats. This uses the view (Qt classes) to process images in - * traditional formats like TIFF, PNG, JPG. That should be moved to - * this presenter when we have the Load/SaveImage algorithm. - * - * @param inputName name of input image - * @param inFormat format the input image is in - * @param outputName name of the output image to produce - * @param outFormat format for the output image - */ -void ImggFormatsConvertPresenter::convert(const std::string &inputName, - const std::string &inFormat, - const std::string &outputName, - const std::string &outFormat) const { - - if ("NXTomo" == outFormat) { - convertToNXTomo(inputName, inFormat, outputName); - } else if ("FITS" == outFormat) { - convertToFITS(inputName, inFormat, outputName); - } else { - if ("FITS" == inFormat) { - auto inWks = loadFITS(inputName); - m_view->writeImg(inWks, outputName, outFormat); - } else { - // other image formats - try { - m_view->convert(inputName, inFormat, outputName, outFormat); - } catch (std::runtime_error &rexc) { - m_view->userError("Error in conversion", - "There was an error when converting the image " + - inputName + " from format " + inFormat + - " to format " + outFormat + - " into the output file " + outputName + - ". Details: " + rexc.what()); - } - } - } -} - -void ImggFormatsConvertPresenter::convertToFITS( - const std::string &inputName, const std::string &inFormat, - const std::string &outputName) const { - - auto inWks = loadImg(inputName, inFormat); - try { - saveFITS(inWks, outputName); - } catch (std::runtime_error &rexc) { - m_view->userError( - "Error in conversion", - "There was an error when converting the image " + inputName + - " (format " + inFormat + - "), trying to write it into FITS format in the output file " + - outputName + ". Details: " + rexc.what()); - } -} - -void ImggFormatsConvertPresenter::convertToNXTomo( - const std::string &inputName, const std::string &inFormat, - const std::string &outputName) const { - - // loadNXTomo is not enabled (and there is no LoadNXTomo algorithm for now) - auto inWks = loadImg(inputName, inFormat); - try { - saveNXTomo(inWks, outputName); - } catch (std::runtime_error &rexc) { - m_view->userError( - "Error in conversion", - "There was an error when converting the image " + inputName + - " (format " + inFormat + - "), trying to write it into NXTomo format in the output file " + - outputName + ". Details: " + rexc.what()); - } -} - -Mantid::API::MatrixWorkspace_sptr -ImggFormatsConvertPresenter::loadImg(const std::string &inputName, - const std::string inFormat) const { - Mantid::API::MatrixWorkspace_sptr wks; - // TODO: This should become the algorithm LoadImage: - // https://github.com/mantidproject/mantid/issues/6843 - if ("FITS" == inFormat) { - wks = loadFITS(inputName); - } else { - wks = m_view->loadImg(inputName, inFormat); - } - return wks; -} - -Mantid::API::MatrixWorkspace_sptr -ImggFormatsConvertPresenter::loadFITS(const std::string &inputName) const { - - const std::string wksGrpName = "__fits_img_to_convert"; - if (Mantid::API::AnalysisDataService::Instance().doesExist(wksGrpName)) { - auto algDel = - Mantid::API::AlgorithmManager::Instance().create("DeleteWorkspace"); - algDel->setChild(true); - algDel->setPropertyValue("Workspace", wksGrpName); - algDel->execute(); - } - // Just run LoadFITS - auto alg = Mantid::API::AlgorithmManager::Instance().create("LoadFITS"); - alg->initialize(); - alg->setChild(true); - alg->setProperty("Filename", inputName); - alg->setProperty("OutputWorkspace", wksGrpName); - alg->setProperty("LoadAsRectImg", true); - alg->execute(); - - if (!alg->isExecuted()) { - throw std::runtime_error("Failed to execute the algorithm " - "LoadFITS to load the image file '" + - inputName + "' in FITS format."); - } - - Mantid::API::Workspace_sptr wks = alg->getProperty("OutputWorkspace"); - auto grp = boost::dynamic_pointer_cast<Mantid::API::WorkspaceGroup>(wks); - if (!grp) { - throw std::runtime_error( - "When loading a FITS image: " + inputName + - ", failed to retrieve the output workspace (group) after " - "executing the algorithm LoadFITS."); - } - auto imgWorkspace = boost::dynamic_pointer_cast<Mantid::API::MatrixWorkspace>( - grp->getItem(grp->size() - 1)); - - return imgWorkspace; -} - -void ImggFormatsConvertPresenter::saveFITS( - Mantid::API::MatrixWorkspace_sptr image, - const std::string &outputName) const { - // Just run LoadFITS - auto alg = Mantid::API::AlgorithmManager::Instance().create("SaveFITS"); - alg->initialize(); - alg->setProperty("InputWorkspace", image); - alg->setProperty("Filename", outputName); - alg->execute(); - - if (!alg->isExecuted()) { - throw std::runtime_error("Failed to execute the algorithm SaveFITS to save " - "an image in FITS format into the file '" + - outputName + "."); - } -} - -void ImggFormatsConvertPresenter::saveNXTomo( - Mantid::API::MatrixWorkspace_sptr image, - const std::string &outputName) const { - - // Run the algorithm SaveNXTomo - auto alg = Mantid::API::AlgorithmManager::Instance().create("SaveNXTomo"); - alg->initialize(); - alg->setProperty("InputWorkspaces", image); - alg->setProperty("Filename", outputName); - alg->setProperty("OverwriteFile", false); - alg->execute(); - - if (!alg->isExecuted()) { - throw std::runtime_error( - "Failed to execute the algorithm SaveNXTomo to save " - "images in NXTomo format into the file '" + - outputName + "."); - } - - g_log.information() - << "Save NXTomo file (overwriting if the file already existed: " - << outputName << '\n'; -} - -} // namespace CustomInterfaces -} // namespace MantidQt diff --git a/MantidQt/CustomInterfaces/src/Tomography/ImggFormatsConvertViewQtWidget.cpp b/MantidQt/CustomInterfaces/src/Tomography/ImggFormatsConvertViewQtWidget.cpp deleted file mode 100644 index 0c709bdea1e..00000000000 --- a/MantidQt/CustomInterfaces/src/Tomography/ImggFormatsConvertViewQtWidget.cpp +++ /dev/null @@ -1,375 +0,0 @@ -#include "MantidQtCustomInterfaces/Tomography/ImggFormatsConvertViewQtWidget.h" -#include "MantidAPI/MatrixWorkspace.h" -#include "MantidAPI/WorkspaceFactory.h" -#include "MantidQtAPI/AlgorithmInputHistory.h" -#include "MantidQtCustomInterfaces/Tomography/ImggFormatsConvertPresenter.h" - -using namespace Mantid::API; -using namespace MantidQt::CustomInterfaces; - -#include <QCloseEvent> -#include <QFileDialog> -#include <QImageReader> -#include <QImageWriter> -#include <QMessageBox> -#include <QSettings> - -#include <QImage> -#include <iostream> - -namespace MantidQt { -namespace CustomInterfaces { - -// this would be more like a CustomWidget if it's eventually moved there -const std::string ImggFormatsConvertViewQtWidget::m_settingsGroup = - "CustomInterfaces/ImggFormatsConvertView"; - -ImggFormatsConvertViewQtWidget::ImggFormatsConvertViewQtWidget(QWidget *parent) - : QWidget(parent), IImggFormatsConvertView(), m_presenter(nullptr) { - initLayout(); -} - -ImggFormatsConvertViewQtWidget::~ImggFormatsConvertViewQtWidget() { - m_presenter->notify(IImggFormatsConvertPresenter::ShutDown); -} - -void ImggFormatsConvertViewQtWidget::initLayout() { - // setup container ui - m_ui.setupUi(this); - - setup(); - // presenter that knows how to handle a view like this. It should - // take care of all the logic. Note the view needs to now the - // concrete presenter here - m_presenter.reset(new ImggFormatsConvertPresenter(this)); - - // it will know what compute resources and tools we have available: - // This view doesn't even know the names of compute resources, etc. - m_presenter->notify(IImggFormatsConvertPresenter::Init); - - // some combo boxes are re-populated by the init process, reload - // settings now: - readSettings(); -} - -void ImggFormatsConvertViewQtWidget::setup() { - - connect(m_ui.pushButton_browse_input, SIGNAL(released()), this, - SLOT(browseImgInputConvertClicked())); - - connect(m_ui.pushButton_browse_output, SIGNAL(released()), this, - SLOT(browseImgOutputConvertClicked())); - - connect(m_ui.pushButton_convert, SIGNAL(released()), this, - SLOT(convertClicked())); -} - -void ImggFormatsConvertViewQtWidget::readSettings() { - QSettings qs; - qs.beginGroup(QString::fromStdString(m_settingsGroup)); - - m_ui.comboBox_input_format->setCurrentIndex( - qs.value("input-format", 0).toInt()); - m_ui.lineEdit_input_path->setText(qs.value("input-path", "").toString()); - - m_ui.comboBox_output_format->setCurrentIndex( - qs.value("output-format", 0).toInt()); - m_ui.comboBox_bit_depth->setCurrentIndex(qs.value("bit-depth", 0).toInt()); - m_ui.comboBox_compression->setCurrentIndex( - qs.value("compression", 0).toInt()); - m_ui.spinBox_max_search_depth->setValue( - qs.value("max-search-depth", 0).toInt()); - m_ui.lineEdit_output_path->setText(qs.value("output-path", "").toString()); - - restoreGeometry(qs.value("interface-win-geometry").toByteArray()); - qs.endGroup(); -} - -void ImggFormatsConvertViewQtWidget::saveSettings() const { - QSettings qs; - qs.beginGroup(QString::fromStdString(m_settingsGroup)); - - qs.setValue("input-format", m_ui.comboBox_input_format->currentIndex()); - qs.setValue("input-path", m_ui.lineEdit_input_path->text()); - - qs.setValue("output-format", m_ui.comboBox_output_format->currentIndex()); - qs.setValue("bit-depth", m_ui.comboBox_bit_depth->currentIndex()); - qs.setValue("compression", m_ui.comboBox_compression->currentIndex()); - qs.setValue("max-search-depth", m_ui.spinBox_max_search_depth->value()); - qs.setValue("output-path", m_ui.lineEdit_output_path->text()); - - qs.setValue("interface-win-geometry", saveGeometry()); - qs.endGroup(); -} - -void ImggFormatsConvertViewQtWidget::browseImgInputConvertClicked() { - grabUserBrowseDir(m_ui.lineEdit_input_path); -} - -void ImggFormatsConvertViewQtWidget::browseImgOutputConvertClicked() { - grabUserBrowseDir(m_ui.lineEdit_output_path); -} - -void ImggFormatsConvertViewQtWidget::convertClicked() { - m_presenter->notify(IImggFormatsConvertPresenter::Convert); -} - -void ImggFormatsConvertViewQtWidget::userWarning( - const std::string &warn, const std::string &description) { - QMessageBox::warning(this, QString::fromStdString(warn), - QString::fromStdString(description), QMessageBox::Ok, - QMessageBox::Ok); -} - -void ImggFormatsConvertViewQtWidget::userError(const std::string &err, - const std::string &description) { - QMessageBox::critical(this, QString::fromStdString(err), - QString::fromStdString(description), QMessageBox::Ok, - QMessageBox::Ok); -} - -void ImggFormatsConvertViewQtWidget::setFormats( - const std::vector<std::string> &fmts, const std::vector<bool> &enableLoad, - const std::vector<bool> &enableSave) { - // same formats for inputs and outputs - setFormatsCombo(m_ui.comboBox_input_format, fmts, enableLoad); - setFormatsCombo(m_ui.comboBox_output_format, fmts, enableSave); - - m_ui.spinBox_max_search_depth->setValue(3); - if (m_ui.comboBox_output_format->count() > 0) { - m_ui.comboBox_output_format->setCurrentIndex(1); - } -} - -void ImggFormatsConvertViewQtWidget::setFormatsCombo( - QComboBox *cbox, const std::vector<std::string> &fmts, - const std::vector<bool> &enable) { - cbox->clear(); - for (const auto &name : fmts) { - cbox->addItem(QString::fromStdString(name)); - } - - if (enable.empty() || enable.size() != fmts.size()) - return; - - for (size_t fmtIdx = 0; fmtIdx < fmts.size(); fmtIdx++) { - if (!enable[fmtIdx]) { - // to display the text in this row as "disabled" - QModelIndex rowIdx = cbox->model()->index(static_cast<int>(fmtIdx), 0); - QVariant disabled(0); - cbox->model()->setData(rowIdx, disabled, Qt::UserRole - 1); - } - } -} - -std::string ImggFormatsConvertViewQtWidget::inputPath() const { - return m_ui.lineEdit_input_path->text().toStdString(); -} - -std::string ImggFormatsConvertViewQtWidget::inputFormatName() const { - const auto cbox = m_ui.comboBox_input_format; - if (!cbox) - return ""; - - return cbox->currentText().toStdString(); -} - -std::string ImggFormatsConvertViewQtWidget::outputPath() const { - return m_ui.lineEdit_output_path->text().toStdString(); -} - -std::string ImggFormatsConvertViewQtWidget::outputFormatName() const { - const auto cbox = m_ui.comboBox_output_format; - if (!cbox) - return ""; - - return cbox->currentText().toStdString(); -} - -bool ImggFormatsConvertViewQtWidget::compressHint() const { - return 0 == m_ui.comboBox_compression->currentIndex(); -} - -void ImggFormatsConvertViewQtWidget::convert( - const std::string &inputName, const std::string &inputFormat, - const std::string &outputName, const std::string &outputFormat) const { - - QImage img = loadImgFile(inputName, inputFormat); - - if (!img.isGrayscale()) { - // Qt5 has QImage::Format_Alpha8; - QImage::Format toFormat = QImage::Format_RGB32; - Qt::ImageConversionFlag toFlags = Qt::MonoOnly; - img = img.convertToFormat(toFormat, toFlags); - } - - writeImgFile(img, outputName, outputFormat); -} - -void ImggFormatsConvertViewQtWidget::writeImg( - MatrixWorkspace_sptr inWks, const std::string &outputName, - const std::string &outFormat) const { - if (!inWks) - return; - auto width = inWks->getNumberHistograms(); - if (0 == width) - return; - auto height = inWks->blocksize(); - - QImage img(QSize(static_cast<int>(width), static_cast<int>(height)), - QImage::Format_Indexed8); - - int tableSize = 256; - QVector<QRgb> grayscale(tableSize); - for (int i = 0; i < grayscale.size(); i++) { - int level = i; // would be equivalent: qGray(i, i, i); - grayscale[i] = qRgb(level, level, level); - } - img.setColorTable(grayscale); - - // only 16 to 8 bits color map supported with current libraries - const double scaleFactor = std::numeric_limits<unsigned short int>::max() / - std::numeric_limits<unsigned char>::max(); - for (int yi = 0; yi < static_cast<int>(width); ++yi) { - const auto &row = inWks->y(yi); - for (int xi = 0; xi < static_cast<int>(width); ++xi) { - int scaled = static_cast<int>(row[xi] / scaleFactor); - // Images not from IMAT, just crop. This needs much improvement when - // we have proper Load/SaveImage algorithms - if (scaled > 255) - scaled = 255; - if (scaled < 0) - scaled = 0; - img.setPixel(xi, yi, scaled); - } - } - - writeImgFile(img, outputName, outFormat); -} - -/** - * Write an image using a QImageWriter - * - * @param img QImage with data ready to be saved - * @param outputName output filename - * @param outFormat format for the image file - */ -void ImggFormatsConvertViewQtWidget::writeImgFile( - const QImage &img, const std::string &outputName, - const std::string &outFormat) const { - // With (simpler but less flexible) QImage: - // img.save(QString::fromStdString(outputName)); - - QImageWriter writer(QString::fromStdString(outputName)); - writer.setFormat(outFormat.c_str()); - if (compressHint()) - writer.setCompression(1); - writer.write(img); -} - -MatrixWorkspace_sptr -ImggFormatsConvertViewQtWidget::loadImg(const std::string &inputName, - const std::string &inFormat) const { - - QImage img = loadImgFile(inputName, inFormat); - int width = img.width(); - int height = img.height(); - - MatrixWorkspace_sptr imgWks = boost::dynamic_pointer_cast<MatrixWorkspace>( - WorkspaceFactory::Instance().create("Workspace2D", height, width + 1, - width)); - imgWks->setTitle(inputName); - const double scaleFactor = std::numeric_limits<unsigned char>::max(); - for (int yi = 0; yi < static_cast<int>(width); ++yi) { - auto &row = imgWks->getSpectrum(yi); - auto &dataY = row.mutableY(); - row.mutableX() = static_cast<double>(yi); - for (int xi = 0; xi < static_cast<int>(width); ++xi) { - QRgb vRgb = img.pixel(xi, yi); - dataY[xi] = scaleFactor * qGray(vRgb); - } - } - - return imgWks; -} - -/** - * Load an image using a QImageReader - * - * @param inputName filename - * @param inFormat format for the image file - * - * @return QImage object with image data read from file - */ -QImage -ImggFormatsConvertViewQtWidget::loadImgFile(const std::string &inputName, - const std::string inFormat) const { - // Simpler but less flexible load with QImage: - // img.load(QString::fromStdString(inputName)); - - QImageReader reader(inputName.c_str()); - if (!reader.autoDetectImageFormat()) { - reader.setFormat(inFormat.c_str()); - } - - return reader.read(); -} - -size_t ImggFormatsConvertViewQtWidget::maxSearchDepth() const { - return static_cast<size_t>(m_ui.spinBox_max_search_depth->value()); -} - -std::string ImggFormatsConvertViewQtWidget::grabUserBrowseDir( - QLineEdit *le, const std::string &userMsg, bool remember) { - - QString prev; - if (le->text().isEmpty()) { - prev = - MantidQt::API::AlgorithmInputHistory::Instance().getPreviousDirectory(); - } else { - prev = le->text(); - } - - QString path( - QFileDialog::getExistingDirectory(this, tr(userMsg.c_str()), prev)); - - if (!path.isEmpty()) { - le->setText(path); - if (remember) { - MantidQt::API::AlgorithmInputHistory::Instance().setPreviousDirectory( - path); - } - } - - return path.toStdString(); -} - -std::string ImggFormatsConvertViewQtWidget::askImgOrStackPath() { - // get path - QString fitsStr = QString("Supported formats: FITS, TIFF and PNG " - "(*.fits *.fit *.tiff *.tif *.png);;" - "FITS, Flexible Image Transport System images " - "(*.fits *.fit);;" - "TIFF, Tagged Image File Format " - "(*.tif *.tiff);;" - "PNG, Portable Network Graphics " - "(*.png);;" - "Other extensions/all files (*)"); - QString prevPath = - MantidQt::API::AlgorithmInputHistory::Instance().getPreviousDirectory(); - QString path(QFileDialog::getExistingDirectory( - this, tr("Open stack of images"), prevPath, QFileDialog::ShowDirsOnly)); - if (!path.isEmpty()) { - MantidQt::API::AlgorithmInputHistory::Instance().setPreviousDirectory(path); - } - - return path.toStdString(); -} - -void ImggFormatsConvertViewQtWidget::closeEvent(QCloseEvent *event) { - m_presenter->notify(IImggFormatsConvertPresenter::ShutDown); - event->accept(); -} - -} // namespace CustomInterfaces -} // namespace MantidQt diff --git a/MantidQt/CustomInterfaces/src/Tomography/StackOfImagesDirs.cpp b/MantidQt/CustomInterfaces/src/Tomography/StackOfImagesDirs.cpp deleted file mode 100644 index 1cfcc3d0443..00000000000 --- a/MantidQt/CustomInterfaces/src/Tomography/StackOfImagesDirs.cpp +++ /dev/null @@ -1,208 +0,0 @@ -#include "MantidQtCustomInterfaces/Tomography/StackOfImagesDirs.h" - -#include <boost/algorithm/string.hpp> - -#include <Poco/DirectoryIterator.h> -#include <Poco/Path.h> - -namespace MantidQt { -namespace CustomInterfaces { - -const std::string StackOfImagesDirs::g_descrComplex = - "A directory (folder) that contains subdirectories with names " - "starting with:\n- 'Data' (for sample images),\n- 'Flat' (for white " - "bean images),\n- 'Dark' (for dark images)\nThe first one is " - "mandatory whereas the other two are optional."; - -const std::string StackOfImagesDirs::g_descrSimple = - "A directory containing (readable) image files."; - -const std::string StackOfImagesDirs::g_descrBoth = "Two alternatives: \n\n" - "Simple: " + - g_descrSimple + - "\n\n" - "Or Full:\n\n" + - g_descrComplex + "\n"; - -const std::string StackOfImagesDirs::g_sampleNamePrefix = "data"; -const std::string StackOfImagesDirs::g_flatNamePrefix = "flat"; -const std::string StackOfImagesDirs::g_darkNamePrefix = "dark"; -const std::string StackOfImagesDirs::g_processedNamePrefix = "processed"; -const std::string StackOfImagesDirs::g_prefilteredNamePrefix = "pre_filtered"; - -StackOfImagesDirs::StackOfImagesDirs(const std::string &path, - bool allowSimpleLayout) - : m_valid(false), m_statusDescStr("Constructed, no checks done yet.") { - findStackDirs(path, allowSimpleLayout); -} - -std::string StackOfImagesDirs::description() const { return m_descr; } - -std::string StackOfImagesDirs::status() const { - if (m_valid) - return "Stack of images is correct"; - else - return "There are errors in the directories and/or files. " + - m_statusDescStr; -} - -std::vector<std::string> StackOfImagesDirs::sampleFiles() const { - return findImgFiles(m_sampleDir); -} -std::vector<std::string> StackOfImagesDirs::flatFiles() const { - return findImgFiles(m_flatDir); -} -std::vector<std::string> StackOfImagesDirs::darkFiles() const { - return findImgFiles(m_darkDir); -} - -void StackOfImagesDirs::findStackDirs(const std::string &path, - bool allowSimpleLayout) { - if (allowSimpleLayout) { - m_descr = g_descrBoth; - } else { - m_descr = g_descrComplex; - } - - if (path.empty()) - return; - - Poco::File dir(path); - if (!dir.isDirectory() || !dir.exists()) - return; - - bool found = false; - // go for the simple layout first (just image files in a flat tree). - if (allowSimpleLayout) { - found = findStackFilesSimple(dir); - } - - if (!found) { - findStackDirsComplex(dir); - } -} - -/** - * Tries to find a stack of images with the simple layout: all sample - * files are in the directory given. - * - * @param dir directory which is the base path for the stack of images, that is, - * which contains image files. - * - * @return whether the stack has been found succesfully - */ -bool StackOfImagesDirs::findStackFilesSimple(Poco::File &dir) { - Poco::DirectoryIterator end; - for (Poco::DirectoryIterator it(dir); it != end; ++it) { - // presence of one regular file is enough - if (it->isFile()) { - m_sampleDir = dir.path(); - m_flatDir = ""; - m_darkDir = ""; - m_valid = true; - } - } - - return m_valid; -} - -/** - * Tries to find a stack of images with the full or complex - * layout. Assumes that the path given has been checked. In a full - * layout the files are arranged in up to three subdirectories: - * - * - path/data*: sample images - * - path/flat*: flat images - * - path/dark*: dark images - * - * @param dir directory to use as base path for the stack of images - * - * @return whether the stack has been found succesfully - */ -bool StackOfImagesDirs::findStackDirsComplex(Poco::File &dir) { - Poco::DirectoryIterator end; - for (Poco::DirectoryIterator it(dir); it != end; ++it) { - if (!it->isDirectory()) { - continue; - } - - const std::string name = it.name(); - - // case insensitive comparison against expected pattersn: data_*, flat_*, - // dark_*, etc. - if (boost::iequals(name.substr(0, g_sampleNamePrefix.length()), - g_sampleNamePrefix)) { - m_sampleDir = it.path().toString(); - } else if (boost::iequals(name.substr(0, g_flatNamePrefix.length()), - g_flatNamePrefix)) { - m_flatDir = it.path().toString(); - } else if (boost::iequals(name.substr(0, g_darkNamePrefix.length()), - g_darkNamePrefix)) { - m_darkDir = it.path().toString(); - } - } - - if (m_sampleDir.empty()) { - m_statusDescStr = "The the sample images directory (" + g_sampleNamePrefix + - "...) has not been found."; - return false; - } - - // can be valid only if we get here. There must be at least one entry that is - // a file - Poco::Path samplesPath(m_sampleDir); - for (Poco::DirectoryIterator it(samplesPath); it != end; ++it) { - if (it->isFile()) { - m_valid = true; - break; - } - } - - if (m_valid) { - m_statusDescStr = "all checks passed"; - } else { - m_statusDescStr = "No files were found in the sample images directory (" + - g_sampleNamePrefix + "...)."; - } - - return m_valid; -} - -std::vector<std::string> -StackOfImagesDirs::findImgFiles(const std::string &path) const { - std::vector<std::string> fnames; - if (path.empty()) { - return fnames; - } - - try { - Poco::File dir(path); - if (!dir.isDirectory() || !dir.exists()) - return fnames; - - // as an alternative could also use Poco::Glob to find the files - Poco::DirectoryIterator it(dir); - Poco::DirectoryIterator end; - while (it != end) { - // TODO: filter names by extension? - // const std::string name = it.name(); - if (it->isFile()) { - fnames.push_back(it.path().toString()); - } - - ++it; - } - - // this assumes the usual sorting of images of a stack (directory): a - // prefix, - // and a sequence number (with a fixed number of digits). - std::sort(fnames.begin(), fnames.end()); - } catch (std::runtime_error &) { - // it's fine if the files are not found, not readable, etc. - } - - return fnames; -} - -} // namespace CustomInterfaces -} // namespace MantidQt diff --git a/MantidQt/CustomInterfaces/src/Tomography/TomoPathsConfig.cpp b/MantidQt/CustomInterfaces/src/Tomography/TomoPathsConfig.cpp deleted file mode 100644 index 15b84c0fade..00000000000 --- a/MantidQt/CustomInterfaces/src/Tomography/TomoPathsConfig.cpp +++ /dev/null @@ -1,18 +0,0 @@ -#include "MantidQtCustomInterfaces/Tomography/TomoPathsConfig.h" - -namespace MantidQt { -namespace CustomInterfaces { - -TomoPathsConfig::TomoPathsConfig() - : m_pathOpenBeamEnabled(true), m_pathDarkEnabled(true), - m_pathBase("/work/imat/phase_commissioning/"), - m_pathFITS(m_pathBase + "data"), m_pathFlat(m_pathBase + "flat"), - m_pathDark(m_pathBase + "dark") {} - -bool TomoPathsConfig::validate() const { - // TODO: too simple for now - return (!m_pathFITS.empty() && !m_pathFlat.empty() && !m_pathDark.empty()); -} - -} // namespace CustomInterfaces -} // namespace MantidQt diff --git a/MantidQt/CustomInterfaces/src/Tomography/TomoReconPostprocSettings.cpp b/MantidQt/CustomInterfaces/src/Tomography/TomoReconPostprocSettings.cpp deleted file mode 100644 index cd3bd710c97..00000000000 --- a/MantidQt/CustomInterfaces/src/Tomography/TomoReconPostprocSettings.cpp +++ /dev/null @@ -1,15 +0,0 @@ -#include "MantidQtCustomInterfaces/Tomography/TomoReconPostprocSettings.h" - -namespace MantidQt { -namespace CustomInterfaces { - -/** - * Default initialization of post-processing options. This should - * represent sensible first time usage defaults that can be used by - * GUIs, etc. - */ -TomoReconPostprocSettings::TomoReconPostprocSettings() - : circMaskRadius(0.94), cutOffLevel(0.0) {} - -} // namespace CustomInterfaces -} // namespace MantidQt diff --git a/MantidQt/CustomInterfaces/src/Tomography/TomoReconPreprocSettings.cpp b/MantidQt/CustomInterfaces/src/Tomography/TomoReconPreprocSettings.cpp deleted file mode 100644 index 919e098f8e3..00000000000 --- a/MantidQt/CustomInterfaces/src/Tomography/TomoReconPreprocSettings.cpp +++ /dev/null @@ -1,17 +0,0 @@ -#include "MantidQtCustomInterfaces/Tomography/TomoReconPreprocSettings.h" - -namespace MantidQt { -namespace CustomInterfaces { - -/** - * Default initialization of pre-processing options. This should - * represent sensible first time usage defaults that can be used by - * GUIs, etc. - */ -TomoReconPreprocSettings::TomoReconPreprocSettings() - : normalizeByAirRegion(true), normalizeByProtonCharge(false), - normalizeByFlats(true), normalizeByDarks(true), medianFilterWidth(3), - rotation(0), maxAngle(360.0), scaleDownFactor(0) {} - -} // namespace CustomInterfaces -} // namespace MantidQt diff --git a/MantidQt/CustomInterfaces/src/Tomography/TomoSystemSettings.cpp b/MantidQt/CustomInterfaces/src/Tomography/TomoSystemSettings.cpp deleted file mode 100644 index b1899615e47..00000000000 --- a/MantidQt/CustomInterfaces/src/Tomography/TomoSystemSettings.cpp +++ /dev/null @@ -1,28 +0,0 @@ -#include "MantidQtCustomInterfaces/Tomography/TomoSystemSettings.h" - -namespace MantidQt { -namespace CustomInterfaces { - -const std::string TomoSystemSettings::g_defSamplesDirPrefix = "data"; -const std::string TomoSystemSettings::g_defFlatsDirPrefix = "flat"; -const std::string TomoSystemSettings::g_defDarksDirPrefix = "dark"; - -const std::string TomoSystemSettings::g_defOutputPathCompPreProcessed = - "pre_processed"; - -const std::string TomoSystemSettings::g_defOutputPathCompReconst = "processed"; - -/** - * Default initialization which should be enough in most cases. - */ -TomoSystemSettings::TomoSystemSettings() - : m_local(), m_remote(), - m_pathComponents({"data", "RB number", "experiment name", "input type"}), - m_samplesDirPrefix(g_defSamplesDirPrefix), - m_flatsDirPrefix(g_defFlatsDirPrefix), - m_darksDirPrefix(g_defDarksDirPrefix), - m_outputPathCompPreProcessed(g_defOutputPathCompPreProcessed), - m_outputPathCompReconst(g_defOutputPathCompReconst) {} - -} // namespace CustomInterfaces -} // namespace MantidQt diff --git a/MantidQt/CustomInterfaces/src/Tomography/TomoSystemSettingsLocal.cpp b/MantidQt/CustomInterfaces/src/Tomography/TomoSystemSettingsLocal.cpp deleted file mode 100644 index 02bd0db9000..00000000000 --- a/MantidQt/CustomInterfaces/src/Tomography/TomoSystemSettingsLocal.cpp +++ /dev/null @@ -1,55 +0,0 @@ -#include "MantidQtCustomInterfaces/Tomography/TomoSystemSettingsLocal.h" -#include "MantidKernel/ConfigService.h" - -#include <Poco/Path.h> - -namespace MantidQt { -namespace CustomInterfaces { - -const std::string TomoSystemSettingsLocal::g_defBasePathTomoData = -#ifdef _WIN32 - "D:\\"; -#else - "${HOME}/imat-data"; -#endif - -const std::string TomoSystemSettingsLocal::g_defRemoteDriveOrMountPoint = -#ifdef _WIN32 - "S:\\imat"; -#else - "/media/scarf"; -#endif - -const std::string TomoSystemSettingsLocal::g_defReconScriptsPath = -#ifdef _WIN32 - "C:/MantidInstall/scripts"; -#else - Poco::Path( - Mantid::Kernel::ConfigService::Instance().getDirectoryOfExecutable()) - .parent() - .append("scripts") - .toString(); -#endif - -const std::string TomoSystemSettingsLocal::g_defExternalInterpreterPath = -#ifdef _WIN32 - // assume we're using Aanconda Python and it is installed in c:/local - // could also be c:/local/anaconda/scripts/ipython - "c:/local/anaconda/python.exe"; -#else - // just use the system Python, assuming is in the system path - "python"; -#endif - -/** - * Default initialization which should be enough in most cases. - */ -TomoSystemSettingsLocal::TomoSystemSettingsLocal() - : m_basePathTomoData(g_defBasePathTomoData), - m_remoteDriveOrMountPoint(g_defRemoteDriveOrMountPoint), - m_reconScriptsPath(g_defReconScriptsPath), - m_externalInterpreterPath(g_defExternalInterpreterPath), m_processes(4), - m_cores(4) {} - -} // namespace CustomInterfaces -} // namespace MantidQt diff --git a/MantidQt/CustomInterfaces/src/Tomography/TomoSystemSettingsRemote.cpp b/MantidQt/CustomInterfaces/src/Tomography/TomoSystemSettingsRemote.cpp deleted file mode 100644 index d2de7dccfbe..00000000000 --- a/MantidQt/CustomInterfaces/src/Tomography/TomoSystemSettingsRemote.cpp +++ /dev/null @@ -1,21 +0,0 @@ -#include "MantidQtCustomInterfaces/Tomography/TomoSystemSettingsRemote.h" - -namespace MantidQt { -namespace CustomInterfaces { - -const std::string TomoSystemSettingsRemote::g_defBasePathTomoData = - "/work/imat"; - -const std::string TomoSystemSettingsRemote::g_defBasePathReconScripts = - "/work/imat/phase_commissioning"; - -/** - * Default initialization which should be enough in most cases. - */ -TomoSystemSettingsRemote::TomoSystemSettingsRemote() - : m_basePathTomoData(g_defBasePathTomoData), - m_basePathReconScripts(g_defBasePathReconScripts), m_nodes(2), - m_cores(4) {} - -} // namespace CustomInterfaces -} // namespace MantidQt diff --git a/MantidQt/CustomInterfaces/src/Tomography/TomoToolConfigDialogAstra.cpp b/MantidQt/CustomInterfaces/src/Tomography/TomoToolConfigDialogAstra.cpp deleted file mode 100644 index 61cf5f5c3ef..00000000000 --- a/MantidQt/CustomInterfaces/src/Tomography/TomoToolConfigDialogAstra.cpp +++ /dev/null @@ -1,45 +0,0 @@ -#include "MantidQtCustomInterfaces/Tomography/TomoToolConfigDialogAstra.h" -#include "MantidQtCustomInterfaces/Tomography/ToolConfigAstraToolbox.h" -#include "MantidQtCustomInterfaces/Tomography/TomoReconToolsUserSettings.h" - -namespace MantidQt { -namespace CustomInterfaces { - -const std::string TomoToolConfigDialogAstra::DEFAULT_TOOL_NAME = "Astra"; -const std::string TomoToolConfigDialogAstra::DEFAULT_TOOL_METHOD = "FBP3D_CUDA"; - -void TomoToolConfigDialogAstra::setupDialogUi() { - m_astraUi.setupUi(m_dialog); - m_astraUi.comboBox_method->clear(); - const auto &methods = getToolMethods(); - for (auto &method : methods) { - m_astraUi.comboBox_method->addItem(QString::fromStdString(method.second)); - } -} - -void TomoToolConfigDialogAstra::initialiseDialog() { m_dialog = new QDialog; } - -void TomoToolConfigDialogAstra::setupToolSettingsFromPaths() { - m_toolSettings = std::make_shared<ToolConfigAstraToolbox>( - m_runPath, m_pathOut + m_localOutNameAppendix, m_paths.pathDarks(), - m_paths.pathOpenBeam(), m_paths.pathSamples()); -} - -void TomoToolConfigDialogAstra::setupMethodSelected() { - const auto &methods = getToolMethods(); - - const int mi = m_astraUi.comboBox_method->currentIndex(); - m_toolMethod = methods[mi].first; -} - -/** Calls the execute of the QDialog -*/ -int TomoToolConfigDialogAstra::executeQt() { return m_dialog->exec(); } - -std::vector<std::pair<std::string, std::string>> -TomoToolConfigDialogAstra::getToolMethods() { - return ToolConfigAstraToolbox::methods(); -} - -} // CustomInterfaces -} // MantidQt \ No newline at end of file diff --git a/MantidQt/CustomInterfaces/src/Tomography/TomoToolConfigDialogBase.cpp b/MantidQt/CustomInterfaces/src/Tomography/TomoToolConfigDialogBase.cpp deleted file mode 100644 index 5d95af10cf4..00000000000 --- a/MantidQt/CustomInterfaces/src/Tomography/TomoToolConfigDialogBase.cpp +++ /dev/null @@ -1,36 +0,0 @@ -#include "MantidQtCustomInterfaces/Tomography/TomoToolConfigDialogBase.h" -#include "MantidQtCustomInterfaces/Tomography/TomoToolConfigDialogTomoPy.h" -#include "MantidQtCustomInterfaces/Tomography/TomoToolConfigDialogAstra.h" -#include "MantidQtCustomInterfaces/Tomography/TomoToolConfigDialogSavu.h" -#include "MantidQtCustomInterfaces/Tomography/TomoToolConfigDialogCustom.h" - -#include "MantidKernel/make_unique.h" - -namespace MantidQt { -namespace CustomInterfaces { - -std::unique_ptr<TomoToolConfigDialogBase> -TomoToolConfigDialogBase::getToolDialogFor(const std::string &toolName) { - - if (toolName == "TomoPy") { - return Mantid::Kernel::make_unique<TomoToolConfigDialogTomoPy>(); - } else if (toolName == "Astra") { - return Mantid::Kernel::make_unique<TomoToolConfigDialogAstra>(); - } else if (toolName == "Savu") { - return Mantid::Kernel::make_unique<TomoToolConfigDialogSavu>(); - } else if (toolName == "Custom command") { - return Mantid::Kernel::make_unique<TomoToolConfigDialogCustom>(); - } - // tool doesn't exist, return nullptr - return nullptr; -} - -void TomoToolConfigDialogBase::handleDialogResult(const int result) { - if (QDialog::Accepted == result) { - // setup the new settings if the user has Accepted - setupMethodSelected(); - setupToolSettingsFromPaths(); - } -} -} // namespace CustomInterfaces -} // namespace MantidQt diff --git a/MantidQt/CustomInterfaces/src/Tomography/TomoToolConfigDialogCustom.cpp b/MantidQt/CustomInterfaces/src/Tomography/TomoToolConfigDialogCustom.cpp deleted file mode 100644 index f8e31af5914..00000000000 --- a/MantidQt/CustomInterfaces/src/Tomography/TomoToolConfigDialogCustom.cpp +++ /dev/null @@ -1,71 +0,0 @@ -#include "MantidQtCustomInterfaces/Tomography/TomoToolConfigDialogCustom.h" -#include "MantidQtCustomInterfaces/Tomography/ToolConfigCustom.h" - -namespace MantidQt { -namespace CustomInterfaces { - -const std::string TomoToolConfigDialogCustom::DEFAULT_TOOL_NAME = - "Custom command"; - -// custom tool doesn't have a default method -const std::string TomoToolConfigDialogCustom::DEFAULT_TOOL_METHOD = ""; - -std::string TomoToolConfigDialogCustom::m_backupCommandLine = ""; - -/** Reads the current strings in the dialogue and creates -* the tool settings from them. If the dialogue is not initialised yet -* the strings will be empty, thus we put the default values -*/ -void TomoToolConfigDialogCustom::setupToolSettingsFromPaths() { - - if (m_isInitialised) { - // None of the other paths matter, because the user could've changed - // them, so ignore them and load the current ones on the dialogue - const std::string run = - m_customUi.lineEdit_runnable->text().toStdString(); // current path - const std::string opts = m_customUi.textEdit_cl_opts->toPlainText() - .toStdString(); // current commands - - // update the settings with the newest information - m_toolSettings = std::make_shared<ToolConfigCustom>(run, opts); - } else { - // create settings with the default values - m_toolSettings = std::make_shared<ToolConfigCustom>(m_runPath, "--help"); - } -} - -void TomoToolConfigDialogCustom::setupMethodSelected() { - - // sets the current runnable path, overriding the default one - m_customUi.lineEdit_runnable->setText(QString::fromStdString(m_runPath)); -} - -void TomoToolConfigDialogCustom::setupDialogUi() { - m_customUi.setupUi(m_dialog); - - if (m_backupCommandLine != "") { - m_customUi.textEdit_cl_opts->setText( - QString::fromStdString(m_backupCommandLine)); - } - - // get default options from command line - const std::string opts = - m_customUi.textEdit_cl_opts->toPlainText().toStdString(); - - // create the default settings - m_toolSettings = std::make_shared<ToolConfigCustom>(m_runPath, opts); -} - -void TomoToolConfigDialogCustom::initialiseDialog() { m_dialog = new QDialog; } - -void TomoToolConfigDialogCustom::handleDialogResult(int result) { - if (QDialog::Accepted == result) { - // if accepted we want to save the information - m_backupCommandLine = - m_customUi.textEdit_cl_opts->toPlainText().toStdString(); - setupToolSettingsFromPaths(); - } -} -int TomoToolConfigDialogCustom::executeQt() { return m_dialog->exec(); } -} // CustomInterfaces -} // MantidQt \ No newline at end of file diff --git a/MantidQt/CustomInterfaces/src/Tomography/TomoToolConfigDialogSavu.cpp b/MantidQt/CustomInterfaces/src/Tomography/TomoToolConfigDialogSavu.cpp deleted file mode 100644 index 2d3aa5a7749..00000000000 --- a/MantidQt/CustomInterfaces/src/Tomography/TomoToolConfigDialogSavu.cpp +++ /dev/null @@ -1,632 +0,0 @@ -#include "MantidAPI/AnalysisDataService.h" -#include "MantidAPI/ITableWorkspace.h" -#include "MantidQtCustomInterfaces/Tomography/TomographyIfaceViewQtGUI.h" - -#include <boost/lexical_cast.hpp> -#include "MantidQtCustomInterfaces/Tomography/TomoToolConfigDialogSavu.h" -#include "MantidQtCustomInterfaces/Tomography/TomoReconToolsUserSettings.h" - -#include <MantidAPI/TableRow.h> -#include <MantidAPI/WorkspaceFactory.h> -#include <Poco/String.h> -#include <json/reader.h> -#include <MantidAPI/NotebookWriter.h> -#include <QFileDialog> -#include <QMessageBox> -#include <MantidAPI/AlgorithmManager.h> - -using namespace Mantid::API; - -namespace MantidQt { -namespace CustomInterfaces { - -TomoToolConfigDialogSavu::TomoToolConfigDialogSavu(QWidget *parent) - : QMainWindow(parent) { - // TODO init the 545231453t54 variables - m_availPlugins = Mantid::API::WorkspaceFactory::Instance().createTable(); - m_availPlugins->addColumns("str", "name", 4); - m_currPlugins = Mantid::API::WorkspaceFactory::Instance().createTable(); - m_currPlugins->addColumns("str", "name", 4); -} - -int TomoToolConfigDialogSavu::executeQt() { - this->show(); - QEventLoop el; - connect(this, SIGNAL(destroyed()), &el, SLOT(quit())); - return el.exec(); -} - -void TomoToolConfigDialogSavu::initialiseDialog() { - throw Mantid::Kernel::Exception::NotImplementedError( - "SAVU interface not implemented"); -} -void TomoToolConfigDialogSavu::setupMethodSelected() { - throw Mantid::Kernel::Exception::NotImplementedError( - "SAVU interface not implemented"); -} -void TomoToolConfigDialogSavu::setupToolSettingsFromPaths() { - throw Mantid::Kernel::Exception::NotImplementedError( - "SAVU interface not implemented"); -} - -void TomoToolConfigDialogSavu::setupDialogUi() { - m_savuUi.setupUi(this); - initSavuWindow(); - this->setWindowModality(Qt::ApplicationModal); -} - -void TomoToolConfigDialogSavu::initSavuWindow() { - // geometry, etc. niceties - // on the left (just plugin names) 1/2, right: 2/3 - QList<int> sizes{100, 200}; - m_savuUi.splitterPlugins->setSizes(std::move(sizes)); - - // Setup Parameter editor tab - loadAvailablePlugins(); - m_savuUi.treeCurrentPlugins->setHeaderHidden(true); - - // Connect slots - // Lists/trees - connect(m_savuUi.listAvailablePlugins, SIGNAL(itemSelectionChanged()), this, - SLOT(availablePluginSelected())); - connect(m_savuUi.treeCurrentPlugins, SIGNAL(itemSelectionChanged()), this, - SLOT(currentPluginSelected())); - connect(m_savuUi.treeCurrentPlugins, SIGNAL(itemExpanded(QTreeWidgetItem *)), - this, SLOT(expandedItem(QTreeWidgetItem *))); - - // Buttons - connect(m_savuUi.btnTransfer, SIGNAL(released()), this, - SLOT(transferClicked())); - connect(m_savuUi.btnMoveUp, SIGNAL(released()), this, SLOT(moveUpClicked())); - connect(m_savuUi.btnMoveDown, SIGNAL(released()), this, - SLOT(moveDownClicked())); - connect(m_savuUi.btnRemove, SIGNAL(released()), this, SLOT(removeClicked())); -} - -// TODO: what's in this file should become a class of its own, -// 'SavuConfigDialog' or similar - -void TomoToolConfigDialogSavu::loadAvailablePlugins() { - // TODO:: load actual plugins when we know them - // creating a few relatively realistic choices for now (should crossh check - // with the savu api when finalized). - // - Should also verify the param string is valid json when setting - - // Create plugin table - Mantid::API::TableRow row = m_availPlugins->appendRow(); - row << "savu.plugins.timeseries_field_corrections" - << "{}" - << "Time Series Field Corrections" - << "Citation info"; - - row = m_availPlugins->appendRow(); - row << "savu.plugins.median_filter" - << "{\"kernel_size\":[1, 3, 3]}" - << "Median Filter" - << "Citation info"; - - row = m_availPlugins->appendRow(); - row << "savu.plugins.vo_centering" - << "{}" - << "Vo Centering" - << "Citation info"; - - row = m_availPlugins->appendRow(); - row << "savu.plugins.simple_recon" - << "{\"center_of_rotation\":86}" - << "Simple Reconstruction" - << "Citation info"; - - row = m_availPlugins->appendRow(); - row << "savu.plugins.astra_recon" - << "{\"center_of_rotation\":\"86\", " - "\"reconsturction_type\":\"SIRT\", \"number_of_iterations\":5}" - << "Simple Reconstruction" - << "Citation info"; - - // Update the UI - refreshAvailablePluginListUI(); -} - -// Reloads the GUI list of available plugins from the data object :: -// Populating only through this ensures correct indexing. -void TomoToolConfigDialogSavu::refreshAvailablePluginListUI() { - // Table WS structure, id/params/name/cite - m_savuUi.listAvailablePlugins->clear(); - const size_t rowcount = m_availPlugins->rowCount(); - for (size_t i = 0; i < rowcount; ++i) { - const QString str = - QString::fromStdString(m_availPlugins->cell<std::string>(i, 2)); - m_savuUi.listAvailablePlugins->addItem(std::move(str)); - } -} - -// Reloads the GUI list of current plugins from the data object :: -// Populating only through this ensures correct indexing. -void TomoToolConfigDialogSavu::refreshCurrentPluginListUI() { - // Table WS structure, id/params/name/cite - m_savuUi.treeCurrentPlugins->clear(); - createPluginTreeEntries(m_currPlugins); -} - -// Updates the selected plugin info from Available plugins list. -void TomoToolConfigDialogSavu::availablePluginSelected() { - if (m_savuUi.listAvailablePlugins->selectedItems().count() != 0) { - const size_t idx = static_cast<size_t>( - m_savuUi.listAvailablePlugins->currentIndex().row()); - if (idx < m_availPlugins->rowCount()) { - m_savuUi.availablePluginDesc->setText( - tableWSRowToString(m_availPlugins, idx)); - } - } -} - -// Updates the selected plugin info from Current plugins list. -void TomoToolConfigDialogSavu::currentPluginSelected() { - if (m_savuUi.treeCurrentPlugins->selectedItems().count() != 0) { - auto currItem = m_savuUi.treeCurrentPlugins->selectedItems()[0]; - - while (currItem->parent() != NULL) - currItem = currItem->parent(); - - int topLevelIndex = - m_savuUi.treeCurrentPlugins->indexOfTopLevelItem(currItem); - - m_savuUi.currentPluginDesc->setText( - tableWSRowToString(m_currPlugins, topLevelIndex)); - } -} - -class OwnTreeWidgetItem : public QTreeWidgetItem { -public: - OwnTreeWidgetItem(QTreeWidgetItem *parent, - QTreeWidgetItem *logicalParent = NULL, - const std::string &key = "") - : QTreeWidgetItem(parent), m_rootParent(logicalParent), m_key(key) {} - - OwnTreeWidgetItem(QStringList list, QTreeWidgetItem *logicalParent = NULL, - const std::string &key = "") - : QTreeWidgetItem(list), m_rootParent(logicalParent), m_key(key) {} - - OwnTreeWidgetItem(QTreeWidgetItem *parent, QStringList list, - QTreeWidgetItem *logicalParent = NULL, - const std::string &key = "") - : QTreeWidgetItem(parent, list), m_rootParent(logicalParent), m_key(key) { - } - - QTreeWidgetItem *getRootParent() { return m_rootParent; } - - std::string getKey() { return m_key; } - -private: - QTreeWidgetItem *m_rootParent; - std::string m_key; -}; - -// On user editing a parameter tree item, update the data object to match. -void TomoToolConfigDialogSavu::paramValModified(QTreeWidgetItem *item, - int /*column*/) { - OwnTreeWidgetItem *ownItem = dynamic_cast<OwnTreeWidgetItem *>(item); - if (!ownItem) - return; - - int topLevelIndex = -1; - if (ownItem->getRootParent() != NULL) { - topLevelIndex = m_savuUi.treeCurrentPlugins->indexOfTopLevelItem( - ownItem->getRootParent()); - } - if (-1 == topLevelIndex) - return; - - // Recreate the json string from the nodes and write back - std::string json = m_currPlugins->cell<std::string>(topLevelIndex, 1); - // potential new line out, and trim spaces - json.erase(std::remove(json.begin(), json.end(), '\n'), json.end()); - json.erase(std::remove(json.begin(), json.end(), '\r'), json.end()); - json = Poco::trimInPlace(json); - - ::Json::Reader r; - ::Json::Value root; - if (r.parse(json, root)) { - // Look for the key and replace it - root[ownItem->getKey()] = ownItem->text(0).toStdString(); - } - - m_currPlugins->cell<std::string>(topLevelIndex, 1) = - ::Json::FastWriter().write(root); - currentPluginSelected(); -} - -// When a top level item is expanded, also expand its child items - if tree -// items -void TomoToolConfigDialogSavu::expandedItem(QTreeWidgetItem *item) { - if (item->parent() == NULL) { - for (int i = 0; i < item->childCount(); ++i) { - item->child(i)->setExpanded(true); - } - } -} - -// Adds one plugin from the available plugins list into the list of -// current plugins -void TomoToolConfigDialogSavu::transferClicked() { - if (0 == m_savuUi.listAvailablePlugins->selectedItems().count()) - return; - - const int idx = m_savuUi.listAvailablePlugins->currentIndex().row(); - const size_t columnCount = m_currPlugins->columnCount(); - - Mantid::API::TableRow row = m_currPlugins->appendRow(); - for (size_t j = 0; j < columnCount; ++j) { - row << m_availPlugins->cell<std::string>(idx, j); - } - createPluginTreeEntry(row); -} - -void TomoToolConfigDialogSavu::moveUpClicked() { - if (0 == m_savuUi.treeCurrentPlugins->selectedItems().count()) - return; - - const size_t idx = - static_cast<size_t>(m_savuUi.treeCurrentPlugins->currentIndex().row()); - if (idx > 0 && idx < m_currPlugins->rowCount()) { - // swap row, all columns - const size_t columnCount = m_currPlugins->columnCount(); - for (size_t j = 0; j < columnCount; ++j) { - const std::string swap = m_currPlugins->cell<std::string>(idx, j); - m_currPlugins->cell<std::string>(idx, j) = - m_currPlugins->cell<std::string>(idx - 1, j); - m_currPlugins->cell<std::string>(idx - 1, j) = swap; - } - refreshCurrentPluginListUI(); - } -} - -void TomoToolConfigDialogSavu::moveDownClicked() { - // TODO: this can be done with the same function as above... - if (0 == m_savuUi.treeCurrentPlugins->selectedItems().count()) - return; - - const size_t idx = - static_cast<size_t>(m_savuUi.treeCurrentPlugins->currentIndex().row()); - if (idx < m_currPlugins->rowCount() - 1) { - // swap all columns - - const size_t columnCount = m_currPlugins->columnCount(); - for (size_t j = 0; j < columnCount; ++j) { - const std::string swap = m_currPlugins->cell<std::string>(idx, j); - m_currPlugins->cell<std::string>(idx, j) = - m_currPlugins->cell<std::string>(idx + 1, j); - m_currPlugins->cell<std::string>(idx + 1, j) = swap; - } - refreshCurrentPluginListUI(); - } -} - -void TomoToolConfigDialogSavu::removeClicked() { - // Also clear ADS entries - if (0 == m_savuUi.treeCurrentPlugins->selectedItems().count()) - return; - - const int idx = m_savuUi.treeCurrentPlugins->currentIndex().row(); - m_currPlugins->removeRow(idx); - - refreshCurrentPluginListUI(); -} - -void TomoToolConfigDialogSavu::menuOpenClicked() { - QString s = QFileDialog::getOpenFileName(0, "Open file", QDir::currentPath(), - "NeXus files (*.nxs);;All files (*)", - new QString("NeXus files (*.nxs)")); - std::string name = s.toStdString(); - - if ("" == name) - return; - - bool opening = true; - if (m_currPlugins->rowCount() > 0) { - QMessageBox::StandardButton reply = QMessageBox::question( - this, "Open file confirmation", - "Opening the configuration file will clear the current list." - "\nWould you like to continue?", - QMessageBox::Yes | QMessageBox::No); - if (reply == QMessageBox::No) { - opening = false; - } - } - - if (opening) { - loadSavuTomoConfig(name, m_currPlugins); - - m_currentParamPath = name; - refreshCurrentPluginListUI(); - } -} - -/** -* Load a savu tomo config file into the current plugin list, overwriting it. -* Uses the algorithm LoadSavuTomoConfig -*/ -void TomoToolConfigDialogSavu::loadSavuTomoConfig( - std::string &filePath, Mantid::API::ITableWorkspace_sptr ¤tPlugins) { - // try to load tomo reconstruction parametereization file - auto alg = Mantid::API::AlgorithmManager::Instance().createUnmanaged( - "LoadSavuTomoConfig"); - alg->initialize(); - alg->setPropertyValue("Filename", filePath); - alg->setPropertyValue("OutputWorkspace", createUniqueNameHidden()); - try { - alg->execute(); - } catch (std::runtime_error &e) { - throw std::runtime_error( - std::string("Error when trying to load tomographic reconstruction " - "parameter file: ") + - e.what()); - } - - // new processing plugins list - try { - currentPlugins = alg->getProperty("OutputWorkspace"); - } catch (std::exception &e) { - userError("Could not load config file", "Failed to load the file " - "with the following error: " + - std::string(e.what())); - } -} -void TomoToolConfigDialogSavu::menuSaveClicked() { - if (m_currentParamPath.empty()) { - menuSaveAsClicked(); - return; - } - - if (0 == m_currPlugins->rowCount()) { - // Alert that the plugin list is empty - QMessageBox::information(this, tr("Unable to save file"), - "The current plugin list is empty, please add one " - "or more to the list."); - } else { - AnalysisDataService::Instance().add(createUniqueNameHidden(), - m_currPlugins); - std::string csvWorkspaceNames = m_currPlugins->getName(); - - auto alg = Mantid::API::AlgorithmManager::Instance().createUnmanaged( - "SaveTomoConfig"); - alg->initialize(); - alg->setPropertyValue("Filename", m_currentParamPath); - alg->setPropertyValue("InputWorkspaces", csvWorkspaceNames); - alg->execute(); - - if (!alg->isExecuted()) { - throw std::runtime_error("Error when trying to save config file"); - } - } -} -size_t TomoToolConfigDialogSavu::g_nameSeqNo = 0; - -// Build a unique (and hidden) name for the table ws -std::string TomoToolConfigDialogSavu::createUniqueNameHidden() { - std::string name; - do { - // with __ prefix => hidden - name = "__TomoConfigTableWS_Seq_" + - boost::lexical_cast<std::string>(g_nameSeqNo++); - } while (AnalysisDataService::Instance().doesExist(name)); - - return name; -} - -void TomoToolConfigDialogSavu::menuSaveAsClicked() { - QString s = QFileDialog::getSaveFileName(0, "Save file", QDir::currentPath(), - "NeXus files (*.nxs);;All files (*)", - new QString("NeXus files (*.nxs)")); - std::string name = s.toStdString(); - if ("" == name) - return; - - m_currentParamPath = name; - menuSaveClicked(); -} - -QString TomoToolConfigDialogSavu::tableWSRowToString(ITableWorkspace_sptr table, - size_t i) { - std::stringstream msg; - msg << "ID: " << table->cell<std::string>(i, 0) - << "\nParams: " << table->cell<std::string>(i, 1) - << "\nName: " << table->cell<std::string>(i, 2) - << "\nCite: " << table->cell<std::string>(i, 3); - return QString::fromStdString(msg.str()); -} - -/** -* Creates a treewidget item for a row of a table workspace. -* -* @param row Row from a table workspace with each row specfying a savu plugin -*/ -void TomoToolConfigDialogSavu::createPluginTreeEntry(TableRow &row) { - QStringList idStr, nameStr, citeStr, paramsStr; - idStr.push_back(QString::fromStdString("ID: " + row.cell<std::string>(0))); - nameStr.push_back( - QString::fromStdString("Name: " + row.cell<std::string>(2))); - citeStr.push_back( - QString::fromStdString("Cite: " + row.cell<std::string>(3))); - paramsStr.push_back(QString::fromStdString("Params:")); - - // Setup editable tree items - QList<QTreeWidgetItem *> items; - OwnTreeWidgetItem *pluginBaseItem = new OwnTreeWidgetItem(nameStr); - OwnTreeWidgetItem *pluginParamsItem = - new OwnTreeWidgetItem(pluginBaseItem, paramsStr, pluginBaseItem); - - // Add to the tree list. Adding now to build hierarchy for later setItemWidget - // call - items.push_back(new OwnTreeWidgetItem(pluginBaseItem, idStr, pluginBaseItem)); - items.push_back( - new OwnTreeWidgetItem(pluginBaseItem, nameStr, pluginBaseItem)); - items.push_back( - new OwnTreeWidgetItem(pluginBaseItem, citeStr, pluginBaseItem)); - items.push_back(pluginParamsItem); - - // Params will be a json string which needs splitting into child tree items - // [key/value] - ::Json::Value root; - std::string paramString = row.cell<std::string>(1); - ::Json::Reader r; - if (r.parse(paramString, root)) { - auto members = root.getMemberNames(); - for (auto it = members.begin(); it != members.end(); ++it) { - OwnTreeWidgetItem *container = - new OwnTreeWidgetItem(pluginParamsItem, pluginBaseItem); - - QWidget *w = new QWidget(); - w->setAutoFillBackground(true); - - QHBoxLayout *layout = new QHBoxLayout(w); - layout->setMargin(1); - QLabel *label1 = new QLabel(QString::fromStdString((*it) + ": ")); - - QTreeWidget *paramContainerTree = new QTreeWidget(w); - connect(paramContainerTree, SIGNAL(itemChanged(QTreeWidgetItem *, int)), - this, SLOT(paramValModified(QTreeWidgetItem *, int))); - paramContainerTree->setHeaderHidden(true); - paramContainerTree->setIndentation(0); - - auto jsonVal = root.get(*it, ""); - std::string valStr = pluginParamValString(jsonVal, *it); - - QStringList paramVal(QString::fromStdString(valStr)); - OwnTreeWidgetItem *paramValueItem = - new OwnTreeWidgetItem(paramVal, pluginBaseItem, *it); - paramValueItem->setFlags(Qt::ItemIsEditable | Qt::ItemIsEnabled); - - paramContainerTree->addTopLevelItem(paramValueItem); - QRect rect = paramContainerTree->visualItemRect(paramValueItem); - paramContainerTree->setMaximumHeight(rect.height()); - paramContainerTree->setFrameShape(QFrame::NoFrame); - - layout->addWidget(label1); - layout->addWidget(paramContainerTree); - - pluginParamsItem->addChild(container); - m_savuUi.treeCurrentPlugins->setItemWidget(container, 0, w); - } - } - - pluginBaseItem->addChildren(items); - m_savuUi.treeCurrentPlugins->addTopLevelItem(pluginBaseItem); -} - -/** -* This is a kind of .asString() method for arrays. It iterates -* through the array elements and builds the string enclosed by []. -* -* @param jsonVal Value of a parameter that seems to be an array -*(isArray()==true) -* @param name Name of the parameter (to give informative messages) -* -* @return String with a parameter value(s), enclosed by [] and -* separated by commas -*/ -std::string -TomoToolConfigDialogSavu::paramValStringFromArray(const Json::Value &jsonVal, - const std::string &name) { - std::string s; - s = "["; - for (Json::ArrayIndex i = 0; i < jsonVal.size(); ++i) { - if (jsonVal[i].isArray()) { - userWarning( - "Could not recognize parameter value in list/array", - "The value of parameter '" + name + - "' could not be interpreted " - "as a string. It does not seem to be well formed or supported. " - "For example, parameter values given as lists of lists are not " - "supported."); - } else { - try { - s += jsonVal[i].asString() + " ,"; - } catch (std::exception &e) { - userWarning( - "Could not recognize value in list/array of values", - "The " + boost::lexical_cast<std::string>(i) + - "-th value of the list/array could not be interpreted " - "as a text string. It will be empty in the list of current " - "plugins. You can still edit it. Error details: " + - std::string(e.what())); - } - } - } - // this could be s.back() with C++11 - s[s.length() - 1] = ']'; // and last comma becomes closing ] - return s; -} - -/** -* Build a string with the value of a parameter in a json -* string. Works for scalar and list/array values. -* -* @param jsonVal Value of a parameter that seems to be an array -* @param name Name of the parameter (to give informative messages) -* -* @return String with a parameter value -*/ -std::string -TomoToolConfigDialogSavu::pluginParamValString(const Json::Value &jsonVal, - const std::string &name) { - std::string s; - // string and numeric values can (normally) be converted to string but arrays - // cannot - if (!jsonVal.isArray()) { - try { - s = jsonVal.asString(); - } catch (std::exception &e) { - userWarning( - "Could not recognize parameter value", - "The value of parameter '" + name + - "' could not be interpreted " - "as a string. It will be empty in the list of current plugins. " - "You can still edit it. Error details: " + - std::string(e.what())); - } - } else { - s = paramValStringFromArray(jsonVal, name); - } - return s; -} - -void TomoToolConfigDialogSavu::createPluginTreeEntries( - Mantid::API::ITableWorkspace_sptr table) { - for (size_t i = 0; i < table->rowCount(); ++i) { - Mantid::API::TableRow r = table->getRow(i); - createPluginTreeEntry(r); - } -} - -/** TODO move into a class, extract from here and QtView interface -* Show an error (serious) message to the user (pop up) -* -* @param err Basic error title -* @param description More detailed explanation, hints, additional -* information, etc. -*/ -void TomoToolConfigDialogSavu::userError(const std::string &err, - const std::string &description) { - QMessageBox::critical(this, QString::fromStdString(err), - QString::fromStdString(description), QMessageBox::Ok, - QMessageBox::Ok); -} - -/** -* Show a warning message to the user (pop up) -* -* @param err Basic error title -* @param description More detailed explanation, hints, additional -* information, etc. -*/ -void TomoToolConfigDialogSavu::userWarning(const std::string &err, - const std::string &description) { - QMessageBox::warning(this, QString::fromStdString(err), - QString::fromStdString(description), QMessageBox::Ok, - QMessageBox::Ok); -} - -} // namespace CustomInterfaces -} // namespace MantidQt diff --git a/MantidQt/CustomInterfaces/src/Tomography/TomoToolConfigDialogTomoPy.cpp b/MantidQt/CustomInterfaces/src/Tomography/TomoToolConfigDialogTomoPy.cpp deleted file mode 100644 index e20fafd4782..00000000000 --- a/MantidQt/CustomInterfaces/src/Tomography/TomoToolConfigDialogTomoPy.cpp +++ /dev/null @@ -1,47 +0,0 @@ -#include "MantidQtCustomInterfaces/Tomography/TomoToolConfigDialogTomoPy.h" -#include "MantidQtCustomInterfaces/Tomography/ToolConfigTomoPy.h" - -namespace MantidQt { -namespace CustomInterfaces { - -const std::string TomoToolConfigDialogTomoPy::DEFAULT_TOOL_NAME = "TomoPy"; -const std::string TomoToolConfigDialogTomoPy::DEFAULT_TOOL_METHOD = "gridrec"; - -void TomoToolConfigDialogTomoPy::setupDialogUi() { - m_tomoPyUi.setupUi(m_dialog); - m_tomoPyUi.comboBox_method->clear(); - - const auto &methods = getToolMethods(); - for (auto &method : methods) { - m_tomoPyUi.comboBox_method->addItem(QString::fromStdString(method.second)); - } -} - -void TomoToolConfigDialogTomoPy::initialiseDialog() { m_dialog = new QDialog; } - -void TomoToolConfigDialogTomoPy::setupToolSettingsFromPaths() { - // TODO: for the output path, probably better to take the sample path, - // then up one level - m_toolSettings = std::make_shared<ToolConfigTomoPy>( - m_runPath, m_pathOut + m_localOutNameAppendix, m_paths.pathDarks(), - m_paths.pathOpenBeam(), m_paths.pathSamples()); -} -void TomoToolConfigDialogTomoPy::setupMethodSelected() { - // move to member/global variable and use more space OR keep here - const auto &methods = getToolMethods(); - - const int mi = m_tomoPyUi.comboBox_method->currentIndex(); - // TODO maybe comboBox_method->currentText? - m_toolMethod = methods[mi].first; -} - -/** Calls the execute of the QDialog -*/ -int TomoToolConfigDialogTomoPy::executeQt() { return m_dialog->exec(); } - -std::vector<std::pair<std::string, std::string>> -TomoToolConfigDialogTomoPy::getToolMethods() { - return ToolConfigTomoPy::methods(); -} -} // Custominterfaces -} // MantidQt diff --git a/MantidQt/CustomInterfaces/src/Tomography/TomographyIfaceModel.cpp b/MantidQt/CustomInterfaces/src/Tomography/TomographyIfaceModel.cpp deleted file mode 100644 index 1ee58d8ace5..00000000000 --- a/MantidQt/CustomInterfaces/src/Tomography/TomographyIfaceModel.cpp +++ /dev/null @@ -1,1048 +0,0 @@ -#include "MantidAPI/AlgorithmManager.h" -#include "MantidAPI/MatrixWorkspace.h" -#include "MantidAPI/WorkspaceGroup.h" -#include "MantidKernel/FacilityInfo.h" -#include "MantidQtAPI/AlgorithmRunner.h" -#include "MantidQtCustomInterfaces/Tomography/TomographyIfaceModel.h" -#include "MantidQtCustomInterfaces/Tomography/TomographyProcess.h" -#include "MantidQtCustomInterfaces/Tomography/TomographyThread.h" - -#include <Poco/Path.h> - -#ifndef _WIN32 -// This is exclusively for kill/waitpid (interim solution, see below) -#include <signal.h> -#include <sys/wait.h> - -#endif - -using namespace Mantid::API; -using namespace MantidQt::CustomInterfaces; - -namespace MantidQt { -namespace CustomInterfaces { - -namespace { -Mantid::Kernel::Logger g_log("TomographyGUI"); -} - -// names by which we know compute resourcess -const std::string TomographyIfaceModel::g_SCARFName = "SCARF@STFC"; -const std::string TomographyIfaceModel::g_LocalResourceName = "Local"; - -const std::string TomographyIfaceModel::g_mainReconstructionScript = - "/Imaging/IMAT/tomo_reconstruct.py"; - -const std::string TomographyIfaceModel::g_tomoScriptFolderPath = "/scripts"; - -// names by which we know image/tomography reconstruction tools (3rd party) -const std::string TomographyIfaceModel::g_TomoPyTool = "TomoPy"; -const std::string TomographyIfaceModel::g_AstraTool = "Astra"; -const std::string TomographyIfaceModel::g_CCPiTool = "CCPi CGLS"; -const std::string TomographyIfaceModel::g_SavuTool = "Savu"; -const std::string TomographyIfaceModel::g_customCmdTool = "Custom command"; - -/** - * Default constructor, but note that this currently relies on the - * SCARF cluster (only in ISIS facility) as the only supported remote - * compute resource. - */ -TomographyIfaceModel::TomographyIfaceModel() - : m_facility("ISIS"), m_experimentRef("RB000000"), m_loggedInUser(""), - m_loggedInComp(""), m_computeResStatus(), m_reconTools(), - m_reconToolsStatus(), m_jobsStatus(), m_prePostProcSettings(), - m_imageStackPreParams(), m_statusMutex(NULL) { - - m_computeRes = {g_SCARFName, g_LocalResourceName}; - - m_SCARFtools = {g_TomoPyTool, g_AstraTool, g_CCPiTool, g_SavuTool, - g_customCmdTool}; - - m_currentToolName = m_SCARFtools.front(); - - m_statusMutex = new QMutex(); -} - -TomographyIfaceModel::~TomographyIfaceModel() { - if (m_statusMutex) - delete m_statusMutex; -} - -void TomographyIfaceModel::cleanup() { - const std::string user = loggedIn(); - if (!user.empty()) { - doLogout(m_loggedInComp, user); - m_loggedInUser = ""; - } -} - -/** - * Check that the selected compute resource is listed as supported and - * usable for the remote manager (if it is not local). Local jobs are - * not supported for the time being, so this currently raises an - * exception if the local resource has been selected. - * - * This should never throw an exception if the - * construction/initialization and setup steps went fine and the rest - * of the code is kept consistent with those steps. - * - * @param res Name of the compute resource selected in the interface - * - * @return Name of a compute resource (which can be the 'Local' one) - * - * @throws std::runtime_error on inconsistent selection of compute - * resource - */ -std::string -TomographyIfaceModel::validateCompResource(const std::string &res) const { - if (res == g_LocalResourceName) { - return g_LocalResourceName; - } - - if (m_computeRes.size() <= 0) { - throw std::runtime_error("No compute resource registered in the list " - "of supported resources. This graphical interface " - "is in an inconsistent status."); - } - - const std::string supported = m_computeRes.front(); - if (supported.empty()) { - throw std::runtime_error("The first compute resource registered in this " - "interface has an empty name."); - } - - if (res != supported) { - throw std::runtime_error("The compute resource selected (" + res + - ") is not the one in principle supported by this " - "interface: " + - supported); - } - - return supported; -} - -/** - * Sets the compute resource that will be used to run reconstruction - * or other types of jobs. It checks that the facility and compute - * resource are fine (the one expected). Otherwise, shows an error - * and not much can be done. - */ -void TomographyIfaceModel::setupComputeResource() { - // m_computeRes is initialized in the constructor and doesn't change - m_computeResStatus.clear(); - - if (!facilitySupported()) { - const std::string facName = - Mantid::Kernel::ConfigService::Instance().getFacility().name(); - throw std::runtime_error( - "Failed to initialize because the facility is " + facName + - " (and not " + m_facility + - "). " - "Facility not supported. This interface is designed " - "to be used at " + - m_facility + - ". You will probably not be able to use it in a useful way " - "because your facility is " + - facName + - ". If you have set that facility by mistake in your settings, " - "please update it."); - } - - // this implies a nearly empty / no functionality interface - if (m_computeRes.size() < 1) { - return; - } - - // assume the present reality: just SCARF - const std::string &required = m_computeRes.front(); - std::vector<std::string> res = Mantid::Kernel::ConfigService::Instance() - .getFacility() - .computeResources(); - if (res.end() == std::find(res.begin(), res.end(), required)) { - throw std::runtime_error( - "Required compute resource: '" + required + - "' not found. " - "This interface requires the " + - required + " compute resource. Even though your current facility is " + - "in principle supported, the compute resource was not found. " - "In principle the compute resource should have been " - "defined in the facilities file for you facility. " - "Please check your settings."); - } - m_computeResStatus.push_back(true); - - // finally, put local as last compute resource, and enable it by default - // TODO: as in validateCompResource() some basic sanity checks could - // be done before enabling it, including availability of the - // necessaryy external tools - m_computeResStatus.push_back(true); -} - -/** - * Sets the tools that can be run once we know the compute resource - * where they're going to run. This is very dependent on how the - * facility and compute resource is adminstered and what the resource - * provides. - * - * @param compRes compute resource for which the tools have to be set - * up. If empty, the default resource is assumed - */ -void TomographyIfaceModel::setupRunTool(const std::string &compRes) { - m_reconToolsStatus.clear(); - - // catch all the useable/relevant tools for the compute - // resources. For the time being this is rather simple (just - // SCARF) and will probably stay like this for a while. - if (g_LocalResourceName == compRes || - ("ISIS" == m_facility && (compRes.empty() || g_SCARFName == compRes))) { - m_reconTools = m_SCARFtools; - } else { - throw std::runtime_error("Cannot setup this interface for the facility: " + - m_facility + - ". There is no information about tools for it. "); - } - // others would/could come here - - for (size_t i = 0; i < m_reconTools.size(); i++) { - // put CCPi but disable it, as it's not yet sorted out how it is - // configured / run - if (g_CCPiTool == m_reconTools[i] || - // also, we cannot run Savu at present, and CCPi is not available - g_SavuTool == m_reconTools[i]) { - m_reconToolsStatus.push_back(false); - } else { - m_reconToolsStatus.push_back(true); - } - } -} - -bool TomographyIfaceModel::facilitySupported() { - const Mantid::Kernel::FacilityInfo &fac = - Mantid::Kernel::ConfigService::Instance().getFacility(); - - return (fac.name() == m_facility); -} - -/** - * Ping the compute resource / server to check if it's alive and - * responding. - * - * @return True if ping succeeded - */ -bool TomographyIfaceModel::doPing(const std::string &compRes) { - // This actually does more than a simple ping. Ping and check that a - // transaction can be created succesfully - try { - auto alg = Mantid::API::AlgorithmManager::Instance().createUnmanaged( - "StartRemoteTransaction"); - alg->initialize(); - alg->setProperty("ComputeResource", compRes); - std::string tid; - alg->execute(); - tid = alg->getPropertyValue("TransactionID"); - g_log.information() << "Pinged '" << compRes - << "'succesfully. Checked that a transaction could " - "be created, with ID: " << tid << '\n'; - } catch (std::runtime_error &e) { - throw std::runtime_error("Error. Failed to ping and start a transaction on " - "the remote resource." + - std::string(e.what())); - } - - return true; -} - -/** - * Log into remote compute resource. - * - * @param compRes Name of the compute resource where to login - * @param user Username - * @param pw Password/authentication credentials as a string - */ -void TomographyIfaceModel::doLogin(const std::string &compRes, - const std::string &user, - const std::string &pw) { - auto alg = - Mantid::API::AlgorithmManager::Instance().createUnmanaged("Authenticate"); - try { - alg->initialize(); - alg->setPropertyValue("UserName", user); - alg->setPropertyValue("ComputeResource", compRes); - alg->setPropertyValue("Password", pw); - alg->execute(); - } catch (std::runtime_error &e) { - throw std::runtime_error("Unexpected error when trying to log into the " - "remote compute resource " + - compRes + " with username " + user + ": " + - e.what()); - } - - // Status: logged in - if (alg->isExecuted()) { - m_loggedInUser = user; - m_loggedInComp = compRes; - } -} - -void TomographyIfaceModel::doLogout(const std::string &compRes, - const std::string &username) { - try { - auto alg = - Mantid::API::AlgorithmManager::Instance().createUnmanaged("Logout"); - alg->initialize(); - alg->setProperty("ComputeResource", compRes); - alg->setProperty("UserName", username); - alg->execute(); - } catch (std::runtime_error &e) { - throw std::runtime_error( - "Error when trying to log out from the remote compute resource " + - compRes + " with username " + username + ": " + e.what()); - } - - m_loggedInUser = ""; -} - -void TomographyIfaceModel::doQueryJobStatus(const std::string &compRes, - std::vector<std::string> &ids, - std::vector<std::string> &names, - std::vector<std::string> &status, - std::vector<std::string> &cmds) { - auto alg = Mantid::API::AlgorithmManager::Instance().createUnmanaged( - "QueryAllRemoteJobs"); - try { - alg->initialize(); - alg->setPropertyValue("ComputeResource", compRes); - alg->execute(); - } catch (std::runtime_error &e) { - throw std::runtime_error( - "Error when trying to query the status of jobs in " + compRes + ": " + - e.what()); - } - ids = alg->getProperty("JobId"); - names = alg->getProperty("JobName"); - status = alg->getProperty("JobStatusString"); - cmds = alg->getProperty("CommandLine"); -} - -/** - * Build the components of the command line to run on the remote or local - * compute resource. Produces a (normally full) path to a runnable, and - * the options (quite like $0 and $* in scripts). - * - * The local and remote command lines look a bit different: - * - local also has the interpreter path at the front: python /scriptPath/ - * --params.. - * - remote only has the script path: /scriptPathOnRemote/ --params.. - * - * @param local Is the resource local or remote - * @param runnable Path to a runnable application (script, python module, etc.) - * @param args A vector that contains all the arguments - * @param allOpts The concatenated arguments in a single string - */ -void TomographyIfaceModel::prepareSubmissionArguments( - const bool local, std::string &runnable, std::vector<std::string> &args, - std::string &allOpts) { - - const std::string tool = usingTool(); - const std::string cmd = m_currentToolSettings->toCommand(); - - std::string longOpt; - // this gets the runnable from the whole string - splitCmdLine(cmd, runnable, longOpt); - - // this is discarded for all tools but the custom command - std::string trailingCommands; - if (local) { - std::string execScriptPath; - splitCmdLine(longOpt, execScriptPath, trailingCommands); - args.emplace_back(execScriptPath); - } - - if (tool == g_customCmdTool) { - // if it's local we need to append the trailingCommands, as the - // external interpreter and script path are already appended, the script - // path has to be in a separate argument member otherwise running the - // external interpreter fails if remote we just want to append all of the - // options, the script path is already appended - args.emplace_back(local ? trailingCommands : longOpt); - allOpts = constructSingleStringFromVector(args); - return; - } - - // appends the additional options tool name, algorithm name, filters, etc - makeTomoRecScriptOptions(local, args); - - checkIfToolIsSetupProperly(tool, cmd, args); - - // used for remote submission - allOpts = constructSingleStringFromVector(args); - - logMsg("Running " + usingTool() + ", with binary: " + runnable + - ", with parameters: " + allOpts); -} - -/** - * Build the command line options string in the way the tomorec - * scripts (remote and local) expect it. - * - * @param local whether to adapt the options for a local run (as - * opposed to a remote compute resource) - * @param opts The vector of arguments in which the additional - * arguments will be inserted - * @return command options ready for the tomorec script - */ -void TomographyIfaceModel::makeTomoRecScriptOptions( - const bool local, std::vector<std::string> &opts) const { - // options with all the info from filters and regions - // 9 is the current number of arguments being added - opts.reserve(9); - - const std::string currentTool = usingTool(); - const std::string toolNameArg = prepareToolNameForArgs(currentTool); - - const std::string toolArgument = "--tool=" + toolNameArg; - - opts.emplace_back(toolArgument); - - opts.emplace_back("--algorithm=" + m_currentToolMethod); - - // TODO fix proper iterations reading from the interface - opts.emplace_back("--num-iter=5"); - - filtersCfgToCmdOpts(m_prePostProcSettings, m_imageStackPreParams, local, - opts); -} - -/** Processes the tool name so that it is appropriate for the command line when - * executed - */ -std::string TomographyIfaceModel::prepareToolNameForArgs( - const std::string &toolName) const { - - // the only processing we have for now is converting it to lower case - std::string outputString = toolName; // copy over the string - std::transform(toolName.cbegin(), toolName.cend(), outputString.begin(), - ::tolower); - return outputString; -} - -std::string TomographyIfaceModel::constructSingleStringFromVector( - const std::vector<std::string> args) const { - std::string allOpts; - for (const auto &arg : args) { - allOpts += arg + " "; - } - return allOpts; -} - -void TomographyIfaceModel::doRemoteRunReconstructionJob( - const std::string &compRes, const std::string &runnable, - const std::string &allOpts) { - // with SCARF we use one (pseudo)-transaction for every submission - auto transAlg = Mantid::API::AlgorithmManager::Instance().createUnmanaged( - "StartRemoteTransaction"); - transAlg->initialize(); - transAlg->setProperty("ComputeResource", compRes); - std::string tid; - try { - transAlg->execute(); - tid = transAlg->getPropertyValue("TransactionID"); - } catch (std::runtime_error &e) { - throw std::runtime_error("Error when trying to start a transaction right " - "before submitting a reconstruction job: " + - std::string(e.what())); - } - - auto submitAlg = Mantid::API::AlgorithmManager::Instance().createUnmanaged( - "SubmitRemoteJob"); - submitAlg->initialize(); - submitAlg->setProperty("ComputeResource", compRes); - submitAlg->setProperty("TaskName", "Mantid tomographic reconstruction job"); - submitAlg->setProperty("TransactionID", tid); - submitAlg->setProperty("ScriptName", runnable); - submitAlg->setProperty("ScriptParams", allOpts); - try { - submitAlg->execute(); - } catch (std::runtime_error &e) { - throw std::runtime_error( - "Error when trying to submit a reconstruction job: " + - std::string(e.what())); - } -} - -/** Starts the local thread with the external reconstruction process - * @param runnable Path to a runnable application (script, python module, etc.) - * @param args A vector that contains all the arguments - * @param allOpts The concatenated arguments in a single string - * @param thread This thread will be started after the worker is set up with the - * runnable and the arguments - * @param worker The worker will only be set up with the runnable and arguments - * @param workerName The process name with which it will be shown in the - * reconstruction jobs. Default is "Mantid_Local" - */ -void TomographyIfaceModel::doLocalRunReconstructionJob( - const std::string &runnable, const std::vector<std::string> &args, - const std::string &allOpts, TomographyThread &thread, - TomographyProcess &worker, const std::string &workerName) { - - // Can only run one reconstruction at a time - // Qt doesn't use exceptions so we can't make sure it ran here - worker.setup(runnable, args, allOpts, workerName); - thread.start(); -} - -void TomographyIfaceModel::addJobToStatus(const qint64 pid, - const std::string &runnable, - const std::string &allOpts, - const std::string &workerName) { - Mantid::API::IRemoteJobManager::RemoteJobInfo info; - info.id = boost::lexical_cast<std::string>(pid); - info.name = pid > 0 ? workerName : "none"; - info.status = pid > 0 ? "Starting" : "Exit"; - info.cmdLine = runnable + " " + allOpts; - m_jobsStatusLocal.emplace_back(info); - doRefreshJobsInfo(g_LocalResourceName); -} - -void TomographyIfaceModel::doCancelJobs(const std::string &compRes, - const std::vector<std::string> &ids) { - for (size_t i = 0; i < ids.size(); i++) { - const std::string id = ids[i]; - auto algJob = Mantid::API::AlgorithmManager::Instance().createUnmanaged( - "AbortRemoteJob"); - algJob->initialize(); - algJob->setPropertyValue("ComputeResource", compRes); - algJob->setPropertyValue("JobID", id); - try { - algJob->execute(); - } catch (std::runtime_error &e) { - throw std::runtime_error( - "Error when trying to cancel a reconstruction job: " + - std::string(e.what())); - } - } - // doesn't do StopRemoteTransaction. If there are multiple jobs per - // transaction there could be others that are still running. -} - -void TomographyIfaceModel::doRefreshJobsInfo(const std::string &compRes) { - - if (g_LocalResourceName == compRes) { - refreshLocalJobsInfo(); - return; - } - - // get the info from the server into data members. This operation is subject - // to delays in the connection, etc. - try { - getJobStatusInfo(compRes); - } catch (std::runtime_error &e) { - g_log.warning() << "There was an issue while trying to retrieve job status " - "information from the remote compute resource (" - << compRes - << "). Stopping periodic (automatic) status update to " - "prevent more failures. You can start the automatic " - "update mechanism again by logging in, as apparently " - "there is some problem with the last session: " - << e.what() << '\n'; - } -} - -void TomographyIfaceModel::refreshLocalJobsInfo() { - for (auto &job : m_jobsStatusLocal) { - if ("Exit" == job.status || "Done" == job.status) - continue; - - if (processIsRunning(boost::lexical_cast<int>(job.id))) { - job.status = "Running"; - } else { - job.status = "Done"; - } - } -} - -void TomographyIfaceModel::updateProcessInJobList(const qint64 pid, - const int exitCode) { - // cast to string from qint64 so we can compare - const std::string processPID = std::to_string(pid); - for (auto &job : m_jobsStatusLocal) { - if (job.id == processPID && exitCode == 1) { - job.status = "Exit"; - } - } -} - -void TomographyIfaceModel::getJobStatusInfo(const std::string &compRes) { - if (m_loggedInUser.empty()) - return; - - std::vector<std::string> ids, names, status, cmds; - doQueryJobStatus(compRes, ids, names, status, cmds); - - size_t jobMax = ids.size(); - if (ids.size() != names.size() || ids.size() != status.size() || - ids.size() != cmds.size()) { - // this should not really happen - jobMax = std::min(ids.size(), names.size()); - jobMax = std::min(jobMax, status.size()); - jobMax = std::min(jobMax, cmds.size()); - g_log.warning() - << "Problem retrieving job status information. " - "The response from the compute resource did not seem " - "correct. The table of jobs may not be fully up to date."; - } - - { - QMutexLocker lockit(m_statusMutex); - m_jobsStatus.clear(); - // TODO: udate when we update to remote algorithms v2 and more - // info might become available from SCARF. - // As SCARF doesn't provide all the info at the moment, the - // IRemoteJobManager::RemoteJobInfo struct is for now used only - // partially (cmds out). So this loop feels both incomplete and an - // unecessary second step that could be avoided. - for (size_t i = 0; i < ids.size(); ++i) { - IRemoteJobManager::RemoteJobInfo ji; - ji.id = ids[i]; - ji.name = names[i]; - ji.status = status[i]; - ji.cmdLine = cmds[i]; - m_jobsStatus.push_back(ji); - } - } -} - -/** - * Make sure that the data paths (sample, dark, open beam) make - * sense. Otherwise, warn the user and log error. - * - * @throw std::runtime_error if the required fields are not set - * properly - */ -void TomographyIfaceModel::checkDataPathsSet() const { - if (!m_pathsConfig.validate()) { - const std::string detail = - "Please define the paths to your dataset images. " - "You have not defined some of the following paths: sample, " - "dark, or open beam images. " - "They are all required to run reconstruction jobs. Please " - "define these paths in the settings of the interface. "; - throw std::runtime_error( - "Cannot run any reconstruction job without the " - "paths to the sample, dark and open beam images. " + - detail); - } -} - -/** - * Whether a process (identified by pid) is running. - * - * This should use Poco::Process, but only more recent Poco versions - * than what we currently support across platforms have the required - * Poco::Process::isRunning. Allternatively, it could use QProcess, - * but that would require Qt 5. - * - * @param pid ID of the process - * - * @return running status - */ -bool TomographyIfaceModel::processIsRunning(qint64 pid) const { -#ifdef _WIN32 - HANDLE handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, static_cast<int>(pid)); - DWORD code; - BOOL rc = GetExitCodeProcess(handle, &code); - CloseHandle(handle); - return (rc && code == STILL_ACTIVE); -#else - // zombie/defunct processes - while (waitpid(-1, 0, WNOHANG) > 0) { - } - return (0 == kill(static_cast<int>(pid), 0)); -#endif - // return Poco::Process::isRunning(pid); -} - -/** - * This can produce a tool-specific warning that can be shown for - * different tools when they are not fully setup (any required - * parameter is missing). - * - * @param tool Name of the tool this warning applies to - * @param cmd command/script/executable derived from the settings - * @param args All the arguments for the run - */ -bool TomographyIfaceModel::checkIfToolIsSetupProperly( - const std::string &tool, const std::string &cmd, - const std::vector<std::string> &args) const { - if (tool.empty() || cmd.empty() || args.empty()) { - const std::string detail = - "Please define the settings of this tool. " - "You have not defined any settings for this tool: " + - tool + - ". Before running it you need to define its settings " - "(method, parameters, etc.). You can do so by clicking on the setup " - "button."; - throw std::runtime_error("Cannot run the tool " + tool + - " without setting it up." + detail); - } - return true; -} - -/** - * Temporary helper to do an operation that shouldn't be needed any longer - * when the code is reorganized to use the tool settings objects better. - */ -void TomographyIfaceModel::splitCmdLine(const std::string &cmd, - std::string &runnable, - std::string &opts) const { - if (cmd.empty()) - return; - - const auto pos = cmd.find(" "); - if (std::string::npos == pos) - return; - - runnable = cmd.substr(0, pos); - opts = cmd.substr(pos + 1); -} - -/** -* Helper to get a FITS image into a workspace. Uses the LoadFITS -* algorithm. If the algorithm throws, this method shows user (pop-up) -* warning/error messages but does not throw. -* -* This method returns a workspace group which most probably you want -* to delete after using the image to draw it. -* -* @param path Path to a FITS image -* -* @return Group Workspace containing a Matrix workspace with a FITS -* image, one pixel per histogram, as loaded by LoadFITS (can be empty -* if the load goes wrong and the workspace is not available from the -* ADS). -*/ -WorkspaceGroup_sptr -TomographyIfaceModel::loadFITSImage(const std::string &path) { - // get fits file into workspace and retrieve it from the ADS - auto alg = AlgorithmManager::Instance().createUnmanaged("LoadFITS"); - alg->initialize(); - alg->setPropertyValue("Filename", path); - std::string wsName = "__fits_ws_tomography_gui"; - alg->setProperty("OutputWorkspace", wsName); - // this is way faster when loading into a MatrixWorkspace - alg->setProperty("LoadAsRectImg", true); - try { - alg->execute(); - } catch (std::exception &e) { - throw std::runtime_error( - "Failed to load image. Could not load this file as a " - "FITS image: " + - std::string(e.what())); - } - if (!alg->isExecuted()) { - throw std::runtime_error( - "Failed to load image correctly. Note that even though " - "the image file has been loaded it seems to contain errors."); - } - WorkspaceGroup_sptr wsg; - MatrixWorkspace_sptr ws; - try { - wsg = AnalysisDataService::Instance().retrieveWS<WorkspaceGroup>(wsName); - ws = AnalysisDataService::Instance().retrieveWS<MatrixWorkspace>( - wsg->getNames()[0]); - } catch (std::exception &e) { - throw std::runtime_error( - "Could not load image contents. An unrecoverable error " - "happened when trying to load the image contents. Cannot " - "display it. Error details: " + - std::string(e.what())); - } - - // draw image from workspace - if (wsg && ws && - Mantid::API::AnalysisDataService::Instance().doesExist(ws->getName())) { - return wsg; - } else { - return WorkspaceGroup_sptr(); - } -} - -void TomographyIfaceModel::logMsg(const std::string &msg) { g_log.notice(msg); } - -void TomographyIfaceModel::logErrMsg(const std::string &msg) { - g_log.error(msg); -} - -/** - * Produces a comma separated list of coordinates as a string of real values - * - * @param coords Coordinates given as point 1 (x,y), point 2 (x,y) - * - * @returns A string like "x1, y1, x2, y2" - */ -std::string boxCoordinatesToCSV(const ImageStackPreParams::Box2D &coords) { - const std::string s_left = std::to_string(coords.second.X()); - const std::string s_top = std::to_string(coords.first.Y()); - const std::string s_right = std::to_string(coords.first.X()); - const std::string s_bottom = std::to_string(coords.second.Y()); - - return s_left + ", " + s_top + ", " + s_right + ", " + s_bottom; -} - -/** - * Build options string to send them to the tomographic reconstruction - * scripts command line. - * - * @param filters Settings for the pre-post processing steps/filters - * - * @param corRegions center and regions selected by the user (region - * of intererst/analysis area and normalization or air region). - * - * @param local whether to adapt the options for a local run (as - * opposed to a remote compute resource) - * - * @param opts array where to add the options (one element will be - * added for every option). - * - * This doesn't belong here and should be moved to more appropriate - * place when the settings settle. - */ -void TomographyIfaceModel::filtersCfgToCmdOpts( - const TomoReconFiltersSettings &filters, - const ImageStackPreParams &corRegions, const bool local, - std::vector<std::string> &opts) const { - - opts.emplace_back("--input-path=" + adaptInputPathForExecution( - m_pathsConfig.pathSamples(), local)); - - const std::string alg = getCurrentToolMethod(); - - // check the general enable option and the dataset specific enable - if (filters.prep.normalizeByFlats && m_pathsConfig.m_pathOpenBeamEnabled) { - const std::string flat = m_pathsConfig.pathOpenBeam(); - if (!flat.empty()) - opts.emplace_back("--input-path-flat=" + - adaptInputPathForExecution(flat, local)); - } - - if (filters.prep.normalizeByDarks && m_pathsConfig.m_pathDarkEnabled) { - const std::string dark = m_pathsConfig.pathDarks(); - if (!dark.empty()) - opts.emplace_back("--input-path-dark=" + - adaptInputPathForExecution(dark, local)); - } - - std::string openList; - std::string closeList; - // TODOMODL how to handle this? we still need to know what the resource is, - // because local is windows and remote is linux - if (local) { - openList = "["; - closeList = "]"; - } else { - openList = "'["; - closeList = "]'"; - } - if ((corRegions.roi.first.X() > 0 || corRegions.roi.second.X() > 0) && - (corRegions.roi.first.Y() > 0 || corRegions.roi.second.Y() > 0)) { - opts.emplace_back("--region-of-interest=" + openList + - boxCoordinatesToCSV(corRegions.roi) + closeList); - } - - if (filters.prep.normalizeByAirRegion) { - if (0 != corRegions.normalizationRegion.first.X() || - 0 != corRegions.normalizationRegion.second.X()) - opts.emplace_back("--air-region=" + openList + - boxCoordinatesToCSV(corRegions.normalizationRegion) + - closeList); - } - - const std::string outBase = - buildOutReconstructionDir(m_pathsConfig.pathSamples(), local); - - // append a 'now' string - auto now = Mantid::Kernel::DateAndTime::getCurrentTime(); - const std::string timeAppendix = now.toFormattedString("%Y%B%d_%H%M%S") + - "_" + std::to_string(now.nanoseconds()); - - // one name for this particular reconstruction, like: - // out_reconstruction_TomoPy_gridrec_ - const std::string reconName = - "reconstruction_" + m_currentToolName + "_" + alg + "_" + timeAppendix; - - const std::string outOpt = outBase + "/" + reconName; - - if (local) { - // doesn't go through the shell so it should not have quotes - opts.emplace_back("--output=" + adaptInputPathForExecution(outOpt, local)); - } else { - opts.emplace_back("--output=\"" + - adaptInputPathForExecution(outOpt, local) + "\""); - } - - // TODO: will/should use m_systemSettings.m_outputPathCompPreProcessed to - // set an option like --output-pre_processed. For now the pre_processed - // files go inside the directory of the reconstructed files. - - opts.emplace_back("--median-filter-size=" + - std::to_string(filters.prep.medianFilterWidth)); - - // Filters: - - // TODO: (we'd require here IMAT specific headers to become available soon) - // if (filters.prep.normalizeByProtonCharge) - - double cor = 0; - cor = corRegions.cor.X(); - opts.emplace_back("--cor=" + std::to_string(cor)); - - int rotationIdx = static_cast<int>(corRegions.rotation / 90); - // filters.prep.rotation - opts.emplace_back("--rotation=" + std::to_string(rotationIdx)); - - // filters.prep.maxAngle - opts.emplace_back("--max-angle=" + std::to_string(filters.prep.maxAngle)); - - // prep.scaleDownFactor - if (filters.prep.scaleDownFactor > 1) - opts.emplace_back("--scale-down=" + - std::to_string(filters.prep.scaleDownFactor)); - - // postp.circMaskRadius - opts.emplace_back("--circular-mask=" + - std::to_string(filters.postp.circMaskRadius)); - - // postp.cutOffLevel - if (filters.postp.cutOffLevel > 0.0) - opts.emplace_back("--cut-off=" + std::to_string(filters.postp.cutOffLevel)); - - // TODO: this should take the several possible alternatives from the user - // interface - opts.emplace_back("--out-img-format=png"); -} - -/** - * Converts paths to paths that will work for the reconstruction - * scripts on the local or remote machine. - * - * @param path path to a directory (samples/flats/darks) - * @param local adapt the path to local or remote execution - * - * @return path string ready to be used by the reconstruction scripts - */ -std::string -TomographyIfaceModel::adaptInputPathForExecution(const std::string &path, - const bool local) const { - if (local) - return path; - - std::string result; - // For example, request /media/scarf/data/RB0000/... - // which needs to be translated into: /work/scarf/data/RB0000/... - if (std::string::npos != - path.find(m_systemSettings.m_local.m_remoteDriveOrMountPoint)) { - result = path; - boost::replace_all(result, - m_systemSettings.m_local.m_remoteDriveOrMountPoint, - m_systemSettings.m_remote.m_basePathTomoData); - boost::replace_all(result, "\\", "/"); - } else { - result = path; - // Remote (to UNIX), assuming SCARF or similar - boost::replace_all(result, "\\", "/"); - if (result.length() >= 2 && ':' == result[1]) { - if (2 == result.length()) - result = ""; // don't accept '/' - else - result = result.substr(2); - } - } - - return result; -} - -/** - * Builds a base path for the output directory and files (which go in - * a subdirectory usually called 'processed' next to the - * samples/flats/darks directories). - * - * @param samplesDir full path to samples - * - * @return path to which an output directory name can be appended, to - * output the reconstructed volume to. - */ -std::string -TomographyIfaceModel::buildOutReconstructionDir(const std::string &samplesDir, - bool) const { - // TODO: guessing from sample dir always at the moment. - // We might want to distinguish local/remote runs at some point - // (second parameter) - // Remote runs would ideally use buildOutReconstructionDirFromSystemRoot() - return buildOutReconstructionDirFromSamplesDir(samplesDir); -} - -/** - * This method enforces the proper - * path following current IMAT rules, regardless of where the samples - * path was located. - * - * @param samplesDir full path to sample images - * - * @param local whether to adapt the path rules options for a local - * run (as opposed to a remote compute resource) - * - * @return path to which an output directory name can be appended, to - * output the reconstructed volume to. - */ -std::string TomographyIfaceModel::buildOutReconstructionDirFromSystemRoot( - const std::string &samplesDir, bool local) const { - // Like /work/imat/data/RB00XYZTUV/sampleA/processed/ - // Split in components like: /work/imat + / + data + / + RB00XYZTUV + / + - // sampleA + / + processed - std::string rootBase; - if (local) { - rootBase = m_systemSettings.m_local.m_basePathTomoData; - } else { - rootBase = m_systemSettings.m_remote.m_basePathTomoData; - } - - // Guess sample name (example: 'sampleA') from the input data path - Poco::Path pathToSample(samplesDir); - pathToSample = pathToSample.parent(); - std::string sampleName = pathToSample.directory(pathToSample.depth() - 1); - // safe fallback for pathological cases (samples in a root directory, etc.) - if (sampleName.empty()) - sampleName = "sample"; - - const std::string outBase = rootBase + "/" + - m_systemSettings.m_pathComponents[0] + "/" + - m_experimentRef + "/" + sampleName + "/" + - m_systemSettings.m_outputPathCompReconst; - - return outBase; -} - -/** - * Builds a base path for the output directory and files by looking - * for the parent of the samples directory. This method will work - * regardless of whether the samples directory location follows the - * proper IMAT conventions. - * - * @param samplesDir full path to samples - * - * @return path to which an output directory name can be appended, to - * output the reconstructed volume to. - */ -std::string TomographyIfaceModel::buildOutReconstructionDirFromSamplesDir( - const std::string &samplesDir) const { - // Guess sample name (example 'sampleA') from the input data/sample - // images path - Poco::Path path(samplesDir); - - path = path.parent(); - path.append(m_systemSettings.m_outputPathCompReconst); - - return path.toString(); -} -} // namespace CustomInterfaces -} // namespace MantidQt diff --git a/MantidQt/CustomInterfaces/src/Tomography/TomographyIfacePresenter.cpp b/MantidQt/CustomInterfaces/src/Tomography/TomographyIfacePresenter.cpp deleted file mode 100644 index b211188bc95..00000000000 --- a/MantidQt/CustomInterfaces/src/Tomography/TomographyIfacePresenter.cpp +++ /dev/null @@ -1,929 +0,0 @@ -#include "MantidAPI/AlgorithmManager.h" -#include "MantidAPI/MatrixWorkspace.h" -#include "MantidAPI/TableRow.h" -#include "MantidAPI/WorkspaceGroup.h" -#include "MantidKernel/ConfigService.h" -#include "MantidKernel/FacilityInfo.h" -#include "MantidQtCustomInterfaces/Tomography/ITomographyIfaceView.h" -#include "MantidQtCustomInterfaces/Tomography/TomoToolConfigDialogBase.h" -#include "MantidQtCustomInterfaces/Tomography/TomographyIfaceModel.h" -#include "MantidQtCustomInterfaces/Tomography/TomographyIfacePresenter.h" -#include "MantidQtCustomInterfaces/Tomography/TomographyProcess.h" -#include "MantidQtCustomInterfaces/Tomography/TomographyThread.h" - -#include <boost/lexical_cast.hpp> - -#include <Poco/DirectoryIterator.h> -#include <Poco/Path.h> - -#include <QFileInfo> -#include <QMutex> -#include <QString> -#include <QThread> -#include <QTimer> - -using namespace Mantid::API; -using namespace MantidQt::CustomInterfaces; - -namespace MantidQt { -namespace CustomInterfaces { - -const std::string TomographyIfacePresenter::g_defOutPathLocal = -#ifdef _WIN32 - "D:/imat-data/"; -#else - "~/imat/"; -#endif - -const std::string TomographyIfacePresenter::g_defOutPathRemote = -#ifdef _WIN32 - "I:/imat/imat-data/"; -#else - "~/imat-data/"; -#endif - -TomographyIfacePresenter::TomographyIfacePresenter(ITomographyIfaceView *view) - : m_view(view), m_model(new TomographyIfaceModel()), - m_statusMutex(new QMutex()), m_keepAliveTimer(nullptr) { - if (!m_view) { - throw std::runtime_error("Severe inconsistency found. Presenter created " - "with an empty/null view (tomography interface). " - "Cannot continue."); - } -} - -TomographyIfacePresenter::~TomographyIfacePresenter() { - cleanup(); - - if (m_keepAliveTimer) - delete m_keepAliveTimer; - - if (m_statusMutex) - delete m_statusMutex; -} - -/** - * Close open sessions, kill timers/threads etc., save settings, etc. for a - * graceful window close/destruct - */ -void TomographyIfacePresenter::cleanup() { - killKeepAliveMechanism(); - m_model->cleanup(); -} - -void TomographyIfacePresenter::notify( - ITomographyIfacePresenter::Notification notif) { - - switch (notif) { - - case ITomographyIfacePresenter::SystemSettingsUpdated: - processSystemSettingsUpdated(); - break; - - case ITomographyIfacePresenter::SetupResourcesAndTools: - processSetupResourcesAndTools(); - break; - - case ITomographyIfacePresenter::CompResourceChanged: - processCompResourceChanged(); - break; - - case ITomographyIfacePresenter::ToolChanged: - processToolChanged(); - break; - - case ITomographyIfacePresenter::TomoPathsChanged: - processTomoPathsChanged(); - break; - - case ITomographyIfacePresenter::TomoPathsEditedByUser: - processTomoPathsEditedByUser(); - break; - - case ITomographyIfacePresenter::LogInRequested: - processLogin(); - break; - - case ITomographyIfacePresenter::LogOutRequested: - processLogout(); - break; - - case ITomographyIfacePresenter::SetupReconTool: - processSetupReconTool(); - break; - - case ITomographyIfacePresenter::RunReconstruct: - processRunRecon(); - break; - - case ITomographyIfacePresenter::RunExternalProcess: - processRunExternalProcess(); - break; - - case ITomographyIfacePresenter::RefreshJobs: - processRefreshJobs(); - break; - - case ITomographyIfacePresenter::CancelJobFromTable: - processCancelJobs(); - break; - - case ITomographyIfacePresenter::VisualizeJobFromTable: - processVisualizeJobs(); - break; - - case ITomographyIfacePresenter::AggregateEnergyBands: - processAggregateEnergyBands(); - break; - - case ITomographyIfacePresenter::LogMsg: - processLogMsg(); - break; - - case ITomographyIfacePresenter::ShutDown: - processShutDown(); - break; - } -} - -void TomographyIfacePresenter::processRunExternalProcess() { - // TODO unify with processRunRecon() - // read the cached variables in view - const std::string &cachedExec = m_view->getCachedExecutable(); - const std::vector<std::string> &cachedArgs = m_view->getCachedArguments(); - - std::string runnable; - std::vector<std::string> args; - std::string allOpts; - // still prepare submission arguments to get the defaults - const bool local = true; - prepareSubmissionArguments(local, runnable, args, allOpts); - - // if custom external is provided, overwrite the default one - runnable = !cachedExec.empty() ? cachedExec : runnable; - - // append the additional args for now - for (const auto &arg : cachedArgs) { - args.emplace_back(arg); - allOpts += arg; - } - - setupAndRunLocalExternalProcess(runnable, args, allOpts); -} - -void TomographyIfacePresenter::setupAndRunLocalExternalProcess( - const std::string &runnable, const std::vector<std::string> &args, - const std::string &allOpts) { - - if (m_reconRunning) { - const auto result = m_view->userConfirmation( - "Reconstruction is RUNNING", - "Are you sure you want to<br>cancel the running reconstruction?"); - - if (!result) { - // user clicked NO, so we don't terminate the running reconstruction and - // simply return - return; - } - } - - // this kills the previous thread forcefully - m_workerThread.reset(); - auto *worker = new MantidQt::CustomInterfaces::TomographyProcess(); - m_workerThread = Mantid::Kernel::make_unique<TomographyThread>(this, worker); - - // Specific connections for this presenter - // we do this so the thread can independently read the process' output and - // only signal the presenter after it's done reading and has something to - // share so it doesn't block the presenter - connect(m_workerThread.get(), SIGNAL(stdOutReady(QString)), this, - SLOT(readWorkerStdOut(QString))); - connect(m_workerThread.get(), SIGNAL(stdErrReady(QString)), this, - SLOT(readWorkerStdErr(QString))); - - // remove the user confirmation for running recon, if the recon has finished - connect(m_workerThread.get(), SIGNAL(workerFinished(qint64, int)), this, - SLOT(emitExternalProcessOutput(qint64, int))); - - connect(worker, SIGNAL(started()), this, SLOT(addProcessToJobList())); - m_model->doLocalRunReconstructionJob(runnable, args, allOpts, *m_workerThread, - *worker, "Auto COR"); -} - -void TomographyIfacePresenter::emitExternalProcessOutput(const qint64 pid, - const int exitCode) { - workerFinished(pid, exitCode); - m_view->emitExternalProcessFinished(m_workerOutputCache); -} - -void TomographyIfacePresenter::processSystemSettingsUpdated() { - m_model->setSystemSettings(m_view->systemSettings()); - - // update the tool information with the new system settings - setupConfigDialogSettingsAndUpdateModel(m_configDialog.get()); -} - -void TomographyIfacePresenter::processSetupResourcesAndTools() { - // first time update, even if not requested by user - processSystemSettingsUpdated(); - - try { - m_model->setupComputeResource(); - if (m_model->computeResources().size() < 1) { - m_view->userWarning("No remote compute resource could be set up!", - "No remote compute resource has been set up. Please " - "note that without a " - "remote compute resource the functionality of this " - "interface might be limited."); - } - m_model->setupRunTool(""); - processTomoPathsChanged(); - - m_view->enableLoggedActions(!m_model->loggedIn().empty()); - - m_view->setComputeResources(m_model->computeResources(), - m_model->computeResourcesStatus()); - m_view->setReconstructionTools(m_model->reconTools(), - m_model->reconToolsStatus()); - } catch (std::runtime_error &e) { - const std::string msg = - "Failed to initialize remote compute resource(s). This " - "custom interface will not work. Error description: " + - std::string(e.what()); - - m_view->enableLoggedActions(false); - // This would ideally be shown to the user as a "fatal error" pop-up, as - // it is an unrecoverable error. But in facilities other than ISIS this - // would block the builds (docs-qthelp). - // m_view->userError("Fatal error", msg); - m_model->logMsg(msg); - } -} - -void TomographyIfacePresenter::processCompResourceChanged() { - const std::string comp = m_view->currentComputeResource(); - - // TODOPRES find a better way to set up the run tool in model - m_model->setupRunTool(comp); - - if (isLocalResourceSelected()) { - m_view->enableLoggedActions(true); - } else { - const bool status = !m_model->loggedIn().empty(); - m_view->enableLoggedActions(status); - } - - // this will udpate the tool after a resource change - setupConfigDialogSettingsAndUpdateModel(m_configDialog.get()); -} - -/** Called when the event ToolChanged fires. It gets the name for the current - * tabToolTip and first tries to create it (if valid tool name), and if that - * succeeds then updates the tool's settings to hold the current path and - * afterwards updates the model's information about the tool's current settings - */ -void TomographyIfacePresenter::processToolChanged() { - const std::string toolName = m_view->currentReconTool(); - - // disallow reconstruct on tools that don't run yet: Savu and CCPi - if (TomographyIfaceModel::g_CCPiTool == toolName) { - m_view->enableRunReconstruct(false); - m_view->enableConfigTool(false); - } else if (TomographyIfaceModel::g_SavuTool == toolName) { - // for now, show setup dialog, but cannot run - m_view->enableRunReconstruct(false); - m_view->enableConfigTool(true); - } else { - // No need to be logged in anymore when local is selected - const bool runningLocally = isLocalResourceSelected(); - m_view->enableRunReconstruct(runningLocally || - !(m_model->loggedIn().empty())); - m_view->enableConfigTool(true); - } - - // return if empty string - if ("" == toolName) { - return; - } - - createConfigDialogUsingToolName(toolName); - // this will set the default settings for the dialog - setupConfigDialogSettingsAndUpdateModel(m_configDialog.get()); -} - -void TomographyIfacePresenter::setupConfigDialogSettingsAndUpdateModel( - TomoToolConfigDialogBase *dialog) { - - // this check prevents a crash on initialisation where Qt passes a tool name - // of "" and then we have a nullptr dialogue - if (dialog) { - setupConfigDialogSettings(*dialog); - updateModelAfterToolChanged(*dialog); - } -} - -/** Uses the static method in TomoToolConfigDialogBase to create the proper tool - * from the provided name - * @param toolName The string holding the tool's name - */ -void TomographyIfacePresenter::createConfigDialogUsingToolName( - const std::string &toolName) { - // free the previous dialogue pointer if any - m_configDialog.reset(); - m_configDialog = TomoToolConfigDialogBase::getToolDialogFor(toolName); -} - -/** Depending on whether local or remote resource is selected, do setup -* the tool's run path, the paths out, the reconstruction index and -* the localOutNameAppendix -* -* @param dialog The dialog pointer that will be set up -*/ -void TomographyIfacePresenter::setupConfigDialogSettings( - TomoToolConfigDialogBase &dialog) { - - if (isLocalResourceSelected()) { - setupConfigDialogSettingsForLocal(dialog); - } else { - setupConfigDialogSettingsForRemote(dialog); - } -} - -/** Configures the dialog settings for local reconstruction, this means settings - * the run command, the pathOut and the name of the output folder - * - * @param dialog The raw dialog pointer that will be configured. - */ -void TomographyIfacePresenter::setupConfigDialogSettingsForLocal( - TomoToolConfigDialogBase &dialog) { - const std::string run = m_model->getExeternalInterpreterPath() + " " + - m_model->getCurrentLocalScriptsBasePath() + - m_model->getTomoScriptLocationPath(); - - const TomoPathsConfig paths = m_view->currentPathsConfig(); - - const std::string pathOut = Poco::Path::expand( - g_defOutPathLocal + "/" + m_model->getCurrentExperimentReference()); - static size_t reconIdx = 1; - const std::string localOutNameAppendix = - std::string("/processed/") + "reconstruction_" + std::to_string(reconIdx); - - dialog.setupDialog(run, paths, pathOut, localOutNameAppendix); -} - -/** Configures the dialog settings for remote reconstruction, this means - * settings - * the run command, the pathOut and the name of the output folder - * - * Currently it does NOT take into account the remote, this is - * something that might be needed in the future if more remote reconstruction - * locations are added, as currently the only one is SCARF - * - * @param dialog The raw dialog pointer that will be configured. - */ -void TomographyIfacePresenter::setupConfigDialogSettingsForRemote( - TomoToolConfigDialogBase &dialog) { - // set up all the information we need for the dialog - const std::string run = m_model->getCurrentRemoteScriptsBasePath() + - m_model->getTomoScriptFolderPath() + - m_model->getTomoScriptLocationPath(); - - const TomoPathsConfig paths = m_view->currentPathsConfig(); - const std::string pathOut = Poco::Path::expand( - g_defOutPathLocal + "/" + m_model->getCurrentExperimentReference()); - static size_t reconIdx = 1; - const std::string localOutNameAppendix = - std::string("/processed/") + "reconstruction_" + std::to_string(reconIdx); - - dialog.setupDialog(run, paths, pathOut, localOutNameAppendix); -} - -/** Updated the model's information about the current tool - * The settings that are updated are: - * - the current tool name - * - the current tool method - * - the current tool settings - * - * @param dialog The raw dialog pointer that will be configured. - */ -void TomographyIfacePresenter::updateModelAfterToolChanged( - const TomoToolConfigDialogBase &dialog) { - - // if passed an empty string don't remove the name - updateModelCurrentToolName(dialog); - updateModelCurrentToolMethod(dialog); - updateModelCurrentToolSettings(dialog); -} - -/** Sets the model's current tool name by getting the tool name from the -* dialogue itself -*/ -void TomographyIfacePresenter::updateModelCurrentToolName( - const TomoToolConfigDialogBase &dialog) { - m_model->usingTool(dialog.getSelectedToolName()); -} -/** Sets the model's current tool method by coyping the -* string over to the model, getting it from the dialogue itself -*/ -void TomographyIfacePresenter::updateModelCurrentToolMethod( - const TomoToolConfigDialogBase &dialog) { - m_model->setCurrentToolMethod(dialog.getSelectedToolMethod()); -} - -/** Shares the pointer with the model's tool settings. We don't want a -* unique_ptr, because the dialogs don't die after they are closed, they die if -* the tool is changed or the whole interface is closed -*/ -void TomographyIfacePresenter::updateModelCurrentToolSettings( - const TomoToolConfigDialogBase &dialog) { - m_model->setCurrentToolSettings(dialog.getSelectedToolSettings()); -} - -/** - * Simply take the paths that the user has provided. - */ -void TomographyIfacePresenter::processTomoPathsChanged() { - m_model->setTomoPathsConfig(m_view->currentPathsConfig()); -} - -/** -* Updates the model with the new path. In the process it also tries to -* guess and find a new path for the flats and darks images from the -* path to the sample images that the user has given. It would normally -* look one level up in the directory tree to see if it can find -* 'dark*' and 'flat*'. -*/ -void TomographyIfacePresenter::processTomoPathsEditedByUser() { - TomoPathsConfig cfg = m_view->currentPathsConfig(); - const std::string samples = cfg.pathSamples(); - if (samples.empty()) - return; - - try { - findFlatsDarksFromSampleGivenByUser(cfg); - } catch (std::exception &exc) { - const std::string msg = "There was a problem while trying to guess the " - "location of dark and flat images from this path " - "to sample images: " + - samples + ". Error details: " + exc.what(); - m_model->logMsg(msg); - } - - m_model->setTomoPathsConfig(cfg); - m_view->updatePathsConfig(cfg); -} - -void TomographyIfacePresenter::findFlatsDarksFromSampleGivenByUser( - TomoPathsConfig &cfg) { - Poco::Path samplesPath(cfg.pathSamples()); - Poco::DirectoryIterator end; - bool foundDark = false; - bool foundFlat = false; - for (Poco::DirectoryIterator it(samplesPath.parent()); it != end; ++it) { - if (!it->isDirectory()) { - continue; - } - - const std::string name = it.name(); - const std::string flatsPrefix = "flat"; - const std::string darksPrefix = "dark"; - - if (boost::iequals(name.substr(0, flatsPrefix.length()), flatsPrefix)) { - cfg.updatePathOpenBeam(it->path(), cfg.m_pathOpenBeamEnabled); - foundFlat = true; - } else if (boost::iequals(name.substr(0, darksPrefix.length()), - darksPrefix)) { - cfg.updatePathDarks(it->path(), cfg.m_pathDarkEnabled); - foundDark = true; - } - if (foundFlat && foundDark) - break; - } -} - -void TomographyIfacePresenter::processLogin() { - if (!m_model->facilitySupported()) { - m_view->userError( - "Fatal error", - "Cannot do any login operation because the current facility is not " - "supported by this interface. Please check the log messages for " - "more " - "details."); - return; - } - - if (!m_model->loggedIn().empty()) { - m_view->userError( - "Better to logout before logging in again", - "You're currently logged in. Please, log out before logging in " - "again if that's what you meant."); - return; - } - - std::string compRes = m_view->currentComputeResource(); - // if local is selected, just take the first remote resource - if (isLocalResourceSelected()) { - compRes = "SCARF@STFC"; - } - try { - const std::string user = m_view->getUsername(); - if (user.empty()) { - m_view->userError( - "Cannot log in", - "To log in you need to specify a username (and a password)."); - return; - } - - const std::string passw = m_view->getPassword(); - if (passw.empty()) { - m_view->userError( - "Cannot log in with an empty password", - "Empty passwords are not allowed. Please provide a password)."); - return; - } - - m_model->doLogin(compRes, user, passw); - } catch (std::exception &e) { - throw(std::string("Problem when logging in. Error description: ") + - e.what()); - } - - bool loggedOK = !m_model->loggedIn().empty(); - m_view->updateLoginControls(loggedOK); - m_view->enableLoggedActions(loggedOK); - - if (!loggedOK) - return; - - try { - m_model->doRefreshJobsInfo(compRes); - } catch (std::exception &e) { - throw(std::string("The login operation went apparently fine but an issue " - "was found while trying to retrieve the status of the " - "jobs currently running on the remote resource. Error " - "description: ") + - e.what()); - } - - startKeepAliveMechanism(m_view->keepAlivePeriod()); - // show table for the first time - processRefreshJobs(); -} - -void TomographyIfacePresenter::processLogout() { - if (m_model->loggedIn().empty()) { - m_model->logMsg("Cannot log out: not logged into any resource."); - return; - } - - try { - std::string compRes = m_view->currentComputeResource(); - // if local is selected, just take the first remote resource - if (isLocalResourceSelected()) { - compRes = "SCARF@STFC"; - } - m_model->doLogout(compRes, m_view->getUsername()); - } catch (std::exception &e) { - throw(std::string("Problem when logging out. Error description: ") + - e.what()); - } - - m_view->updateLoginControls(false); -} - -void TomographyIfacePresenter::processSetupReconTool() { - const std::string ¤tReconTool = m_view->currentReconTool(); - - // this check prevents a crash on initialisation where Qt passes a tool name - // of "" and then we have a nullptr dialogue - auto dialog = m_configDialog.get(); - if (dialog) { - if (TomographyIfaceModel::g_CCPiTool != currentReconTool) { - // give pointer to showToolConfig, so it can run the dialogue - m_view->showToolConfig(*dialog); - updateModelAfterToolChanged(*dialog); - } - } -} - -void TomographyIfacePresenter::processRunRecon() { - TomoPathsConfig paths = m_view->currentPathsConfig(); - if (paths.pathSamples().empty()) { - m_view->userWarning("Sample images path not set!", - "The path to the sample images " - "is strictly required to start " - "a reconstruction"); - return; - } - - // we have to branch out to handle local and remote somewhere - const bool local = isLocalResourceSelected(); - - std::string runnable; - std::vector<std::string> args; - std::string allOpts; - - prepareSubmissionArguments(local, runnable, args, allOpts); - try { - if (local) { - setupAndRunLocalReconstruction(runnable, args, allOpts); - - // start the refresh jobs timer if not running - startKeepAliveMechanism(m_view->keepAlivePeriod()); - } else { - // get the actual compute resource name - const std::string computingResouce = m_view->currentComputeResource(); - m_model->doRemoteRunReconstructionJob(computingResouce, runnable, - allOpts); - } - } catch (std::exception &e) { - m_view->userWarning("Issue when trying to start a job", e.what()); - } - - processRefreshJobs(); -} - -bool TomographyIfacePresenter::userConfirmationToCancelRecon() { - if (m_reconRunning) { - const bool result = m_view->userConfirmation( - "Reconstruction is RUNNING", - "Are you sure you want to<br>cancel the running reconstruction?"); - - if (!result) { - // user clicked NO, so we don't terminate the running reconstruction and - // simply return - return false; - } - m_reconRunning = false; - } - return true; -} - -void TomographyIfacePresenter::setupAndRunLocalReconstruction( - const std::string &runnable, const std::vector<std::string> &args, - const std::string &allOpts) { - - if (!userConfirmationToCancelRecon()) { - // user didnt confirm - return; - } - - // this kills the previous thread forcefully - m_workerThread.reset(); - auto *worker = new MantidQt::CustomInterfaces::TomographyProcess(); - m_workerThread = Mantid::Kernel::make_unique<TomographyThread>(this, worker); - - // Specific connections for this presenter - // we do this so the thread can independently read the process' output and - // only signal the presenter after it's done reading and has something to - // share so it doesn't block the presenter - connect(m_workerThread.get(), SIGNAL(stdOutReady(QString)), this, - SLOT(readWorkerStdOut(QString))); - connect(m_workerThread.get(), SIGNAL(stdErrReady(QString)), this, - SLOT(readWorkerStdErr(QString))); - - // remove the user confirmation for running recon, if the recon has finished - connect(m_workerThread.get(), SIGNAL(workerFinished(qint64, int)), this, - SLOT(workerFinished(qint64, int))); - - connect(worker, SIGNAL(started()), this, SLOT(addProcessToJobList())); - - m_model->doLocalRunReconstructionJob(runnable, args, allOpts, *m_workerThread, - *worker, "Reconstruction"); -} - -/** Simply reset the switch that tracks if a recon is running and - * update the process job in the reconstruction list - */ -void TomographyIfacePresenter::workerFinished(const qint64 pid, - const int exitCode) { - m_reconRunning = false; - m_model->updateProcessInJobList(pid, exitCode); - processRefreshJobs(); -} - -void TomographyIfacePresenter::reconProcessFailedToStart() { - m_view->userError("Reconstruction failed to start", - "The reconstruction process has encountered an error and " - "has failed to start."); -} - -void TomographyIfacePresenter::addProcessToJobList() { - auto *worker = qobject_cast<TomographyProcess *>(sender()); - const qint64 pid = worker->getPID(); - const auto runnable = worker->getRunnable(); - const auto args = worker->getArgs(); - const auto workerName = worker->getName(); - - m_workerThread->setProcessPID(pid); - - m_model->addJobToStatus(pid, runnable, args, workerName); - - // update here that the reconstruction is running - m_reconRunning = true; - - processRefreshJobs(); -} - -void TomographyIfacePresenter::readWorkerStdOut(const QString &workerString) { - m_workerOutputCache.append(workerString); - m_model->logMsg(workerString.toStdString()); -} - -void TomographyIfacePresenter::readWorkerStdErr(const QString &workerString) { - m_workerErrorCache.append(workerString); - m_model->logErrMsg(workerString.toStdString()); -} - -bool TomographyIfacePresenter::isLocalResourceSelected() const { - return m_model->localComputeResource() == m_view->currentComputeResource(); -} - -void TomographyIfacePresenter::processRefreshJobs() { - m_model->doRefreshJobsInfo(m_view->currentComputeResource()); - - { - QMutexLocker lockit(m_statusMutex); - - m_view->updateJobsInfoDisplay(m_model->jobsStatus(), - m_model->jobsStatusLocal()); - } -} - -void TomographyIfacePresenter::processCancelJobs() { - const std::string &resource = m_view->currentComputeResource(); - if (isLocalResourceSelected() && userConfirmationToCancelRecon()) { - // if local and user confirmed - m_workerThread.reset(); - } else { - m_model->doCancelJobs(resource, m_view->processingJobsIDs()); - } -} - -void TomographyIfacePresenter::processVisualizeJobs() { - doVisualize(m_view->processingJobsIDs()); -} - -void TomographyIfacePresenter::doVisualize( - const std::vector<std::string> &ids) { - m_model->logMsg(" Visualizing results from job: " + ids.front()); - m_view->userWarning("Visualizing not implemented", "Visualizing of the data " - "has not been implemented " - "yet and is unsupported"); - // TODOPRES: open dialog, send to Paraview, etc. -} - -void TomographyIfacePresenter::processLogMsg() { - std::vector<std::string> msgs = m_view->logMsgs(); - for (size_t i = 0; i < msgs.size(); i++) { - m_model->logMsg(msgs[i]); - } -} - -void TomographyIfacePresenter::processAggregateEnergyBands() { - auto algParams = m_view->currentAggregateBandsParams(); - - // check necessary parameters - if (algParams.end() == algParams.find("InputPath") || - algParams.end() == algParams.find("OutputPath") || - algParams["InputPath"].empty() || algParams["OutputPath"].empty()) { - m_view->userError("Invalid input properties", - "You need to provide the input properties InputPath and " - "OutputPath. Both are mandatory and should point to " - "existing directories"); - return; - } - - // check the paths are usable - if (!usableEnergyBandsPaths(algParams)) - return; - - const std::string algName = "ImggAggregateWavelengths"; - auto alg = Mantid::API::AlgorithmManager::Instance().create(algName); - try { - alg->initialize(); - for (const auto ¶m : algParams) { - alg->setPropertyValue(param.first, param.second); - } - } catch (std::runtime_error &rexc) { - m_view->userError("Problem when initializing algorithm", - "Could not initialize the algorithm " + algName + - " with the options currently set. Error details: " + - rexc.what()); - } - - // pass hot potato to the view which has the algorithm runner - m_view->runAggregateBands(alg); - - m_model->logMsg(" The energy/wavelength bands are being aggregated in the " - "background. You can check the log messages and the " - "algorithms window to track its progress. "); -} - -/** - * Checks that the input/output directories exists and are readable - * - * @param algParams parameters to be passed to the bands aggregation - * algorithm - * - * @return whether it is safe to use the path properties/options given - */ -bool TomographyIfacePresenter::usableEnergyBandsPaths( - const std::map<std::string, std::string> &algParams) { - bool usable = false; - try { - const std::string name = algParams.at("InputPath"); - Poco::File inPath(name); - if (!inPath.canRead() || !inPath.isDirectory()) { - m_view->userError("Invalid input path", - "The input path must be a readable directory: " + name); - return usable; - } - } catch (Poco::FileNotFoundException &rexc) { - m_view->userError("Invalid input path", - "The input path must exist on disk. Details: " + - std::string(rexc.what())); - return usable; - } - try { - const std::string name = algParams.at("OutputPath"); - Poco::File outPath(name); - if (!outPath.canRead() || !outPath.isDirectory()) { - m_view->userError("Invalid output path", - "The output path must be a readable directory: " + - name); - return usable; - } - } catch (Poco::FileNotFoundException &rexc) { - m_view->userError("Invalid output path", - "The output path must exist on disk. Details: " + - std::string(rexc.what())); - return usable; - } - - usable = true; - return usable; -} - -void TomographyIfacePresenter::processShutDown() { - m_view->saveSettings(); - cleanup(); -} - -void TomographyIfacePresenter::startKeepAliveMechanism(int period) { - if (period <= 0) { - m_model->logMsg("Tomography GUI: not starting the keep-alive mechanism. " - "You might be logged out by the remote compute resource " - "after some minutes " - "depending on system configuration."); - return; - } - - // timer is already running, so return - if (m_keepAliveTimer) { - return; - } - - m_model->logMsg( - "Tomography GUI: starting mechanism to periodically query the " - "status of jobs. This will update the status of running jobs every " + - boost::lexical_cast<std::string>(period) + - " seconds. You can also update it at any moment by clicking " - "on the refresh button. This periodic update mechanism is " - "also expected to keep sessions on remote compute resources " - "alive after logging in."); - - if (m_keepAliveTimer) - delete m_keepAliveTimer; - m_keepAliveTimer = new QTimer(this); // no-parent so it can be moveToThread - - m_keepAliveTimer->setInterval(1000 * period); // interval in ms - - // remove previous connections - m_keepAliveTimer->disconnect(); - - connect(m_keepAliveTimer, SIGNAL(timeout()), this, - SLOT(processRefreshJobs())); - - m_keepAliveTimer->start(); -} - -void TomographyIfacePresenter::killKeepAliveMechanism() { - if (m_keepAliveTimer) - m_keepAliveTimer->stop(); -} - -void TomographyIfacePresenter::prepareSubmissionArguments( - const bool local, std::string &runnable, std::vector<std::string> &args, - std::string &allOpts) { - // update the filters and ROI settings - // pre-/post processing steps and filters - m_model->setPrePostProcSettings(m_view->prePostProcSettings()); - // center of rotation and regions - m_model->setImageStackPreParams(m_view->currentROIEtcParams()); - - // we have to branch out to handle local and remote somewhere - m_model->prepareSubmissionArguments(local, runnable, args, allOpts); -} -} // namespace CustomInterfaces -} // namespace MantidQt diff --git a/MantidQt/CustomInterfaces/src/Tomography/TomographyIfaceViewQtGUI.cpp b/MantidQt/CustomInterfaces/src/Tomography/TomographyIfaceViewQtGUI.cpp deleted file mode 100644 index 3a0899615e3..00000000000 --- a/MantidQt/CustomInterfaces/src/Tomography/TomographyIfaceViewQtGUI.cpp +++ /dev/null @@ -1,1894 +0,0 @@ -#include "MantidAPI/AlgorithmManager.h" -#include "MantidAPI/AnalysisDataService.h" -#include "MantidAPI/ITableWorkspace.h" -#include "MantidAPI/MatrixWorkspace.h" -#include "MantidAPI/Run.h" -#include "MantidAPI/WorkspaceFactory.h" -#include "MantidKernel/ConfigService.h" -#include "MantidQtAPI/AlgorithmInputHistory.h" - -#include "MantidQtAPI/HelpWindow.h" -#include "MantidQtCustomInterfaces/Tomography/TomoSystemSettings.h" -#include "MantidQtCustomInterfaces/Tomography/TomographyIfacePresenter.h" -#include "MantidQtCustomInterfaces/Tomography/TomographyIfaceViewQtGUI.h" -#include "MantidQtCustomInterfaces/Tomography/ToolConfigAstraToolbox.h" -#include "MantidQtCustomInterfaces/Tomography/ToolConfigCustom.h" - -#include "MantidQtCustomInterfaces/Tomography/TomoToolConfigDialogBase.h" - -using namespace Mantid::API; -using namespace MantidQt::CustomInterfaces; - -#include <boost/lexical_cast.hpp> - -#include <Poco/File.h> -#include <Poco/Path.h> - -#include <QFileDialog> -#include <QFileSystemModel> -#include <QMessageBox> -#include <QPainter> -#include <QSettings> - -namespace MantidQt { -namespace CustomInterfaces { - -const std::string TomographyIfaceViewQtGUI::g_styleSheetOffline = - "QPushButton { " - "margin: 6px;" - "border-color: #0c457e;" - "border-style: outset;" - "border-radius: 3px;" - "border-width: 0px;" - "color: black;" - "background-color: rgb(180, 180, 180); " - "}" - "QPushButton:flat { " - "background-color: rgb(180, 180, 180); " - "}" - "QPushButton:pressed { " - "background-color: rgb(180, 180, 180) " - "}"; - -const std::string TomographyIfaceViewQtGUI::g_styleSheetOnline = - "QPushButton { " - "margin: 6px;" - "border-color: #0c457e;" - "border-style: outset;" - "border-radius: 3px;" - "border-width: 0px;" - "color: black;" - "background-color: rgb(140, 255, 140); " - "}" - "QPushButton:flat { background-color: rgb(120, 255, 120); " - "}" - "QPushButton:pressed { background-color: rgb(120, 255, 120); " - "}"; - -// For paths where Python third party tools are installed, if they're -// not included in the system python path. For example you could have -// put the AstraToolbox package in -// C:/local/tomo-tools/astra/astra-1.6-python27-win-x64/astra-1.6 -// Leaving this empty implies that the tools must have been installed -// in the system Python path. As an example, in the Anaconda python -// distribution for windows it could be in: -// c:/local/Anaconda/Lib/site-packages/ -std::vector<std::string> TomographyIfaceViewQtGUI::g_defAddPathPython; - -const std::string TomographyIfaceViewQtGUI::g_SCARFName = "SCARF@STFC"; -const std::string TomographyIfaceViewQtGUI::g_defOutPathLocal = -#ifdef _WIN32 - "D:/imat-data/"; -#else - "~/imat/"; -#endif - -// TODOVIEW: could use ConfigService::isNetworkDrive(const std::string &) -const std::string TomographyIfaceViewQtGUI::g_defOutPathRemote = -#ifdef _WIN32 - "I:/imat/imat-data/"; -#else - "~/imat-data/"; -#endif - -const std::string TomographyIfaceViewQtGUI::g_defParaviewPath = -#ifdef _WIN32 - "C:\\Program Files\\ParaView\\"; -#else - "/usr/bin/"; -#endif - -const std::string TomographyIfaceViewQtGUI::g_defParaviewAppendPath = -#ifdef _WIN32 - "bin\\paraview.exe"; -#else - "paraview"; -#endif - -const std::string notAvailTool = "This tool is not available on this platform"; - -const std::string TomographyIfaceViewQtGUI::g_defOctopusVisPath = -#ifdef _WIN32 - "C:/Program Files/Octopus Imaging/Octopus Visualisation"; -#else - notAvailTool; -#endif - -const std::string TomographyIfaceViewQtGUI::g_defOctopusAppendPath = -#ifdef _WIN32 - "octoviewer3d.exe"; -#else - notAvailTool; -#endif - -const std::string TomographyIfaceViewQtGUI::g_defProcessedSubpath = "processed"; - -// phase or cycle component, like: phase_commissioning, cycle_15_4, cycle_16_1 -const std::string TomographyIfaceViewQtGUI::g_defPathComponentPhase = - "phase_commissioning"; - -const std::string TomographyIfaceViewQtGUI::g_defExperimentRef = "RB000000"; - -const std::string TomographyIfaceViewQtGUI::g_defPathReconScripts = -#ifdef _WIN32 - "C:/MantidInstall/scripts"; -#else - QDir::currentPath().toStdString(); -#endif - -const std::string TomographyIfaceViewQtGUI::g_defPathReconOut = -#ifdef _WIN32 - "D:/imat"; -#else - "~/imat/"; -#endif - -// Add this class to the list of specialised dialogs in this namespace -DECLARE_SUBWINDOW(TomographyIfaceViewQtGUI) - -/** - * Default constructor, but note that this interface currently - * relies on the SCARF cluster (only in ISIS facility) as the only - * supported remote compute resource. - * - * @param parent Parent window (most likely the Mantid main app window). - */ -TomographyIfaceViewQtGUI::TomographyIfaceViewQtGUI(QWidget *parent) - : UserSubWindow(parent), ITomographyIfaceView(), m_tabROIWidget(nullptr), - m_tabImggFormats(nullptr), m_processingJobsIDs(), m_currentComputeRes(""), - m_currentReconTool("TomoPy"), m_imgPath(""), m_logMsgs(), - m_systemSettings(), m_settings(), - m_settingsGroup("CustomInterfaces/Tomography"), - m_settingsSubGroupEnergy(m_settingsGroup + "/EnergyBands"), - m_aggAlgRunner(), m_availPlugins(), m_currPlugins(), m_currentParamPath(), - m_presenter(nullptr) {} - -TomographyIfaceViewQtGUI::~TomographyIfaceViewQtGUI() {} - -void TomographyIfaceViewQtGUI::initLayout() { - // setup container ui - m_ui.setupUi(this); - // add tab contents and set up their ui's - QWidget *tabRunW = new QWidget(m_ui.tabMain); - m_uiTabRun.setupUi(tabRunW); - m_ui.tabMain->addTab(tabRunW, QString("Run")); - - // this is a Qt widget, let Qt manage the pointer - m_tabROIWidget = new TomographyROIViewQtWidget(m_ui.tabMain); - m_ui.tabMain->addTab(m_tabROIWidget, QString("ROI etc.")); - - QWidget *tabFiltersW = new QWidget(); - m_uiTabFilters.setupUi(tabFiltersW); - m_ui.tabMain->addTab(tabFiltersW, QString("Filters")); - - QWidget *tabVizW = new QWidget(); - m_uiTabVisualize.setupUi(tabVizW); - m_ui.tabMain->addTab(tabVizW, QString("Visualize")); - - // this is a Qt widget, let Qt manage the pointer - QWidget *m_tabImggFormats = new ImggFormatsConvertViewQtWidget(); - m_ui.tabMain->addTab(m_tabImggFormats, QString("Convert")); - - QWidget *tabEBandsW = new QWidget(); - m_uiTabEnergy.setupUi(tabEBandsW); - m_ui.tabMain->addTab(tabEBandsW, QString("Energy bands")); - - QWidget *tabSystemSettingsW = new QWidget(); - m_uiTabSystemSettings.setupUi(tabSystemSettingsW); - m_ui.tabMain->addTab(tabSystemSettingsW, QString("System")); - - readSettings(); - - // basic UI setup - doSetupGeneralWidgets(); - doSetupSectionSystemSettings(); - doSetupSectionRun(); - doSetupSectionFilters(); - doSetupSectionRoi(); - - // extra / experimental tabs: - doSetupSectionVisualize(); - doSetupSectionEnergy(); - - // presenter that knows how to handle a ITomographyIfaceView should take care - // of all the logic - // note the view needs to now the concrete presenter - m_presenter.reset(new TomographyIfacePresenter(this)); - - // it will know what compute resources and tools we have available: - // This view doesn't even know the names of compute resources, etc. - m_presenter->notify(ITomographyIfacePresenter::SetupResourcesAndTools); -} - -void TomographyIfaceViewQtGUI::doSetupSectionRoi() { - // connect the auto CoR button to run an external python process - connect(m_tabROIWidget, - SIGNAL(findCORClickedSignal(std::string, std::vector<std::string>)), - this, - SLOT(runExternalProcess(std::string, std::vector<std::string>))); - connect(this, SIGNAL(externalProcessFinished(QString)), m_tabROIWidget, - SLOT(readCoRFromProcessOutput(QString))); - - connect(m_tabROIWidget, SIGNAL(imageOrStackLoadedSignal(std::string)), this, - SLOT(imageOrStackLoadedInRoi(std::string))); -} - -void TomographyIfaceViewQtGUI::imageOrStackLoadedInRoi( - const std::string &path) { - m_pathsConfig.updatePathSamples(path); - m_presenter->notify(ITomographyIfacePresenter::TomoPathsEditedByUser); -} - -void TomographyIfaceViewQtGUI::runExternalProcess( - const std::string &exec, const std::vector<std::string> &args) { - m_extExec = exec; - m_extArgs = args; - m_presenter->notify(ITomographyIfacePresenter::RunExternalProcess); -} - -void TomographyIfaceViewQtGUI::doSetupGeneralWidgets() { - - connect(m_ui.pushButton_help, SIGNAL(released()), this, SLOT(openHelpWin())); - // note connection to the parent window, otherwise you'd be left - // with an empty frame window - if (this->parent()) { - connect(m_ui.pushButton_close, SIGNAL(released()), this->parent(), - SLOT(close())); - } -} - -void TomographyIfaceViewQtGUI::doSetupSectionRun() { - // geometry, etc. niceties - // on the left (just plugin names) 1/2, right: 2/3 - QList<int> sizes; - sizes.push_back(420); - sizes.push_back(80); - m_uiTabRun.splitter_run_main_vertical->setSizes(sizes); - - sizes[0] = 470; - sizes[1] = 30; - m_uiTabRun.splitter_image_resource->setSizes(sizes); - - sizes[0] = 400; - sizes[1] = 100; - m_uiTabRun.splitter_run_jobs->setSizes(sizes); - - updateCompResourceStatus(false); - - // enable by default, which will use default tools setups - m_uiTabRun.pushButton_reconstruct->setEnabled(true); - // setup always possible with local compute resource - // m_uiTabRun.pushButton_run_tool_setup->setEnabled(false); - m_uiTabRun.pushButton_run_tool_setup->setEnabled(true); - m_uiTabRun.pushButton_run_job_cancel->setEnabled(false); - m_uiTabRun.pushButton_run_job_visualize->setEnabled(false); - - // Button signals - connect(m_uiTabRun.pushButton_reconstruct, SIGNAL(released()), this, - SLOT(reconstructClicked())); - connect(m_uiTabRun.pushButton_run_tool_setup, SIGNAL(released()), this, - SLOT(toolSetupClicked())); - connect(m_uiTabRun.pushButton_run_refresh, SIGNAL(released()), this, - SLOT(jobTableRefreshClicked())); - connect(m_uiTabRun.pushButton_run_job_visualize, SIGNAL(released()), this, - SLOT(runVisualizeClicked())); - connect(m_uiTabRun.pushButton_run_job_cancel, SIGNAL(released()), this, - SLOT(jobCancelClicked())); - - // RB number changes - connect(m_uiTabRun.lineEdit_experiment_reference, SIGNAL(editingFinished()), - this, SLOT(updatedExperimentReference())); - - // update tools for a resource - connect(m_uiTabRun.comboBox_run_compute_resource, - SIGNAL(currentIndexChanged(int)), this, - SLOT(compResourceIndexChanged(int))); - - connect(m_uiTabRun.comboBox_run_tool, SIGNAL(currentIndexChanged(int)), this, - SLOT(runToolIndexChanged(int))); - - // populate setup values from defaults - const TomoPathsConfig cfg = currentPathsConfig(); - m_uiTabRun.lineEdit_path_samples->setText( - QString::fromStdString(cfg.pathSamples())); - m_uiTabRun.lineEdit_path_flats->setText( - QString::fromStdString(cfg.pathOpenBeam())); - m_uiTabRun.checkBox_path_flats->setChecked(cfg.m_pathOpenBeamEnabled); - m_uiTabRun.lineEdit_path_darks->setText( - QString::fromStdString(cfg.pathDarks())); - m_uiTabRun.checkBox_path_darks->setChecked(cfg.m_pathDarkEnabled); - - m_uiTabRun.lineEdit_SCARF_password->setText(""); - m_uiTabRun.pushButton_SCARF_login->setEnabled(true); - m_uiTabRun.pushButton_SCARF_logout->setEnabled(false); - - // check boxes to enable search for dark and flat images - connect(m_uiTabRun.checkBox_path_flats, SIGNAL(stateChanged(int)), this, - SLOT(flatsPathCheckStatusChanged(int))); - connect(m_uiTabRun.checkBox_path_darks, SIGNAL(stateChanged(int)), this, - SLOT(darksPathCheckStatusChanged(int))); - - // 'browse' buttons for image paths - connect(m_uiTabRun.pushButton_samples_dir, SIGNAL(released()), this, - SLOT(samplesPathBrowseClicked())); - connect(m_uiTabRun.pushButton_flats_dir, SIGNAL(released()), this, - SLOT(flatsPathBrowseClicked())); - connect(m_uiTabRun.pushButton_darks_dir, SIGNAL(released()), this, - SLOT(darksPathBrowseClicked())); - - // also manage the edit fields when edited non-programmatically - connect(m_uiTabRun.lineEdit_path_samples, SIGNAL(editingFinished()), this, - SLOT(samplesPathEditedByUser())); - connect(m_uiTabRun.lineEdit_path_flats, SIGNAL(editingFinished()), this, - SLOT(flatsPathEditedByUser())); - - connect(m_uiTabRun.lineEdit_path_darks, SIGNAL(editingFinished()), this, - SLOT(darksPathEditedByUser())); - - m_uiTabRun.lineEdit_path_samples->setText( - QString::fromStdString(m_pathsConfig.pathSamples())); - m_uiTabRun.lineEdit_path_flats->setText( - QString::fromStdString(m_pathsConfig.pathOpenBeam())); - m_uiTabRun.lineEdit_path_darks->setText( - QString::fromStdString(m_pathsConfig.pathDarks())); - - // log in/out - connect(m_uiTabRun.pushButton_SCARF_login, SIGNAL(released()), this, - SLOT(SCARFLoginClicked())); - connect(m_uiTabRun.pushButton_SCARF_logout, SIGNAL(released()), this, - SLOT(SCARFLogoutClicked())); -} - -void TomographyIfaceViewQtGUI::doSetupSectionFilters() { - connect(m_uiTabFilters.pushButton_reset, SIGNAL(released()), this, - SLOT(resetPrePostFilters())); -} - -void TomographyIfaceViewQtGUI::doSetupSectionVisualize() { - // TODOVIEW: take g_def values first time, when Qsettings are empty, then from - // QSettings - m_setupParaviewPath = g_defParaviewPath; - m_setupProcessedSubpath = g_defProcessedSubpath; - m_setupOctopusVisPath = g_defOctopusVisPath; - - m_uiTabVisualize.lineEdit_paraview_location->setText( - QString::fromStdString(g_defParaviewPath)); - - // make a file system model for the visualization browser - QFileSystemModel *model = new QFileSystemModel; - model->setRootPath(QDir::currentPath()); - - // set the model for the visualization browser - m_uiTabVisualize.treeView_files->setModel(model); - m_uiTabVisualize.treeView_files->setSelectionMode( - QTreeView::ExtendedSelection); - m_uiTabVisualize.treeView_files->setSelectionBehavior(QTreeView::SelectRows); - - // display: current dir - const QString startDir = - QString::fromStdString(Poco::Path::expand(g_defOutPathLocal)); - - // start at default local path when possible - const QString path = - QString::fromStdString(Poco::Path::expand(g_defOutPathLocal)); - if (!path.isEmpty()) { - m_uiTabVisualize.treeView_files->setRootIndex(model->index(path)); - } else { - m_uiTabVisualize.treeView_files->setRootIndex( - model->index(QDir::currentPath())); - } - - connect(m_uiTabVisualize.pushButton_paraview, SIGNAL(released()), this, - SLOT(sendToParaviewClicked())); - - connect(m_uiTabVisualize.pushButton_octopus, SIGNAL(released()), this, - SLOT(sendToOctopusVisClicked())); - - connect(m_uiTabVisualize.pushButton_browse_files, SIGNAL(released()), this, - SLOT(browseFilesToVisualizeClicked())); - - connect(m_uiTabVisualize.pushButton_local_default_dir, SIGNAL(released()), - this, SLOT(defaultDirLocalVisualizeClicked())); - connect(m_uiTabVisualize.pushButton_remote_default_dir, SIGNAL(released()), - this, SLOT(defaultDirRemoteVisualizeClicked())); - - connect(m_uiTabVisualize.pushButton_browse_paraview, SIGNAL(released()), this, - SLOT(browseVisToolParaviewClicked())); - connect(m_uiTabVisualize.pushButton_browse_octopus, SIGNAL(released()), this, - SLOT(browseVisToolOctopusClicked())); -} - -void TomographyIfaceViewQtGUI::doSetupSectionSystemSettings() { - // All possible modifications to system settings - connect(m_uiTabSystemSettings.lineEdit_path_comp_1st, - SIGNAL(editingFinished()), this, SLOT(systemSettingsEdited())); - connect(m_uiTabSystemSettings.lineEdit_path_comp_input_samples, - SIGNAL(editingFinished()), this, SLOT(systemSettingsEdited())); - connect(m_uiTabSystemSettings.lineEdit_path_comp_input_flats, - SIGNAL(editingFinished()), this, SLOT(systemSettingsEdited())); - connect(m_uiTabSystemSettings.lineEdit_path_comp_input_darks, - SIGNAL(editingFinished()), this, SLOT(systemSettingsEdited())); - - connect(m_uiTabSystemSettings.lineEdit_path_comp_out_processed, - SIGNAL(editingFinished()), this, SLOT(systemSettingsEdited())); - connect(m_uiTabSystemSettings.lineEdit_path_comp_out_preprocessed, - SIGNAL(editingFinished()), this, SLOT(systemSettingsEdited())); - - connect(m_uiTabSystemSettings.lineEdit_remote_base_path_data, - SIGNAL(editingFinished()), this, SLOT(systemSettingsEdited())); - connect(m_uiTabSystemSettings.lineEdit_remote_scripts_base_dir, - SIGNAL(editingFinished()), this, SLOT(systemSettingsEdited())); - - connect(m_uiTabSystemSettings.lineEdit_on_local_data_drive_or_path, - SIGNAL(textChanged(const QString &)), this, - SLOT(systemSettingsEdited())); - connect(m_uiTabSystemSettings.lineEdit_on_local_remote_data_drive_path, - SIGNAL(textChanged(const QString &)), this, - SLOT(systemSettingsEdited())); - - connect(m_uiTabSystemSettings.lineEdit_local_recon_scripts, - SIGNAL(textChanged(const QString &)), this, - SLOT(systemSettingsEdited())); - - // 'browse' buttons for local (data) settings: - connect(m_uiTabSystemSettings.pushButton_on_local_data_drive_or_path, - SIGNAL(released()), this, SLOT(browseLocalInOutDirClicked())); - connect(m_uiTabSystemSettings.pushButton_on_local_remote_data_drive_path, - SIGNAL(released()), this, SLOT(browseLocalRemoteDriveOrPath())); - - // reset setup of the remote - connect(m_uiTabSystemSettings.pushButton_reset_scripts_base_dir_remote, - SIGNAL(released()), this, SLOT(resetRemoteSetup())); - - // remote execution settings - connect(m_uiTabSystemSettings.spinBox_remote_cores, SIGNAL(editingFinished()), - this, SLOT(systemSettingsNumericEdited())); - connect(m_uiTabSystemSettings.spinBox_remote_cores, SIGNAL(editingFinished()), - this, SLOT(systemSettingsNumericEdited())); - - // remote local settings - connect(m_uiTabSystemSettings.spinBox_local_processes, - SIGNAL(editingFinished()), this, SLOT(systemSettingsNumericEdited())); - connect(m_uiTabSystemSettings.spinBox_local_cores, SIGNAL(editingFinished()), - this, SLOT(systemSettingsNumericEdited())); - - // 'browse' buttons for local (scripts) settings: - connect(m_uiTabSystemSettings.pushButton_local_recon_scripts_dir, - SIGNAL(released()), this, SLOT(browseLocalReconScriptsDirClicked())); - - connect(m_uiTabSystemSettings.pushButton_local_external_interpreter, - SIGNAL(released()), this, - SLOT(browseLocalExternalInterpreterClicked())); - - connect(m_uiTabSystemSettings.pushButton_reset_all, SIGNAL(released()), this, - SLOT(resetSystemSettings())); -} - -void TomographyIfaceViewQtGUI::resetRemoteSetup() { - m_uiTabSystemSettings.lineEdit_remote_base_path_data->setText( - QString::fromStdString(TomoSystemSettingsRemote::g_defBasePathTomoData)); - m_uiTabSystemSettings.lineEdit_remote_scripts_base_dir->setText( - QString::fromStdString( - TomoSystemSettingsRemote::g_defBasePathReconScripts)); - m_uiTabSystemSettings.spinBox_remote_nodes->setValue(1); - m_uiTabSystemSettings.spinBox_remote_cores->setValue(8); -} - -void TomographyIfaceViewQtGUI::setComputeResources( - const std::vector<std::string> &resources, - const std::vector<bool> &enabled) { - // set up the compute resource - QComboBox *cr = m_uiTabRun.comboBox_run_compute_resource; - if (!cr || resources.size() != enabled.size()) - return; - - cr->clear(); - - for (size_t ri = 0; ri < resources.size(); ri++) { - cr->addItem(QString::fromStdString(resources[ri])); - - if (!enabled[ri]) { - // trick to display the text in a disabled row - QModelIndex idx = cr->model()->index(static_cast<int>(ri), 0); - QVariant disabled(0); - cr->model()->setData(idx, disabled, Qt::UserRole - 1); - } - } -} - -void TomographyIfaceViewQtGUI::setReconstructionTools( - const std::vector<std::string> &tools, const std::vector<bool> &enabled) { - - // set up the reconstruction tool - QComboBox *rt = m_uiTabRun.comboBox_run_tool; - if (!rt || tools.size() != enabled.size()) - return; - - rt->clear(); - - for (size_t ti = 0; ti < tools.size(); ti++) { - rt->addItem(QString::fromStdString(tools[ti])); - - if (!enabled[ti]) { - // trick to display it in a disabled row - QModelIndex idx = rt->model()->index(static_cast<int>(ti), 0); - QVariant disabled(0); - rt->model()->setData(idx, disabled, Qt::UserRole - 1); - } - } -} - -/** - * Enables/disables buttons that require the user to be logged into - * the (remote) compute resource, for example: reconstruct (submit job), - * cancel job, etc. - */ -void TomographyIfaceViewQtGUI::enableLoggedActions(bool enable) { - // TODOVIEW: this may not make sense anymore when/if the "Local" compute - // resource is used in the future (except when none of the tools - // supported are available/detected on "Local") - std::vector<QPushButton *> buttons; - buttons.push_back(m_uiTabRun.pushButton_run_refresh); - buttons.push_back(m_uiTabRun.pushButton_run_job_cancel); - // no visualization yet, need vsi etc. support - // buttons.push_back(m_uiTabRun.pushButton_run_job_visualize); - buttons.push_back(m_uiTabRun.pushButton_reconstruct); - - for (size_t i = 0; i < buttons.size(); ++i) { - buttons[i]->setEnabled(enable); - } - - if (!enable) { - m_uiTabRun.pushButton_reconstruct->setToolTip( - "Start reconstruction job. You need to be logged in to use this"); - } else { - m_uiTabRun.pushButton_reconstruct->setToolTip(""); - } -} - -/** - * Handle display of the current status of the remote/local compute resource - * that is selected by the user. - * - * @param online whether to show good/working/online status - */ -void TomographyIfaceViewQtGUI::updateCompResourceStatus(bool online) { - if (online) { - m_uiTabRun.pushButton_remote_status->setText("Online"); - // push buttons won't work with something like: - // m_uiTabRun.pushButton_remote_status->setBackground(QColor(120, 255, - // 120)); - m_uiTabRun.pushButton_remote_status->setStyleSheet( - QString::fromStdString(g_styleSheetOnline)); - } else { - m_uiTabRun.pushButton_remote_status->setText("Offline"); - m_uiTabRun.pushButton_remote_status->setStyleSheet( - QString::fromStdString(g_styleSheetOffline)); - } -} - -#ifndef _MSC_VER -QDataStream &operator>>(QDataStream &stream, size_t &num) { - qint64 i; - stream >> i; - if (QDataStream::Ok == stream.status()) { - num = i; - } - return stream; -} -#endif - -inline QDataStream &operator>>(QDataStream &stream, std::string &str) { - QString s; - stream >> s; - str = s.toStdString(); - return stream; -} - -/// deserialize the remote part of the system settings, from a QDataStream <= -/// QByteArray -QDataStream &operator>>(QDataStream &stream, TomoSystemSettingsRemote &ssr) { - // clang-format off - stream >> ssr.m_basePathTomoData - >> ssr.m_basePathReconScripts - >> ssr.m_nodes - >> ssr.m_cores; - // clang-format on - - return stream; -} - -/// deserialize the local part of the system settings, from a QDataStream <= -/// QByteArray -QDataStream &operator>>(QDataStream &stream, TomoSystemSettingsLocal &ssl) { - // clang-format off - stream >> ssl.m_basePathTomoData - >> ssl.m_remoteDriveOrMountPoint - >> ssl.m_reconScriptsPath - >> ssl.m_externalInterpreterPath - >> ssl.m_processes - >> ssl.m_cores; - // clang-format on - - return stream; -} - -/// deserialize system settings, from a QDataStream <= QByteArray -QDataStream &operator>>(QDataStream &stream, TomoSystemSettings &ss) { - stream >> ss.m_local >> ss.m_remote; - for (size_t i = 0; i < ss.m_pathComponents.size(); i++) { - stream >> ss.m_pathComponents[i]; - } - // clang-format off - stream >> ss.m_samplesDirPrefix - >> ss.m_flatsDirPrefix - >> ss.m_darksDirPrefix - >> ss.m_outputPathCompPreProcessed - >> ss.m_outputPathCompReconst; - // clang-format on - - return stream; -} - -/// deserialize a filters settings, from a QDataStream <= QByteArray -QDataStream &operator>>(QDataStream &stream, TomoReconFiltersSettings &fs) { - // clang-format off - stream >> fs.prep.normalizeByAirRegion - >> fs.prep.normalizeByProtonCharge - >> fs.prep.normalizeByFlats - >> fs.prep.normalizeByDarks - >> fs.prep.medianFilterWidth - >> fs.prep.rotation - >> fs.prep.maxAngle - >> fs.prep.scaleDownFactor - >> fs.postp.circMaskRadius - >> fs.postp.cutOffLevel - >> fs.outputPreprocImages; - // clang-format on - fs.prep.rotation *= 90; - - return stream; -} - -/// deserialize an input paths configuration -QDataStream &operator>>(QDataStream &stream, TomoPathsConfig &cfg) { - QString samples; - QString ob; - bool obEnabled; - QString darks; - bool darksEnabled; - stream >> samples >> ob >> obEnabled >> darks >> darksEnabled; - cfg.updatePathSamples(samples.toStdString()); - cfg.updatePathOpenBeam(ob.toStdString(), obEnabled); - cfg.updatePathDarks(darks.toStdString(), darksEnabled); - - return stream; -} - -/** - * Load the settings for the tabs and widgets of the interface. This - * relies on Qt settings functionality (QSettings class). - * - * This includes setting the default browsing directory to be the - * default save directory. - */ -void TomographyIfaceViewQtGUI::readSettings() { - QSettings qs; - qs.beginGroup(QString::fromStdString(m_settingsGroup)); - - m_settings.SCARFBasePath = - qs.value("SCARF-base-path", - QString::fromStdString(m_settings.SCARFBasePath)) - .toString() - .toStdString(); - // WARNING: it's critical to keep 'false' as default value, otherwise - // tests and scripted runs may have issues. The CI builds could get stuck - // when closing this interface. - m_settings.onCloseAskForConfirmation = - qs.value("on-close-ask-for-confirmation", false).toBool(); - - m_settings.useKeepAlive = - qs.value("use-keep-alive", m_settings.useKeepAlive).toInt(); - - // User parameters for reconstructions - m_setupExperimentRef = qs.value("experiment-reference", - QString::fromStdString(g_defExperimentRef)) - .toString() - .toStdString(); - - m_uiTabRun.lineEdit_SCARF_username->setText( - qs.value("SCARF-remote-username", - QString::fromStdString( - Mantid::Kernel::ConfigService::Instance().getUsername())) - .toString()); - - m_uiTabSystemSettings.lineEdit_remote_base_path_data->setText( - QString::fromStdString(m_settings.SCARFBasePath)); - QByteArray rawSysSettings = qs.value("system-settings").toByteArray(); - QDataStream streamSys(rawSysSettings); - TomoSystemSettings sysSettings; - streamSys >> sysSettings; - if (QDataStream::Ok == streamSys.status()) { - updateSystemSettingsTabFields(sysSettings); - } else { - updateSystemSettingsTabFields(TomoSystemSettings()); - } - - // Get input paths (sample/dark/flats) - QByteArray rawInputPaths = - qs.value("input-paths-samples-flats-darks").toByteArray(); - QDataStream streamPaths(rawInputPaths); - TomoPathsConfig inputPaths; - streamPaths >> inputPaths; - if (QDataStream::Ok == streamPaths.status()) { - updatePathsConfig(inputPaths); - } else { - // factory defaults / blank/unknown paths - updatePathsConfig(TomoPathsConfig()); - } - - // Get all the pre-/post-processing options from a stream - QByteArray rawFiltersSettings = qs.value("filters-settings").toByteArray(); - QDataStream streamFilters(rawFiltersSettings); - TomoReconFiltersSettings filtersSettings; - streamFilters >> filtersSettings; - if (QDataStream::Ok == streamFilters.status()) { - setPrePostProcSettings(filtersSettings); - } else { - // something wrong in the settings previously saved => go back to factory - // defaults - setPrePostProcSettings(TomoReconFiltersSettings()); - } - - int pathSize = qs.beginReadArray("path-default-add-for-python"); - for (int i = 0; i < pathSize; ++i) { - qs.setArrayIndex(i); - m_defAddPathPython.push_back( - qs.value("value", "").toString().toStdString()); - } - if (0 == m_defAddPathPython.size()) - m_defAddPathPython = g_defAddPathPython; - qs.endArray(); - - // general GUI state - m_ui.tabMain->setCurrentIndex(qs.value("selected-tab-index").toInt()); - - restoreGeometry(qs.value("interface-win-geometry").toByteArray()); - - readSettingsEnergy(); - - qs.endGroup(); -} - -#ifndef _MSC_VER -QDataStream &operator<<(QDataStream &stream, size_t const &num) { - return stream << static_cast<qint64>(num); -} -#endif - -inline QDataStream &operator<<(QDataStream &stream, std::string const &str) { - stream << QString::fromStdString(str); - return stream; -} - -/// serialize the local part of the system settings as a QDataStream => -/// QByteArray -QDataStream &operator<<(QDataStream &stream, - TomoSystemSettingsLocal const &ssl) { - // clang-format off - stream << ssl.m_basePathTomoData - << ssl.m_remoteDriveOrMountPoint - << ssl.m_reconScriptsPath - << ssl.m_externalInterpreterPath - << ssl.m_processes - << ssl.m_cores; - // clang-format on - - return stream; -} - -/// serialize the remote part of the system settings as a QDataStream => -/// QByteArray -QDataStream &operator<<(QDataStream &stream, - TomoSystemSettingsRemote const &ssr) { - // clang-format off - stream << ssr.m_basePathTomoData - << ssr.m_basePathReconScripts - << ssr.m_nodes - << ssr.m_cores; - // clang-format on - - return stream; -} - -/// serialize system settings as a QDataStream => QByteArray -QDataStream &operator<<(QDataStream &stream, TomoSystemSettings const &ss) { - // clang-format off - stream << ss.m_local << ss.m_remote; - for (const auto comp : ss.m_pathComponents) { - stream << comp; - } - stream << ss.m_samplesDirPrefix - << ss.m_flatsDirPrefix - << ss.m_darksDirPrefix - << ss.m_outputPathCompPreProcessed - << ss.m_outputPathCompReconst; - // clang-format on - - return stream; -} - -/// serialize a filters settings, as a QDataStream => QByteArray -QDataStream &operator<<(QDataStream &stream, - TomoReconFiltersSettings const &fs) { - // clang-format off - stream << fs.prep.normalizeByAirRegion - << fs.prep.normalizeByProtonCharge - << fs.prep.normalizeByFlats - << fs.prep.normalizeByDarks - << fs.prep.medianFilterWidth - << (fs.prep.rotation/90) - << fs.prep.maxAngle - << fs.prep.scaleDownFactor - << fs.postp.circMaskRadius - << fs.postp.cutOffLevel - << fs.outputPreprocImages; - // clang-format on - - return stream; -} - -/// serialize an input paths config (samples/darks/flats) -QDataStream &operator<<(QDataStream &stream, TomoPathsConfig const &cfg) { - // clang-format off - stream << QString::fromStdString(cfg.pathSamples()) - << QString::fromStdString(cfg.pathOpenBeam()) - << cfg.m_pathOpenBeamEnabled - << QString::fromStdString(cfg.pathDarks()) - << cfg.m_pathDarkEnabled; - // clang-format on - - return stream; -} - -/** - * Save persistent settings. Qt based. - */ -void TomographyIfaceViewQtGUI::saveSettings() const { - QSettings qs; - qs.beginGroup(QString::fromStdString(m_settingsGroup)); - - saveSettingsEnergy(); - - qs.setValue("on-close-ask-for-confirmation", - m_settings.onCloseAskForConfirmation); - qs.setValue("use-keep-alive", m_settings.useKeepAlive); - - qs.setValue("experiment-reference", - QString::fromStdString(m_setupExperimentRef)); - - qs.setValue("SCARF-remote-username", - m_uiTabRun.lineEdit_SCARF_username->text()); - - // Save all the SystemSettings via a Qt stream - QByteArray sysSettings; - QDataStream streamSys(&sysSettings, QIODevice::WriteOnly); - streamSys << systemSettings(); - qs.setValue("system-settings", sysSettings); - QString s = m_uiTabSystemSettings.lineEdit_remote_base_path_data->text(); - qs.setValue("SCARF-base-path", s); - - // Save input data paths (samples/flats/darks, etc.) - QByteArray pathsConfig; - QDataStream streamPaths(&pathsConfig, QIODevice::WriteOnly); - streamPaths << currentPathsConfig(); - qs.setValue("input-paths-samples-flats-darks", pathsConfig); - - // Save all the pre-/post-processing options through a stream - QByteArray filtersSettings; - QDataStream streamFilters(&filtersSettings, QIODevice::WriteOnly); - streamFilters << grabPrePostProcSettings(); - qs.setValue("filters-settings", filtersSettings); - - // User parameters for reconstructions - qs.setValue("RB-number", QString::fromStdString(m_setupExperimentRef)); - - qs.beginWriteArray("path-default-add-for-python"); - for (size_t i = 0; i < m_defAddPathPython.size(); ++i) { - qs.setArrayIndex(static_cast<int>(i)); - qs.setValue("value", QString::fromStdString(m_defAddPathPython[i])); - } - qs.endArray(); - - // general GUI status - qs.setValue("selected-tab-index", m_ui.tabMain->currentIndex()); - - qs.setValue("interface-win-geometry", saveGeometry()); - - qs.endGroup(); -} - -/// needs to at least update the 'tool' combo box -void TomographyIfaceViewQtGUI::compResourceIndexChanged(int /* i */) { - QComboBox *rt = m_uiTabRun.comboBox_run_compute_resource; - if (!rt) - return; - - m_currentComputeRes = rt->currentText().toStdString(); - m_presenter->notify(ITomographyIfacePresenter::CompResourceChanged); -} - -void TomographyIfaceViewQtGUI::runToolIndexChanged(int /* i */) { - QComboBox *rt = m_uiTabRun.comboBox_run_tool; - m_currentReconTool = rt->currentText().toStdString(); - m_presenter->notify(ITomographyIfacePresenter::ToolChanged); -} - -void TomographyIfaceViewQtGUI::enableConfigTool(bool on) { - m_uiTabRun.pushButton_run_tool_setup->setEnabled(on); -} - -void TomographyIfaceViewQtGUI::enableRunReconstruct(bool on) { - m_uiTabRun.pushButton_reconstruct->setEnabled(on); -} - -/** - * Update or toggle on/off the log in/out control widgets (like - * enabling/disabling push buttons, updating a display that tells the - * user if we're logged in, etc.). - * - * @param loggedIn Status (true when logged in) - */ -void TomographyIfaceViewQtGUI::updateLoginControls(bool loggedIn) { - m_uiTabRun.pushButton_SCARF_login->setEnabled(!loggedIn); - m_uiTabRun.pushButton_SCARF_logout->setEnabled(loggedIn); - - enableLoggedActions(loggedIn); - updateCompResourceStatus(loggedIn); -} - -/** - * Slot for when the 'login' or similar button is clicked (released) - */ -void TomographyIfaceViewQtGUI::SCARFLoginClicked() { - m_presenter->notify(ITomographyIfacePresenter::LogInRequested); -} - -/** - * Slot for when the 'logout' or similar button is clicked (released) - */ -void TomographyIfaceViewQtGUI::SCARFLogoutClicked() { - m_presenter->notify(ITomographyIfacePresenter::LogOutRequested); -} - -/** - * Slot for when the user requests to open the tool specific setup dialog. - */ -void TomographyIfaceViewQtGUI::toolSetupClicked() { - QComboBox *rt = m_uiTabRun.comboBox_run_tool; - if (!rt) - return; - - m_presenter->notify(ITomographyIfacePresenter::SetupReconTool); -} - -/** - * Takes and displays a new configuration of paths to - * sample/flats/dark input images. - */ -void TomographyIfaceViewQtGUI::updatePathsConfig(const TomoPathsConfig &cfg) { - m_uiTabRun.lineEdit_path_samples->setText( - QString::fromStdString(cfg.pathSamples())); - m_uiTabRun.lineEdit_path_flats->setText( - QString::fromStdString(cfg.pathOpenBeam())); - m_uiTabRun.checkBox_path_flats->setChecked(cfg.m_pathOpenBeamEnabled); - m_uiTabRun.lineEdit_path_darks->setText( - QString::fromStdString(cfg.pathDarks())); - m_uiTabRun.checkBox_path_darks->setChecked(cfg.m_pathDarkEnabled); - m_pathsConfig = cfg; -} - -/** - * Updates the view/forms with new system settings (local and remote, - * including multiple paths and path components) - */ -void TomographyIfaceViewQtGUI::updateSystemSettingsTabFields( - const TomoSystemSettings &setts) { - // paths and related - m_uiTabSystemSettings.lineEdit_path_comp_1st->setText( - QString::fromStdString(setts.m_pathComponents[0])); - // Not modifyable at the moment: m_uiTabSystemSettings.lineEdit_path_comp_2nd; - // Not modifyable at the moment: m_uiTabSystemSettings.lineEdit_path_comp_3rd; - m_uiTabSystemSettings.lineEdit_path_comp_input_samples->setText( - QString::fromStdString(setts.m_samplesDirPrefix)); - - m_uiTabSystemSettings.lineEdit_path_comp_input_flats->setText( - QString::fromStdString(setts.m_flatsDirPrefix)); - - m_uiTabSystemSettings.lineEdit_path_comp_input_darks->setText( - QString::fromStdString(setts.m_darksDirPrefix)); - - m_uiTabSystemSettings.lineEdit_path_comp_out_preprocessed->setText( - QString::fromStdString(setts.m_outputPathCompPreProcessed)); - - m_uiTabSystemSettings.lineEdit_path_comp_out_processed->setText( - QString::fromStdString(setts.m_outputPathCompReconst)); - - m_uiTabSystemSettings.lineEdit_remote_base_path_data->setText( - QString::fromStdString(setts.m_remote.m_basePathTomoData)); - - m_uiTabSystemSettings.lineEdit_remote_scripts_base_dir->setText( - QString::fromStdString(setts.m_remote.m_basePathReconScripts)); - - m_uiTabSystemSettings.lineEdit_on_local_data_drive_or_path->setText( - QString::fromStdString(setts.m_local.m_basePathTomoData)); - - m_uiTabSystemSettings.lineEdit_on_local_remote_data_drive_path->setText( - QString::fromStdString(setts.m_local.m_remoteDriveOrMountPoint)); - - // scripts and processes - m_uiTabSystemSettings.spinBox_remote_nodes->setValue(setts.m_remote.m_nodes); - m_uiTabSystemSettings.spinBox_remote_cores->setValue(setts.m_remote.m_cores); - - m_uiTabSystemSettings.spinBox_local_processes->setValue( - setts.m_local.m_processes); - m_uiTabSystemSettings.spinBox_local_cores->setValue(setts.m_local.m_cores); - - m_uiTabSystemSettings.lineEdit_local_recon_scripts->setText( - QString::fromStdString(setts.m_local.m_reconScriptsPath)); - m_uiTabSystemSettings.lineEdit_local_external_interpreter->setText( - QString::fromStdString(setts.m_local.m_externalInterpreterPath)); -} - -/** - * Displays and gets the results of a tool specific configuration dialog. - * - * @param dialog The pointer to the current dialog - */ -void TomographyIfaceViewQtGUI::showToolConfig( - TomoToolConfigDialogBase &dialog) { - - // execute also intiialises all the parts of the GUI - dialog.initialiseGUIandExecute(); -} - -/** - * Slot - when the user clicks the 'reconstruct data' or similar button. - */ -void TomographyIfaceViewQtGUI::reconstructClicked() { - m_presenter->notify(ITomographyIfacePresenter::RunReconstruct); -} - -/** - * Slot - when the user clicks the 'visualize job results' or similar button. - */ -void TomographyIfaceViewQtGUI::runVisualizeClicked() { - QTableWidget *tbl = m_uiTabRun.tableWidget_run_jobs; - const int idCol = 2; - QTableWidgetItem *hdr = tbl->horizontalHeaderItem(idCol); - if ("ID" != hdr->text()) - throw std::runtime_error("Expected to get the Id of jobs from the " - "second column of the table of jobs, but I " - "found this at that column: " + - hdr->text().toStdString()); - - QModelIndexList idSel = tbl->selectionModel()->selectedRows(); - if (idSel.count() <= 0) - return; - - const std::string id = tbl->item(idSel[0].row(), idCol)->text().toStdString(); - if (idSel.count() > 1) { - m_processingJobsIDs.clear(); - m_processingJobsIDs.push_back(id); - m_presenter->notify(ITomographyIfacePresenter::VisualizeJobFromTable); - } -} - -/** - * Slot - when the user clicks the 'cancel job' or similar button. - */ -void TomographyIfaceViewQtGUI::jobCancelClicked() { - m_processingJobsIDs.clear(); - QTableWidget *tbl = m_uiTabRun.tableWidget_run_jobs; - const int idCol = 2; - QTableWidgetItem *hdr = tbl->horizontalHeaderItem(idCol); - if ("ID" != hdr->text()) - throw std::runtime_error("Expected to get the Id of jobs from the " - "second column of the table of jobs, but I " - "found this at that column: " + - hdr->text().toStdString()); - - QModelIndexList idSel = tbl->selectionModel()->selectedRows(); - for (int i = 0; i < idSel.count(); ++i) { - const std::string id = - tbl->item(idSel[i].row(), idCol)->text().toStdString(); - m_processingJobsIDs.push_back(id); - } - - m_presenter->notify(ITomographyIfacePresenter::CancelJobFromTable); -} - -/** - * Slot - when the user clicks the 'refresh job list/table' or similar button. - */ -void TomographyIfaceViewQtGUI::jobTableRefreshClicked() { - m_presenter->notify(ITomographyIfacePresenter::RefreshJobs); -} - -/** - * Update the job status and general info table/tree from the info - * stored in this class' data members, which ideally should have - * information from a recent query to the server. - */ -void TomographyIfaceViewQtGUI::updateJobsInfoDisplay( - const std::vector<Mantid::API::IRemoteJobManager::RemoteJobInfo> &status, - const std::vector<Mantid::API::IRemoteJobManager::RemoteJobInfo> & - localStatus) { - - QTableWidget *t = m_uiTabRun.tableWidget_run_jobs; - bool sort = t->isSortingEnabled(); - t->setRowCount(static_cast<int>(status.size() + localStatus.size())); - - for (size_t i = 0; i < status.size(); ++i) { - int ii = static_cast<int>(i); - t->setItem(ii, 0, - new QTableWidgetItem(QString::fromStdString(g_SCARFName))); - t->setItem(ii, 1, - new QTableWidgetItem(QString::fromStdString(status[i].name))); - t->setItem(ii, 2, - new QTableWidgetItem(QString::fromStdString(status[i].id))); - - t->setItem(ii, 3, - new QTableWidgetItem(QString::fromStdString(status[i].status))); - - // beware "Exit" is called "Exited" on the web portal, but the REST - // responses - // call it "Exit" - if (std::string::npos != status[i].status.find("Exit") || - std::string::npos != status[i].status.find("Suspend")) - t->item(ii, 3)->setBackground(QColor(255, 120, 120)); // Qt::red - else if (std::string::npos != status[i].status.find("Pending")) - t->item(ii, 3)->setBackground(QColor(150, 150, 150)); // Qt::gray - else if (std::string::npos != status[i].status.find("Running") || - std::string::npos != status[i].status.find("Active")) - t->item(ii, 3)->setBackground(QColor(120, 120, 255)); // Qt::blue - else if (std::string::npos != status[i].status.find("Finished") || - std::string::npos != status[i].status.find("Done")) - t->item(ii, 3)->setBackground(QColor(120, 255, 120)); // Qt::green - - t->setItem(ii, 4, - new QTableWidgetItem(QString::fromStdString(status[i].cmdLine))); - } - - // Local processes - for (size_t i = 0; i < localStatus.size(); ++i) { - - // This won't work well, at least on windows. - // bool runs = Poco::isRunning( - // boost::lexical_cast<Poco::Process::PID>(localStatus[i].id)); - // if (!runs) - // m_localStatus[i].status = "Done"; - - int ii = static_cast<int>(status.size() + i); - t->setItem(ii, 0, new QTableWidgetItem(QString::fromStdString("local"))); - t->setItem(ii, 1, new QTableWidgetItem( - QString::fromStdString(localStatus[i].name))); - t->setItem(ii, 2, - new QTableWidgetItem(QString::fromStdString(localStatus[i].id))); - - t->setItem(ii, 3, new QTableWidgetItem( - QString::fromStdString(localStatus[i].status))); - - // beware "Exit" is called "Exited" on the web portal, but the - // REST responses call it "Exit" - if (std::string::npos != localStatus[i].status.find("Exit") || - std::string::npos != localStatus[i].status.find("Suspend")) - t->item(ii, 3)->setBackground(QColor(255, 120, 120)); // Qt::red - else if (std::string::npos != localStatus[i].status.find("Pending")) - t->item(ii, 3)->setBackground(QColor(150, 150, 150)); // Qt::gray - else if (std::string::npos != localStatus[i].status.find("Running") || - std::string::npos != localStatus[i].status.find("Active")) - t->item(ii, 3)->setBackground(QColor(120, 120, 255)); // Qt::blue - else if (std::string::npos != localStatus[i].status.find("Finished") || - std::string::npos != localStatus[i].status.find("Done")) - t->item(ii, 3)->setBackground(QColor(120, 255, 120)); // Qt::green - - t->setItem(ii, 4, new QTableWidgetItem( - QString::fromStdString(localStatus[i].cmdLine))); - } - - t->setSortingEnabled(sort); -} - -std::string TomographyIfaceViewQtGUI::getUsername() const { - if (g_SCARFName == - m_uiTabRun.comboBox_run_compute_resource->currentText().toStdString()) - return m_uiTabRun.lineEdit_SCARF_username->text().toStdString(); - else - return "invalid"; -} - -/** - * Retrieve the username being used for the selected compute resource. - * - * @return Username ready to be used in remote queries - */ -std::string TomographyIfaceViewQtGUI::getPassword() const { - if (g_SCARFName == - m_uiTabRun.comboBox_run_compute_resource->currentText().toStdString()) - return m_uiTabRun.lineEdit_SCARF_password->text().toStdString(); - else - return "none"; -} - -void TomographyIfaceViewQtGUI::flatsPathCheckStatusChanged(int status) { - bool enable(0 != status); - - // grab new value and enable/disable related widgets - m_pathsConfig.m_pathOpenBeamEnabled = enable; - m_uiTabRun.lineEdit_path_flats->setEnabled(enable); - m_uiTabRun.pushButton_flats_dir->setEnabled(enable); - m_presenter->notify(ITomographyIfacePresenter::TomoPathsChanged); -} - -void TomographyIfaceViewQtGUI::darksPathCheckStatusChanged(int status) { - bool enable(0 != status); - - m_pathsConfig.m_pathDarkEnabled = enable; - m_uiTabRun.lineEdit_path_darks->setEnabled(enable); - m_uiTabRun.pushButton_darks_dir->setEnabled(enable); - m_presenter->notify(ITomographyIfacePresenter::TomoPathsChanged); -} - -void TomographyIfaceViewQtGUI::samplesPathBrowseClicked() { - std::string str; - processPathBrowseClick(m_uiTabRun.lineEdit_path_samples, str); - if (!str.empty()) { - m_pathsConfig.updatePathSamples(str); - m_presenter->notify(ITomographyIfacePresenter::TomoPathsEditedByUser); - } -} - -void TomographyIfaceViewQtGUI::flatsPathBrowseClicked() { - std::string str; - processPathBrowseClick(m_uiTabRun.lineEdit_path_flats, str); - if (!str.empty()) { - m_pathsConfig.updatePathOpenBeam( - str, m_uiTabRun.checkBox_path_flats->isChecked()); - m_presenter->notify(ITomographyIfacePresenter::TomoPathsChanged); - } -} - -void TomographyIfaceViewQtGUI::darksPathBrowseClicked() { - std::string str; - processPathBrowseClick(m_uiTabRun.lineEdit_path_darks, str); - if (!str.empty()) { - m_pathsConfig.updatePathDarks(str, - m_uiTabRun.checkBox_path_darks->isChecked()); - m_presenter->notify(ITomographyIfacePresenter::TomoPathsChanged); - } -} - -void TomographyIfaceViewQtGUI::samplesPathEditedByUser() { - const std::string path = - m_uiTabRun.lineEdit_path_samples->text().toStdString(); - m_pathsConfig.updatePathSamples(path); - m_presenter->notify(ITomographyIfacePresenter::TomoPathsEditedByUser); -} - -void TomographyIfaceViewQtGUI::flatsPathEditedByUser() { - const std::string path = m_uiTabRun.lineEdit_path_flats->text().toStdString(); - m_pathsConfig.updatePathOpenBeam(path, - m_uiTabRun.checkBox_path_flats->isChecked()); - m_presenter->notify(ITomographyIfacePresenter::TomoPathsChanged); -} - -void TomographyIfaceViewQtGUI::darksPathEditedByUser() { - const std::string path = m_uiTabRun.lineEdit_path_darks->text().toStdString(); - m_pathsConfig.updatePathDarks(path, - m_uiTabRun.checkBox_path_flats->isChecked()); - m_presenter->notify(ITomographyIfacePresenter::TomoPathsChanged); -} - -void TomographyIfaceViewQtGUI::browseLocalInOutDirClicked() { - checkUserBrowseDir( - m_uiTabSystemSettings.lineEdit_on_local_data_drive_or_path); -} - -void TomographyIfaceViewQtGUI::browseLocalRemoteDriveOrPath() { - checkUserBrowseDir( - m_uiTabSystemSettings.lineEdit_on_local_remote_data_drive_path); -} - -void TomographyIfaceViewQtGUI::browseLocalReconScriptsDirClicked() { - checkUserBrowseDir(m_uiTabSystemSettings.lineEdit_local_recon_scripts, - "Select location of scripts (scripts subdirectory/folder " - "in the Mantid installation", - false); - systemSettingsEdited(); -} - -void TomographyIfaceViewQtGUI::browseLocalExternalInterpreterClicked() { - checkUserBrowseFile(m_uiTabSystemSettings.lineEdit_local_external_interpreter, - "Select interpreter executable", false); - systemSettingsEdited(); -} - -/** - * Get path from user and update a line edit and a variable. - * - * @param le a line edit where the path is shown. - * - * @param data variable where the path is stored (in addition to the line - * edit object). - */ -void TomographyIfaceViewQtGUI::processPathBrowseClick(QLineEdit *le, - std::string &data) { - QString algPrev = - MantidQt::API::AlgorithmInputHistory::Instance().getPreviousDirectory(); - /* - // This would remember every widget's old value, and not the last path - QString prev; - if (le->text().isEmpty()) { - prev = algPrev; - } else { - prev = le->text(); - } - */ - QString prev = algPrev; - - QString path(QFileDialog::getExistingDirectory( - this, tr("Open directory/folder"), prev)); - - if (!path.isEmpty()) { - le->setText(path); - data = path.toStdString(); - - MantidQt::API::AlgorithmInputHistory::Instance().setPreviousDirectory(path); - } -} - -TomoReconFiltersSettings TomographyIfaceViewQtGUI::prePostProcSettings() const { - return grabPrePostProcSettings(); -} - -TomoReconFiltersSettings -TomographyIfaceViewQtGUI::grabPrePostProcSettings() const { - TomoReconFiltersSettings opts; - - // pre-processing - opts.prep.normalizeByAirRegion = - m_uiTabFilters.checkBox_normalize_by_air_region->isChecked(); - - // TODOVIEW - // m_uiTabFilters.checkBox_normalize_by_proton_charge is disabled for now - opts.prep.normalizeByProtonCharge = false; - - opts.prep.normalizeByFlats = - m_uiTabFilters.checkBox_normalize_by_flats->isChecked(); - - opts.prep.normalizeByDarks = - m_uiTabFilters.checkBox_normalize_by_darks->isChecked(); - - // TODOVIEW - // m_uiTabFilters.checkBox_corrections_MCP_detector is disabled for now - - opts.prep.medianFilterWidth = static_cast<size_t>( - m_uiTabFilters.spinBox_prep_median_filter_width->value()); - - opts.prep.rotation = - 90 * m_uiTabFilters.comboBox_prep_rotation->currentIndex(); - - opts.prep.maxAngle = m_uiTabFilters.doubleSpinBox_prep_max_angle->value(); - - opts.prep.scaleDownFactor = - static_cast<size_t>(m_uiTabFilters.spinBox_prep_scale_factor->value()); - - // post-processing - opts.postp.circMaskRadius = - m_uiTabFilters.doubleSpinBox_post_circ_mask->value(); - - opts.postp.cutOffLevel = m_uiTabFilters.doubleSpinBox_post_cutoff->value(); - - // outputs - opts.outputPreprocImages = - m_uiTabFilters.checkBox_out_preproc_images->isChecked(); - - return opts; -} - -void TomographyIfaceViewQtGUI::setPrePostProcSettings( - const TomoReconFiltersSettings &opts) { - - // pre-processing - m_uiTabFilters.checkBox_normalize_by_air_region->setChecked( - opts.prep.normalizeByAirRegion); - - m_uiTabFilters.checkBox_normalize_by_proton_charge->setChecked( - opts.prep.normalizeByProtonCharge); - - m_uiTabFilters.checkBox_normalize_by_flats->setChecked( - opts.prep.normalizeByFlats); - - m_uiTabFilters.checkBox_normalize_by_darks->setChecked( - opts.prep.normalizeByDarks); - - m_uiTabFilters.spinBox_prep_median_filter_width->setValue( - static_cast<int>(opts.prep.medianFilterWidth)); - - m_uiTabFilters.comboBox_prep_rotation->setCurrentIndex( - static_cast<int>(opts.prep.rotation / 90)); - - m_uiTabFilters.doubleSpinBox_prep_max_angle->setValue(opts.prep.maxAngle); - - m_uiTabFilters.spinBox_prep_scale_factor->setValue( - static_cast<int>(opts.prep.scaleDownFactor)); - - // post-processing - m_uiTabFilters.doubleSpinBox_post_circ_mask->setValue( - opts.postp.circMaskRadius); - - m_uiTabFilters.doubleSpinBox_post_cutoff->setValue(opts.postp.cutOffLevel); - - // outputs - m_uiTabFilters.checkBox_out_preproc_images->setChecked( - opts.outputPreprocImages); -} - -TomoSystemSettings TomographyIfaceViewQtGUI::systemSettings() const { - return grabSystemSettingsFromUser(); -} - -TomoSystemSettings -TomographyIfaceViewQtGUI::grabSystemSettingsFromUser() const { - TomoSystemSettings setts; - - // paths and related - setts.m_pathComponents[0] = - m_uiTabSystemSettings.lineEdit_path_comp_1st->text().toStdString(); - // Not modifiable at the moment: - // m_uiTabSystemSettings.lineEdit_path_comp_2nd; - // Not modifiable at the moment: - // m_uiTabSystemSettings.lineEdit_path_comp_3rd; - setts.m_samplesDirPrefix = - m_uiTabSystemSettings.lineEdit_path_comp_input_samples->text() - .toStdString(); - setts.m_flatsDirPrefix = - m_uiTabSystemSettings.lineEdit_path_comp_input_flats->text() - .toStdString(); - setts.m_darksDirPrefix = - m_uiTabSystemSettings.lineEdit_path_comp_input_darks->text() - .toStdString(); - - setts.m_outputPathCompPreProcessed = - m_uiTabSystemSettings.lineEdit_path_comp_out_preprocessed->text() - .toStdString(); - setts.m_outputPathCompReconst = - m_uiTabSystemSettings.lineEdit_path_comp_out_processed->text() - .toStdString(); - - setts.m_remote.m_basePathTomoData = - m_uiTabSystemSettings.lineEdit_remote_base_path_data->text() - .toStdString(); - setts.m_remote.m_basePathReconScripts = - m_uiTabSystemSettings.lineEdit_remote_scripts_base_dir->text() - .toStdString(); - - setts.m_local.m_basePathTomoData = - m_uiTabSystemSettings.lineEdit_on_local_data_drive_or_path->text() - .toStdString(); - setts.m_local.m_remoteDriveOrMountPoint = - m_uiTabSystemSettings.lineEdit_on_local_remote_data_drive_path->text() - .toStdString(); - - // scripts and processes - setts.m_remote.m_nodes = m_uiTabSystemSettings.spinBox_remote_nodes->value(); - setts.m_remote.m_cores = m_uiTabSystemSettings.spinBox_remote_cores->value(); - - setts.m_local.m_processes = - m_uiTabSystemSettings.spinBox_local_processes->value(); - setts.m_local.m_cores = m_uiTabSystemSettings.spinBox_local_cores->value(); - - setts.m_local.m_reconScriptsPath = - m_uiTabSystemSettings.lineEdit_local_recon_scripts->text().toStdString(); - - setts.m_local.m_externalInterpreterPath = - m_uiTabSystemSettings.lineEdit_local_external_interpreter->text() - .toStdString(); - - setts.m_experimentReference = - m_uiTabRun.lineEdit_experiment_reference->text().toStdString(); - - return setts; -} - -void TomographyIfaceViewQtGUI::sendToOctopusVisClicked() { - sendToVisTool("Octopus Visualization 3D", m_setupOctopusVisPath, - g_defOctopusAppendPath); -} - -void TomographyIfaceViewQtGUI::sendToParaviewClicked() { - sendToVisTool("ParaView", m_setupParaviewPath, g_defParaviewAppendPath); -} - -/** - * Start a third party tool as a process. TODOVIEW: This is a very early - * experimental implementation that should be moved out of this view. - * - * @param toolName Human understandable name of the tool/program - * @param pathString Path where the tool is installed - * @param appendBin string to append to the path if required, example: - * bin/tool.exe - */ -void TomographyIfaceViewQtGUI::sendToVisTool(const std::string &toolName, - const std::string &pathString, - const std::string &appendBin) { - // prepare external tool executable path - Poco::Path tmpPath(pathString); - if (!appendBin.empty()) { - tmpPath.append(appendBin); - } - const std::string toolPath = tmpPath.toString(); - - // get path to pass as parameter - const QFileSystemModel *model = dynamic_cast<QFileSystemModel *>( - m_uiTabVisualize.treeView_files->model()); - if (!model) - return; - - const auto selection = - m_uiTabVisualize.treeView_files->selectionModel()->selectedIndexes(); - // just take the first selected item/directory - if (selection.empty()) - return; - QString selPath = model->filePath(selection.first()); - - // Execute - std::vector<std::string> args; - args.push_back(selPath.toStdString()); - - sendLog("Executing visualization tool: " + toolName + ". Executing: '" + - toolPath + "', with parameters: '" + args[0] + "'."); - try { - Mantid::Kernel::ConfigService::Instance().launchProcess(toolPath, args); - } catch (std::runtime_error &rexc) { - sendLog("The execution of " + toolName + "failed. details: " + - std::string(rexc.what())); - userWarning("Execution failed ", - "Coult not execute the tool. Error details: " + - std::string(rexc.what())); - } -} - -void TomographyIfaceViewQtGUI::browseFilesToVisualizeClicked() { - // an alternative would be to start from the current selection, instead of - // the - // current root: - const QFileSystemModel *model = dynamic_cast<QFileSystemModel *>( - m_uiTabVisualize.treeView_files->model()); - if (!model) - return; - - const QString currentPath = model->rootPath(); - QString path(QFileDialog::getExistingDirectory( - this, tr("Select root directory/folder with processed data " - "(reconstructions) under it"), - currentPath)); - - if (!path.isEmpty()) { - m_uiTabVisualize.treeView_files->setRootIndex(model->index(path)); - } -} - -// helper that should go to the presenter. Makes sure that the path is -// effectively readable -std::string TomographyIfaceViewQtGUI::checkDefaultVisualizeDir( - const std::string &basePath, const std::string &appendComp) { - Poco::Path location(Poco::Path::expand(basePath)); - location.append(appendComp); - Poco::File locationDir(location); - - std::string path; - if (locationDir.exists()) { - path = location.toString(); - } else { - userWarning( - "Cannot open the path", - "Cannot open " + location.toString() + - ". Please check that it exists on your system and it is readable."); - } - - return path; -} - -void TomographyIfaceViewQtGUI::defaultDirLocalVisualizeClicked() { - const QFileSystemModel *model = dynamic_cast<QFileSystemModel *>( - m_uiTabVisualize.treeView_files->model()); - if (!model) - return; - - // TODOVIEW: this should be moved to presenter? - std::string checkedPath = checkDefaultVisualizeDir( - m_uiTabSystemSettings.lineEdit_on_local_data_drive_or_path->text() - .toStdString(), - m_uiTabSystemSettings.lineEdit_path_comp_1st->text().toStdString()); - - const QString path = QString::fromStdString(checkedPath); - if (!path.isEmpty()) { - m_uiTabVisualize.treeView_files->setRootIndex(model->index(path)); - } -} - -void TomographyIfaceViewQtGUI::defaultDirRemoteVisualizeClicked() { - const QFileSystemModel *model = dynamic_cast<QFileSystemModel *>( - m_uiTabVisualize.treeView_files->model()); - if (!model) - return; - - // TODOVIEW: this should be moved to presenter? - std::string checkedPath = checkDefaultVisualizeDir( - m_uiTabSystemSettings.lineEdit_on_local_remote_data_drive_path->text() - .toStdString(), - m_uiTabSystemSettings.lineEdit_path_comp_1st->text().toStdString()); - - const QString path = QString::fromStdString(checkedPath); - if (!path.isEmpty()) { - m_uiTabVisualize.treeView_files->setRootIndex(model->index(path)); - } -} - -void TomographyIfaceViewQtGUI::browseVisToolParaviewClicked() { - m_setupParaviewPath = - checkUserBrowseDir(m_uiTabVisualize.lineEdit_paraview_location); -} - -void TomographyIfaceViewQtGUI::browseVisToolOctopusClicked() { - m_setupOctopusVisPath = - checkUserBrowseDir(m_uiTabVisualize.lineEdit_octopus_vis_location); -} - -/** - * Show the usual pop-up asking for a directory. Checks if the - * directory is valid, and updates the "previous/last directory" for - * the next browse directory. - * - * @param le line edit object on which the path is displayed. - * - * @param userMsg message to show in the pop-up window - * - * @param remember whether to remember this path for the next time - * that a browse-directory button is used. Normally you would set it - * to true for the data paths, but not for things like executable, - * external tools, etc. - * - * @return the directory path as a string - */ -std::string TomographyIfaceViewQtGUI::checkUserBrowseDir( - QLineEdit *le, const std::string &userMsg, bool remember) { - - QString prev; - if (le->text().isEmpty()) { - prev = - MantidQt::API::AlgorithmInputHistory::Instance().getPreviousDirectory(); - } else { - prev = le->text(); - } - - QString path( - QFileDialog::getExistingDirectory(this, tr(userMsg.c_str()), prev)); - - if (!path.isEmpty()) { - le->setText(path); - if (remember) { - MantidQt::API::AlgorithmInputHistory::Instance().setPreviousDirectory( - path); - } - } - - return path.toStdString(); -} - -/** - * Show the usual pop-up asking for an (existing) file. Checks if a - * file is actually selected, and updates the "previous/last directory" for - * the next browse file/directory. - * - * @param le line edit object on which the path is displayed. - * - * @param userMsg message to show in the pop-up window - * - * @param remember whether to remember this path for the next time - * that a browse-file/directory button is used. Normally you would set - * it to true for the data paths, but not for things like executable, - * external tools, etc. - * - * @return the file path as a string - */ -std::string TomographyIfaceViewQtGUI::checkUserBrowseFile( - QLineEdit *le, const std::string &userMsg, bool remember) { - - QString prev; - if (le->text().isEmpty()) { - prev = - MantidQt::API::AlgorithmInputHistory::Instance().getPreviousDirectory(); - } else { - prev = le->text(); - } - - QString path(QFileDialog::getOpenFileName(this, tr(userMsg.c_str()), prev)); - - if (!path.isEmpty()) { - le->setText(path); - if (remember) { - MantidQt::API::AlgorithmInputHistory::Instance().setPreviousDirectory( - path); - } - } - - return path.toStdString(); -} - -void TomographyIfaceViewQtGUI::resetPrePostFilters() { - auto reply = QMessageBox::question( - this, "Reset Confirmation", "Are you sure you want to <br><strong>RESET " - "ALL</strong> Filter settings?<br>This " - "action cannot be undone!", - QMessageBox::Yes | QMessageBox::No); - // default constructors with factory defaults - if (reply == QMessageBox::Yes) { - TomoReconFiltersSettings def; - setPrePostProcSettings(def); - } -} - -void TomographyIfaceViewQtGUI::systemSettingsEdited() { - m_presenter->notify(ITomographyIfacePresenter::SystemSettingsUpdated); -} - -void TomographyIfaceViewQtGUI::systemSettingsNumericEdited() { - m_presenter->notify(ITomographyIfacePresenter::SystemSettingsUpdated); -} - -void TomographyIfaceViewQtGUI::resetSystemSettings() { - const auto title = "Reset Confirmation"; - const auto body = "Are you sure you want to <br><strong>RESET " - "ALL</strong> System settings?<br>This " - "action cannot be undone!"; - // default constructors with factory defaults - if (userConfirmation(title, body)) { - // From factory defaults - TomoSystemSettings defaults; - updateSystemSettingsTabFields(defaults); - } -} - -/** - * Prompts the user for confirmation with a yes/no dialogue. - * The body can use HTML formatting. - * - * @param title The title that the message has - * @param body The body that the message has. This CAN use HTML formatting - */ -bool TomographyIfaceViewQtGUI::userConfirmation(const std::string &title, - const std::string &body) { - auto reply = QMessageBox::question(this, QString::fromStdString(title), - QString::fromStdString(body), - QMessageBox::Yes | QMessageBox::No); - return reply == QMessageBox::Yes; -} - -/** -* Show a warning message to the user (pop up) -* -* @param err Basic error title -* @param description More detailed explanation, hints, additional -* information, etc. -*/ -void TomographyIfaceViewQtGUI::userWarning(const std::string &err, - const std::string &description) { - QMessageBox::warning(this, QString::fromStdString(err), - QString::fromStdString(description), QMessageBox::Ok, - QMessageBox::Ok); -} - -void TomographyIfaceViewQtGUI::updatedExperimentReference() { - m_setupExperimentRef = - m_uiTabRun.lineEdit_experiment_reference->text().toStdString(); - // Might have to change: m_uiTabSystemSettings.lineEdit_local_out_recon_dir - // as - // well -} - -/** - * To log a message without waiting. - */ -void TomographyIfaceViewQtGUI::sendLog(const std::string &msg) { - m_logMsgs.push_back(msg); - m_presenter->notify(ITomographyIfacePresenter::LogMsg); - m_logMsgs.clear(); -} - -/** - * Show an error (serious) message to the user (pop up) - * - * @param err Basic error title - * @param description More detailed explanation, hints, additional - * information, etc. - */ -void TomographyIfaceViewQtGUI::userError(const std::string &err, - const std::string &description) { - QMessageBox::critical(this, QString::fromStdString(err), - QString::fromStdString(description), QMessageBox::Ok, - QMessageBox::Ok); -} - -void TomographyIfaceViewQtGUI::closeEvent(QCloseEvent *event) { - int answer = QMessageBox::AcceptRole; - - bool ask = m_settings.onCloseAskForConfirmation; - if (ask) { - QMessageBox msgBox; - msgBox.setWindowTitle("Close the tomographic reconstruction interface"); - // with something like this, we'd have layout issues: - // msgBox.setStandardButtons(QMessageBox::No | QMessageBox::Yes); - // msgBox.setDefaultButton(QMessageBox::Yes); - msgBox.setIconPixmap(QPixmap(":/win/unknown.png")); - QCheckBox confirmCheckBox("Always ask for confirmation", &msgBox); - confirmCheckBox.setCheckState(Qt::Checked); - msgBox.layout()->addItem(new QSpacerItem(0, 0, QSizePolicy::Expanding)); - msgBox.layout()->addWidget(&confirmCheckBox); - QPushButton *bYes = msgBox.addButton("Yes", QMessageBox::YesRole); - bYes->setIcon(style()->standardIcon(QStyle::SP_DialogYesButton)); - QPushButton *bNo = msgBox.addButton("No", QMessageBox::NoRole); - bNo->setIcon(style()->standardIcon(QStyle::SP_DialogNoButton)); - msgBox.setDefaultButton(bNo); - msgBox.setText("You are about to close this interface"); - msgBox.setInformativeText( - "If you close this interface you will need to log in again " - "and you might loose some of the current state. Jobs running on " - "remote " - "compute resources will remain unaffected though. Are you sure?"); - - m_settings.onCloseAskForConfirmation = confirmCheckBox.isChecked(); - answer = msgBox.exec(); - } - - if (answer == QMessageBox::AcceptRole) { - // TODOVIEW? cleanup(); - m_presenter->notify(ITomographyIfacePresenter::ShutDown); - event->accept(); - } else { - event->ignore(); - } -} - -void TomographyIfaceViewQtGUI::openHelpWin() { - MantidQt::API::HelpWindow::showCustomInterface( - NULL, QString("Tomographic_Reconstruction")); -} - -void TomographyIfaceViewQtGUI::emitExternalProcessFinished(const QString &str) { - emit externalProcessFinished(str); -} -} // namespace CustomInterfaces -} // namespace MantidQt diff --git a/MantidQt/CustomInterfaces/src/Tomography/TomographyROIPresenter.cpp b/MantidQt/CustomInterfaces/src/Tomography/TomographyROIPresenter.cpp deleted file mode 100644 index f7fc10bd615..00000000000 --- a/MantidQt/CustomInterfaces/src/Tomography/TomographyROIPresenter.cpp +++ /dev/null @@ -1,603 +0,0 @@ -#include "MantidAPI/AlgorithmManager.h" -#include "MantidAPI/AnalysisDataService.h" -#include "MantidAPI/MatrixWorkspace.h" -#include "MantidAPI/WorkspaceGroup.h" -#include "MantidQtAPI/BatchAlgorithmRunner.h" -#include "MantidQtCustomInterfaces/Tomography/ITomographyROIView.h" -#include "MantidQtCustomInterfaces/Tomography/ImageStackPreParams.h" -#include "MantidQtCustomInterfaces/Tomography/TomographyProcess.h" -#include "MantidQtCustomInterfaces/Tomography/TomographyROIPresenter.h" -#include "MantidQtCustomInterfaces/Tomography/TomographyThread.h" - -using namespace MantidQt::CustomInterfaces; - -namespace MantidQt { -namespace CustomInterfaces { - -namespace { -Mantid::Kernel::Logger g_log("ImageROI"); -} - -const std::string TomographyROIPresenter::g_wsgName = - "__tomography_gui_stack_fits_viewer_sample_images"; -const std::string TomographyROIPresenter::g_wsgFlatsName = - "__tomography_gui_stack_fits_viewer_flat_images"; -const std::string TomographyROIPresenter::g_wsgDarksName = - "__tomography_gui_stack_fits_viewer_dark_images"; - -bool TomographyROIPresenter::g_warnIfUnexpectedFileExtensions = false; - -TomographyROIPresenter::TomographyROIPresenter(ITomographyROIView *view) - : m_playStatus(false), m_stackPath(), m_view(view), - m_model(new ImageStackPreParams()) { - if (!m_view) { - throw std::runtime_error("Severe inconsistency found. Presenter created " - "with an empty/null view (tomography interface). " - "Cannot continue."); - } - m_algRunner = - Mantid::Kernel::make_unique<MantidQt::API::BatchAlgorithmRunner>(); -} - -TomographyROIPresenter::~TomographyROIPresenter() { cleanup(); } - -void TomographyROIPresenter::cleanup() {} - -void TomographyROIPresenter::notify(Notification notif) { - - switch (notif) { - - case ITomographyROIPresenter::Init: - processInit(); - break; - - case ITomographyROIPresenter::BrowseImage: - processBrowseImage(); - break; - - case ITomographyROIPresenter::BrowseStack: - processBrowseStack(); - break; - - case ITomographyROIPresenter::ChangeImageType: - processChangeImageType(); - break; - - case ITomographyROIPresenter::ChangeRotation: - processChangeRotation(); - break; - - case ITomographyROIPresenter::UpdateImgIndex: - processUpdateImgIndex(); - break; - - case ITomographyROIPresenter::PlayStartStop: - processPlayStartStop(); - break; - - case ITomographyROIPresenter::UpdateColorMap: - processUpdateColorMap(); - break; - - case ITomographyROIPresenter::ColorRangeUpdated: - processColorRangeUpdated(); - break; - - case ITomographyROIPresenter::SelectCoR: - processSelectCoR(); - break; - - case ITomographyROIPresenter::SelectROI: - processSelectROI(); - break; - - case ITomographyROIPresenter::SelectNormalization: - processSelectNormalization(); - break; - - case ITomographyROIPresenter::FinishedCoR: - processFinishedCoR(); - break; - - case ITomographyROIPresenter::FinishedROI: - processFinishedROI(); - break; - - case ITomographyROIPresenter::FinishedNormalization: - processFinishedNormalization(); - break; - - case ITomographyROIPresenter::ResetCoR: - processResetCoR(); - break; - - case ITomographyROIPresenter::ResetROI: - processResetROI(); - break; - - case ITomographyROIPresenter::ResetNormalization: - processResetNormalization(); - break; - - case ITomographyROIPresenter::ShutDown: - processShutDown(); - break; - } -} - -void TomographyROIPresenter::processInit() { - ImageStackPreParams p; - m_view->setParams(p); -} - -void TomographyROIPresenter::processBrowseImage() { - const std::string path = m_view->askImagePath(); - - if (path.empty()) - return; - - m_stackPath = path; - processLoadSingleImage(); - m_view->imageOrStackLoaded(trimFileNameFromPath(path)); -} - -void TomographyROIPresenter::processBrowseStack() { - const std::string path = m_view->askImagePath("Open directory"); - - if (path.empty()) - return; - - // we're loading at stack so we trim the filename - const std::string trimmedPath = trimFileNameFromPath(path); - - m_stackPath = trimmedPath; - processLoadStackOfImages(); - m_view->imageOrStackLoaded(trimmedPath); -} - -/** - * Validates the input stack of images (directories and files), and - * shows warning/error messages as needed. The outocome of the - * validation can be checkec via isValid() on the returned stack of - * images object. - * - * @param path user provided path to the stack of images - * - * @return a stack of images built from the path passed, not - * necessarily correct (check with isValid()) - */ -StackOfImagesDirs -TomographyROIPresenter::checkInputStack(const std::string &path) { - StackOfImagesDirs soid(path, true); - - const std::string soiPath = soid.sampleImagesDir(); - if (soiPath.empty()) { - m_view->userWarning("Error trying to find a stack of images", - "Could not find the sample images directory. The stack " - "of images is expected as: \n\n" + - soid.description()); - } else if (!soid.isValid()) { - m_view->userWarning("Error while checking/validating the stack of images", - "The stack of images could not be loaded correctly. " + - soid.status()); - } - - return soid; -} - -void TomographyROIPresenter::processLoadSingleImage() { - try { - auto &ads = Mantid::API::AnalysisDataService::Instance(); - if (ads.doesExist(g_wsgName)) { - ads.remove(g_wsgName); - } - if (ads.doesExist(g_wsgFlatsName)) { - ads.remove(g_wsgFlatsName); - } - if (ads.doesExist(g_wsgDarksName)) { - ads.remove(g_wsgDarksName); - } - } catch (std::runtime_error &rexc) { - g_log.warning("There was a problem while trying to remove apparently " - "existing workspaces. Error details: " + - std::string(rexc.what())); - } - - loadFITSImage(m_stackPath, g_wsgName); - setupAlgorithmRunnerAfterLoad(); -} - -void TomographyROIPresenter::processLoadStackOfImages() { - StackOfImagesDirs soid(""); - try { - soid = checkInputStack(m_stackPath); - } catch (std::exception &e) { - // Poco::FileNotFoundException: this should never happen, unless - // the open dir dialog misbehaves unexpectedly, or in tests - m_view->userWarning("Error trying to open directories/files", - "The path selected via the dialog cannot be openend or " - "there was a problem while trying to access it. This " - "is an unexpected inconsistency. Error details: " + - std::string(e.what())); - } - - if (!soid.isValid()) - return; - - std::vector<std::string> imgs = soid.sampleFiles(); - if (0 >= imgs.size()) { - m_view->userWarning( - "Error while trying to find image/projection files in the stack " - "directories", - "Could not find any (image) file in the samples subdirectory: " + - soid.sampleImagesDir()); - return; - } - - loadFITSStack(soid, g_wsgName, g_wsgFlatsName, g_wsgDarksName); - m_stackFlats = nullptr; - m_stackDarks = nullptr; - setupAlgorithmRunnerAfterLoad(); -} - -void TomographyROIPresenter::setupAlgorithmRunnerAfterLoad() { - // reset any previous connections - m_algRunner.get()->disconnect(); - connect(m_algRunner.get(), SIGNAL(batchComplete(bool)), this, - SLOT(finishedLoadStack(bool)), Qt::QueuedConnection); - - m_view->enableActions(false); - m_algRunner->executeBatchAsync(); -} - -void TomographyROIPresenter::finishedLoadStack(bool error) { - if (error) { - m_view->userWarning("Could not load the stack of images", - - "There was a failure while running the Mantid " - "algorithms that tried to load the stack of images. " - "Please check the error logs for details."); - m_view->enableActions(true); - return; - } - - const auto &ads = Mantid::API::AnalysisDataService::Instance(); - try { - m_stackSamples = ads.retrieveWS<Mantid::API::WorkspaceGroup>(g_wsgName); - } catch (std::exception &e) { - m_view->userWarning("Could not load the stack of sample images", - - "Could not produce a workspace group for the " - "stack of sample images. Cannot " - "display this stack. Please check the error log " - "for further details. Error when trying to " - "retrieve the sample images workspace: " + - std::string(e.what())); - m_view->enableActions(true); - return; - } - - // TODO: could be useful to do a check like this on wsg->size()? - // if (wsg && - // Mantid::API::AnalysisDataService::Instance().doesExist(wsg->name()) && - // wsg->size() > 0 && imgs.size() >= wsg->size()) { - // return wsg; - // } else { - // return Mantid::API::WorkspaceGroup_sptr(); - // } - - try { - m_stackSamples = ads.retrieveWS<Mantid::API::WorkspaceGroup>(g_wsgName); - Mantid::API::MatrixWorkspace_sptr ws = - ads.retrieveWS<Mantid::API::MatrixWorkspace>( - m_stackSamples->getNames()[0]); - } catch (std::exception &exc) { - m_view->userWarning( - "Failed to load contents for at least the first sample image", - "Could not load image contents for the first image file. " - "An unrecoverable error happened when trying to load the " - "image contents. Cannot display it. Error details: " + - std::string(exc.what())); - m_view->enableActions(true); - return; - } - - size_t imgCount = m_stackSamples->size(); - if (0 == imgCount) { - m_view->userWarning( - "Failed to load any FITS images - directory structure issue", - "Even though a directory apparently holding a stack of images was " - "found, " - "it was not possible to load any image file correctly from: " + - m_stackPath); - m_view->enableActions(true); - return; - } - - // check flats and darks - try { - if (ads.doesExist(g_wsgFlatsName)) { - m_stackFlats = - ads.retrieveWS<Mantid::API::WorkspaceGroup>(g_wsgFlatsName); - } - } catch (std::runtime_error &exc) { - m_view->userWarning("Failed to load the stack of flat (open beam) images", - "Could not produce a workspace group for the " - "stack of flat images. Cannot " - "display the flat images of this stack. " - "Please check the error log " - "for further details. Error when trying to " - "retrieve the flat images workspace:" + - std::string(exc.what())); - } - - try { - if (ads.doesExist(g_wsgDarksName)) { - m_stackDarks = - ads.retrieveWS<Mantid::API::WorkspaceGroup>(g_wsgDarksName); - } - } catch (std::runtime_error &exc) { - m_view->userWarning( - "Failed to load the stack of dark images", - "Could not produce a workspace group for the " - "stack of dark images. Cannot " - "display the dark images of this stack. Please check the error log " - "for further details. Error when trying to " - "retrieve the dark images workspace:" + - std::string(exc.what())); - } - - m_view->showStack(m_stackSamples, m_stackFlats, m_stackDarks); - m_view->enableActions(true); -} - -void TomographyROIPresenter::processChangeImageType() { - m_view->updateImageType(m_view->currentImageTypeStack()); -} - -void TomographyROIPresenter::processChangeRotation() { - m_view->updateRotationAngle(m_view->currentRotationAngle()); -} - -void TomographyROIPresenter::processUpdateImgIndex() { - m_view->updateImgWithIndex(m_view->currentImgIndex()); -} - -void TomographyROIPresenter::processPlayStartStop() { - auto wsg = m_view->currentImageTypeStack(); - if (!wsg) - return; - - if (wsg->size() <= 1) { - m_view->userWarning( - "Cannot \"play\" a single image", - "The stack currently loaded has a single image. Cannot play it."); - return; - } - - if (m_playStatus) { - m_view->playStop(); - m_playStatus = false; - m_view->enableActions(true); - } else { - m_view->enableActions(false); - m_playStatus = true; - m_view->playStart(); - } -} - -void TomographyROIPresenter::processUpdateColorMap() { - std::string filename = m_view->askColorMapFile(); - if (filename.empty()) - return; - - m_view->updateColorMap(filename); -} - -void TomographyROIPresenter::processColorRangeUpdated() { - m_view->updateImgWithIndex(m_view->currentImgIndex()); -} - -void TomographyROIPresenter::processSelectCoR() { - m_view->changeSelectionState(ITomographyROIView::SelectCoR); -} - -void TomographyROIPresenter::processSelectROI() { - m_view->changeSelectionState(ITomographyROIView::SelectROIFirst); -} - -void TomographyROIPresenter::processSelectNormalization() { - m_view->changeSelectionState(ITomographyROIView::SelectNormAreaFirst); -} - -void TomographyROIPresenter::processFinishedCoR() { - m_view->changeSelectionState(ITomographyROIView::SelectNone); -} - -void TomographyROIPresenter::processFinishedROI() { - m_view->changeSelectionState(ITomographyROIView::SelectNone); -} - -void TomographyROIPresenter::processFinishedNormalization() { - m_view->changeSelectionState(ITomographyROIView::SelectNone); -} - -void TomographyROIPresenter::processResetCoR() { - m_view->resetCoR(); - m_view->changeSelectionState(ITomographyROIView::SelectNone); -} - -void TomographyROIPresenter::processResetROI() { - m_view->resetROI(); - m_view->changeSelectionState(ITomographyROIView::SelectNone); -} - -void TomographyROIPresenter::processResetNormalization() { - m_view->resetNormArea(); - m_view->changeSelectionState(ITomographyROIView::SelectNone); -} - -void TomographyROIPresenter::processShutDown() { m_view->saveSettings(); } - -void TomographyROIPresenter::loadFITSStack(const StackOfImagesDirs &soid, - const std::string &wsgName, - const std::string &wsgFlatsName, - const std::string &wsgDarksName) { - const std::vector<std::string> &imgs = soid.sampleFiles(); - if (imgs.empty()) - return; - - loadFITSList(imgs, wsgName); - - auto flats = soid.flatFiles(); - m_stackFlats = nullptr; - loadFITSList(flats, wsgFlatsName); - - auto darks = soid.darkFiles(); - m_stackDarks = nullptr; - loadFITSList(darks, wsgDarksName); -} - -void TomographyROIPresenter::loadFITSList(const std::vector<std::string> &imgs, - const std::string &wsName) { - - auto &ads = Mantid::API::AnalysisDataService::Instance(); - try { - if (ads.doesExist(wsName)) { - ads.remove(wsName); - } - } catch (std::runtime_error &exc) { - m_view->userError( - "Error accessing the analysis data service", - "There was an error while accessing the Mantid analysis data service " - "to check for the presence of (and remove if present) workspace '" + - wsName + "'. This is a severe inconsistency . Error details:: " + - std::string(exc.what())); - } - - // This would be the alternative that loads images one by one (one - // algorithm run per image file) - // for (size_t i = 0; i < imgs.size(); ++i) { - // loadFITSImage(imgs[i], wsName); - // } - - // Load all requested/supported image files using a list with their names - try { - const std::string allPaths = filterImagePathsForFITSStack(imgs); - if (allPaths.empty()) { - return; - } - loadFITSImage(allPaths, wsName); - } catch (std::runtime_error &exc) { - m_view->userWarning("Error trying to start the loading of FITS file(s)", - "There was an error which prevented the file(s) from " - "being loaded. Details: " + - std::string(exc.what())); - } -} - -/** - * Produces a string with paths separated by commas. Takes the patsh from the - * input paths string but selects only the ones that look consistent with the - * supported format / extension. - * - * @param paths of the supposedly image files - * - * @return string with comma separated value (paths) ready to be passed as - *input - * to LoadFITS or similar algorithms - */ -std::string TomographyROIPresenter::filterImagePathsForFITSStack( - const std::vector<std::string> &paths) { - std::string allPaths = ""; - - // Let's take only the ones that we can effectively load - const std::string expectedShort = "fit"; - const std::string expectedLong = "fits"; - const std::string summedSkipStr = "_SummedImg."; - std::vector<std::string> unexpectedFiles, summedFiles; - for (const auto &pathStr : paths) { - const std::string extShort = pathStr.substr(pathStr.size() - 3); - const std::string extLong = pathStr.substr(pathStr.size() - 4); - // exception / sum images generated by some detectors - if (std::string::npos != pathStr.find(summedSkipStr)) { - summedFiles.push_back(pathStr); - } else if (extShort != expectedShort && extLong != expectedLong) { - unexpectedFiles.push_back(pathStr); - } else { - if (allPaths.empty()) { - allPaths = pathStr; - } else { - allPaths.append(", " + pathStr); - } - } - } - - // If needed, give a warning once, at the end - if (!unexpectedFiles.empty()) { - std::string filesStrMsg = ""; - for (auto path : unexpectedFiles) { - filesStrMsg += path + "\n"; - } - - const std::string msg = - "Found files with unrecognized or unsupported extension in this " - "stack ( " + - m_stackPath + "). Expected files with extension '" + expectedShort + - "' or '" + expectedLong + - "' the following file(s) were found (and not loaded):" + filesStrMsg; - - if (g_warnIfUnexpectedFileExtensions) { - m_view->userWarning("Files with invalid/unrecognized extension found in " - "the stack of images", - msg); - } - g_log.warning(msg); - } - if (!summedFiles.empty()) { - std::string filesStrMsg = ""; - for (auto path : summedFiles) { - filesStrMsg += path + "\n"; - } - - const std::string msg = - "Found file(s) that look like summed images (have '" + summedSkipStr + - "' in their name) in this " - "stack ( " + - m_stackPath + "). Ignoring them under the assumption that these are " - "note original images. Please make sure that this is " - "correct. The files ignored are: " + - filesStrMsg; - - if (g_warnIfUnexpectedFileExtensions) { - m_view->userWarning("Files that presumably are summed images have been " - "found in the stack of images", - msg); - } - g_log.warning(msg); - } - - return allPaths; -} - -void TomographyROIPresenter::loadFITSImage(const std::string &path, - const std::string &wsName) { - // get fits file into workspace and retrieve it from the ADS - auto alg = Mantid::API::AlgorithmManager::Instance().create("LoadFITS"); - try { - alg->initialize(); - alg->setPropertyValue("Filename", path); - alg->setProperty("OutputWorkspace", wsName); - // this is way faster when loading into a MatrixWorkspace - alg->setProperty("LoadAsRectImg", true); - } catch (std::exception &e) { - throw std::runtime_error("Failed to initialize the mantid algorithm to " - "load images. Error description: " + - std::string(e.what())); - } - - m_algRunner->addAlgorithm(alg); -} - -} // namespace CustomInterfaces -} // namespace MantidQt diff --git a/MantidQt/CustomInterfaces/src/Tomography/TomographyROIViewQtWidget.cpp b/MantidQt/CustomInterfaces/src/Tomography/TomographyROIViewQtWidget.cpp deleted file mode 100644 index 91d90683a34..00000000000 --- a/MantidQt/CustomInterfaces/src/Tomography/TomographyROIViewQtWidget.cpp +++ /dev/null @@ -1,1366 +0,0 @@ -#include "MantidAPI/MatrixWorkspace.h" -#include "MantidAPI/Run.h" -#include "MantidAPI/WorkspaceGroup.h" -#include "MantidKernel/ConfigService.h" -#include "MantidQtAPI/AlgorithmInputHistory.h" -#include "MantidQtAPI/AlgorithmRunner.h" -#include "MantidQtAPI/MantidColorMap.h" - -#include "MantidQtCustomInterfaces/Tomography/TomographyROIPresenter.h" -#include "MantidQtCustomInterfaces/Tomography/TomographyROIViewQtWidget.h" - -using namespace Mantid::API; -using namespace MantidQt::CustomInterfaces; - -#include <QCloseEvent> -#include <QDir> -#include <QFileDialog> -#include <QMessageBox> -#include <QPainter> -#include <QSettings> -#include <QTimer> - -namespace MantidQt { -namespace CustomInterfaces { - -// this would be more like a CustomWidget if it's eventually moved there -const std::string TomographyROIViewQtWidget::m_settingsGroup = - "CustomInterfaces/TomographyROIView"; - -TomographyROIViewQtWidget::TomographyROIViewQtWidget(QWidget *parent) - : QWidget(parent), ITomographyROIView(), m_colorMapFilename(), - m_imgWidth(0), m_imgHeight(0), m_selectionState(SelectNone), - m_presenter(NULL) { - initLayout(); - - // using an event filter. might be worth refactoring into a specific - // QLabel + selection of ROI+NormArea+CoR class - // not using Qwt Pickers to avoid Qwt version issues.. - m_ui.label_img->installEventFilter(this); -} - -TomographyROIViewQtWidget::~TomographyROIViewQtWidget() { - m_presenter->notify(TomographyROIPresenter::ShutDown); -} - -void TomographyROIViewQtWidget::setParams(ImageStackPreParams ¶ms) { - m_params = params; - setParamWidgets(m_params); -} - -void TomographyROIViewQtWidget::initLayout() { - // setup container ui - m_ui.setupUi(this); - - QList<int> sizes; - sizes.push_back(1000); - sizes.push_back(200); - // between image and right panel - m_ui.splitter_main_horiz->setSizes(sizes); - - sizes.clear(); - sizes.push_back(200); - sizes.push_back(50); - // between color bar and coordinates panel - m_ui.splitter_right_horiz->setSizes(sizes); - - m_ui.comboBox_image_type->setCurrentIndex(0); - m_ui.comboBox_rotation->setCurrentIndex(0); - - sizes.clear(); - sizes.push_back(10); - sizes.push_back(1000); - m_ui.splitter_img_vertical->setSizes(sizes); - m_ui.horizontalScrollBar_img_stack->setEnabled(false); - m_ui.lineEdit_img_seq->setText("---"); - m_ui.label_img_name->setText("none"); - - enableParamWidgets(false); - m_ui.colorBarWidget->setEnabled(false); - - m_ui.colorBarWidget->setViewRange(1, 65536); - m_ui.colorBarWidget->setAutoScale(true); - m_ui.colorBarWidget->setCheckBoxMode( - MantidWidgets::ColorBarWidget::ADD_AUTOSCALE_ON_LOAD); - m_ui.colorBarWidget->setAutoScaleTooltipText( - "This flag signals that the color scale range\n" - "will be set automatically to the current slice range\n" - "when an image is loaded. Note that auto\n" - "scaling will be applied when an image is loaded\n" - "for the very first time."); - - readSettings(); - - setupConnections(); - - initParamWidgets(1, 1); - grabCoRFromWidgets(); - grabROIFromWidgets(); - grabNormAreaFromWidgets(); - - // presenter that knows how to handle a ITomographyROIView should take care - // of all the logic. Note the view needs to now the concrete presenter here - m_presenter.reset(new TomographyROIPresenter(this)); - - // it will know what compute resources and tools we have available: - // This view doesn't even know the names of compute resources, etc. - m_presenter->notify(TomographyROIPresenter::Init); -} - -void TomographyROIViewQtWidget::setupConnections() { - - // 'browse' buttons - connect(m_ui.pushButton_browse_img, SIGNAL(released()), this, - SLOT(browseImageClicked())); - - connect(m_ui.pushButton_browse_stack, SIGNAL(released()), this, - SLOT(browseStackClicked())); - - connect(m_ui.pushButton_cor, SIGNAL(released()), this, SLOT(corClicked())); - connect(m_ui.pushButton_cor_reset, SIGNAL(released()), this, - SLOT(corResetClicked())); - - connect(m_ui.pushButton_roi, SIGNAL(released()), this, SLOT(roiClicked())); - connect(m_ui.pushButton_roi_reset, SIGNAL(released()), this, - SLOT(roiResetClicked())); - - connect(m_ui.pushButton_norm_area, SIGNAL(released()), this, - SLOT(normAreaClicked())); - connect(m_ui.pushButton_norm_area_reset, SIGNAL(released()), this, - SLOT(normAreaResetClicked())); - - // "Play" the stack for quick visualization of input images - connect(m_ui.pushButton_play, SIGNAL(released()), this, SLOT(playClicked())); - - // Clicking Auto COR - connect(m_ui.pushButton_center_find, SIGNAL(released()), this, - SLOT(findCORClicked())); - - // image sequence scroll/slide: - connect(m_ui.horizontalScrollBar_img_stack, SIGNAL(valueChanged(int)), this, - SLOT(updateFromImagesSlider(int))); - - // changing CoR tool - connect(m_ui.comboBox_center_method, SIGNAL(currentIndexChanged(int)), this, - SLOT(autoCoRToolChanged(int))); - - // image rotation - connect(m_ui.comboBox_rotation, SIGNAL(currentIndexChanged(int)), this, - SLOT(rotationUpdated(int))); - - // image type - connect(m_ui.comboBox_image_type, SIGNAL(currentIndexChanged(int)), this, - SLOT(imageTypeUpdated(int))); - - // parameter (points) widgets - connect(m_ui.spinBox_cor_x, SIGNAL(valueChanged(int)), this, - SLOT(valueUpdatedCoR(int))); - connect(m_ui.spinBox_cor_y, SIGNAL(valueChanged(int)), this, - SLOT(valueUpdatedCoR(int))); - - connect(m_ui.spinBox_roi_right, SIGNAL(valueChanged(int)), this, - SLOT(valueUpdatedROI(int))); - connect(m_ui.spinBox_roi_top, SIGNAL(valueChanged(int)), this, - SLOT(valueUpdatedROI(int))); - connect(m_ui.spinBox_roi_left, SIGNAL(valueChanged(int)), this, - SLOT(valueUpdatedROI(int))); - connect(m_ui.spinBox_roi_bottom, SIGNAL(valueChanged(int)), this, - SLOT(valueUpdatedROI(int))); - - connect(m_ui.spinBox_norm_right, SIGNAL(valueChanged(int)), this, - SLOT(valueUpdatedNormArea(int))); - connect(m_ui.spinBox_norm_top, SIGNAL(valueChanged(int)), this, - SLOT(valueUpdatedNormArea(int))); - connect(m_ui.spinBox_norm_left, SIGNAL(valueChanged(int)), this, - SLOT(valueUpdatedNormArea(int))); - connect(m_ui.spinBox_norm_bottom, SIGNAL(valueChanged(int)), this, - SLOT(valueUpdatedNormArea(int))); - - // colors - connect(m_ui.colorBarWidget, SIGNAL(colorBarDoubleClicked()), this, - SLOT(loadColorMapRequest())); - - connect(m_ui.colorBarWidget, SIGNAL(changedColorRange(double, double, bool)), - this, SLOT(colorRangeChanged())); -} - -void TomographyROIViewQtWidget::readSettings() { - QSettings qs; - qs.beginGroup(QString::fromStdString(m_settingsGroup)); - - // Color bar widget settings - // The factory default would be "Gray.map" - const auto mapsDir = QString::fromStdString( - Mantid::Kernel::ConfigService::Instance().getString( - "colormaps.directory")); - const auto defMapFile = - QFileInfo(mapsDir).absoluteDir().filePath("Gamma1.map"); - const auto filepath = qs.value("colorbar-file", defMapFile).toString(); - m_ui.colorBarWidget->getColorMap().loadMap(filepath); - m_ui.colorBarWidget->updateColorMap(); - - m_ui.colorBarWidget->setScale(qs.value("colorbar-scale-type", 0).toInt()); - m_ui.colorBarWidget->setExponent( - qs.value("colorbar-power-exponent", 2.0).toDouble()); - m_ui.colorBarWidget->setAutoScale( - qs.value("colorbar-autoscale", false).toBool()); - // ColorBarWidget doesn't support setting "AutoColorScaleforCurrentSlice" - // qsetting: "colorbar-autoscale-current-slice" - - restoreGeometry(qs.value("interface-win-geometry").toByteArray()); - qs.endGroup(); -} - -void TomographyROIViewQtWidget::saveSettings() const { - QSettings qs; - qs.beginGroup(QString::fromStdString(m_settingsGroup)); - - // Color bar widget settings - qs.setValue("colorbar-file", - m_ui.colorBarWidget->getColorMap().getFilePath()); - qs.setValue("colorbar-scale-type", m_ui.colorBarWidget->getScale()); - qs.setValue("colorbar-power-exponent", m_ui.colorBarWidget->getExponent()); - qs.setValue("colorbar-autoscale", m_ui.colorBarWidget->getAutoScale()); - qs.setValue("colorbar-autoscale-current-slice", - m_ui.colorBarWidget->getAutoScaleforCurrentSlice()); - - qs.setValue("interface-win-geometry", saveGeometry()); - qs.endGroup(); -} - -ImageStackPreParams TomographyROIViewQtWidget::userSelection() const { - return m_params; -} - -void TomographyROIViewQtWidget::changeSelectionState( - const ITomographyROIView::SelectionState &state) { - m_selectionState = state; -} - -void TomographyROIViewQtWidget::showStack(const std::string & /*path*/) { - // TODO: - // a) load as proper stack of images workspace - this can only be done when - // we have a first working version of the "lean MD workspace". This method - // would then load into one workspace of such type. - // b) load as workspace group - this is done in the overloaded method below - - // enableParamWidgets(true); -} - -void TomographyROIViewQtWidget::showStack( - const Mantid::API::WorkspaceGroup_sptr &wsg, - const Mantid::API::WorkspaceGroup_sptr &wsgFlats, - const Mantid::API::WorkspaceGroup_sptr &wsgDarks) { - if (0 == wsg->size()) - return; - - m_stackSamples = wsg; - m_stackFlats = wsgFlats; - m_stackDarks = wsgDarks; - - resetWidgetsOnNewStack(); - - size_t width = 0, height = 0; - try { - MatrixWorkspace_sptr ws = - boost::dynamic_pointer_cast<MatrixWorkspace>(wsg->getItem(0)); - if (!ws) - return; - width = ws->blocksize(); - height = ws->getNumberHistograms(); - } catch (std::exception &e) { - QMessageBox::warning(this, "Cannot load image information", - "There was a problem while " - " trying to find the size of the image: " + - QString::fromStdString(e.what())); - } - - showProjection(m_stackSamples, 0); - initParamWidgets(width, height); - refreshImage(); - enableParamWidgets(true); - enableImageTypes(wsg && wsg->size() > 0, wsgFlats && wsgFlats->size() > 0, - wsgDarks && wsgDarks->size() > 0); -} - -void TomographyROIViewQtWidget::showProjection( - const Mantid::API::WorkspaceGroup_sptr &wsg, size_t idx) { - - m_params.rotation = 0; - m_ui.comboBox_rotation->setCurrentIndex(0); - showProjectionImage(wsg, idx, 0); - - // give name, set up scroll/slider - std::string name; - try { - MatrixWorkspace_sptr ws = - boost::dynamic_pointer_cast<MatrixWorkspace>(wsg->getItem(idx)); - if (!ws) - return; - name = ws->run().getLogData("run_title")->value(); - } catch (std::exception &e) { - QMessageBox::warning(this, "Cannot load image information", - "There was a problem while " - " trying to find the name of the image: " + - QString::fromStdString(e.what())); - } - m_ui.label_img_name->setText(QString::fromStdString(name)); - - const size_t numPics = wsg->size(); - m_ui.lineEdit_img_seq->setText( - QString::fromStdString("1/" + boost::lexical_cast<std::string>(numPics))); - m_ui.horizontalScrollBar_img_stack->setValue(static_cast<int>(idx)); -} - -void TomographyROIViewQtWidget::userWarning(const std::string &err, - const std::string &description) { - QMessageBox::warning(this, QString::fromStdString(err), - QString::fromStdString(description), QMessageBox::Ok, - QMessageBox::Ok); -} - -void TomographyROIViewQtWidget::userError(const std::string &err, - const std::string &description) { - QMessageBox::critical(this, QString::fromStdString(err), - QString::fromStdString(description), QMessageBox::Ok, - QMessageBox::Ok); -} - -void TomographyROIViewQtWidget::enableActions(bool enable) { - m_ui.pushButton_browse_img->setEnabled(enable); - m_ui.pushButton_browse_stack->setEnabled(enable); - m_ui.pushButton_play->setEnabled(enable); - m_ui.pushButton_center_find->setEnabled(enable); - - m_ui.colorBarWidget->setEnabled(enable); - - m_ui.comboBox_center_method->setEnabled(enable); - m_ui.comboBox_image_type->setEnabled(enable); - m_ui.comboBox_rotation->setEnabled(enable); - m_ui.groupBox_cor->setEnabled(enable); - m_ui.groupBox_roi->setEnabled(enable); - m_ui.groupBox_norm->setEnabled(enable); -} - -std::string TomographyROIViewQtWidget::askImagePath( - const std::string &windowTitle = "Open image") { - // only FITS is supported right now - QString fitsStr = QString("Supported formats: FITS" - "(*.fits *.fit);;" - "FITS, Flexible Image Transport System images " - "(*.fits *.fit);;"); - QString prevPath = - MantidQt::API::AlgorithmInputHistory::Instance().getPreviousDirectory(); - QString filepath(QFileDialog::getOpenFileName(this, tr(windowTitle.c_str()), - prevPath, fitsStr)); - if (!filepath.isEmpty()) { - MantidQt::API::AlgorithmInputHistory::Instance().setPreviousDirectory( - filepath); - } - - return filepath.toStdString(); -} - -void TomographyROIViewQtWidget::enableImageTypes(bool enableSamples, - bool enableFlats, - bool enableDarks) { - QComboBox *itypes = m_ui.comboBox_image_type; - if (!itypes || 3 != itypes->count()) - return; - - std::vector<bool> enable = {enableSamples, enableFlats, enableDarks}; - for (size_t idx = 0; idx < enable.size(); idx++) { - QVariant var; - if (!enable[idx]) { - var = 0; - } else { - var = 1 | 32; - } - // trick to display a combobox entry as a disabled/enabled row - QModelIndex modelIdx = itypes->model()->index(static_cast<int>(idx), 0); - itypes->model()->setData(modelIdx, var, Qt::UserRole - 1); - } -} - -void TomographyROIViewQtWidget::resetCoR() { - int midx = - (m_ui.spinBox_cor_x->minimum() + m_ui.spinBox_cor_x->maximum()) / 2; - m_ui.spinBox_cor_x->setValue(midx); - int midy = - (m_ui.spinBox_cor_y->minimum() + m_ui.spinBox_cor_y->maximum()) / 2; - m_ui.spinBox_cor_y->setValue(midy); -} - -void TomographyROIViewQtWidget::resetROI() { - m_ui.spinBox_roi_left->setValue(0); - m_ui.spinBox_roi_top->setValue(0); - m_ui.spinBox_roi_right->setValue(m_ui.spinBox_roi_right->maximum()); - m_ui.spinBox_roi_bottom->setValue(m_ui.spinBox_roi_bottom->maximum()); -} - -void TomographyROIViewQtWidget::resetNormArea() { - m_ui.spinBox_norm_right->setValue(0); - m_ui.spinBox_norm_top->setValue(0); - m_ui.spinBox_norm_left->setValue(0); - m_ui.spinBox_norm_bottom->setValue(0); -} - -void TomographyROIViewQtWidget::resetWidgetsOnNewStack() { - m_ui.horizontalScrollBar_img_stack->setEnabled(true); - m_ui.horizontalScrollBar_img_stack->setMinimum(0); - m_ui.horizontalScrollBar_img_stack->setMaximum( - static_cast<int>(m_stackSamples->size() - 1)); - m_ui.comboBox_rotation->setCurrentIndex(0); -} - -void TomographyROIViewQtWidget::valueUpdatedCoR(int) { - grabCoRFromWidgets(); - refreshImage(); -} - -void TomographyROIViewQtWidget::valueUpdatedROI(int) { - grabROIFromWidgets(); - refreshImage(); -} - -void TomographyROIViewQtWidget::valueUpdatedNormArea(int) { - grabNormAreaFromWidgets(); - refreshImage(); -} - -/** - * Parameter values from spin box widgets => coordinate parameters - * data member - */ -void TomographyROIViewQtWidget::grabCoRFromWidgets() { - m_params.cor = Mantid::Kernel::V2D(m_ui.spinBox_cor_x->value(), - m_ui.spinBox_cor_y->value()); -} - -void TomographyROIViewQtWidget::grabROIFromWidgets() { - m_params.roi = - std::make_pair(Mantid::Kernel::V2D(m_ui.spinBox_roi_right->value(), - m_ui.spinBox_roi_top->value()), - Mantid::Kernel::V2D(m_ui.spinBox_roi_left->value(), - m_ui.spinBox_roi_bottom->value())); -} - -void TomographyROIViewQtWidget::grabNormAreaFromWidgets() { - m_params.normalizationRegion = - std::make_pair(Mantid::Kernel::V2D(m_ui.spinBox_norm_right->value(), - m_ui.spinBox_norm_top->value()), - Mantid::Kernel::V2D(m_ui.spinBox_norm_left->value(), - m_ui.spinBox_norm_bottom->value())); -} - -/** - * Updates the image view with the current image index and selection - * of parameters (ROI, normalization area, CoR). This needs to be used - * for every event that modifies the current image and/or selection of - * parameters. - */ -void TomographyROIViewQtWidget::refreshImage() { - - const QPixmap *pp = m_ui.label_img->pixmap(); - if (!pp) - return; - - m_ui.label_img->setMaximumWidth(static_cast<int>(m_imgWidth)); - m_ui.label_img->setMaximumHeight(static_cast<int>(m_imgHeight)); - - QPixmap toDisplay(*m_basePixmap.get()); - QPainter painter(&toDisplay); - - drawCenterCrossSymbol(painter, m_params.cor); - - drawBoxROI(painter, m_params.roi.first, m_params.roi.second); - - drawBoxNormalizationRegion(painter, m_params.normalizationRegion.first, - m_params.normalizationRegion.second); - - m_ui.label_img->setPixmap(toDisplay); -} - -void TomographyROIViewQtWidget::refreshCoR() { - const QPixmap *pp = m_ui.label_img->pixmap(); - if (!pp) - return; - - grabCoRFromWidgets(); - - QPixmap toDisplay(*m_basePixmap.get()); - QPainter painter(&toDisplay); - drawCenterCrossSymbol(painter, m_params.cor); - - m_ui.label_img->setPixmap(toDisplay); -} - -void TomographyROIViewQtWidget::refreshROI() { - const QPixmap *pp = m_ui.label_img->pixmap(); - if (!pp) - return; - - grabROIFromWidgets(); - // TODO: display proper symbol - - // QPixmap const *pm = m_ui.label_img->pixmap(); - QPixmap toDisplay(*m_basePixmap.get()); - QPainter painter(&toDisplay); - drawBoxROI(painter, m_params.roi.first, m_params.roi.second); - - m_ui.label_img->setPixmap(toDisplay); -} - -void TomographyROIViewQtWidget::refreshNormArea() { - // TODO: display proper symbol - const QPixmap *pp = m_ui.label_img->pixmap(); - if (!pp) - return; - - grabNormAreaFromWidgets(); - - // QPixmap const *pm = m_ui.label_img->pixmap(); - QPixmap toDisplay(*m_basePixmap.get()); - QPainter painter(&toDisplay); - - drawBoxNormalizationRegion(painter, m_params.normalizationRegion.first, - m_params.normalizationRegion.second); - - m_ui.label_img->setPixmap(toDisplay); -} - -void TomographyROIViewQtWidget::drawCenterCrossSymbol( - QPainter &painter, const Mantid::Kernel::V2D ¢er) const { - // TODO: display settings / nicer symbol? - - QPen penCoR(Qt::red); - painter.setPen(penCoR); - painter.drawLine( - static_cast<int>(center.X() - 5), static_cast<int>(center.Y()), - static_cast<int>(center.X() + 5), static_cast<int>(center.Y())); - painter.drawLine( - static_cast<int>(center.X()), static_cast<int>(center.Y() - 5), - static_cast<int>(center.X()), static_cast<int>(center.Y() + 5)); -} - -void TomographyROIViewQtWidget::drawBoxROI( - QPainter &painter, const Mantid::Kernel::V2D &first, - const Mantid::Kernel::V2D &second) const { - QPen penROI(Qt::green); - painter.setPen(penROI); - painter.drawRect(static_cast<int>(first.X()), static_cast<int>(first.Y()), - static_cast<int>(second.X() - first.X()), - static_cast<int>(second.Y() - first.Y())); -} - -void TomographyROIViewQtWidget::drawBoxNormalizationRegion( - QPainter &painter, const Mantid::Kernel::V2D &first, - const Mantid::Kernel::V2D &second) const { - QPen penNA(Qt::yellow); - painter.setPen(penNA); - painter.drawRect(static_cast<int>(first.X()), static_cast<int>(first.Y()), - static_cast<int>(second.X() - first.X()), - static_cast<int>(second.Y() - first.Y())); -} - -void TomographyROIViewQtWidget::enableParamWidgets(bool enable) { - m_ui.comboBox_image_type->setEnabled(enable); - m_ui.comboBox_rotation->setEnabled(enable); - - m_ui.groupBox_cor->setEnabled(enable); - m_ui.groupBox_roi->setEnabled(enable); - m_ui.groupBox_norm->setEnabled(enable); -} - -void TomographyROIViewQtWidget::initParamWidgets(size_t maxWidth, - size_t maxHeight) { - m_imgWidth = static_cast<int>(maxWidth); - m_imgHeight = static_cast<int>(maxHeight); - - m_ui.spinBox_cor_x->setMinimum(0); - m_ui.spinBox_cor_x->setMaximum(m_imgWidth - 1); - m_ui.spinBox_cor_y->setMinimum(0); - m_ui.spinBox_cor_y->setMaximum(m_imgHeight - 1); - resetCoR(); - - m_ui.spinBox_roi_right->setMinimum(0); - m_ui.spinBox_roi_right->setMaximum(m_imgWidth - 1); - m_ui.spinBox_roi_top->setMinimum(0); - m_ui.spinBox_roi_top->setMaximum(m_imgHeight - 1); - - m_ui.spinBox_roi_left->setMinimum(0); - m_ui.spinBox_roi_left->setMaximum(m_imgWidth - 1); - m_ui.spinBox_roi_bottom->setMinimum(0); - m_ui.spinBox_roi_bottom->setMaximum(m_imgHeight - 1); - - resetROI(); - - m_ui.spinBox_norm_right->setMinimum(0); - m_ui.spinBox_norm_right->setMaximum(m_imgWidth - 1); - m_ui.spinBox_norm_top->setMinimum(0); - m_ui.spinBox_norm_top->setMaximum(m_imgHeight - 1); - - m_ui.spinBox_norm_left->setMinimum(0); - m_ui.spinBox_norm_left->setMaximum(m_imgWidth - 1); - m_ui.spinBox_norm_bottom->setMinimum(0); - m_ui.spinBox_norm_bottom->setMaximum(m_imgHeight - 1); - - resetNormArea(); -} - -void TomographyROIViewQtWidget::setParamWidgets(ImageStackPreParams ¶ms) { - if (params.rotation > 0 && params.rotation <= 360) { - m_ui.comboBox_rotation->setCurrentIndex( - static_cast<int>(params.rotation / 90.0f) % 4); - } else { - m_ui.comboBox_rotation->setCurrentIndex(0); - } - - m_ui.spinBox_cor_x->setValue(static_cast<int>(params.cor.X())); - m_ui.spinBox_cor_y->setValue(static_cast<int>(params.cor.Y())); - - m_ui.spinBox_roi_right->setValue(static_cast<int>(params.roi.first.X())); - m_ui.spinBox_roi_top->setValue(static_cast<int>(params.roi.first.Y())); - - m_ui.spinBox_roi_left->setValue(static_cast<int>(params.roi.second.X())); - m_ui.spinBox_roi_bottom->setValue(static_cast<int>(params.roi.second.Y())); - - m_ui.spinBox_norm_right->setValue( - static_cast<int>(params.normalizationRegion.first.X())); - m_ui.spinBox_norm_top->setValue( - static_cast<int>(params.normalizationRegion.first.Y())); - - m_ui.spinBox_norm_left->setValue( - static_cast<int>(params.normalizationRegion.second.X())); - m_ui.spinBox_norm_bottom->setValue( - static_cast<int>(params.normalizationRegion.second.Y())); -} - -void TomographyROIViewQtWidget::corClicked() { - m_presenter->notify(ITomographyROIPresenter::SelectCoR); -} - -void TomographyROIViewQtWidget::corResetClicked() { - m_presenter->notify(ITomographyROIPresenter::ResetCoR); - refreshImage(); -} - -void TomographyROIViewQtWidget::roiClicked() { - m_presenter->notify(ITomographyROIPresenter::SelectROI); -} - -void TomographyROIViewQtWidget::roiResetClicked() { - m_presenter->notify(ITomographyROIPresenter::ResetROI); - refreshImage(); -} - -void TomographyROIViewQtWidget::normAreaClicked() { - m_presenter->notify(ITomographyROIPresenter::SelectNormalization); -} - -void TomographyROIViewQtWidget::normAreaResetClicked() { - m_presenter->notify(ITomographyROIPresenter::ResetNormalization); - refreshImage(); -} - -void TomographyROIViewQtWidget::playClicked() { - m_presenter->notify(ITomographyROIPresenter::PlayStartStop); -} - -void TomographyROIViewQtWidget::playStart() { - m_ui.pushButton_play->setText("Stop"); - // start timer - m_playTimer = Mantid::Kernel::make_unique<QTimer>(this); - connect(m_playTimer.get(), SIGNAL(timeout()), this, SLOT(updatePlay())); - m_playTimer->start(133); - m_ui.pushButton_play->setEnabled(true); -} - -void TomographyROIViewQtWidget::playStop() { - // stop timer - m_playTimer->stop(); - m_ui.pushButton_play->setText("Play"); -} - -void TomographyROIViewQtWidget::updatePlay() { - // TODO: maybe change to sample? Not obvious what would be users' - // preference - int val = m_ui.horizontalScrollBar_img_stack->value(); - ++val; - if (m_ui.horizontalScrollBar_img_stack->maximum() <= val) { - val = m_ui.horizontalScrollBar_img_stack->minimum(); - } - m_ui.horizontalScrollBar_img_stack->setValue(val); - showProjectionImage(m_stackSamples, val, currentRotationAngle()); -} - -void TomographyROIViewQtWidget::browseStackClicked() { - m_presenter->notify(ITomographyROIPresenter::BrowseStack); -} - -void TomographyROIViewQtWidget::browseImageClicked() { - m_presenter->notify(ITomographyROIPresenter::BrowseImage); -} - -void TomographyROIViewQtWidget::updateFromImagesSlider(int /* current */) { - m_presenter->notify(ITomographyROIPresenter::UpdateImgIndex); -} - -void TomographyROIViewQtWidget::imageTypeUpdated(int /* idx */) { - m_presenter->notify(TomographyROIPresenter::ChangeImageType); -} - -void TomographyROIViewQtWidget::rotationUpdated(int /* idx */) { - m_params.rotation = - static_cast<float>(m_ui.comboBox_rotation->currentIndex()) * 90.0f; - m_presenter->notify(TomographyROIPresenter::ChangeRotation); -} - -void TomographyROIViewQtWidget::autoCoRToolChanged(int /* idx */) { - // todo notify presenter that the tool is changed, however for now we only - // have one tool -> tomopy -} - -size_t TomographyROIViewQtWidget::currentImgIndex() const { - return m_ui.horizontalScrollBar_img_stack->value(); -} - -void TomographyROIViewQtWidget::updateImgWithIndex(size_t idx) { - int max = m_ui.horizontalScrollBar_img_stack->maximum(); - int current = m_ui.horizontalScrollBar_img_stack->value(); - - m_ui.lineEdit_img_seq->setText( - QString::fromStdString(boost::lexical_cast<std::string>(current + 1) + - "/" + boost::lexical_cast<std::string>(max + 1))); - - showProjectionImage(currentImageTypeStack(), idx, currentRotationAngle()); -} - -void TomographyROIViewQtWidget::showProjectionImage( - const Mantid::API::WorkspaceGroup_sptr &wsg, size_t idx, - float rotationAngle) { - - size_t width, height; - std::string imgName; - Mantid::API::MatrixWorkspace_sptr ws; - try { - checkNewProjectionImage(wsg, idx, width, height, ws, imgName); - } catch (std::runtime_error &rexc) { - QMessageBox::critical(this, "Cannot load image", - "There was a problem while trying to " - "find essential parameters of the image. Details: " + - QString::fromStdString(rexc.what())); - return; - } - - m_ui.label_img_name->setText(QString::fromStdString(imgName)); - // load / transfer image into a QImage, handling the rotation, width height - // consistently - QPixmap pixmap = transferWSImageToQPixmap(ws, width, height, rotationAngle); - - m_ui.label_img->setPixmap(pixmap); - m_ui.label_img->show(); - m_basePixmap.reset(new QPixmap(pixmap)); - - refreshImage(); -} - -/** - * Paint an image from a workspace (MatrixWorkspace) into a - * QPixmap. The QPixmap can then be display by for example setting - * it into a QLabel widget. - * - * @param ws image workspace - * - * @param width width of the image in pixels - * - * @param height height of the image in pixels - * - * @param rotationAngle rotate the image by this angle with respect to the - * original image in the workspace when displaying it - */ -QPixmap TomographyROIViewQtWidget::transferWSImageToQPixmap( - const MatrixWorkspace_sptr ws, size_t width, size_t height, - float rotationAngle) { - - QImage rawImg(QSize(static_cast<int>(width), static_cast<int>(height)), - QImage::Format_RGB32); - - double minVal = std::numeric_limits<double>::max(), - maxVal = std::numeric_limits<double>::min(); - // find min and max to scale pixel values, whether from user-given - // range, or auto-range - if (!m_ui.colorBarWidget->getAutoScale()) { - minVal = m_ui.colorBarWidget->getMinimum(); - maxVal = m_ui.colorBarWidget->getMaximum(); - } else { - - getPixelMinMax(ws, minVal, maxVal); - if (maxVal <= minVal) { - QMessageBox::warning( - this, "Empty image!", - "The image could be loaded but it contains " - "effectively no information, all pixels have the same value."); - // black picture - QPixmap pix(static_cast<int>(width), static_cast<int>(height)); - pix.fill(QColor(0, 0, 0)); - return pix; - } - m_ui.colorBarWidget->setViewRange(minVal, maxVal); - } - const double max_min = maxVal - minVal; - const double scaleFactor = 255.0 / max_min; - - // normal Qt rgb values - QwtDoubleInterval rgbInterval(0.0, 255.0); - const QVector<QRgb> colorTable = - m_ui.colorBarWidget->getColorMap().colorTable(rgbInterval); - rawImg.setColorTable(colorTable); - - for (size_t yi = 0; yi < width; ++yi) { - const auto &yvec = ws->readY(yi); - for (size_t xi = 0; xi < width; ++xi) { - const double &v = yvec[xi]; - const int scaled = static_cast<int>(scaleFactor * (v - minVal)); - // You would use this for a trivial mapping of valus to colors: - // Coloring the range min-max in gray scale. But setColorTable() - // is used to apply different color maps from files QRgb vRgb = - // qRgb(scaled, scaled, scaled); - // rawImg.setPixel(static_cast<int>(rotX), static_cast<int>(rotY), - // scaled); - size_t rotX = 0, rotY = 0; - if (0 == rotationAngle) { - rotX = xi; - rotY = yi; - } else if (90 == rotationAngle) { - rotX = height - (yi + 1); - rotY = xi; - } else if (180 == rotationAngle) { - rotX = width - (xi + 1); - rotY = height - (yi + 1); - } else if (270 == rotationAngle) { - rotX = yi; - rotY = width - (xi + 1); - } - - const auto rgb = - m_ui.colorBarWidget->getColorMap().rgb(rgbInterval, scaled); - rawImg.setPixel(static_cast<int>(rotX), static_cast<int>(rotY), rgb); - // This would be faster, using the look-up color table, but for unknown - // reasons MantidColorMap::colorTable forces linear scale. - // rawImg.setPixel(static_cast<int>(rotX), static_cast<int>(rotY), - // colorTable[scaled]); - } - } - - // paint image direct from QImage object - QPixmap pix = QPixmap::fromImage(rawImg); - // Alternative, drawing with a painter: - // QPixmap pix(static_cast<int>(width), static_cast<int>(height)); - // QPainter painter; - // painter.begin(&pix); - // painter.drawImage(0, 0, rawImg); - // painter.end(); - - return pix; -} - -/** - * Finds several parameters from an image in a stack (given the group - * of images and an index), checking for errors. This is meant to be - * used whenever a new image is going to be shown (for example when - * using the slider to go through a stack). - * - * @param wsg the group of images - * @param idx index of the image - * @param width width or number of columns (in pixels) - * @param height height or number of rows (in pixels) - * @param imgWS image workspace corresponding to the index given - * @param imgName name of the image (normally derived from the - * original filename) - * - * @throws runtime_error when unrecoverable errors are found (no - * data, issue with dimensions, etc.). - */ -void TomographyROIViewQtWidget::checkNewProjectionImage( - const Mantid::API::WorkspaceGroup_sptr &wsg, size_t idx, size_t &width, - size_t &height, Mantid::API::MatrixWorkspace_sptr &imgWS, - std::string &imgName) { - try { - imgWS = boost::dynamic_pointer_cast<MatrixWorkspace>(wsg->getItem(idx)); - if (!imgWS) - return; - } catch (std::exception &exc) { - throw std::runtime_error("Could not find the image data: " + - std::string(exc.what())); - } - - try { - getCheckedDimensions(imgWS, width, height); - } catch (std::runtime_error &rexc) { - throw std::runtime_error("Could not find the width of the image: " + - std::string(rexc.what())); - } - - try { - imgName = imgWS->run().getLogData("run_title")->value(); - } catch (std::exception &e) { - QMessageBox::warning( - this, "Cannot load image information", - "There was a problem while " - " trying to find the name (run_title log entry) of the image: " + - QString::fromStdString(e.what())); - } -} - -/** - * Gets the width and height of an image MatrixWorkspace. - * - * @param ws image workspace - * - * @param width width of the image in pixels (bins) - * - * @param height height of the image in pixels (histograms) - * - * @throws runtime_error if there are problems when retrieving the - * width/height or if they are inconsistent. - */ -void TomographyROIViewQtWidget::getCheckedDimensions( - const MatrixWorkspace_sptr ws, size_t &width, size_t &height) { - const size_t MAXDIM = 2048 * 32; - const std::string widthLogName = "Axis1"; - try { - width = boost::lexical_cast<size_t>( - ws->run().getLogData(widthLogName)->value()); - // TODO: add a settings option for this (like max mem allocation for - // images)? - if (width >= MAXDIM) - width = MAXDIM; - } catch (std::exception &exc) { - throw std::runtime_error( - "Could not find the width of the image from the run log data (entry: " + - widthLogName + "). Error: " + exc.what()); - } - - const std::string heightLogName = "Axis2"; - try { - height = boost::lexical_cast<size_t>( - ws->run().getLogData(heightLogName)->value()); - if (height >= MAXDIM) - height = MAXDIM; - } catch (std::exception &exc) { - throw std::runtime_error("could not find the height of the image from the " - "run log data (entry: " + - heightLogName + "). Error: " + exc.what()); - } - - // images are loaded as 1 histogram == 1 row (1 bin per image column): - size_t histos = ws->getNumberHistograms(); - size_t bins = ws->blocksize(); - if (height != histos || width != bins) { - throw std::runtime_error( - "Image dimensions do not match in the input image workspace. " - "Could not load the expected " - "number of rows and columns. The width and height found in the run log " - "data of the input files is: " + - std::to_string(width) + ", " + std::to_string(height) + - ", but the number of bins, histograms in " - "the workspace loaded is: " + - std::to_string(histos) + ", " + std::to_string(bins) + "."); - } -} - -void TomographyROIViewQtWidget::getPixelMinMax(MatrixWorkspace_sptr ws, - double &min, double &max) { - for (size_t i = 0; i < ws->getNumberHistograms(); ++i) { - for (size_t j = 0; j < ws->blocksize(); ++j) { - const double &v = ws->readY(i)[j]; - if (v < min) - min = v; - if (v > max) - max = v; - } - } -} - -float TomographyROIViewQtWidget::currentRotationAngle() const { - return m_params.rotation; -} - -void TomographyROIViewQtWidget::updateRotationAngle(float angle) { - if (angle < 0 || (0 != static_cast<int>(angle) % 90)) - return; - - m_params.rotation = angle; - m_ui.comboBox_rotation->setCurrentIndex( - static_cast<int>((static_cast<int>(angle) / 90) % 4)); - - showProjectionImage(currentImageTypeStack(), currentImgIndex(), - currentRotationAngle()); -} - -void TomographyROIViewQtWidget::updateImageType( - const Mantid::API::WorkspaceGroup_sptr wsg) { - if (!wsg || 0 == wsg->size()) - return; - - const int newIdx = 0; - m_ui.horizontalScrollBar_img_stack->setEnabled(true); - m_ui.horizontalScrollBar_img_stack->setMinimum(0); - m_ui.horizontalScrollBar_img_stack->setValue(newIdx); - m_ui.horizontalScrollBar_img_stack->setMaximum( - static_cast<int>(wsg->size() - 1)); - - const size_t numPics = wsg->size(); - m_ui.lineEdit_img_seq->setText( - QString::fromStdString("1/" + boost::lexical_cast<std::string>(numPics))); - - showProjectionImage(wsg, currentImgIndex(), currentRotationAngle()); -} - -Mantid::API::WorkspaceGroup_sptr -TomographyROIViewQtWidget::currentImageTypeStack() const { - int type = m_ui.comboBox_image_type->currentIndex(); - - if (1 == type) { - return m_stackFlats; - } else if (2 == type) { - return m_stackDarks; - } else { - return m_stackSamples; - } -} - -/** - * Qt events filter for the mouse click and click&drag events that are - * used to select points and rectangles. Part of the logic of the - * selection is handled here. The test on the presenter can only test - * the begin and end of the selection. For full testability (including - * the mouse interaction), this method should be implemented fully in - * terms of notifications to the presenter. This would require a bunch - * of new notifications in ITomographyROIPresenter, and making at least all - * the mouseUpdateCoR, mouseUpdateROICorners12, mouseXXX methods - * public in this view interface. This can be considered at a later - * stage. - * - * @param obj object concerned by the event - * @param event event received (mouse click, release, move, etc.) - **/ -bool TomographyROIViewQtWidget::eventFilter(QObject *obj, QEvent *event) { - // quick ignore - if (ITomographyROIView::SelectNone == m_selectionState) - return false; - - if (m_ui.label_img == obj) { - - QPoint p = m_ui.label_img->mapFromGlobal(QCursor::pos()); - int x = p.x(); - int y = p.y(); - // ignore potential clicks outside of the image - if (x >= m_imgWidth || y >= m_imgHeight || x < 0 || y < 0) - return false; - - auto type = event->type(); - if (type == QEvent::MouseButtonPress) { - - if (ITomographyROIView::SelectCoR == m_selectionState) { - mouseUpdateCoR(x, y); - } else if (ITomographyROIView::SelectROIFirst == m_selectionState) { - mouseUpdateROICornersStartSelection(x, y); - } else if (ITomographyROIView::SelectNormAreaFirst == m_selectionState) { - mouseUpdateNormAreaCornersStartSelection(x, y); - } - - } else if (type == QEvent::MouseMove) { - - if (ITomographyROIView::SelectROISecond == m_selectionState) { - mouseUpdateROICornerContinuedSelection(x, y); - } else if (ITomographyROIView::SelectNormAreaSecond == m_selectionState) { - mouseUpdateNormAreaCornerContinuedSelection(x, y); - } - } else if (type == QEvent::MouseButtonRelease) { - - if (ITomographyROIView::SelectROISecond == m_selectionState) { - mouseFinishROI(x, y); - } else if (ITomographyROIView::SelectNormAreaSecond == m_selectionState) { - mouseFinishNormArea(x, y); - } - } - } - // pass on the event up to the parent class - return false; -} - -/** - * Parameter values from mouse position (at a relevant event like - * first click, or last release) => spin box widgets, AND coordinate - * parameters data member. This grabs the Center of Rotation (CoR) - * - * @param x position on x axis (local to the image) - * @param y position on y axis (local to the image) - */ -void TomographyROIViewQtWidget::grabCoRFromMousePoint(const int x, - const int y) { - // m_params.cor = Mantid::Kernel::V2D(x, y); - m_ui.spinBox_cor_x->setValue(x); - m_ui.spinBox_cor_y->setValue(y); -} - -void TomographyROIViewQtWidget::grabROICorner1FromMousePoint(const int x, - const int y) { - // this is re-used for Norm Region selection as you cannot be selecting both - // at the same time - m_startOfRectangle.right = x; - m_startOfRectangle.top = y; - - m_ui.spinBox_roi_right->setValue(x); - m_ui.spinBox_roi_top->setValue(y); -} - -void TomographyROIViewQtWidget::grabROICorner2FromMousePoint(const int x, - const int y) { - updateValuesForSpinBoxes(x, y, m_startOfRectangle, m_ui.spinBox_roi_left, - m_ui.spinBox_roi_top, m_ui.spinBox_roi_right, - m_ui.spinBox_roi_bottom); -} - -void TomographyROIViewQtWidget::grabNormAreaCorner1FromMousePoint(const int x, - const int y) { - // this is re-used for Norm Region selection as you cannot be selecting both - // at the same time - m_startOfRectangle.right = x; - m_startOfRectangle.top = y; - - m_ui.spinBox_norm_right->setValue(x); - m_ui.spinBox_norm_top->setValue(y); -} - -void TomographyROIViewQtWidget::grabNormAreaCorner2FromMousePoint(const int x, - const int y) { - - updateValuesForSpinBoxes(x, y, m_startOfRectangle, m_ui.spinBox_norm_left, - m_ui.spinBox_norm_top, m_ui.spinBox_norm_right, - m_ui.spinBox_norm_bottom); -} - -void TomographyROIViewQtWidget::updateValuesForSpinBoxes( - const int x, const int y, const RectangleXY startPositions, - QSpinBox *spinLeft, QSpinBox *spinTop, QSpinBox *spinRight, - QSpinBox *spinBottom) { - - // put at the top so that it has chance to fire before a setValue event - spinLeft->blockSignals(true); - spinTop->blockSignals(true); - spinRight->blockSignals(true); - spinBottom->blockSignals(true); - - int left = x; - int right = startPositions.right; - int bottom = y; - int top = startPositions.top; - - // left side is over the right one - if (left > right) { - std::swap(left, right); - } - - if (top > bottom) { - std::swap(top, bottom); - } - - spinLeft->setValue(left); - spinTop->setValue(top); - spinRight->setValue(right); - spinBottom->setValue(bottom); - - spinLeft->blockSignals(false); - spinTop->blockSignals(false); - spinRight->blockSignals(false); - spinBottom->blockSignals(false); -} - -/** - * This is an update and implicity a finish, as there's only one - * update for the CoR (single point-click). The coordinates count as - * usual in Qt widgets. Top-left is (0,0). - * - * @param x position on x axis (local to the image) - * @param y position on y axis (local to the image) - */ -void TomographyROIViewQtWidget::mouseUpdateCoR(const int x, const int y) { - grabCoRFromMousePoint(x, y); - refreshImage(); - - m_presenter->notify(ITomographyROIPresenter::FinishedCoR); -} - -/** - * Start of ROI selection (or first click after pushing "select - * ROI". The rectangle starts as a point from the mouse click. - * - * @param x position on x axis (local to the image) - * @param y position on y axis (local to the image) - */ -void TomographyROIViewQtWidget::mouseUpdateROICornersStartSelection( - const int x, const int y) { - grabROICorner1FromMousePoint(x, y); - grabROICorner2FromMousePoint(x, y); - refreshImage(); - m_selectionState = ITomographyROIView::SelectROISecond; -} - -/** - * Change the rectangle while pressing the mouse button. The first - * corner stays at the first click, now only the second corner changes - * to the new mouse position. On release of the mouse button we'll get - * to mouseFinishROICorner2() and end the selection of the ROI. - * - * @param x position on x axis (local to the image) - * @param y position on y axis (local to the image) - */ -void TomographyROIViewQtWidget::mouseUpdateROICornerContinuedSelection( - const int x, const int y) { - grabROICorner2FromMousePoint(x, y); - grabROIFromWidgets(); - refreshImage(); -} - -/** - * End of ROI selection (or mouse button release after clicking once - * and move, all after pushing "select ROI". The second corner of the - * rectangle is set at the current position. - * - * @param x position on x axis (local to the image) - * @param y position on y axis (local to the image) - */ -void TomographyROIViewQtWidget::mouseFinishROI(const int x, const int y) { - grabROICorner2FromMousePoint(x, y); - refreshImage(); - m_presenter->notify(ITomographyROIPresenter::FinishedROI); -} - -void TomographyROIViewQtWidget::mouseUpdateNormAreaCornersStartSelection( - const int x, const int y) { - grabNormAreaCorner1FromMousePoint(x, y); - grabNormAreaCorner2FromMousePoint(x, y); - refreshImage(); - m_selectionState = ITomographyROIView::SelectNormAreaSecond; -} - -void TomographyROIViewQtWidget::mouseUpdateNormAreaCornerContinuedSelection( - const int x, const int y) { - grabNormAreaCorner2FromMousePoint(x, y); - grabNormAreaFromWidgets(); - refreshImage(); -} - -void TomographyROIViewQtWidget::mouseFinishNormArea(const int x, const int y) { - grabNormAreaCorner2FromMousePoint(x, y); - refreshImage(); - m_presenter->notify(ITomographyROIPresenter::FinishedNormalization); -} - -/** - * Slot for the signal emitted by the color bar widget when the user - * requests a new color map. - */ -void TomographyROIViewQtWidget::loadColorMapRequest() { - m_presenter->notify(ITomographyROIPresenter::UpdateColorMap); -} - -std::string TomographyROIViewQtWidget::askColorMapFile() { - QString filename = MantidColorMap::loadMapDialog( - QString::fromStdString(m_colorMapFilename), this); - return filename.toStdString(); -} - -void TomographyROIViewQtWidget::updateColorMap(const std::string &filename) { - // Load from file - m_ui.colorBarWidget->getColorMap().loadMap(QString::fromStdString(filename)); - m_ui.colorBarWidget->updateColorMap(); - - // if (!m_colorMapFilename.empty()) - // updateColorMap(m_colorMapFilename); - m_ui.colorBarWidget->setViewRange(1, 65536); - - m_presenter->notify(ITomographyROIPresenter::ColorRangeUpdated); -} - -/** - * Slot for the signal emitted by the color bar widget when there's an - * update in the values - */ -void TomographyROIViewQtWidget::colorRangeChanged() { - // the presenter should handle the image display update - m_presenter->notify(ITomographyROIPresenter::ColorRangeUpdated); -} - -void TomographyROIViewQtWidget::closeEvent(QCloseEvent *event) { - m_presenter->notify(ITomographyROIPresenter::ShutDown); - event->accept(); -} - -void TomographyROIViewQtWidget::readCoRFromProcessOutput(const QString &str) { - if (str.isEmpty()) { - // the process string is empty, it is likely the process crashed or was - // unable to execute properly - return; - } - - // The COR will be printed on the last line of the output, and will be the - // only - // output on the line, the way we read it here, is to just the last line, - // starting from the back and going until the first new line. - // Cropping that out will be the COR that the script found. - // ........ other strings above ........ - // 145 - const std::string output = str.toStdString(); - - // -- to not be on the null character - auto back_iterator = --(output.cend()); - std::string cor_number; - for (; back_iterator != output.cbegin(); --back_iterator) { - if (*back_iterator == '\n') { - // found the last new line - cor_number = std::string(back_iterator + 1, output.cend()); - break; - } - } - int centreOfRotationValue = 0; - try { - centreOfRotationValue = std::stoi(cor_number); - } catch (std::invalid_argument &) { - // output centreOfRotationValue cannot be converted, do not change anything - // and just return - // silently - return; - } - m_ui.spinBox_cor_x->setValue(centreOfRotationValue); - // middle of image is ((bottom - top) / 2) - // center is (top location + middle) - int imageCentre = - m_ui.spinBox_roi_top->value() + - ((m_ui.spinBox_roi_bottom->value() - m_ui.spinBox_roi_top->value()) / 2); - - m_ui.spinBox_cor_y->setValue(imageCentre); - - // refresh all coordinate variables - grabCoRFromWidgets(); - grabROIFromWidgets(); - grabNormAreaFromWidgets(); - // redraw the image with the rectangles - refreshImage(); -} - -// TomographyROIViewQtWidget Signals -void TomographyROIViewQtWidget::findCORClicked() { - // this will run a --find-cor, empty executable path string signifies that - // the default external interpretor will be used - emit(findCORClickedSignal("", {"--find-cor"})); -} - -void TomographyROIViewQtWidget::imageOrStackLoaded(const std::string &path) { - emit(imageOrStackLoadedSignal(path)); -} -} // namespace CustomInterfaces -} // namespace MantidQt diff --git a/MantidQt/CustomInterfaces/src/Tomography/ToolConfig.cpp b/MantidQt/CustomInterfaces/src/Tomography/ToolConfig.cpp deleted file mode 100644 index 5ef6a0785a7..00000000000 --- a/MantidQt/CustomInterfaces/src/Tomography/ToolConfig.cpp +++ /dev/null @@ -1,85 +0,0 @@ -#include "MantidQtCustomInterfaces/Tomography/ToolConfigAstraToolbox.h" -#include "MantidQtCustomInterfaces/Tomography/ToolConfigCustom.h" -#include "MantidQtCustomInterfaces/Tomography/ToolConfigTomoPy.h" - -#include <boost/lexical_cast.hpp> - -namespace MantidQt { -namespace CustomInterfaces { - -// pairs of name-in-the-tool, human-readable-name -const std::vector< - std::pair<std::string, std::string>> ToolConfigTomoPy::g_tomopyMethods = { - std::make_pair("gridrec", "gridrec: Fourier grid reconstruction " - "algorithm (Dowd, 19999; Rivers, 2006)"), - std::make_pair("sirt", - "sirt: Simultaneous algebraic reconstruction technique"), - - std::make_pair("art", - "art: Algebraic reconstruction technique (Kak, 1998)"), - std::make_pair("bart", "bart: Block algebraic reconstruction technique."), - std::make_pair("fbp", "fbp: Filtered back-projection algorithm"), - std::make_pair("mlem", "mlem: Maximum-likelihood expectation maximization " - "algorithm (Dempster, 1977)"), - std::make_pair("osem", "osem: Ordered-subset expectation maximization " - "algorithm (Hudson, 1994)"), - std::make_pair("ospml_hybrid", - "ospml_hybrid: Ordered-subset penalized maximum " - "likelihood algorithm with weighted " - "linear and quadratic penalties"), - std::make_pair("ospml_quad", "ospml_quad: Ordered-subset penalized maximum " - "likelihood algorithm with quadratic " - "penalties"), - std::make_pair("pml_hybrid", - "pml_hybrid: Penalized maximum likelihood algorithm " - "with weighted linear and quadratic " - "penalties (Chang, 2004)"), - std::make_pair("pml_quad", "pml_quad: Penalized maximum likelihood " - "algorithm with quadratic penalty"), -}; - -ToolConfigTomoPy::ToolConfigTomoPy() - : TomoRecToolConfig(""), m_pathOut(""), m_pathDark(""), m_pathOpen(""), - m_pathSample("") {} - -ToolConfigTomoPy::ToolConfigTomoPy(const std::string &runnable, - const std::string &pathOut, - const std::string &pathDark, - const std::string &pathOpen, - const std::string &pathSample) - : TomoRecToolConfig(runnable), m_pathOut(pathOut), m_pathDark(pathDark), - m_pathOpen(pathOpen), m_pathSample(pathSample) {} - -std::string ToolConfigTomoPy::makeCmdLineOptions() const { - return "--input-path=" + m_pathSample + " --output-path=" + m_pathOut; -} - -ToolConfigAstraToolbox::ToolConfigAstraToolbox() - : TomoRecToolConfig(""), m_pathOut(""), m_pathDark(""), m_pathOpen(""), - m_pathSample("") {} - -ToolConfigAstraToolbox::ToolConfigAstraToolbox(const std::string &runnable, - const std::string &pathOut, - const std::string &pathDark, - const std::string &pathOpen, - const std::string &pathSample) - : TomoRecToolConfig(runnable), m_pathOut(pathOut), m_pathDark(pathDark), - m_pathOpen(pathOpen), m_pathSample(pathSample) {} - -std::string ToolConfigAstraToolbox::makeCmdLineOptions() const { - return " --input-path=" + m_pathSample + " --output-path=" + m_pathOut; -} - -const std::vector<std::pair< - std::string, std::string>> ToolConfigAstraToolbox::g_astraMethods = { - std::make_pair("FBP3D_CUDA", "FBP 3D: Filtered Back-Propagation"), - std::make_pair( - "SIRT3D_CUDA", - "SIRT 3D: Simultaneous Iterative Reconstruction Technique algorithm"), - std::make_pair("CGLS3D_CUDA", - "CGLS 3D: Conjugate gradient least square algorithm"), - std::make_pair("FDK_CUDA", "FDK 3D: Feldkamp-Davis-Kress algorithm for " - "3D circular cone beam data sets")}; - -} // namespace CustomInterfaces -} // namespace MantidQt diff --git a/MantidQt/CustomInterfaces/test/ImggFormatsConvertPresenterTest.h b/MantidQt/CustomInterfaces/test/ImggFormatsConvertPresenterTest.h deleted file mode 100644 index fa5c6eaf5cc..00000000000 --- a/MantidQt/CustomInterfaces/test/ImggFormatsConvertPresenterTest.h +++ /dev/null @@ -1,108 +0,0 @@ -#ifndef MANTID_CUSTOMINTERFACES_IMGGFORMATSCONVERTPRESENTERTEST_H -#define MANTID_CUSTOMINTERFACES_IMGGFORMATSCONVERTPRESENTERTEST_H - -#include "MantidAPI/FrameworkManager.h" -#include "MantidQtCustomInterfaces/Tomography/ImggFormatsConvertPresenter.h" - -#include <cxxtest/TestSuite.h> -#include "ImggFormatsConvertViewMock.h" - -using namespace MantidQt::CustomInterfaces; -using testing::TypedEq; -using testing::Return; - -class ImggFormatsConvertPresenterTest : public CxxTest::TestSuite { - -public: - // This pair of boilerplate methods prevent the suite being created statically - // This means the constructor isn't called when running other tests - static ImggFormatsConvertPresenterTest *createSuite() { - return new ImggFormatsConvertPresenterTest(); - } - - static void destroySuite(ImggFormatsConvertPresenterTest *suite) { - delete suite; - } - - ImggFormatsConvertPresenterTest() { - Mantid::API::FrameworkManager::Instance(); // make sure framework is - // initialized - } - - void setUp() override { - m_view.reset(new testing::NiceMock<ImggFormatsConvertViewMock>()); - m_presenter.reset( - new MantidQt::CustomInterfaces::ImggFormatsConvertPresenter( - m_view.get())); - } - - void tearDown() override { - TS_ASSERT(testing::Mock::VerifyAndClearExpectations(m_view.get())); - } - - void test_init() { - testing::NiceMock<ImggFormatsConvertViewMock> mockView; - MantidQt::CustomInterfaces::ImggFormatsConvertPresenter pres(&mockView); - - EXPECT_CALL(mockView, setFormats(testing::_, testing::_, testing::_)) - .Times(1); - - // No errors, no warnings - EXPECT_CALL(mockView, userError(testing::_, testing::_)).Times(0); - EXPECT_CALL(mockView, userWarning(testing::_, testing::_)).Times(0); - - pres.notify(IImggFormatsConvertPresenter::Init); - TSM_ASSERT("Mock view not used as expected. Some EXPECT_CALL conditions " - "were not satisfied", - testing::Mock::VerifyAndClearExpectations(&mockView)); - } - - void test_convertFails() { - testing::NiceMock<ImggFormatsConvertViewMock> mockView; - MantidQt::CustomInterfaces::ImggFormatsConvertPresenter pres(&mockView); - - EXPECT_CALL(mockView, inputPath()).Times(1).WillRepeatedly(Return("")); - EXPECT_CALL(mockView, outputPath()).Times(1).WillRepeatedly(Return("")); - EXPECT_CALL(mockView, maxSearchDepth()).Times(1).WillRepeatedly(Return(3)); - // should not get there - EXPECT_CALL(mockView, inputFormatName()).Times(0); - EXPECT_CALL(mockView, outputFormatName()).Times(0); - - // empty paths should produce an error - EXPECT_CALL(mockView, userError(testing::_, testing::_)).Times(1); - EXPECT_CALL(mockView, userWarning(testing::_, testing::_)).Times(0); - - pres.notify(IImggFormatsConvertPresenter::Convert); - TSM_ASSERT("Mock view not used as expected. Some EXPECT_CALL conditions " - "were not satisfied", - testing::Mock::VerifyAndClearExpectations(&mockView)); - } - - void test_shutDown() { - testing::NiceMock<ImggFormatsConvertViewMock> mockView; - MantidQt::CustomInterfaces::ImggFormatsConvertPresenter pres(&mockView); - - EXPECT_CALL(mockView, saveSettings()).Times(1); - - // No errors, no warnings - EXPECT_CALL(mockView, userError(testing::_, testing::_)).Times(0); - EXPECT_CALL(mockView, userWarning(testing::_, testing::_)).Times(0); - - pres.notify(IImggFormatsConvertPresenter::ShutDown); - TSM_ASSERT("Mock view not used as expected. Some EXPECT_CALL conditions " - "were not satisfied", - testing::Mock::VerifyAndClearExpectations(&mockView)); - } - -private: - std::unique_ptr<testing::NiceMock<ImggFormatsConvertViewMock>> m_view; - - std::unique_ptr<MantidQt::CustomInterfaces::ImggFormatsConvertPresenter> - m_presenter; - // To have one FITS, etc. - Mantid::API::MatrixWorkspace_sptr m_ws; - static std::string g_scarfName; - static std::string g_ccpi; -}; - -#endif // MANTID_CUSTOMINTERFACES_IMGGFORMATSCONVERTPRESENTERTEST_H diff --git a/MantidQt/CustomInterfaces/test/ImggFormatsConvertViewMock.h b/MantidQt/CustomInterfaces/test/ImggFormatsConvertViewMock.h deleted file mode 100644 index 497be107528..00000000000 --- a/MantidQt/CustomInterfaces/test/ImggFormatsConvertViewMock.h +++ /dev/null @@ -1,74 +0,0 @@ -#ifndef MANTID_CUSTOMINTERFACES_IMGGFORMATSCONVERTVIEWMOCK_H -#define MANTID_CUSTOMINTERFACES_IMGGFORMATSCONVERTVIEWMOCK_H - -#include "MantidAPI/MatrixWorkspace_fwd.h" -#include "MantidKernel/WarningSuppressions.h" -#include "MantidQtCustomInterfaces/Tomography/IImggFormatsConvertView.h" - -#include <gmock/gmock.h> - -GCC_DIAG_OFF_SUGGEST_OVERRIDE - -// This is a simple mock for the tomo interface view when using SCARF. -class ImggFormatsConvertViewMock - : public MantidQt::CustomInterfaces::IImggFormatsConvertView { -public: - // void userWarning(const std::string &warn, const std::string &description) - MOCK_METHOD2(userWarning, - void(const std::string &warn, const std::string &description)); - - // void userError(const std::string &err, const std::string &description) - MOCK_METHOD2(userError, - void(const std::string &err, const std::string &description)); - - // void setFormats(const std::vector<std::string> &fmts, - // std::vector<bool> &enableLoad, std::vector<bool> &enableSave) - MOCK_METHOD3(setFormats, void(const std::vector<std::string> &fmts, - const std::vector<bool> &enableLoad, - const std::vector<bool> &enableSave)); - - // std::string inputPath() const - MOCK_CONST_METHOD0(inputPath, std::string()); - - // std::string inputFormatName() const - MOCK_CONST_METHOD0(inputFormatName, std::string()); - - // std::string outputPath() const - MOCK_CONST_METHOD0(outputPath, std::string()); - - // std::string outputFormatName() const - MOCK_CONST_METHOD0(outputFormatName, std::string()); - - // bool compressHint() const - MOCK_CONST_METHOD0(compressHint, bool()); - - // void convert(const std::string &inputName, const std::string - // &inputFormat, const std::string &outputName, const std::string - // &outputFormat) const - MOCK_CONST_METHOD4(convert, void(const std::string &inputName, - const std::string &inputFormat, - const std::string &outputName, - const std::string &outputFormat)); - - // void writeImg(MatrixWorkspace_sptr inWks, const std::string - // &outputName, const std::string &outFormat) const - - MOCK_CONST_METHOD3(writeImg, void(Mantid::API::MatrixWorkspace_sptr inWks, - const std::string &outputName, - const std::string &outFormat)); - - // MatrixWorkspace_sptr loadImg(const std::string &inputName, const - // std::string &inputFormat) const - MOCK_CONST_METHOD2( - loadImg, Mantid::API::MatrixWorkspace_sptr(const std::string &outputName, - const std::string &outFormat)); - - // size_t maxSearchDepth() const - MOCK_CONST_METHOD0(maxSearchDepth, size_t()); - - // void saveSettings() const - MOCK_CONST_METHOD0(saveSettings, void()); -}; - -GCC_DIAG_ON_SUGGEST_OVERRIDE -#endif // MANTID_CUSTOMINTERFACES_IMGGFORMATSCONVERTVIEWMOCK_H diff --git a/MantidQt/CustomInterfaces/test/StackOfImagesDirsTest.h b/MantidQt/CustomInterfaces/test/StackOfImagesDirsTest.h deleted file mode 100644 index 803eaece6bb..00000000000 --- a/MantidQt/CustomInterfaces/test/StackOfImagesDirsTest.h +++ /dev/null @@ -1,111 +0,0 @@ -#ifndef MANTID_CUSTOMINTERFACES_STACKOFIMAGESDIRSTEST_H -#define MANTID_CUSTOMINTERFACES_STACKOFIMAGESDIRSTEST_H - -#include "MantidAPI/FrameworkManager.h" -#include "MantidQtCustomInterfaces/Tomography/StackOfImagesDirs.h" - -#include <boost/scoped_ptr.hpp> - -#include <cxxtest/TestSuite.h> - -using namespace MantidQt::CustomInterfaces; - -class StackOfImagesDirsTest : public CxxTest::TestSuite { - -public: - // This pair of boilerplate methods prevent the suite being created statically - // This means the constructor isn't called when running other tests - static StackOfImagesDirsTest *createSuite() { - return new StackOfImagesDirsTest(); - } - - static void destroySuite(StackOfImagesDirsTest *suite) { delete suite; } - - StackOfImagesDirsTest() { - Mantid::API::FrameworkManager::Instance(); // make sure the framework is - // initialized - } - - void setUp() override { - // just to test more dynamic allocation - m_soid.reset(new StackOfImagesDirs("")); - } - - void tearDown() override {} - - void test_construct() { - StackOfImagesDirs obj(""); - - TSM_ASSERT("A stack just constructed with an empty path string should not " - "be valid", - !obj.isValid()); - } - - void test_description() { - StackOfImagesDirs obj(""); - - TS_ASSERT_THROWS_NOTHING(obj.description()); - TSM_ASSERT("A description string should be produced", - "" != obj.description()); - } - - void test_status() { - StackOfImagesDirs obj(""); - - TS_ASSERT_THROWS_NOTHING(obj.description()); - TSM_ASSERT("A status string should be produced", "" != obj.status()); - } - - void test_sampleImagesDir() { - StackOfImagesDirs obj(""); - - TS_ASSERT_THROWS_NOTHING(obj.description()); - TSM_ASSERT("The sample images directory of an empty stack should be empty", - "" == obj.sampleImagesDir()); - } - - void test_flatImagesDir() { - StackOfImagesDirs obj(""); - - TS_ASSERT_THROWS_NOTHING(obj.description()); - TSM_ASSERT("The flat images directory of an empty stack should be empty", - "" == obj.flatImagesDir()); - } - - void test_darkImagesDir() { - StackOfImagesDirs obj(""); - - TS_ASSERT_THROWS_NOTHING(obj.description()); - TSM_ASSERT("The dark images directory of an empty stack should be empty", - "" == obj.flatImagesDir()); - } - - void test_sampleFiles() { - StackOfImagesDirs obj(""); - - TS_ASSERT_THROWS_NOTHING(obj.description()); - TSM_ASSERT("There should not be any sample files in an empty stack", - 0 == obj.sampleImagesDir().size()); - } - - void test_flatFiles() { - StackOfImagesDirs obj(""); - - TS_ASSERT_THROWS_NOTHING(obj.description()); - TSM_ASSERT("There should not be any flat image files in an empty stack", - 0 == obj.flatImagesDir().size()); - } - - void test_darkFiles() { - StackOfImagesDirs obj(""); - - TS_ASSERT_THROWS_NOTHING(obj.description()); - TSM_ASSERT("There should not be any dark image files in an empty stack", - 0 == obj.darkImagesDir().size()); - } - -private: - boost::scoped_ptr<StackOfImagesDirs> m_soid; -}; - -#endif /* MANTID_CUSTOMINTERFACES_STACKOFIMAGESDIRSTEST_H */ diff --git a/MantidQt/CustomInterfaces/test/TomographyIfaceModelTest.h b/MantidQt/CustomInterfaces/test/TomographyIfaceModelTest.h deleted file mode 100644 index 8abf9d97d95..00000000000 --- a/MantidQt/CustomInterfaces/test/TomographyIfaceModelTest.h +++ /dev/null @@ -1,406 +0,0 @@ -#ifndef MANTID_CUSTOMINTERFACES_TOMOGRAPHYIFACEMODELTEST_H -#define MANTID_CUSTOMINTERFACES_TOMOGRAPHYIFACEMODELTEST_H - -#include "MantidAPI/FrameworkManager.h" -#include "MantidAPI/MatrixWorkspace.h" -#include "MantidKernel/ConfigService.h" -#include "MantidKernel/FacilityInfo.h" - -#include "MantidQtCustomInterfaces/Tomography/TomographyIfaceModel.h" - -#include "MantidQtCustomInterfaces/Tomography/TomoToolConfigDialogBase.h" - -#include <cxxtest/TestSuite.h> - -using namespace Mantid::API; -using namespace MantidQt::CustomInterfaces; - -class TomographyIfaceModelTest : public CxxTest::TestSuite { - -public: - // This pair of boilerplate methods prevent the suite being created statically - // This means the constructor isn't called when running other tests - static TomographyIfaceModelTest *createSuite() { - return new TomographyIfaceModelTest(); - } - - static void destroySuite(TomographyIfaceModelTest *suite) { delete suite; } - - TomographyIfaceModelTest() { - Mantid::API::FrameworkManager::Instance(); // make sure framework is - // initialized - } - - void test_noInit() { - auto model = Mantid::Kernel::make_unique<TomographyIfaceModel>(); - - TSM_ASSERT_EQUALS("Unexpected number of compute resources", - model->computeResources().size(), 2); - - TSM_ASSERT_EQUALS("Unexpected number of compute resources (status)", - model->computeResourcesStatus().size(), 0); - - TSM_ASSERT_EQUALS("Unexpected default tool", model->usingTool(), "TomoPy"); - - TSM_ASSERT_EQUALS("Unexpected name for local machine", - model->localComputeResource(), "Local"); - } - - void test_setupComputeResource() { - auto model = Mantid::Kernel::make_unique<TomographyIfaceModel>(); - - model->setupComputeResource(); - - TSM_ASSERT_EQUALS("Unexpected number of compute resources", - model->computeResources().size(), 2); - - auto status = model->computeResourcesStatus(); - TSM_ASSERT_EQUALS("Unexpected number of compute resources (status)", - status.size(), 2); - TSM_ASSERT("Unexpected status for first compute resource ", status[0]); - TSM_ASSERT("Unexpected status for second compute resource ", status[1]); - - TSM_ASSERT_THROWS_NOTHING("Problem in cleanup", model->cleanup()); - } - - void test_setupToolsDefaults() { - TomographyIfaceModel model; - - model.setupRunTool("Local"); - - TSM_ASSERT_EQUALS("Unexpected number of reconstruction tools", - model.reconTools().size(), 5); - - const auto status = model.reconToolsStatus(); - - const std::vector<bool> expected = {true, true, false, false, true}; - TSM_ASSERT_EQUALS("Unexpected number of reconstruction tools (status)", - status.size(), 5); - for (size_t idx = 0; idx < status.size(); ++idx) { - TSM_ASSERT("Unexpected status for tool number " + std::to_string(idx + 1), - status[idx] == expected[idx]); - } - } - - void test_facilities() { - TomographyIfaceModel model; - - // save original facility - const Mantid::Kernel::FacilityInfo &prevFac = - Mantid::Kernel::ConfigService::Instance().getFacility(); - - Mantid::Kernel::ConfigService::Instance().setFacility("ISIS"); - auto isSupported = model.facilitySupported(); - TSM_ASSERT("This facility should be supported", isSupported); - - const std::vector<std::string> otherFacilities = {"SNS", "HFIR", "ILL", - "ANSTO", "TEST_LIVE"}; - for (const auto &facility : otherFacilities) { - Mantid::Kernel::ConfigService::Instance().setFacility(facility); - TSM_ASSERT("This facility should not be supported", - !model.facilitySupported()); - } - - // restore facility - Mantid::Kernel::ConfigService::Instance().setFacility(prevFac.name()); - } - - void test_jobsStatus() { - TomographyIfaceModel model; - - model.setupComputeResource(); - model.setupRunTool("Local"); - - TSM_ASSERT_THROWS_NOTHING("Problem with experiment number", - model.setExperimentReference("RB0001234")); - - auto sts = model.jobsStatus(); - TSM_ASSERT_EQUALS("Unexpected number of jobs", sts.size(), 0); - - auto localSts = model.jobsStatusLocal(); - TSM_ASSERT_EQUALS("Unexpected number of jobs (local)", localSts.size(), 0); - - model.refreshLocalJobsInfo(); - localSts = model.jobsStatusLocal(); - TSM_ASSERT_EQUALS("Unexpected number of jobs (local), after refreshing", - localSts.size(), 0); - - model.doRefreshJobsInfo("phony"); - sts = model.jobsStatus(); - TSM_ASSERT_EQUALS("Unexpected number of jobs, after refreshing", sts.size(), - 0); - } - - void test_pingFail() { - TomographyIfaceModel model; - - TSM_ASSERT_THROWS("Exception not thrown as expected - ping local", - model.doPing("Local"), std::invalid_argument); - } - - void test_loginFail() { - TomographyIfaceModel model; - - TSM_ASSERT_EQUALS("Should not be logged in", model.loggedIn(), ""); - - TSM_ASSERT_THROWS("Exception not thrown as expected - login local", - model.doLogin("Local", "foo_user", "password"), - std::invalid_argument); - } - - void test_logoutFail() { - TomographyIfaceModel model; - - TSM_ASSERT_THROWS("Exception not thrown as expected - logout local", - model.doLogout("Local", "foo_user"), - std::invalid_argument); - } - - void test_queryFail() { - TomographyIfaceModel model; - - std::vector<std::string> ids; - std::vector<std::string> names; - std::vector<std::string> status; - std::vector<std::string> cmds; - TSM_ASSERT_THROWS("Exception not thrown as expected - ping local", - model.doQueryJobStatus("Local", ids, names, status, cmds), - std::invalid_argument); - TS_ASSERT_EQUALS(ids.size(), 0); - TS_ASSERT_EQUALS(names.size(), 0); - TS_ASSERT_EQUALS(status.size(), 0); - TS_ASSERT_EQUALS(cmds.size(), 0); - } - - void test_cancelFail() { - TomographyIfaceModel model; - - TSM_ASSERT_EQUALS("Should not be logged in", model.loggedIn(), ""); - - const std::vector<std::string> ids = {"none", "inexistent"}; - TSM_ASSERT_THROWS("Exception not thrown as expected - login local", - model.doCancelJobs("Local", ids), std::invalid_argument); - } - - void test_loadFITSFail() { - TomographyIfaceModel model; - - TSM_ASSERT_THROWS("Exception not thrown as expected - load FITS", - model.loadFITSImage("/i_dont_exist.nope"), - std::invalid_argument); - } - - // this currently just transforms the names to lower case - void test_prepareToolNameForArgs() { - - TestableTomographyIfaceModel model; - - const std::string exp1 = model.prepareToolNameForArgs("TomoPy"); - const std::string exp2 = model.prepareToolNameForArgs("Astra"); - const std::string exp3 = model.prepareToolNameForArgs("Savu"); - const std::string exp4 = model.prepareToolNameForArgs("Custom Command"); - - TS_ASSERT_EQUALS(exp1, "tomopy"); - TS_ASSERT_EQUALS(exp2, "astra"); - TS_ASSERT_EQUALS(exp3, "savu"); - TS_ASSERT_EQUALS(exp4, "custom command"); - // although custom command never reaches that function - } - - void test_makeRemoteRunnableWithOptionsCustom() { - std::string inputRunnable = "/scriptPath/"; - // the custom one just processes a single member - std::vector<std::string> inputArgsVector{ - "--some params --some other params"}; - - TestableTomographyIfaceModel model; - - std::string inputArgsString = - model.constructSingleStringFromVector(inputArgsVector); - - std::shared_ptr<TomoRecToolConfig> d = std::shared_ptr<TomoRecToolConfig>( - new ToolConfigCustom(inputRunnable, inputArgsString)); - - model.usingTool(TestableTomographyIfaceModel::g_customCmdTool); - model.setCurrentToolMethod("gridrec"); - - model.setCurrentToolSettings(d); - - const bool local = false; - - std::string actualRunnable; - std::string allOpts; - std::vector<std::string> actualArgsVector; - model.prepareSubmissionArguments(local, actualRunnable, actualArgsVector, - allOpts); - - std::string expectedRunnable = "/scriptPath/"; - // the space at the end is necessary, because of how - // constructSingleStringFromVector works - std::vector<std::string> expectedArgsVector{ - "--some params --some other params "}; - doTestExpectedRunnableAndArguments(expectedRunnable, actualRunnable, - expectedArgsVector, actualArgsVector); - } - - void test_makeLocalRunnableWithOptionsCustom() { - std::string inputRunnable = "python /scriptPath/"; - // the custom one just processes a single member - std::vector<std::string> inputArgsVector{ - "--some params --some other params"}; - - TestableTomographyIfaceModel model; - - std::string inputArgsString = - model.constructSingleStringFromVector(inputArgsVector); - - std::shared_ptr<TomoRecToolConfig> d = std::shared_ptr<TomoRecToolConfig>( - new ToolConfigCustom(inputRunnable, inputArgsString)); - - model.usingTool(TestableTomographyIfaceModel::g_customCmdTool); - model.setCurrentToolMethod("gridrec"); - - model.setCurrentToolSettings(d); - - const bool local = true; - - std::string actualRunnable; - std::string allOpts; - - std::vector<std::string> actualArgsVector; - model.prepareSubmissionArguments(local, actualRunnable, actualArgsVector, - allOpts); - - std::string expectedRunnable = "python"; - // the space at the end is necessary, because of how - // constructSingleStringFromVector works - std::vector<std::string> expectedArgsVector{ - "/scriptPath/", "--some params --some other params "}; - doTestExpectedRunnableAndArguments(expectedRunnable, actualRunnable, - expectedArgsVector, actualArgsVector); - } - - void test_makeRemoteRunnableWithOptions() { - std::string expectedRunnable = - "/work/imat/phase_commissioning/scripts/Imaging/" - "IMAT/tomo_reconstruct.py"; - TomoPathsConfig pathConfig; - - const std::string pathOut = "/work/imat"; - static size_t reconIdx = 1; - const std::string localOutNameAppendix = std::string("/processed/") + - "reconstruction_" + - std::to_string(reconIdx); - - std::shared_ptr<TomoRecToolConfig> d = std::shared_ptr<TomoRecToolConfig>( - new ToolConfigTomoPy(expectedRunnable, pathOut + localOutNameAppendix, - pathConfig.pathDarks(), pathConfig.pathOpenBeam(), - pathConfig.pathSamples())); - - TestableTomographyIfaceModel model; - - model.usingTool(TestableTomographyIfaceModel::g_TomoPyTool); - model.setCurrentToolMethod("gridrec"); - - model.setCurrentToolSettings(d); - - const bool local = false; - - std::string allOpts; - std::string actualRunnable; - std::vector<std::string> actualArgsVector; - model.prepareSubmissionArguments(local, actualRunnable, actualArgsVector, - allOpts); - - std::vector<std::string> expectedArgsVector{ - "--tool=tomopy", "--algorithm=gridrec", "--num-iter=5", - "--input-path=" + pathConfig.pathSamples(), - "--input-path-flat=" + pathConfig.pathOpenBeam(), - "--input-path-dark=" + pathConfig.pathDarks(), - "--output=\"/work/imat/phase_commissioning/processed/" - "reconstruction_TomoPy_gridrec_2016October20_113701_413275000", - "--median-filter-size=3", "--cor=0.000000", "--rotation=0", - "--max-angle=360.000000", "--circular-mask=0.940000", - "--out-img-format=png"}; - doTestExpectedRunnableAndArguments(expectedRunnable, actualRunnable, - expectedArgsVector, actualArgsVector); - } - - void test_makeLocalRunnableWithOptions() { - std::string inputRunnable = "python " - "/work/imat/phase_commissioning/scripts/" - "Imaging/IMAT/tomo_reconstruct.py"; - - TomoPathsConfig pathConfig; - const std::string pathOut = "~/imat/RB000XXX"; - static size_t reconIdx = 1; - const std::string localOutNameAppendix = std::string("/processed/") + - "reconstruction_" + - std::to_string(reconIdx); - - std::shared_ptr<TomoRecToolConfig> d = std::shared_ptr<TomoRecToolConfig>( - new ToolConfigTomoPy(inputRunnable, pathOut + localOutNameAppendix, - pathConfig.pathDarks(), pathConfig.pathOpenBeam(), - pathConfig.pathSamples())); - - TestableTomographyIfaceModel model; - - model.usingTool(TestableTomographyIfaceModel::g_TomoPyTool); - model.setCurrentToolMethod("gridrec"); - - model.setCurrentToolSettings(d); - - const bool local = true; - - // should be just the externalInterpretor path - std::string actualRunnable; - std::string allOpts; - std::vector<std::string> actualArgsVector; - model.prepareSubmissionArguments(local, actualRunnable, actualArgsVector, - allOpts); - - std::string expectedRunnable = "python"; - std::vector<std::string> expectedArgsVector{ - "/work/imat/phase_commissioning/scripts/Imaging/IMAT/" - "tomo_reconstruct.py", - "--tool=tomopy", "--algorithm=gridrec", "--num-iter=5", - "--input-path=/work/imat/phase_commissioning/data", - "--input-path-flat=/work/imat/phase_commissioning/flat", - "--input-path-dark=/work/imat/phase_commissioning/dark", - "--output=/work/imat/phase_commissioning/processed/" - "reconstruction_TomoPy_gridrec_2016October20_113701_413275000", - "--median-filter-size=3", "--cor=0.000000", "--rotation=0", - "--max-angle=360.000000", "--circular-mask=0.940000", - "--out-img-format=png"}; - - doTestExpectedRunnableAndArguments(expectedRunnable, actualRunnable, - expectedArgsVector, actualArgsVector); - } - -private: - // inner class to access the model's protected functions - class TestableTomographyIfaceModel : public TomographyIfaceModel { - friend class TomographyIfaceModelTest; - TestableTomographyIfaceModel() : TomographyIfaceModel() {} - }; - - void doTestExpectedRunnableAndArguments( - const std::string &expectedRunnable, const std::string &actualRunnable, - const std::vector<std::string> &expectedArguments, - const std::vector<std::string> &actualArguments) { - TSM_ASSERT_EQUALS("Local interpreter executable not properly separated", - actualRunnable, expectedRunnable); - TSM_ASSERT_EQUALS("Invalid argument size", expectedArguments.size(), - actualArguments.size()); - - for (size_t i = 0; i < expectedArguments.size(); ++i) { - // this is the --output one that varies depending on time, so just skip - if (expectedArguments[i].substr(0, 8) == "--output") { - continue; - } - TS_ASSERT_EQUALS(expectedArguments[i], actualArguments[i]); - } - } -}; - -#endif // MANTID_CUSTOMINTERFACES_TOMOGRAPHYIFACEMODELTEST_H diff --git a/MantidQt/CustomInterfaces/test/TomographyIfacePresenterTest.h b/MantidQt/CustomInterfaces/test/TomographyIfacePresenterTest.h deleted file mode 100644 index 5af4eff11e6..00000000000 --- a/MantidQt/CustomInterfaces/test/TomographyIfacePresenterTest.h +++ /dev/null @@ -1,732 +0,0 @@ -#ifndef MANTID_CUSTOMINTERFACES_TOMOGRAPHYIFACEPRESENTERTEST_H -#define MANTID_CUSTOMINTERFACES_TOMOGRAPHYIFACEPRESENTERTEST_H - -#include "MantidAPI/FrameworkManager.h" -#include "MantidAPI/MatrixWorkspace.h" -#include "MantidQtCustomInterfaces/Tomography/TomographyIfacePresenter.h" - -#include "TomographyViewMock.h" -#include <cxxtest/TestSuite.h> - -using namespace MantidQt::CustomInterfaces; -using testing::TypedEq; -using testing::Return; - -class TomographyIfacePresenterTest : public CxxTest::TestSuite { - -public: - // This pair of boilerplate methods prevent the suite being created statically - // This means the constructor isn't called when running other tests - static TomographyIfacePresenterTest *createSuite() { - return new TomographyIfacePresenterTest(); - } - - static void destroySuite(TomographyIfacePresenterTest *suite) { - delete suite; - } - - TomographyIfacePresenterTest() { - // make sure the framework is initialized - Mantid::API::FrameworkManager::Instance(); - } - - void setUp() override { - m_view.reset(new testing::NiceMock<MockTomographyIfaceView>()); - m_presenter.reset( - new MantidQt::CustomInterfaces::TomographyIfacePresenter(m_view.get())); - } - - void tearDown() override { - TS_ASSERT(testing::Mock::VerifyAndClearExpectations(m_view.get())); - } - - void test_setupSystemSettings() { - testing::NiceMock<MockTomographyIfaceView> mockView; - MantidQt::CustomInterfaces::TomographyIfacePresenter pres(&mockView); - - // system settings should be self-contained - no need for any of these: - EXPECT_CALL(mockView, currentPathsConfig()).Times(0); - EXPECT_CALL(mockView, enableLoggedActions(false)).Times(0); - EXPECT_CALL(mockView, setComputeResources(testing::_, testing::_)).Times(0); - EXPECT_CALL(mockView, setReconstructionTools(testing::_, testing::_)) - .Times(0); - - EXPECT_CALL(mockView, systemSettings()) - .Times(1) - .WillOnce(Return(TomoSystemSettings())); - - // No errors/warnings - EXPECT_CALL(mockView, userError(testing::_, testing::_)).Times(0); - EXPECT_CALL(mockView, userWarning(testing::_, testing::_)).Times(0); - - pres.notify(ITomographyIfacePresenter::SystemSettingsUpdated); - TSM_ASSERT( - "Mock not used as expected. Some EXPECT_CALL conditions were not " - "satisfied.", - testing::Mock::VerifyAndClearExpectations(&mockView)) - } - - void test_setupGood() { - testing::NiceMock<MockTomographyIfaceView> mockView; - MantidQt::CustomInterfaces::TomographyIfacePresenter pres(&mockView); - - // needs the basic paths at a very minimum - EXPECT_CALL(mockView, currentPathsConfig()) - .Times(1) - .WillOnce(Return(TomoPathsConfig())); - - EXPECT_CALL(mockView, systemSettings()) - .Times(1) - .WillOnce(Return(TomoSystemSettings())); - EXPECT_CALL(mockView, enableLoggedActions(false)).Times(1); - EXPECT_CALL(mockView, setComputeResources(testing::_, testing::_)).Times(1); - EXPECT_CALL(mockView, setReconstructionTools(testing::_, testing::_)) - .Times(1); - - // No errors/warnings - EXPECT_CALL(mockView, userError(testing::_, testing::_)).Times(0); - EXPECT_CALL(mockView, userWarning(testing::_, testing::_)).Times(0); - - pres.notify(ITomographyIfacePresenter::SetupResourcesAndTools); - TSM_ASSERT( - "Mock not used as expected. Some EXPECT_CALL conditions were not " - "satisfied.", - testing::Mock::VerifyAndClearExpectations(&mockView)) - } - - void test_setupWithWrongTool() { - testing::NiceMock<MockTomographyIfaceView> mockView; - MantidQt::CustomInterfaces::TomographyIfacePresenter pres(&mockView); - - EXPECT_CALL(mockView, systemSettings()) - .Times(1) - .WillOnce(Return(TomoSystemSettings())); - EXPECT_CALL(mockView, enableLoggedActions(false)).Times(1); - EXPECT_CALL(mockView, setComputeResources(testing::_, testing::_)).Times(1); - EXPECT_CALL(mockView, setReconstructionTools(testing::_, testing::_)) - .Times(1); - - // but this should be called once at setup time - EXPECT_CALL(mockView, currentPathsConfig()) - .Times(1) - .WillOnce(Return(TomoPathsConfig())); - - // One error, no warnings - EXPECT_CALL(mockView, userError(testing::_, testing::_)).Times(0); - EXPECT_CALL(mockView, userWarning(testing::_, testing::_)).Times(0); - - pres.notify(ITomographyIfacePresenter::SetupResourcesAndTools); - - // needs one tool at a very minimum - EXPECT_CALL(mockView, currentReconTool()).Times(1).WillOnce(Return(g_ccpi)); - // and basic tools settings - EXPECT_CALL(mockView, currentPathsConfig()).Times(0); - - // tool config not available - EXPECT_CALL(mockView, showToolConfig(testing::_)).Times(0); - // this also implies that a second call to reconToolsSettings doesn't occur - - pres.notify(ITomographyIfacePresenter::SetupReconTool); - TSM_ASSERT( - "Mock not used as expected. Some EXPECT_CALL conditions were not " - "satisfied.", - testing::Mock::VerifyAndClearExpectations(&mockView)) - } - - // setup reconstruction tool now in preseter, have a unit test - void test_setupReconToolGood() { - testing::NiceMock<MockTomographyIfaceView> mockView; - MantidQt::CustomInterfaces::TomographyIfacePresenter pres(&mockView); - - EXPECT_CALL(mockView, systemSettings()).Times(0); - // needs the basic paths at a very minimum - EXPECT_CALL(mockView, currentReconTool()) - .Times(2) - .WillRepeatedly(Return("TomoPy")); - // and basic tools settings - TomoPathsConfig toolPaths; - EXPECT_CALL(mockView, currentPathsConfig()) - .Times(1) - .WillOnce(Return(toolPaths)); - - EXPECT_CALL(mockView, showToolConfig(testing::_)).Times(1); - - // No errors/warnings - EXPECT_CALL(mockView, userError(testing::_, testing::_)).Times(0); - EXPECT_CALL(mockView, userWarning(testing::_, testing::_)).Times(0); - - pres.notify(ITomographyIfacePresenter::ToolChanged); - pres.notify(ITomographyIfacePresenter::SetupReconTool); - TSM_ASSERT( - "Mock not used as expected. Some EXPECT_CALL conditions were not " - "satisfied.", - testing::Mock::VerifyAndClearExpectations(&mockView)) - } - - void test_valuesAtInit() { - testing::NiceMock<MockTomographyIfaceView> mockView; - MantidQt::CustomInterfaces::TomographyIfacePresenter pres(&mockView); - - EXPECT_CALL(mockView, systemSettings()) - .Times(1) - .WillOnce(Return(TomoSystemSettings())); - // needs basic paths config - using defaults - EXPECT_CALL(mockView, currentPathsConfig()) - .Times(1) - .WillOnce(Return(TomoPathsConfig())); - // No errors, no warnings - EXPECT_CALL(mockView, userError(testing::_, testing::_)).Times(0); - EXPECT_CALL(mockView, userWarning(testing::_, testing::_)).Times(0); - - pres.notify(ITomographyIfacePresenter::SetupResourcesAndTools); - TSM_ASSERT( - "Mock not used as expected. Some EXPECT_CALL conditions were not " - "satisfied.", - testing::Mock::VerifyAndClearExpectations(&mockView)) - } - - void test_logOut_notIn() { - testing::NiceMock<MockTomographyIfaceView> mockView; - MantidQt::CustomInterfaces::TomographyIfacePresenter pres(&mockView); - - // would need compute resource and username if logged in - EXPECT_CALL(mockView, getUsername()).Times(0); - EXPECT_CALL(mockView, updateLoginControls(testing::_)).Times(0); - - // No errors, no warnings - EXPECT_CALL(mockView, userError(testing::_, testing::_)).Times(0); - EXPECT_CALL(mockView, userWarning(testing::_, testing::_)).Times(0); - - pres.notify(ITomographyIfacePresenter::LogOutRequested); - TSM_ASSERT( - "Mock not used as expected. Some EXPECT_CALL conditions were not " - "satisfied.", - testing::Mock::VerifyAndClearExpectations(&mockView)) - } - - void test_changeTool() { - testing::NiceMock<MockTomographyIfaceView> mockView; - MantidQt::CustomInterfaces::TomographyIfacePresenter pres(&mockView); - - std::vector<std::string> tools{"Astra", "TomoPy"}; - - TomoPathsConfig toolPaths; - for (const auto &tool : tools) { - // expect the current paths config will be read only once - EXPECT_CALL(mockView, currentPathsConfig()) - .Times(1) - .WillOnce(Return(toolPaths)); - - // expect the current reconstruction tool will be called only once - EXPECT_CALL(mockView, currentReconTool()).Times(1).WillOnce(Return(tool)); - - EXPECT_CALL(mockView, enableRunReconstruct(testing::_)).Times(1); - EXPECT_CALL(mockView, enableConfigTool(testing::_)).Times(1); - - // No errors, no warnings - EXPECT_CALL(mockView, userError(testing::_, testing::_)).Times(0); - EXPECT_CALL(mockView, userWarning(testing::_, testing::_)).Times(0); - - pres.notify(ITomographyIfacePresenter::ToolChanged); - } - TSM_ASSERT( - "Mock not used as expected. Some EXPECT_CALL conditions were not " - "satisfied.", - testing::Mock::VerifyAndClearExpectations(&mockView)) - } - - void test_changeResource() { - testing::NiceMock<MockTomographyIfaceView> mockView; - MantidQt::CustomInterfaces::TomographyIfacePresenter pres(&mockView); - - EXPECT_CALL(mockView, currentReconTool()).Times(0); - - // No errors, no warnings - EXPECT_CALL(mockView, userError(testing::_, testing::_)).Times(0); - EXPECT_CALL(mockView, userWarning(testing::_, testing::_)).Times(0); - - pres.notify(ITomographyIfacePresenter::CompResourceChanged); - TSM_ASSERT( - "Mock not used as expected. Some EXPECT_CALL conditions were not " - "satisfied.", - testing::Mock::VerifyAndClearExpectations(&mockView)) - } - - void test_changePathsWithBrowseEmpty() { - testing::NiceMock<MockTomographyIfaceView> mockView; - MantidQt::CustomInterfaces::TomographyIfacePresenter pres(&mockView); - - EXPECT_CALL(mockView, updatePathsConfig(testing::_)).Times(0); - EXPECT_CALL(mockView, experimentReference()).Times(0); - - // needs some basic paths config - using defaults from constructor - EXPECT_CALL(mockView, currentPathsConfig()) - .Times(1) - .WillOnce(Return(TomoPathsConfig())); - - // No errors, no warnings - EXPECT_CALL(mockView, userError(testing::_, testing::_)).Times(0); - EXPECT_CALL(mockView, userWarning(testing::_, testing::_)).Times(0); - - pres.notify(ITomographyIfacePresenter::TomoPathsChanged); - TSM_ASSERT( - "Mock not used as expected. Some EXPECT_CALL conditions were not " - "satisfied.", - testing::Mock::VerifyAndClearExpectations(&mockView)) - } - - void test_changePathsWithBrowseNonEmpty() { - for (bool enableFlatDark : {true, false}) { - testing::NiceMock<MockTomographyIfaceView> mockView; - MantidQt::CustomInterfaces::TomographyIfacePresenter pres(&mockView); - - TomoPathsConfig cfg; - cfg.updatePathSamples("/nowhere/foo_samples"); - cfg.updatePathOpenBeam("/nonexistent/bla_ob", enableFlatDark); - cfg.updatePathDarks("/missing_place/bla_dark", enableFlatDark); - mockView.updatePathsConfig(cfg); - - EXPECT_CALL(mockView, updatePathsConfig(testing::_)).Times(0); - EXPECT_CALL(mockView, experimentReference()).Times(0); - - // needs some basic paths config - using test / inexistent paths - EXPECT_CALL(mockView, currentPathsConfig()) - .Times(1) - .WillOnce(Return(cfg)); - - // No errors, no warnings - EXPECT_CALL(mockView, userError(testing::_, testing::_)).Times(0); - EXPECT_CALL(mockView, userWarning(testing::_, testing::_)).Times(0); - - pres.notify(ITomographyIfacePresenter::TomoPathsChanged); - TSM_ASSERT( - "Mock not used as expected. Some EXPECT_CALL conditions were not " - "satisfied.", - testing::Mock::VerifyAndClearExpectations(&mockView)) - } - } - - void test_changePathsEditingByHandEmpty() { - testing::NiceMock<MockTomographyIfaceView> mockView; - MantidQt::CustomInterfaces::TomographyIfacePresenter pres(&mockView); - - EXPECT_CALL(mockView, updatePathsConfig(testing::_)).Times(1); - EXPECT_CALL(mockView, experimentReference()).Times(0); - - // needs some basic paths config - using defaults from constructor - EXPECT_CALL(mockView, currentPathsConfig()) - .Times(1) - .WillOnce(Return(TomoPathsConfig())); - - // No errors, no warnings - EXPECT_CALL(mockView, userError(testing::_, testing::_)).Times(0); - EXPECT_CALL(mockView, userWarning(testing::_, testing::_)).Times(0); - - pres.notify(ITomographyIfacePresenter::TomoPathsEditedByUser); - TSM_ASSERT( - "Mock not used as expected. Some EXPECT_CALL conditions were not " - "satisfied.", - testing::Mock::VerifyAndClearExpectations(&mockView)) - } - - void test_changePathsEditingByHand() { - testing::NiceMock<MockTomographyIfaceView> mockView; - MantidQt::CustomInterfaces::TomographyIfacePresenter pres(&mockView); - - EXPECT_CALL(mockView, experimentReference()).Times(0); - - // give only the samples path - TomoPathsConfig cfg; - cfg.updatePathSamples("/nowhere/foo_samples"); - mockView.updatePathsConfig(cfg); - - EXPECT_CALL(mockView, updatePathsConfig(testing::_)).Times(1); - - // needs some basic paths config - using defaults from constructor - EXPECT_CALL(mockView, currentPathsConfig()) - .Times(1) - .WillOnce(Return(TomoPathsConfig())); - - // No errors, no warnings - EXPECT_CALL(mockView, userError(testing::_, testing::_)).Times(0); - EXPECT_CALL(mockView, userWarning(testing::_, testing::_)).Times(0); - - pres.notify(ITomographyIfacePresenter::TomoPathsEditedByUser); - TSM_ASSERT( - "Mock not used as expected. Some EXPECT_CALL conditions were not " - "satisfied.", - testing::Mock::VerifyAndClearExpectations(&mockView)) - } - - void test_loginFails() { - testing::NiceMock<MockTomographyIfaceView> mockView; - MantidQt::CustomInterfaces::TomographyIfacePresenter pres(&mockView); - - // 1 Error, no warnings - EXPECT_CALL(mockView, userError(testing::_, testing::_)).Times(1); - EXPECT_CALL(mockView, userWarning(testing::_, testing::_)).Times(0); - - pres.notify(ITomographyIfacePresenter::LogInRequested); - TSM_ASSERT( - "Mock not used as expected. Some EXPECT_CALL conditions were not " - "satisfied.", - testing::Mock::VerifyAndClearExpectations(&mockView)) - } - - void test_runFails() { - testing::NiceMock<MockTomographyIfaceView> mockView; - MantidQt::CustomInterfaces::TomographyIfacePresenter pres(&mockView); - - EXPECT_CALL(mockView, systemSettings()) - .Times(1) - .WillOnce(Return(TomoSystemSettings())); - - // needs basic paths config - using defaults - EXPECT_CALL(mockView, currentPathsConfig()) - .Times(1) - .WillOnce(Return(TomoPathsConfig())); - - // No errors, no warnings - EXPECT_CALL(mockView, userError(testing::_, testing::_)).Times(0); - EXPECT_CALL(mockView, userWarning(testing::_, testing::_)).Times(0); - - // EXPECT_CALL(mockView, userWarning(testing::_, testing::_)).Times(0); - pres.notify(ITomographyIfacePresenter::SetupResourcesAndTools); - TSM_ASSERT( - "Mock not used as expected. Some EXPECT_CALL conditions were not " - "satisfied.", - testing::Mock::VerifyAndClearExpectations(&mockView)) - } - - void test_log() { - testing::NiceMock<MockTomographyIfaceView> mockView; - MantidQt::CustomInterfaces::TomographyIfacePresenter pres(&mockView); - - std::vector<std::string> msgs; - msgs.emplace_back("foo log"); - msgs.emplace_back("baz log"); - - EXPECT_CALL(mockView, logMsgs()).Times(1).WillOnce(Return(msgs)); - - // No errors, no warnings - EXPECT_CALL(mockView, userError(testing::_, testing::_)).Times(0); - EXPECT_CALL(mockView, userWarning(testing::_, testing::_)).Times(0); - - pres.notify(ITomographyIfacePresenter::LogMsg); - TSM_ASSERT( - "Mock not used as expected. Some EXPECT_CALL conditions were not " - "satisfied.", - testing::Mock::VerifyAndClearExpectations(&mockView)) - } - - void test_refreshJobsNotIn() { - testing::NiceMock<MockTomographyIfaceView> mockView; - MantidQt::CustomInterfaces::TomographyIfacePresenter pres(&mockView); - - EXPECT_CALL(mockView, updateJobsInfoDisplay(testing::_, testing::_)) - .Times(1); - - // No errors, no warnings - EXPECT_CALL(mockView, userError(testing::_, testing::_)).Times(0); - EXPECT_CALL(mockView, userWarning(testing::_, testing::_)).Times(0); - - pres.notify(ITomographyIfacePresenter::RefreshJobs); - TSM_ASSERT( - "Mock not used as expected. Some EXPECT_CALL conditions were not " - "satisfied.", - testing::Mock::VerifyAndClearExpectations(&mockView)) - } - - void test_cancelJobNotIn() { - testing::NiceMock<MockTomographyIfaceView> mockView; - MantidQt::CustomInterfaces::TomographyIfacePresenter pres(&mockView); - - EXPECT_CALL(mockView, updateJobsInfoDisplay(testing::_, testing::_)) - .Times(1); - - // No errors, no warnings - EXPECT_CALL(mockView, userError(testing::_, testing::_)).Times(0); - EXPECT_CALL(mockView, userWarning(testing::_, testing::_)).Times(0); - - pres.notify(ITomographyIfacePresenter::RefreshJobs); - TSM_ASSERT( - "Mock not used as expected. Some EXPECT_CALL conditions were not " - "satisfied.", - testing::Mock::VerifyAndClearExpectations(&mockView)) - } - - void test_systemSettingsDefs() { - TomoSystemSettings sets; - - const std::string msg = "Global tomography system settings default values " - "should be as expected"; - - TSM_ASSERT_EQUALS(msg + " (number of path components for image data)", - sets.m_pathComponents.size(), 4); - - TSM_ASSERT_EQUALS(msg + " (prefix for sample images dir)", - sets.m_samplesDirPrefix, "data"); - - TSM_ASSERT_EQUALS(msg + " (prefix for flat/open beam images dir)", - sets.m_flatsDirPrefix, "flat"); - - TSM_ASSERT_EQUALS(msg + " (prefix for dark images dir)", - sets.m_darksDirPrefix, "dark"); - - TSM_ASSERT_EQUALS( - msg + " (path component in the output for pre-processed images)", - sets.m_outputPathCompPreProcessed, "pre_processed"); - - TSM_ASSERT_EQUALS(msg + " (path component in the output for " - "processed/reconstructed images/volumes)", - sets.m_outputPathCompReconst, "processed"); - } - - void test_systemSettingsDefsLocal() { - TomoSystemSettings sets; - - const std::string msg = - "Local system settings default values should be as expected"; - - // Normally this would be 3 for Win32 (example: D:\) and - // >=5 otherwise - const std::string path = sets.m_local.m_basePathTomoData; - TSM_ASSERT_LESS_THAN_EQUALS( - msg + " (base path for tomography data too short)", 3, path.length()); - } - - void test_systemSettingsDefsRemote() { - TomoSystemSettings sets; - - const std::string msg = - "Remote system settings default values should be as expected"; - - TSM_ASSERT_EQUALS(msg + " (base path for tomography data)", - sets.m_remote.m_basePathTomoData, "/work/imat"); - - TSM_ASSERT_EQUALS(msg + " (base path for reconstruction scripts)", - sets.m_remote.m_basePathReconScripts, - "/work/imat/phase_commissioning"); - } - - void test_filtersSettings() { - TomoReconFiltersSettings def; - - // When the presenter uses these settings for job submission there - // the test should be extended with something like this: - // EXPECT_CALL(mockView, prePostProcSettings()).Times(1).WillOnce( - // Return("TomoPy")); - - TSM_ASSERT_EQUALS("Pre-processing filter settings default values should be " - "as expected (normalization by air region)", - def.prep.normalizeByAirRegion, true); - - TSM_ASSERT_EQUALS("Pre-processing settings default values should be as " - "expected (proton-charge normalization)", - def.prep.normalizeByProtonCharge, false); - - TSM_ASSERT_EQUALS("Pre-processing filter settings default values should be " - "as expected (normalization by flat images)", - def.prep.normalizeByFlats, true); - - TSM_ASSERT_EQUALS("Pre-processing filter settings default values should be " - "as expected (normalization by dark images)", - def.prep.normalizeByDarks, true); - - TSM_ASSERT_EQUALS("Pre-processing settings default values should be as " - "expected (median filter width)", - def.prep.medianFilterWidth, 3); - - TSM_ASSERT_EQUALS("Pre-processing settings default values should be as " - "expected (rotation)", - def.prep.rotation, 0); - - TSM_ASSERT_EQUALS("Pre-processing settings default values should be as " - "expected (maximum angle)", - def.prep.maxAngle, 360.0); - - TSM_ASSERT_LESS_THAN_EQUALS( - "Pre-processing settings default values should be as " - "expected (scale down)", - def.prep.scaleDownFactor, 1); - - TSM_ASSERT_DELTA("Post-processing settings default values should be as " - "expected (circular mask)", - def.postp.circMaskRadius, 0.94, 1e-5); - - TSM_ASSERT_EQUALS("Post-processing settings default values should be as " - "expected (cut-off)", - def.postp.cutOffLevel, 0.0); - - TSM_ASSERT_EQUALS("Output settings default values should be as expected", - def.outputPreprocImages, true); - } - - void test_aggregateBandsFailsMissingPaths() { - testing::NiceMock<MockTomographyIfaceView> mockView; - MantidQt::CustomInterfaces::TomographyIfacePresenter pres(&mockView); - - // Empty params, missing the required ones for sure - EXPECT_CALL(mockView, currentAggregateBandsParams()) - .Times(1) - .WillOnce(Return(std::map<std::string, std::string>())); - - // Error - EXPECT_CALL(mockView, userError(testing::_, testing::_)).Times(1); - EXPECT_CALL(mockView, userWarning(testing::_, testing::_)).Times(0); - - pres.notify(ITomographyIfacePresenter::AggregateEnergyBands); - TSM_ASSERT( - "Mock not used as expected. Some EXPECT_CALL conditions were not " - "satisfied.", - testing::Mock::VerifyAndClearExpectations(&mockView)) - } - - void test_aggregateBandsFailsWrongPaths() { - testing::NiceMock<MockTomographyIfaceView> mockView; - MantidQt::CustomInterfaces::TomographyIfacePresenter pres(&mockView); - - std::map<std::string, std::string> params; - params["InputPath"] = "I_cannot_be_found_fail_"; - params["OutputPath"] = "fail_for_sure_i_m_not_found"; - params["UniformBands"] = "2"; - params["OutPrefixBands"] = "band_prefix_"; - params["InuptImageFormat"] = "FITS"; - params["OutputImageFormat"] = "FITS"; - - // Will contain wrong values in the required paths - EXPECT_CALL(mockView, currentAggregateBandsParams()) - .Times(1) - .WillOnce(Return(params)); - - // Error - EXPECT_CALL(mockView, userError(testing::_, testing::_)).Times(1); - EXPECT_CALL(mockView, userWarning(testing::_, testing::_)).Times(0); - - pres.notify(ITomographyIfacePresenter::AggregateEnergyBands); - TSM_ASSERT( - "Mock not used as expected. Some EXPECT_CALL conditions were not " - "satisfied.", - testing::Mock::VerifyAndClearExpectations(&mockView)) - } - - // disabled as this is I/O intensive and uses the algorithm runner (Qt) - void disabled_test_aggregateBandsRuns() { - testing::NiceMock<MockTomographyIfaceView> mockView; - MantidQt::CustomInterfaces::TomographyIfacePresenter pres(&mockView); - - std::map<std::string, std::string> params; - params["InputPath"] = "here_some_valid_input_images_path_"; - params["OutputPath"] = "here_some_valid_existing_output_path"; - params["UniformBands"] = "1"; - params["OutPrefixBands"] = "band_prefix_"; - params["InputImageFormat"] = "FITS"; - params["OutputImageFormat"] = "FITS"; - - EXPECT_CALL(mockView, runAggregateBands(testing::_)).Times(1); - - // No errors, no warnings - EXPECT_CALL(mockView, userError(testing::_, testing::_)).Times(0); - EXPECT_CALL(mockView, userWarning(testing::_, testing::_)).Times(0); - - pres.notify(ITomographyIfacePresenter::AggregateEnergyBands); - TSM_ASSERT( - "Mock not used as expected. Some EXPECT_CALL conditions were not " - "satisfied.", - testing::Mock::VerifyAndClearExpectations(&mockView)) - } - - void test_sillySessionRemote() { - // the user does a few silly things... - testing::NiceMock<MockTomographyIfaceView> mockView; - MantidQt::CustomInterfaces::TomographyIfacePresenter pres(&mockView); - - EXPECT_CALL(mockView, systemSettings()).Times(0); - - EXPECT_CALL(mockView, currentPathsConfig()) - .Times(1) - .WillOnce(Return(TomoPathsConfig())); - - // user changes some paths - pres.notify(ITomographyIfacePresenter::TomoPathsChanged); - EXPECT_CALL(mockView, currentComputeResource()) - .WillRepeatedly(Return(g_scarfName)); - - // user changes the compute resource - pres.notify(ITomographyIfacePresenter::CompResourceChanged); - - EXPECT_CALL(mockView, currentReconTool()) - .Times(2) - .WillRepeatedly(Return("TomoPy")); - - // and basic tools settings - EXPECT_CALL(mockView, currentPathsConfig()) - .Times(1) - .WillOnce(Return(TomoPathsConfig())); - - // the tool changed event sets up the tool's paths - pres.notify(ITomographyIfacePresenter::ToolChanged); - // user opens dialog and sets up a reconstruction tool - pres.notify(ITomographyIfacePresenter::SetupReconTool); - - TomoPathsConfig pathsCfg; - EXPECT_CALL(mockView, currentPathsConfig()) - .Times(1) - .WillOnce(Return(pathsCfg)); - - ImageStackPreParams roiEtc; - EXPECT_CALL(mockView, currentROIEtcParams()) - .Times(1) - .WillOnce(Return(roiEtc)); - - TomoReconFiltersSettings filters; - EXPECT_CALL(mockView, prePostProcSettings()) - .Times(1) - .WillOnce(Return(filters)); - - // No errors, no warnings - EXPECT_CALL(mockView, userError(testing::_, testing::_)).Times(0); - - // we get one warning from trying to submit a job to remote - EXPECT_CALL(mockView, userWarning(testing::_, testing::_)).Times(1); - - // finally, user tries to run a reconstruction job - pres.notify(ITomographyIfacePresenter::RunReconstruct); - TSM_ASSERT( - "Mock not used as expected. Some EXPECT_CALL conditions were not " - "satisfied.", - testing::Mock::VerifyAndClearExpectations(&mockView)) - } - - void test_shutDown() { - testing::NiceMock<MockTomographyIfaceView> mockView; - MantidQt::CustomInterfaces::TomographyIfacePresenter pres(&mockView); - - EXPECT_CALL(mockView, saveSettings()).Times(1); - // No errors, no warnings - EXPECT_CALL(mockView, userError(testing::_, testing::_)).Times(0); - EXPECT_CALL(mockView, userWarning(testing::_, testing::_)).Times(0); - - pres.notify(ITomographyIfacePresenter::ShutDown); - TSM_ASSERT( - "Mock not used as expected. Some EXPECT_CALL conditions were not " - "satisfied.", - testing::Mock::VerifyAndClearExpectations(&mockView)) - } - -private: - // boost::shared_ptr - boost::scoped_ptr<testing::NiceMock<MockTomographyIfaceView>> m_view; - // MockTomographyIfaceModel *m_model; - boost::scoped_ptr<MantidQt::CustomInterfaces::TomographyIfacePresenter> - m_presenter; - // To have one FITS, etc. - Mantid::API::MatrixWorkspace_sptr m_ws; - static std::string g_scarfName; - static std::string g_ccpi; -}; - -std::string TomographyIfacePresenterTest::g_scarfName = "SCARF@STFC"; -std::string TomographyIfacePresenterTest::g_ccpi = "CCPi CGLS"; - -#endif // MANTID_CUSTOMINTERFACES_TOMOGRAPHYIFACEPRESENTERTEST_H diff --git a/MantidQt/CustomInterfaces/test/TomographyROIPresenterTest.h b/MantidQt/CustomInterfaces/test/TomographyROIPresenterTest.h deleted file mode 100644 index a79981a47c5..00000000000 --- a/MantidQt/CustomInterfaces/test/TomographyROIPresenterTest.h +++ /dev/null @@ -1,679 +0,0 @@ -#ifndef MANTID_CUSTOMINTERFACES_TOMOGRAPHYROIPRESENTERTEST_H -#define MANTID_CUSTOMINTERFACES_TOMOGRAPHYROIPRESENTERTEST_H - -#include "MantidAPI/FrameworkManager.h" -#include "MantidAPI/MatrixWorkspace.h" -#include "MantidAPI/WorkspaceGroup.h" -#include "MantidQtCustomInterfaces/Tomography/TomographyROIPresenter.h" -#include "MantidTestHelpers/FakeObjects.h" - -#include <cxxtest/TestSuite.h> - -#include <Poco/File.h> - -#include "TomographyROIViewMock.h" - -using namespace MantidQt::CustomInterfaces; -using testing::TypedEq; -using testing::Return; - -class TomographyROIPresenterTest : public CxxTest::TestSuite { - -public: - // This pair of boilerplate methods prevent the suite being created statically - // This means the constructor isn't called when running other tests - static TomographyROIPresenterTest *createSuite() { - return new TomographyROIPresenterTest(); - } - - static void destroySuite(TomographyROIPresenterTest *suite) { delete suite; } - - TomographyROIPresenterTest() { - Mantid::API::FrameworkManager::Instance(); // make sure the framework is - // initialized - } - - void setUp() override { - m_view.reset(new testing::NiceMock<MockTomographyROIView>()); - m_presenter.reset( - new MantidQt::CustomInterfaces::TomographyROIPresenter(m_view.get())); - } - - void tearDown() override { - TS_ASSERT(testing::Mock::VerifyAndClearExpectations(m_view.get())); - } - - void test_initOK() { - testing::NiceMock<MockTomographyROIView> mockView; - MantidQt::CustomInterfaces::TomographyROIPresenter pres(&mockView); - - EXPECT_CALL(mockView, setParams(testing::_)).Times(1); - - EXPECT_CALL(mockView, resetCoR()).Times(0); - EXPECT_CALL(mockView, resetROI()).Times(0); - EXPECT_CALL(mockView, resetNormArea()).Times(0); - EXPECT_CALL(mockView, resetWidgetsOnNewStack()).Times(0); - EXPECT_CALL(mockView, currentRotationAngle()).Times(0); - EXPECT_CALL(mockView, updateRotationAngle(testing::_)).Times(0); - - // No errors/warnings - EXPECT_CALL(mockView, userError(testing::_, testing::_)).Times(0); - EXPECT_CALL(mockView, userWarning(testing::_, testing::_)).Times(0); - - pres.notify(TomographyROIPresenter::Init); - - TSM_ASSERT( - "Mock not used as expected. Some EXPECT_CALL conditions were not " - "satisfied.", - testing::Mock::VerifyAndClearExpectations(&mockView)); - } - - void test_initWithWrongParams() { - testing::NiceMock<MockTomographyROIView> mockView; - MantidQt::CustomInterfaces::TomographyROIPresenter pres(&mockView); - - EXPECT_CALL(mockView, setParams(testing::_)).Times(1); - - EXPECT_CALL(mockView, resetWidgetsOnNewStack()).Times(0); - - // One error, no warnings - EXPECT_CALL(mockView, userError(testing::_, testing::_)).Times(0); - EXPECT_CALL(mockView, userWarning(testing::_, testing::_)).Times(0); - - pres.notify(TomographyROIPresenter::Init); - - TSM_ASSERT( - "Mock not used as expected. Some EXPECT_CALL conditions were not " - "satisfied.", - testing::Mock::VerifyAndClearExpectations(&mockView)); - } - - void test_browseSingleImg_EmptyPath() { - testing::NiceMock<MockTomographyROIView> mockView; - MantidQt::CustomInterfaces::TomographyROIPresenter pres(&mockView); - - EXPECT_CALL(mockView, askImagePath(testing::_)).Times(1); - - // No error, no warning, just ignore - EXPECT_CALL(mockView, userError(testing::_, testing::_)).Times(0); - EXPECT_CALL(mockView, userWarning(testing::_, testing::_)).Times(0); - - // because the path is wrong this should not happen - EXPECT_CALL(mockView, resetWidgetsOnNewStack()).Times(0); - - // should not get there because there's no stack/img - it's just ignored: - EXPECT_CALL(mockView, showStack(testing::An<const std::string &>())) - .Times(0); - EXPECT_CALL( - mockView, - showStack(testing::An<const Mantid::API::WorkspaceGroup_sptr &>(), - testing::An<const Mantid::API::WorkspaceGroup_sptr &>(), - testing::An<const Mantid::API::WorkspaceGroup_sptr &>())) - .Times(0); - EXPECT_CALL(mockView, updateImgWithIndex(testing::_)).Times(0); - - pres.notify(ITomographyROIPresenter::BrowseImage); - - TSM_ASSERT( - "Mock not used as expected. Some EXPECT_CALL conditions were not " - "satisfied.", - testing::Mock::VerifyAndClearExpectations(&mockView)); - } - - void test_browseStack_EmptyPath() { - testing::NiceMock<MockTomographyROIView> mockView; - MantidQt::CustomInterfaces::TomographyROIPresenter pres(&mockView); - - EXPECT_CALL(mockView, askImagePath(testing::_)) - .Times(1) - .WillOnce(Return("")); - - // No error, no warnings, just ignored - EXPECT_CALL(mockView, userError(testing::_, testing::_)).Times(0); - EXPECT_CALL(mockView, userWarning(testing::_, testing::_)).Times(0); - - // because the path is wrong this should not happen - EXPECT_CALL(mockView, resetWidgetsOnNewStack()).Times(0); - - // should not get there: - EXPECT_CALL(mockView, showStack(testing::An<const std::string &>())) - .Times(0); - EXPECT_CALL( - mockView, - showStack(testing::An<const Mantid::API::WorkspaceGroup_sptr &>(), - testing::An<const Mantid::API::WorkspaceGroup_sptr &>(), - testing::An<const Mantid::API::WorkspaceGroup_sptr &>())) - .Times(0); - EXPECT_CALL(mockView, updateImgWithIndex(testing::_)).Times(0); - - pres.notify(ITomographyROIPresenter::BrowseStack); - - TSM_ASSERT( - "Mock not used as expected. Some EXPECT_CALL conditions were not " - "satisfied.", - testing::Mock::VerifyAndClearExpectations(&mockView)); - } - - void test_browseStack_WrongPath() { - testing::NiceMock<MockTomographyROIView> mockView; - MantidQt::CustomInterfaces::TomographyROIPresenter pres(&mockView); - - EXPECT_CALL(mockView, askImagePath(testing::_)) - .Times(1) - .WillOnce(Return("dont_look_for_me_i_dont_exist")); - - // A warning - EXPECT_CALL(mockView, userError(testing::_, testing::_)).Times(0); - EXPECT_CALL(mockView, userWarning(testing::_, testing::_)).Times(1); - - // because the path is wrong this should not happen - EXPECT_CALL(mockView, resetWidgetsOnNewStack()).Times(0); - - // should not get there because there's no stack/img - EXPECT_CALL(mockView, showStack(testing::An<const std::string &>())) - .Times(0); - EXPECT_CALL( - mockView, - showStack(testing::An<const Mantid::API::WorkspaceGroup_sptr &>(), - testing::An<const Mantid::API::WorkspaceGroup_sptr &>(), - testing::An<const Mantid::API::WorkspaceGroup_sptr &>())) - .Times(0); - EXPECT_CALL(mockView, updateImgWithIndex(testing::_)).Times(0); - - // this exception is currently handled, and a warning given - // TSM_ASSERT_THROWS("There should be an exception if there is an unexpected - // " - // "error with the images path", - // pres.notify(ITomographyROIPresenter::BrowseImgOrStack), - // Poco::FileNotFoundException); - pres.notify(ITomographyROIPresenter::BrowseStack); - - TSM_ASSERT( - "Mock not used as expected. Some EXPECT_CALL conditions were not " - "satisfied.", - testing::Mock::VerifyAndClearExpectations(&mockView)); - } - - void test_changeImageType() { - testing::NiceMock<MockTomographyROIView> mockView; - MantidQt::CustomInterfaces::TomographyROIPresenter pres(&mockView); - - Mantid::API::WorkspaceGroup_sptr stack; - EXPECT_CALL(mockView, currentImageTypeStack()) - .Times(1) - .WillOnce(Return(stack)); - EXPECT_CALL(mockView, updateImageType(stack)).Times(1); - - // should not mix up with the img index - EXPECT_CALL(mockView, currentImgIndex()).Times(0); - EXPECT_CALL(mockView, updateImgWithIndex(testing::_)).Times(0); - - // Change without issues - EXPECT_CALL(mockView, userError(testing::_, testing::_)).Times(0); - EXPECT_CALL(mockView, userWarning(testing::_, testing::_)).Times(0); - - pres.notify(ITomographyROIPresenter::ChangeImageType); - - TSM_ASSERT( - "Mock not used as expected. Some EXPECT_CALL conditions were not " - "satisfied.", - testing::Mock::VerifyAndClearExpectations(&mockView)); - } - - void test_changeRotation() { - testing::NiceMock<MockTomographyROIView> mockView; - MantidQt::CustomInterfaces::TomographyROIPresenter pres(&mockView); - - EXPECT_CALL(mockView, currentRotationAngle()).Times(1).WillOnce(Return(0)); - EXPECT_CALL(mockView, updateRotationAngle(0.0f)).Times(1); - - // No errors, no warnings - EXPECT_CALL(mockView, userError(testing::_, testing::_)).Times(0); - EXPECT_CALL(mockView, userWarning(testing::_, testing::_)).Times(0); - - pres.notify(ITomographyROIPresenter::ChangeRotation); - - TSM_ASSERT( - "Mock not used as expected. Some EXPECT_CALL conditions were not " - "satisfied.", - testing::Mock::VerifyAndClearExpectations(&mockView)); - } - - void test_updateImgIndex() { - testing::NiceMock<MockTomographyROIView> mockView; - MantidQt::CustomInterfaces::TomographyROIPresenter pres(&mockView); - - int idx = 0; - EXPECT_CALL(mockView, currentImgIndex()).Times(1).WillOnce(Return(idx)); - - EXPECT_CALL(mockView, updateImgWithIndex(idx)).Times(1); - - // No errors, no warnings - EXPECT_CALL(mockView, userError(testing::_, testing::_)).Times(0); - EXPECT_CALL(mockView, userWarning(testing::_, testing::_)).Times(0); - - pres.notify(ITomographyROIPresenter::UpdateImgIndex); - - TSM_ASSERT( - "Mock not used as expected. Some EXPECT_CALL conditions were not " - "satisfied.", - testing::Mock::VerifyAndClearExpectations(&mockView)); - } - - // when the user clicks on 'play', with no images - void test_playStartEmpty() { - testing::NiceMock<MockTomographyROIView> mockView; - MantidQt::CustomInterfaces::TomographyROIPresenter pres(&mockView); - - EXPECT_CALL(mockView, currentImgIndex()).Times(0); - - Mantid::API::WorkspaceGroup_sptr emptyStack; - EXPECT_CALL(mockView, currentImageTypeStack()) - .Times(1) - .WillOnce(Return(emptyStack)); - - EXPECT_CALL(mockView, enableActions(false)).Times(0); - EXPECT_CALL(mockView, playStart()).Times(0); - - // No errors, no warnings - EXPECT_CALL(mockView, userError(testing::_, testing::_)).Times(0); - EXPECT_CALL(mockView, userWarning(testing::_, testing::_)).Times(0); - - pres.notify(ITomographyROIPresenter::PlayStartStop); - - TSM_ASSERT( - "Mock not used as expected. Some EXPECT_CALL conditions were not " - "satisfied.", - testing::Mock::VerifyAndClearExpectations(&mockView)); - } - - // try to play a single image => a warning will pop up - void test_playStartSingleImage() { - testing::NiceMock<MockTomographyROIView> mockView; - MantidQt::CustomInterfaces::TomographyROIPresenter pres(&mockView); - - auto stack = boost::make_shared<Mantid::API::WorkspaceGroup>(); - auto img = boost::make_shared<WorkspaceTester>(); - stack->addWorkspace(img); - - EXPECT_CALL(mockView, currentImgIndex()).Times(0); - - EXPECT_CALL(mockView, currentImageTypeStack()) - .Times(1) - .WillOnce(Return(stack)); - - // for a single image, there should be a warning message, and we - // should not even try to play - EXPECT_CALL(mockView, enableActions(false)).Times(0); - EXPECT_CALL(mockView, playStart()).Times(0); - - // No errors, no warnings - EXPECT_CALL(mockView, userError(testing::_, testing::_)).Times(0); - EXPECT_CALL(mockView, userWarning(testing::_, testing::_)).Times(1); - - pres.notify(ITomographyROIPresenter::PlayStartStop); - - TSM_ASSERT( - "Mock not used as expected. Some EXPECT_CALL conditions were not " - "satisfied.", - testing::Mock::VerifyAndClearExpectations(&mockView)); - } - - // when the user clicks on 'play' with a reasonable stack of images - void test_playOK() { - testing::NiceMock<MockTomographyROIView> mockView; - MantidQt::CustomInterfaces::TomographyROIPresenter pres(&mockView); - - auto stack = boost::make_shared<Mantid::API::WorkspaceGroup>(); - auto img = boost::make_shared<WorkspaceTester>(); - auto img2 = boost::make_shared<WorkspaceTester>(); - stack->addWorkspace(img); - stack->addWorkspace(img2); - - EXPECT_CALL(mockView, currentImageTypeStack()) - .Times(1) - .WillOnce(Return(stack)); - - EXPECT_CALL(mockView, currentImgIndex()).Times(0); - - EXPECT_CALL(mockView, enableActions(testing::_)).Times(1); - EXPECT_CALL(mockView, playStart()).Times(1); - EXPECT_CALL(mockView, playStop()).Times(0); - - // No errors, no warnings - EXPECT_CALL(mockView, userError(testing::_, testing::_)).Times(0); - EXPECT_CALL(mockView, userWarning(testing::_, testing::_)).Times(0); - - // start to play - pres.notify(ITomographyROIPresenter::PlayStartStop); - - TSM_ASSERT( - "Mock not used as expected. Some EXPECT_CALL conditions were not " - "satisfied.", - testing::Mock::VerifyAndClearExpectations(&mockView)); - } - - // when the user clicks on 'play', then 'stop', with a reasonable stack of - // images - void test_playStartStop() { - testing::NiceMock<MockTomographyROIView> mockView; - MantidQt::CustomInterfaces::TomographyROIPresenter pres(&mockView); - - auto stack = boost::make_shared<Mantid::API::WorkspaceGroup>(); - auto img = boost::make_shared<WorkspaceTester>(); - auto img2 = boost::make_shared<WorkspaceTester>(); - stack->addWorkspace(img); - stack->addWorkspace(img2); - - EXPECT_CALL(mockView, currentImageTypeStack()) - .Times(2) - .WillRepeatedly(Return(stack)); - - EXPECT_CALL(mockView, currentImgIndex()).Times(0); - - EXPECT_CALL(mockView, enableActions(testing::_)).Times(2); - EXPECT_CALL(mockView, playStart()).Times(1); - EXPECT_CALL(mockView, playStop()).Times(1); - - // No errors, no warnings - EXPECT_CALL(mockView, userError(testing::_, testing::_)).Times(0); - EXPECT_CALL(mockView, userWarning(testing::_, testing::_)).Times(0); - - // start first - pres.notify(ITomographyROIPresenter::PlayStartStop); - // then stop - pres.notify(ITomographyROIPresenter::PlayStartStop); - - TSM_ASSERT( - "Mock not used as expected. Some EXPECT_CALL conditions were not " - "satisfied.", - testing::Mock::VerifyAndClearExpectations(&mockView)); - } - - void test_updateColorMapEmpty() { - testing::NiceMock<MockTomographyROIView> mockView; - MantidQt::CustomInterfaces::TomographyROIPresenter pres(&mockView); - - EXPECT_CALL(mockView, askColorMapFile()).Times(1).WillOnce(Return("")); - - // Should not get there - EXPECT_CALL(mockView, updateColorMap(testing::_)).Times(0); - - // No errors, no warnings - EXPECT_CALL(mockView, userError(testing::_, testing::_)).Times(0); - EXPECT_CALL(mockView, userWarning(testing::_, testing::_)).Times(0); - - pres.notify(ITomographyROIPresenter::UpdateColorMap); - - TSM_ASSERT( - "Mock not used as expected. Some EXPECT_CALL conditions were not " - "satisfied.", - testing::Mock::VerifyAndClearExpectations(&mockView)); - } - - void test_updateColorMapOK() { - testing::NiceMock<MockTomographyROIView> mockView; - MantidQt::CustomInterfaces::TomographyROIPresenter pres(&mockView); - - const std::string filename = "test_inexistent_colormap.map"; - EXPECT_CALL(mockView, askColorMapFile()) - .Times(1) - .WillOnce(Return(filename)); - - EXPECT_CALL(mockView, updateColorMap(filename)).Times(1); - - // No errors, no warnings - EXPECT_CALL(mockView, userError(testing::_, testing::_)).Times(0); - EXPECT_CALL(mockView, userWarning(testing::_, testing::_)).Times(0); - - pres.notify(ITomographyROIPresenter::UpdateColorMap); - - TSM_ASSERT( - "Mock not used as expected. Some EXPECT_CALL conditions were not " - "satisfied.", - testing::Mock::VerifyAndClearExpectations(&mockView)); - } - - void test_changeColorRange() { - testing::NiceMock<MockTomographyROIView> mockView; - MantidQt::CustomInterfaces::TomographyROIPresenter pres(&mockView); - - EXPECT_CALL(mockView, askColorMapFile()).Times(0); - - size_t img_idx = 0; - EXPECT_CALL(mockView, currentImgIndex()).Times(1).WillOnce(Return(img_idx)); - EXPECT_CALL(mockView, updateImgWithIndex(img_idx)).Times(1); - - // No errors, no warnings - EXPECT_CALL(mockView, userError(testing::_, testing::_)).Times(0); - EXPECT_CALL(mockView, userWarning(testing::_, testing::_)).Times(0); - - pres.notify(ITomographyROIPresenter::ColorRangeUpdated); - - TSM_ASSERT( - "Mock not used as expected. Some EXPECT_CALL conditions were not " - "satisfied.", - testing::Mock::VerifyAndClearExpectations(&mockView)); - } - - void test_selectCoR() { - testing::NiceMock<MockTomographyROIView> mockView; - MantidQt::CustomInterfaces::TomographyROIPresenter pres(&mockView); - - EXPECT_CALL(mockView, changeSelectionState(ITomographyROIView::SelectCoR)) - .Times(1); - - // No errors, no warnings - EXPECT_CALL(mockView, userError(testing::_, testing::_)).Times(0); - EXPECT_CALL(mockView, userWarning(testing::_, testing::_)).Times(0); - - pres.notify(ITomographyROIPresenter::SelectCoR); - - TSM_ASSERT( - "Mock not used as expected. Some EXPECT_CALL conditions were not " - "satisfied.", - testing::Mock::VerifyAndClearExpectations(&mockView)); - } - - void test_resetCoR() { - testing::NiceMock<MockTomographyROIView> mockView; - MantidQt::CustomInterfaces::TomographyROIPresenter pres(&mockView); - - EXPECT_CALL(mockView, resetCoR()).Times(1); - EXPECT_CALL(mockView, changeSelectionState(ITomographyROIView::SelectNone)) - .Times(1); - - // just a few calls that should not happen - EXPECT_CALL(mockView, resetROI()).Times(0); - EXPECT_CALL(mockView, showStack(testing::An<const std::string &>())) - .Times(0); - EXPECT_CALL( - mockView, - showStack(testing::An<const Mantid::API::WorkspaceGroup_sptr &>(), - testing::An<const Mantid::API::WorkspaceGroup_sptr &>(), - testing::An<const Mantid::API::WorkspaceGroup_sptr &>())) - .Times(0); - EXPECT_CALL(mockView, updateImgWithIndex(testing::_)).Times(0); - - // No errors, no warnings - EXPECT_CALL(mockView, userError(testing::_, testing::_)).Times(0); - EXPECT_CALL(mockView, userWarning(testing::_, testing::_)).Times(0); - - pres.notify(ITomographyROIPresenter::ResetCoR); - - TSM_ASSERT( - "Mock not used as expected. Some EXPECT_CALL conditions were not " - "satisfied.", - testing::Mock::VerifyAndClearExpectations(&mockView)); - } - - void test_selectROI() { - testing::NiceMock<MockTomographyROIView> mockView; - MantidQt::CustomInterfaces::TomographyROIPresenter pres(&mockView); - - EXPECT_CALL(mockView, changeSelectionState( - ITomographyROIView::SelectROIFirst)).Times(1); - - // No errors, no warnings - EXPECT_CALL(mockView, userError(testing::_, testing::_)).Times(0); - EXPECT_CALL(mockView, userWarning(testing::_, testing::_)).Times(0); - - pres.notify(ITomographyROIPresenter::SelectROI); - - TSM_ASSERT( - "Mock not used as expected. Some EXPECT_CALL conditions were not " - "satisfied.", - testing::Mock::VerifyAndClearExpectations(&mockView)); - } - - void test_finishROI() { - testing::NiceMock<MockTomographyROIView> mockView; - MantidQt::CustomInterfaces::TomographyROIPresenter pres(&mockView); - - EXPECT_CALL(mockView, changeSelectionState(ITomographyROIView::SelectNone)) - .Times(1); - - // No errors, no warnings - EXPECT_CALL(mockView, userError(testing::_, testing::_)).Times(0); - EXPECT_CALL(mockView, userWarning(testing::_, testing::_)).Times(0); - - pres.notify(ITomographyROIPresenter::FinishedROI); - - TSM_ASSERT( - "Mock not used as expected. Some EXPECT_CALL conditions were not " - "satisfied.", - testing::Mock::VerifyAndClearExpectations(&mockView)); - } - - void test_resetROI() { - testing::NiceMock<MockTomographyROIView> mockView; - MantidQt::CustomInterfaces::TomographyROIPresenter pres(&mockView); - - EXPECT_CALL(mockView, resetROI()).Times(1); - EXPECT_CALL(mockView, changeSelectionState(ITomographyROIView::SelectNone)) - .Times(1); - - // just a few calls that should not happen - EXPECT_CALL(mockView, resetCoR()).Times(0); - EXPECT_CALL(mockView, showStack(testing::An<const std::string &>())) - .Times(0); - EXPECT_CALL( - mockView, - showStack(testing::An<const Mantid::API::WorkspaceGroup_sptr &>(), - testing::An<const Mantid::API::WorkspaceGroup_sptr &>(), - testing::An<const Mantid::API::WorkspaceGroup_sptr &>())) - .Times(0); - EXPECT_CALL(mockView, updateImgWithIndex(testing::_)).Times(0); - - // No errors, no warnings - EXPECT_CALL(mockView, userError(testing::_, testing::_)).Times(0); - EXPECT_CALL(mockView, userWarning(testing::_, testing::_)).Times(0); - - pres.notify(ITomographyROIPresenter::ResetROI); - - TSM_ASSERT( - "Mock not used as expected. Some EXPECT_CALL conditions were not " - "satisfied.", - testing::Mock::VerifyAndClearExpectations(&mockView)); - } - - void test_selectNormalization() { - testing::NiceMock<MockTomographyROIView> mockView; - MantidQt::CustomInterfaces::TomographyROIPresenter pres(&mockView); - - EXPECT_CALL(mockView, - changeSelectionState(ITomographyROIView::SelectNormAreaFirst)) - .Times(1); - - // No errors, no warnings - EXPECT_CALL(mockView, userError(testing::_, testing::_)).Times(0); - EXPECT_CALL(mockView, userWarning(testing::_, testing::_)).Times(0); - - pres.notify(ITomographyROIPresenter::SelectNormalization); - - TSM_ASSERT( - "Mock not used as expected. Some EXPECT_CALL conditions were not " - "satisfied.", - testing::Mock::VerifyAndClearExpectations(&mockView)); - } - - void test_finishNormalization() { - testing::NiceMock<MockTomographyROIView> mockView; - MantidQt::CustomInterfaces::TomographyROIPresenter pres(&mockView); - - EXPECT_CALL(mockView, changeSelectionState(ITomographyROIView::SelectNone)) - .Times(1); - - // No errors, no warnings - EXPECT_CALL(mockView, userError(testing::_, testing::_)).Times(0); - EXPECT_CALL(mockView, userWarning(testing::_, testing::_)).Times(0); - - pres.notify(ITomographyROIPresenter::FinishedNormalization); - - TSM_ASSERT( - "Mock not used as expected. Some EXPECT_CALL conditions were not " - "satisfied.", - testing::Mock::VerifyAndClearExpectations(&mockView)); - } - - void test_resetNormalization() { - testing::NiceMock<MockTomographyROIView> mockView; - MantidQt::CustomInterfaces::TomographyROIPresenter pres(&mockView); - - EXPECT_CALL(mockView, resetNormArea()).Times(1); - EXPECT_CALL(mockView, changeSelectionState(ITomographyROIView::SelectNone)) - .Times(1); - - // just a few calls that should not happen - EXPECT_CALL(mockView, resetCoR()).Times(0); - EXPECT_CALL(mockView, resetROI()).Times(0); - EXPECT_CALL(mockView, showStack(testing::An<const std::string &>())) - .Times(0); - EXPECT_CALL( - mockView, - showStack(testing::An<const Mantid::API::WorkspaceGroup_sptr &>(), - testing::An<const Mantid::API::WorkspaceGroup_sptr &>(), - testing::An<const Mantid::API::WorkspaceGroup_sptr &>())) - .Times(0); - EXPECT_CALL(mockView, updateImgWithIndex(testing::_)).Times(0); - - // No errors, no warnings - EXPECT_CALL(mockView, userError(testing::_, testing::_)).Times(0); - EXPECT_CALL(mockView, userWarning(testing::_, testing::_)).Times(0); - - pres.notify(ITomographyROIPresenter::ResetNormalization); - - TSM_ASSERT( - "Mock not used as expected. Some EXPECT_CALL conditions were not " - "satisfied.", - testing::Mock::VerifyAndClearExpectations(&mockView)); - } - - void test_shutDown() { - testing::NiceMock<MockTomographyROIView> mockView; - MantidQt::CustomInterfaces::TomographyROIPresenter pres(&mockView); - - EXPECT_CALL(mockView, saveSettings()).Times(1); - // No errors, no warnings - EXPECT_CALL(mockView, userError(testing::_, testing::_)).Times(0); - EXPECT_CALL(mockView, userWarning(testing::_, testing::_)).Times(0); - - pres.notify(TomographyROIPresenter::ShutDown); - - TSM_ASSERT( - "Mock not used as expected. Some EXPECT_CALL conditions were not " - "satisfied.", - testing::Mock::VerifyAndClearExpectations(&mockView)); - } - -private: - // boost::shared_ptr - boost::scoped_ptr<testing::NiceMock<MockTomographyROIView>> m_view; - boost::scoped_ptr<MantidQt::CustomInterfaces::TomographyROIPresenter> - m_presenter; - - // To have one FITS, etc. - Mantid::API::MatrixWorkspace_sptr m_ws; -}; - -#endif // MANTID_CUSTOMINTERFACES_TOMOGRAPHYROIPRESENTERTEST_H diff --git a/MantidQt/CustomInterfaces/test/TomographyROIViewMock.h b/MantidQt/CustomInterfaces/test/TomographyROIViewMock.h deleted file mode 100644 index c818e6ee7aa..00000000000 --- a/MantidQt/CustomInterfaces/test/TomographyROIViewMock.h +++ /dev/null @@ -1,112 +0,0 @@ -#ifndef MANTID_CUSTOMINTERFACES_TOMOGRAPHYROIVIEWMOCK_H -#define MANTID_CUSTOMINTERFACES_TOMOGRAPHYROIVIEWMOCK_H - -#include "MantidKernel/WarningSuppressions.h" -#include "MantidQtCustomInterfaces/Tomography/ITomographyIfaceView.h" - -#include <gmock/gmock.h> - -GCC_DIAG_OFF_SUGGEST_OVERRIDE - -class MockTomographyROIView - : public MantidQt::CustomInterfaces::ITomographyROIView { -public: - // void initParams(ImageStackPreParams ¶ms) - MOCK_METHOD1(setParams, - void(MantidQt::CustomInterfaces::ImageStackPreParams &)); - - // ImageStackPreParams userSelection() const; - MOCK_CONST_METHOD0(userSelection, - MantidQt::CustomInterfaces::ImageStackPreParams()); - - // SelectionState selectionState() const; - MOCK_CONST_METHOD0(selectionState, SelectionState()); - - // void changeSelectionState(const SelectionState state); - MOCK_METHOD1(changeSelectionState, - void(const ITomographyROIView::SelectionState &)); - - // void showStack(const std::string &path); - MOCK_METHOD1(showStack, void(const std::string &)); - - // void showStack(Mantid::API::WorkspaceGroup_sptr &ws, - // Mantid::API::WorkspaceGroup_sptr &wsgFlats, - // Mantid::API::WorkspaceGroup_sptr &wsgDarks); - MOCK_METHOD3(showStack, void(const Mantid::API::WorkspaceGroup_sptr &, - const Mantid::API::WorkspaceGroup_sptr &, - const Mantid::API::WorkspaceGroup_sptr &)); - - // const Mantid::API::WorkspaceGroup_sptr stackSamples() const; - MOCK_CONST_METHOD0(stackSamples, const Mantid::API::WorkspaceGroup_sptr()); - - // void showProjection(const Mantid::API::WorkspaceGroup_sptr &wsg, size_t - // idx); - MOCK_METHOD2(showProjection, - void(const Mantid::API::WorkspaceGroup_sptr &wsg, size_t idx)); - - // void userWarning(const std::string &warn, const std::string &description) - MOCK_METHOD2(userWarning, - void(const std::string &warn, const std::string &description)); - - // void userError(const std::string &err, const std::string &description) - MOCK_METHOD2(userError, - void(const std::string &err, const std::string &description)); - - // void enableActions(bool enable) - MOCK_METHOD1(enableActions, void(bool)); - - // Mantid::API::WorkspaceGroup_sptr currentImageTypeStack() const - MOCK_CONST_METHOD0(currentImageTypeStack, Mantid::API::WorkspaceGroup_sptr()); - - // void updateImageType(const Mantid::API::WorkspaceGroup_sptr wsg) - MOCK_METHOD1(updateImageType, - void(const Mantid::API::WorkspaceGroup_sptr wsg)); - - // size_t currentImgIndex() const; - MOCK_CONST_METHOD0(currentImgIndex, size_t()); - - // void updateImgWithIndex(size_t idx) - MOCK_METHOD1(updateImgWithIndex, void(size_t)); - - // void playStart( idx) - MOCK_METHOD0(playStart, void()); - - // void playStop() - MOCK_METHOD0(playStop, void()); - - // float currentRotationAngle() const - MOCK_CONST_METHOD0(currentRotationAngle, float()); - - // void updateRotationAngle(float angle) - MOCK_METHOD1(updateRotationAngle, void(float)); - - // std::string askImgOrStackPath(); - MOCK_METHOD1(askImagePath, std::string(const std::string &)); - - // std::string askColorMapFile(); - MOCK_METHOD0(askColorMapFile, std::string()); - - MOCK_METHOD1(imageOrStackLoaded, void(const std::string &)); - - // void updateColorMap(const std::string &filename); - MOCK_METHOD1(updateColorMap, void(const std::string &)); - - // void saveSettings() const {} - MOCK_CONST_METHOD0(saveSettings, void()); - - // void resetCoR() - MOCK_METHOD0(resetCoR, void()); - - // void resetROI() - MOCK_METHOD0(resetROI, void()); - - // void resetNormArea() - MOCK_METHOD0(resetNormArea, void()); - - // void resetNormArea() - MOCK_METHOD0(resetWidgetsOnNewStack, void()); -}; - -GCC_DIAG_ON_SUGGEST_OVERRIDE - -#endif // MANTID_CUSTOMINTERFACES_TOMOGRAPHYROIVIEWMOCK_H diff --git a/MantidQt/CustomInterfaces/test/TomographyViewMock.h b/MantidQt/CustomInterfaces/test/TomographyViewMock.h deleted file mode 100644 index 542dbfed903..00000000000 --- a/MantidQt/CustomInterfaces/test/TomographyViewMock.h +++ /dev/null @@ -1,139 +0,0 @@ -#ifndef MANTID_CUSTOMINTERFACES_TOMOGRAPHYIFACEVIEWMOCK_H -#define MANTID_CUSTOMINTERFACES_TOMOGRAPHYIFACEVIEWMOCK_H - -#include "MantidKernel/WarningSuppressions.h" -#include "MantidQtCustomInterfaces/Tomography/ITomographyIfaceView.h" - -#include <QString> - -#include <gmock/gmock.h> - -GCC_DIAG_OFF_SUGGEST_OVERRIDE - -// This is a simple mock for the tomo interface view when using SCARF. -class MockTomographyIfaceView - : public MantidQt::CustomInterfaces::ITomographyIfaceView { -public: - // void userWarning(const std::string &warn, const std::string &description) - // {} - MOCK_METHOD2(userWarning, - void(const std::string &warn, const std::string &description)); - - // void userError(const std::string &err, const std::string &description) {} - MOCK_METHOD2(userError, - void(const std::string &err, const std::string &description)); - - // std::vector<std::string> logMsgs() const {} - MOCK_CONST_METHOD0(logMsgs, std::vector<std::string>()); - - // void setComputeResources(const std::vector<std::string> &resources, - // const std::vector<bool> &enabled) {} - MOCK_METHOD2(setComputeResources, - void(const std::vector<std::string> &resources, - const std::vector<bool> &enabled)); - - // void setReconstructionTools(const std::vector<std::string> &tools, - // const std::vector<bool> &enabled) {} - MOCK_METHOD2(setReconstructionTools, - void(const std::vector<std::string> &tools, - const std::vector<bool> &enabled)); - - // void saveSettings() const {} - MOCK_CONST_METHOD0(saveSettings, void()); - - // std::string getPassword() const {} - MOCK_CONST_METHOD0(getUsername, std::string()); - - // std::string experimentReference() const {} - MOCK_CONST_METHOD0(experimentReference, std::string()); - - // std::string getPassword() const {} - MOCK_CONST_METHOD0(getPassword, std::string()); - - // std::vector<std::string> processingJobsIDs() const {} - MOCK_CONST_METHOD0(processingJobsIDs, std::vector<std::string>()); - - // std::string currentComputeResource() const {} - MOCK_CONST_METHOD0(currentComputeResource, std::string()); - - // std::string currentReconTool() const {} - MOCK_CONST_METHOD0(currentReconTool, std::string()); - - // void updateLoginControls(bool loggedIn) {} - MOCK_METHOD1(updateLoginControls, void(bool loggedIn)); - - // void enableLoggedActions(bool enable) {} - MOCK_METHOD1(enableLoggedActions, void(bool enable)); - - // void enableConfigTool(bool on) {} - MOCK_METHOD1(enableConfigTool, void(bool on)); - - // void enableRunReconstruct(bool on) {} - MOCK_METHOD1(enableRunReconstruct, void(bool on)); - - // TomoPathsConfig currentPathsConfig() const {} - MOCK_CONST_METHOD0(currentPathsConfig, - MantidQt::CustomInterfaces::TomoPathsConfig()); - - // void updatePathsConfig(const TomoPathsConfig &cfg) - MOCK_METHOD1(updatePathsConfig, - void(const MantidQt::CustomInterfaces::TomoPathsConfig &cfg)); - - // ImageStackPreParams currentROIEtcParams() const = 0; - MOCK_CONST_METHOD0(currentROIEtcParams, - MantidQt::CustomInterfaces::ImageStackPreParams()); - - // void showToolConfig(const std::string &name) {} - MOCK_METHOD1( - showToolConfig, - void(MantidQt::CustomInterfaces::TomoToolConfigDialogBase &dialog)); - - // virtual void updateJobsInfoDisplay( const - // std::vector<Mantid::API::IRemoteJobManager::RemoteJobInfo> - // &status, const - // std::vector<Mantid::API::IRemoteJobManager::RemoteJobInfo> & - // localStatus) = 0; - MOCK_METHOD2( - updateJobsInfoDisplay, - void(const std::vector<Mantid::API::IRemoteJobManager::RemoteJobInfo> & - status, - const std::vector<Mantid::API::IRemoteJobManager::RemoteJobInfo> & - localStatus)); - - // TomoSystemSettings systemSettings() const - MOCK_CONST_METHOD0(systemSettings, - MantidQt::CustomInterfaces::TomoSystemSettings()); - - // MantidQt::CustomInterfaces::TomoReconToolsUserSettings - // prePostProcSettings() const - MOCK_CONST_METHOD0(prePostProcSettings, - MantidQt::CustomInterfaces::TomoReconFiltersSettings()); - - // virtual std::map<std::string, std::string> - // currentAggregateBandsParams() const - typedef std::map<std::string, std::string> - workaroundForMSVCIssueWithVariadicMacros; - MOCK_CONST_METHOD0(currentAggregateBandsParams, - workaroundForMSVCIssueWithVariadicMacros()); - - // virtual void runAggregateBands(Mantid::API::IAlgorithm_sptr alg) - MOCK_METHOD1(runAggregateBands, void(Mantid::API::IAlgorithm_sptr alg)); - - // virtual bool userConfirmation(const std::string &title, const std::string - // &body) - MOCK_METHOD2(userConfirmation, - bool(const std::string &title, const std::string &body)); - - // virtual std::string getCachedExecutable() const = 0; - MOCK_CONST_METHOD0(getCachedExecutable, std::string()); - - // virtual std::vector<std::string> getCachedArguments() const = 0; - MOCK_CONST_METHOD0(getCachedArguments, std::vector<std::string>()); - - // virtual void externalProcessFinished(const QString &str) = 0; - MOCK_METHOD1(emitExternalProcessFinished, void(const QString &str)); -}; - -GCC_DIAG_ON_SUGGEST_OVERRIDE - -#endif // MANTID_CUSTOMINTERFACES_TOMOGRAPHYIFACEVIEWMOCK_H diff --git a/docs/source/algorithms/ImggAggregateWavelengths-v1.rst b/docs/source/algorithms/ImggAggregateWavelengths-v1.rst deleted file mode 100644 index 834b945dde7..00000000000 --- a/docs/source/algorithms/ImggAggregateWavelengths-v1.rst +++ /dev/null @@ -1,163 +0,0 @@ - -.. algorithm:: - -.. summary:: - -.. alias:: - -.. properties:: - -Description ------------ - -.. warning:: - - This algorithm is experimental and it is at the moment being - developed for a specific instrument (IMAT at ISIS). It might be - changed significantly, renamed, or even removed without a - notification, should instrument scientists decide to do so. - -.. warning:: - - The property **ToFRanges** requires specific headers in the input - (FITS) files and it is not enabled. At the moment, trying to use - this property will produce an error. - -This algorithm aggregates images from multiple energy bands or -wavelengths into one or more output wavelength bands. The algorithm -applies to energy selective imaging data. It aggregates images by -summing up counts, and assumes that the image pixel values represent -neutron counts. - -Given an input path (directory) and an output path (directory) the -algorithm will combine images from the input path and write the result -into the output path. Two different uses are considered: neutron -radiography (single projection angle) and tomography (multiple -projection angles). The image format supported is FITS (using the -algorithm :ref:`algm-LoadFITS`). - -The algorithm produces its main outputs as files on disk. It also -outputs two values: the number of projections (or angles) processed -successfully (which will be always one for neutron radiography), and -the number of wavelength bands aggregated. One and only one of the -options **UniformBands**, **IndexRanges** or **ToFRanges** must be -specified. This defines the number of output bands and how the input -bands are aggregated or combined into the output bands. - -For the sake of simplicity let us explain first the files that the -algorithm produces when a single output band is generated. This single -output band could correspond to the aggregation of all or a subset of -the input bands. This is the case when the property UniformBands is -set to 1, or the properties **IndexRanges** or **ToFRanges** are set -to a single range (and not multiple ranges separated by commas). - -For neutron radiography data the input path points to a set of image -files where every file is assumed to correspond to a different -wavelength or energy band. The algorithm will produce an image in the -output path by combining the energy bands selected (as specified in -the algorithm options, and using all the input images as default). - -For neutron tomography data the input path points to a set of -subdirectories, one per projection angle, and each of them containing -image files. It is assumed that each of the directories corresponds to -a projection angle. The algorithm will produce as many images in the -output path as subdirectories are found in the input path a single -image in the output path by combining the energy bands selected, -separately for every input subdirectory, i.e., projection angle -(selecting the bands as specified in the algorithm options, and using -all the input bands as default). The images are written in a -subdirectory that is named depending on the type of aggregation -used. For the uniform bands (**UniformBands** property) the -subdirectory will be named **bands_uniform_idx_<start>_to_<end>**, -where **<start>** and **<end>** are the limits of the range(s). When -the index ranges option (**IndexRanges**) is used the names of the -output subdirectory will be named -**bands_index_idx_<start>_to_<end>**. And when the time of flight -range option (**ToFRanges**) is used the names will be -**bands_tof_idx_<start>_to_<end>**. The initial prefix -(bands_uniform, bands_index, bands_tof) can be mofified via the -input properties **OutputSubdirsPrefixUniformBands**, -**OutputSubdirsPrefixIndexBands**, **OutputSubdirsPrefixToFBands**, -respectively. - -The output images are created as described above when there is a -single output band or stack of images. When multiple output ranges are -specified the outputs are produced similarly but every range will be -generated in a separate subdirectory created under the output path -given to the algorithm. For example the algorithm would produce -subdirectories named bands_by_index_idx_0_99, -bands_by_index_idx_50_149, and bands_by_index_idx_99_149, or -bands_uniform_idx_0_49, bands_uniform_idx_50_99. - -A relevant consideration is how to use the range options to generate -multiple output stacks of images. This is very important for -performance reasons and concerns how to use the properties -**IndexRanges** and **ToFRanges**. The comma separated list of ranges -enables the user to generate multiple output stacks of images in one -call to this algorithm. The same result can be obtained by calling the -algorithm repeatedly with the different individual ranges, one at a -time. This second alternative would be significantly slower though, -and it is discouraged to use that approach in scripts. That is because -the algorithm would need to read through the input images for every -individual call. This can make a big different in terms of run time, -given that this algorithm is meant to process large sets of images -which can take of the order of tens of minutes or hours to read and/or -write depending on the disk resources available. - - -As the algorithm tries to find images and subdirectories with images -from the input path, to decide whether to process the data as a single -projection (radiography) or multiple projections (tomography), there -can be ambiguities. When an input path is given that contains both -image files and subdirectories with image files, the algorithm -processes the image files and does not try to process the -subdirectories. That is, it is assumed that the input path given -contains data for a single projection, and that the subdirectories do -not necessarily contain images for different projections (tomography -data). - -Usage ------ - -**Example - ImggAggregateWavelengthsSingleProjection** - -.. code-block:: python - - # Create an image combining all energy bands - projections, bands = ImggAggregateWavelengths(InputPath='D:\Data\RB000000\SampleA\', - OutputPath='D:\Data\RB000000\SampleA_all_wavelenghts' - UniformBands=1) - - if 1 != projections: - print "An error happened. Expected to process one projection but processed: {0}".format(projections) - # Print some details - print "Wrote a projection image combining {1} wavelength bands".format(bands) - -Output: - -.. code-block:: none - - Wrote a projection image combining 2000 wavelength bands - -**Example - ImggAggregateWavelengthsTomography** - -.. code-block:: python - - # Create a stack of images that can be used in tomographic reconstruction - angles, bands = ImggAggregateWavelengths(InputPath='D:\Data\RB000000\SampleA\', - OutputPath='D:\Data\RB000000\SampleA\all_wavelenghts', - UniformBands=1) - - # Print some details - print "Wrote {0} projection images, each combining {1} wavelength bands".format(angles, bands) - -Output: - -.. code-block:: none - - Wrote 144 projection images, each combining 2000 wavelength bands - -.. categories:: - -.. sourcelink:: - diff --git a/docs/source/algorithms/ImggTomographicReconstruction-v1.rst b/docs/source/algorithms/ImggTomographicReconstruction-v1.rst deleted file mode 100644 index 709b0f076e9..00000000000 --- a/docs/source/algorithms/ImggTomographicReconstruction-v1.rst +++ /dev/null @@ -1,125 +0,0 @@ - -.. algorithm:: - -.. summary:: - -.. alias:: - -.. properties:: - -Description ------------ - -.. warning:: This is an early, experimental version of the algorithm. - -The input and output workspaces are workspace groups where every -element is an image workspace. In the input workspace every image is a -2D projection from a different angle whereas in the output workspace -every image is a slice of a reconstructed 3D volume. The input -workspace must have one image workspace per projection from a -tomography imaging experiment. The output workspace will have one -image workspace for every slice of the output reconstructed volume. - -The following method is supported: FBP (following the TomoPy -implementation [TomoPy2014]). - -The implementation of TomoPy methods are based on the TomoPy source -code available from https://github.com/tomopy/tomopy/, which is: - -:: - - Copyright 2015. UChicago Argonne, LLC. This software was produced - under U.S. Government contract DE-AC02-06CH11357 for Argonne National - Laboratory (ANL), which is operated by UChicago Argonne, LLC for the - U.S. Department of Energy. The U.S. Government has rights to use, - reproduce, and distribute this software. NEITHER THE GOVERNMENT NOR - UChicago Argonne, LLC MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR - ASSUMES ANY LIABILITY FOR THE USE OF THIS SOFTWARE. If software is - modified to produce derivative works, such modified software should - be clearly marked, so as not to confuse it with the version available - from ANL. - - Additionally, redistribution and use in source and binary forms, with - or without modification, are permitted provided that the following - conditions are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the - distribution. - - * Neither the name of UChicago Argonne, LLC, Argonne National - Laboratory, ANL, the U.S. Government, nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY UChicago Argonne, LLC AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL UChicago - Argonne, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. - -References: - -.. [TomoPy2014] Gursoy D, De Carlo F, Xiao X, - Jacobsen C. (2014). TomoPy: a framework for the analysis of - synchrotron tomographic data. J. Synchrotron Rad. 21. 1188-1193 - doi:10.1107/S1600577514013939 - - -Usage ------ - -**Example - ReconstructProjections** - -.. testcode:: ReconstructProjections - - # Note: you would load FITS images like this: - # wsg = LoadFITS(Filename='FITS_small_01.fits', LoadAsRectImg=1, OutputWorkspace='projections') - wsg_name = 'projections' - # Produce 16 projections with 32x32 pixels - projections = [] - unit_label=UnitFactory.create('Label') - unit_label.setLabel('width','cm') - for proj in range(0, 8): - wks_name = 'wks_proj_' + str(proj) - wks = CreateSampleWorkspace(NumBanks=32, BankPixelWidth=1, XMin=0, XMax=32, BinWidth=1, OutputWorkspace=wks_name) - wks.getAxis(0).setUnit('Label') - projections.append(wks) - wsg_proj = GroupWorkspaces(projections, OutputWorkspace=wsg_name) - wsg_reconstructed = ImggTomographicReconstruction(InputWorkspace=wsg_proj, CenterOfRotation=15) - rows = wsg_reconstructed.getItem(0).getNumberHistograms() - columns = wsg_reconstructed.getItem(0).blocksize() - print ("The output reconstruction has {0} slices of {1} by {2} pixels". - format(wsg_reconstructed.size(), rows, columns)) - slice_idx = 2 - coord_x = 8 - coord_y = 15 - print ("Value of pixel at coordinate ({0},{1}) in slice {2}: {3:.1f}". - format(coord_x, coord_y, slice_idx, - wsg_reconstructed.getItem(2).readY(coord_y)[coord_x])) - -.. testcleanup:: ReconstructProjections - - DeleteWorkspace(wsg_name) - -Output: - -.. testoutput:: ReconstructProjections - - The output reconstruction has 32 slices of 32 by 32 pixels - Value of pixel at coordinate (8,15) in slice 2: 2.4 - -.. categories:: - -.. sourcelink:: diff --git a/docs/source/algorithms/LoadSavuTomoConfig-v1.rst b/docs/source/algorithms/LoadSavuTomoConfig-v1.rst deleted file mode 100644 index 3ba9bc8ffb7..00000000000 --- a/docs/source/algorithms/LoadSavuTomoConfig-v1.rst +++ /dev/null @@ -1,76 +0,0 @@ -.. algorithm:: - -.. summary:: - -.. alias:: - -.. properties:: - -Description ------------ - -This algorithm reads a tomographic reconstruction parameterization -(configuration) file and stores the configuration in a `TableWorkspace -<http://www.mantidproject.org/TableWorkspace>`_. The file is expected -to follow the format used in the savu tomography reconstruction -pipeline `<https://github.com/DiamondLightSource/Savu>`__. These files -specify a sequence of plugins to be used for tomographic -reconstruction. For each plugin four fields are given in this order: -id, parameters, name, and cite. All fields are character strings. The -parameters field is formatted as a JSON string of name,value -pairs. The workspace produced has one row for every plugin found in -the input file, and four columns of string type. - -This algorithm is used by the IMAT tomography reconstruction interface -(GUI) to load and display configurations that can then be edited and -saved. - -Usage ------ - -**Example** - -.. testcode:: LoadSavuTomoConfig - - tws = LoadSavuTomoConfig("savu_test_data_process03.nxs", OutputWorkspace='savu_tomo_config') - print "Number of columns: %d" % tws.columnCount() - print "Number of rows / processing plugins: %d" % tws.rowCount() - print "Cell 0,0: %s" % tws.cell(0,0) - print "Cell 0,1: %s" % tws.cell(0,1) - print "Cell 0,2: %s" % tws.cell(0,2) - print "Cell 0,3: %s" % tws.cell(0,3) - print "Cell 1,0: %s" % tws.cell(1,0) - print "Cell 1,1: %s" % tws.cell(1,1) - print "Cell 1,2: %s" % tws.cell(1,2) - print "Cell 1,3: %s" % tws.cell(1,3) - print "Cell 2,0: %s" % tws.cell(2,0) - print "Cell 2,1: %s" % tws.cell(2,1) - print "Cell 2,2: %s" % tws.cell(2,2) - print "Cell 2,3: %s" % tws.cell(2,3) - -.. testcleanup:: LoadSavuTomoConfig - - DeleteWorkspace(tws) - -Output: - -.. testoutput:: LoadSavuTomoConfig - - Number of columns: 4 - Number of rows / processing plugins: 3 - Cell 0,0: savu.plugins.timeseries_field_corrections - Cell 0,1: {} - Cell 0,2: Timeseries Field Corrections - Cell 0,3: Not available - Cell 1,0: savu.plugins.median_filter - Cell 1,1: {"kernel_size": [1, 3, 3]} - Cell 1,2: Median Filter - Cell 1,3: Not available - Cell 2,0: savu.plugins.simple_recon - Cell 2,1: {"center_of_rotation": 86} - Cell 2,2: Simple Reconstruction - Cell 2,3: Not available - -.. categories:: - -.. sourcelink:: diff --git a/docs/source/algorithms/SCARFTomoReconstruction-v1.rst b/docs/source/algorithms/SCARFTomoReconstruction-v1.rst deleted file mode 100644 index 5dc8c313a62..00000000000 --- a/docs/source/algorithms/SCARFTomoReconstruction-v1.rst +++ /dev/null @@ -1,89 +0,0 @@ -.. algorithm:: - -.. summary:: - -.. alias:: - -.. properties:: - -Description ------------ - -Algorithm to control jobs running on the SCARF computer cluster at -RAL, STFC (see http://www.scarf.rl.ac.uk/ for more information). This -algorithm can be used to log in and out from the cluster, and to -initiate, query the status of, or cancel a job. It has been introduced -to control tomographic reconstruction jobs but in principle it can be -used for any other task. - -In a typical use case or session you would use the algorithm a first -time to login (for which you need to select the 'LogIn' action and set -the username and password fields). After this step you can use the -algorithm again several times, to submit jobs (setting the action -'SubmitJob'), query the status of the jobs running on the computer -cluster (setting the action to 'JobStatus' or 'JobStatusByID'), cancel -jobs (setting the action 'CancelJob') and log out from the cluster -(action 'LogOut'). You can also upload and download files. After -logging out, subsequent submit or status queries will fail with an -informative message. Note that the server will log out users every -undetermined amount of time, which depends on server settings. - -In principle, in a simple use case, the same username will be used in -all the calls to this algorithm. This means that you type in the -username only the first time that you use this algorithm, as it will -be remembered and filled in automatically in the next calls. But note -that it is possible to change the username passed to the algorithm -every time you call the algorithm. This means that you can use this -algorithm to control jobs for multiple users simultaneously from the -same instance of Mantid. You can use for example use the username -associated to a particular project or instrument, and in parallel your -personal username for different jobs (which can be useful to -distinguish quick tests, calibration of parameters, etc.). For this to -work, you of course need to perform a 'LogIn' action for every -username that is used in submit or query status actions. - -The 'JobStatus' and 'JobStatusByID' actions produce an output several -output properties with status and general information about the jobs, -as retrieved from the compute resource/server. - -The algorithm relies on a web service provided by the SCARF computer -cluster in order to control jobs on the cluster. If you use this -algorithm from its dialog (for example starting it from the algorithm -explorer in Mantid) the password will not be shown on the screen. This -algorithm can be used interactively. In such case, it is absolutely -not recommended to call it from scripts or the Python script -interpreter window, as you will be passing passwords as plain text. - -The alternative ways to monitor and control your jobs are via shell -login and via the web platform at https://portal.scarf.rl.ac.uk/. - -This algorithm is used by other components of Mantid, in particular -the custom graphical interface for tomography (IMAT instrument). - -Usage ------ - -**Example** - -.. testcode:: SCARFTomoReconstruction - - try: - SCARFTomoReconstruction(UserName='foouser', Action='Login') - except ValueError: - print "ValueError, as expected, because no Password= parameter given" - - try: - SCARFTomoReconstruction(UserName='foouser', Action='Submit') - except ValueError: - print "ValueError, as expected, as it was not previously logged on" - -Output: - -.. testoutput:: SCARFTomoReconstruction - - ValueError, as expected, because no Password= parameter given - ValueError, as expected, as it was not previously logged on - -.. categories:: - -.. sourcelink:: diff --git a/docs/source/algorithms/SaveSavuTomoConfig-v1.rst b/docs/source/algorithms/SaveSavuTomoConfig-v1.rst deleted file mode 100644 index ddedb427278..00000000000 --- a/docs/source/algorithms/SaveSavuTomoConfig-v1.rst +++ /dev/null @@ -1,66 +0,0 @@ -.. algorithm:: - -.. summary:: - -.. alias:: - -.. properties:: - -Description ------------ - -This algorithm writes a file with tomographic reconstruction -parameterization (configuration) file using the format of the savu -tomography reconstruction pipeline -(`<https://github.com/DiamondLightSource/Savu>`__). The parameters are -taken from a list of `TableWorkspace -<http://www.mantidproject.org/TableWorkspace>`_ workspaces. The data -in every workspace is expected to have four columns, with each row -specifying one plugin. For every plugin four character string -attributes (four columns) must be given, in this order: id, parameters -(JSON string of name-value pairs), name, and cite (citation -information about plugin documentation and authors). - -This algorithm is used by the IMAT tomography reconstruction interface -(GUI) to save configuration files that can then be used to run -tomography reconstruction jobs using the savu pipeline. - -Usage ------ - -**Example** - -.. testcode:: SaveSavuTomoConfig - - import os.path - tws_name = 'saveSavuTomoTest' - tws = CreateEmptyTableWorkspace(OutputWorkspace=tws_name) - tws.addColumn('str', 'ID') - tws.addColumn('str', 'Parameters') - tws.addColumn('str', 'Name') - tws.addColumn('str', 'Cite') - tws.addRow(['savu.id1', '{"param11": val1', 'plugin name1', 'cite info1']) - tws.addRow(['savu.id2', '{"param21": val2', 'plugin name2', 'cite info2']) - print "Columns: %d" % tws.columnCount() - print "Rows: %d" % tws.rowCount() - out_fname = 'saveSavuTomoTest.nxs' - SaveSavuTomoConfig(Filename=out_fname, InputWorkspaces='saveSavuTomoTest') - res = os.path.isfile(out_fname) - print "Save result: ", res - -.. testcleanup:: SaveSavuTomoConfig - - DeleteWorkspace(tws) - os.remove(out_fname) - -Output: - -.. testoutput:: SaveSavuTomoConfig - - Columns: 4 - Rows: 2 - Save result: True - -.. categories:: - -.. sourcelink:: diff --git a/docs/source/interfaces/Tomographic_Reconstruction.rst b/docs/source/interfaces/Tomographic_Reconstruction.rst deleted file mode 100644 index 3fa4756f6d2..00000000000 --- a/docs/source/interfaces/Tomographic_Reconstruction.rst +++ /dev/null @@ -1,497 +0,0 @@ -Tomographic Reconstruction -========================== - -.. contents:: Table of Contents - :local: - -Overview --------- - -This interface aims at integrating and simplifying the following tasks -related to tomographic reconstruction and imaging with neutrons. While -much of its functionality is being developed in a generic way, it is -presently being tested and trialed for the IMAT instrument at ISIS. - -.. interface:: Tomographic Reconstruction - :align: center - :width: 600 - -An important feature of this interface is the capability to submit -jobs to a remote compute resource (a compute cluster for -example). Currently remote jobs are run on the `SCARF cluster -<http://www.scarf.rl.ac.uk/>`_, administered by the Scientific -Computing Department of STFC. You can also use this cluster via remote -login and through its `web portal -<https://portal.scarf.rl.ac.uk/>`_. This resource is available for -ISIS users. - -.. warning:: This interface is undergoing heavy works. The tabs are - subject to changes and reorganization. New functionality is being added - and the pre-post-processing and reconstruction workflow is being - modified based on feedback from initial test data. - -Interface at a glance ---------------------- - -By default the interface shows the *Run* tab, where you can visualize -images, submit reconstruction jobs, see and control the status of the -jobs submitted recently. - -.. figure:: /images/tomo_tab1_submission_reconstruction_jobs.png - :align: right - :scale: 50% - -In the *Setup* tab you can set the details of the remote and/or local -compute resources. Importantly, here is where you can set you username -and password to log into the remote compute resource. To be able to -run jobs remotely you first need to log into the remote compute -resource. Once you log in, an automatic mechanism will periodically -query the status of jobs (for example every minute). You can also -update it at any time by clicking on the refresh button. - -In the *Setup* tab you also have to set the folders/directories where the -input data for reconstruction jobs is found. This information is -required every time you start analyzing a new dataset. The required -fields are: - -Samples directory - Directory containing the sample images - -Open beam directory - Where to find the open beam (flat/white) image(s) - -Dark field directory - Where to find the dark image(s) - -.. figure:: /images/tomo_tab2_setup_authentication.png - :align: center - :scale: 60% - -**NB**: This interface is under heavy development. Several practical -details lack polishing and/or are missing. This implies that there may -be usability issues at times and some steps may not be as intuitive or -simple as they could. Please, do not hesitate to provide suggestions -and feedback. - -The next sections provide further details that might be needed to -fully understand the process of generating tomographic reconstructions -with this interface. - -Tools ------ - -At the moment two reconstruction tools are being set up and trialed on -SCARF and some ISIS machines: - -* `TomoPy - <https://www1.aps.anl.gov/Science/Scientific-Software/TomoPy>`_ - -* `Astra Toolbox <http://visielab.uantwerpen.be/astra-toolbox>`_ found from - `here <http://sourceforge.net/p/astra-toolbox/wiki/Home/>`_. - -References for the Astra Toolbox: - -* W. van Aarle, W J. Palenstijn, J. De - Beenhouwer, T. Altantzis, S. Bals, K. J. Batenburg, and J. Sijbers, - "The ASTRA Toolbox: a platform for advanced algorithm development in - electron tomography", Ultramicroscopy, Vol. 147, p. 35–47, (2015) - -* W J. Palenstijn, K J. Batenburg, and J. Sijbers, "Performance - improvements for iterative electron tomography reconstruction using - graphics processing units (GPUs)", Journal of structural biology, - vol. 176, issue 2, pp. 250-253, 2011 - -References for TomoPy: - -* Gursoy D, De Carlo F, Xiao X, Jacobsen C. (2014). TomoPy: a - framework for the analysis of synchrotron tomographic - data. J. Synchrotron Rad. 21. 1188-1193 - doi:10.1107/S1600577514013939 - -In the near future it is expected that support will be added for -`Savu: Tomography Reconstruction Pipeline -<https://github.com/DiamondLightSource/Savu>`_, developed at the -Diamond Light Source. - -References for Savu: - -* Atwood R C, Bodey A J, Price S W T, Basham M and Drakopoulos M - 2015 A high-throughput system for high-quality tomographic reconstruction of - large datasets at diamond light source Philosophical Transactions A 373 20140398 - -Data formats ------------- - -In principle, users do not need to deal with specificities of -different file formats. That is the aim of this interface, but as it -is currently being developed, and for reference a brief list of -relevant file and data formats is given here: - -* FITS: `Flexible Image Transport System format - <http://en.wikipedia.org/wiki/FITS>`__ used to store images in - files. You can see the details on how FITS images can be loaded into - Mantid in the documentation of the algorithm :ref:`LoadFITS <algm-LoadFITS>`. - -* TIFF: `Tagged Image File Format - <http://en.wikipedia.org/wiki/Tagged_Image_File_Format>`__ images - used as FITS for image or slice files. This format is presently not - supported in the Mantid data analysis framework but it is used in - the tomographic reconstruction interface. - -* Diamond Light Source (DLS) NXTomo: a specific NeXus format used by - some of the tools that this interface supports or will support. See - next sections for details. - -These formats are used in different processing steps and parts of this -interface. For example, you can visualize FITS and TIFF images in the -**Run** tab and also in the **ROI etc.** tab. As another example, the -reconstruction tools typically need as inputs at least a stack of -images which can be in different formats, including a set of FITS or -TIFF files, or a single DLS NXTomo file. Other third party tools use -files in these formats as inputs, outputs or both. - -Data locations --------------- - -This is dependent on the facility and instrument. - -.. warning:: This is work in progress. At ISIS, in principle data will - be replicated in the ISIS archive, the IMAT disk space on - the cluster SCARF (remote compute resource), and possibly - an IMAT analysis machine. - -The path to the files of a particular tomographic reconstruction -consists of several components. An example path would be (on a Windows -system where the input/output data is on the drive "D"): - -* D:/data/RB987654321/experiment_foo/ - -where: - -* *data* is the root or base path for all tomography data. This folder - or directory is synchronized (at least partially) between the remote - compute resource and the (local) instrument analysis machine. - -* *RB987654321* is the experiment reference number (or so-called RB number) which usually starts with the prefix "RB". - -* *experiment_foo* is a name given by the user to the particular - experiment the data comes from. This is specified in free form. - -* inside the path there will normally be at least three folders or subdirectories for the sample, flat, and dark images: - - - data - - flat - - dark - - -As the files are mirrored on the remote computer cluster, if a network -drive has been added (or mapped) in the local system, for example -using the drive "S:", then the following path would contain a similar -tree of image files: - -* D:/data/RB987654321/experiment_foo/ - -The equivalent on a non-Windows system would be for example: - -* /media/scarf/data/RB987654321/experiment_foo/ - -These and related parameters can be inspected and modified in the -**System** tab. Their default values are -set for the current setup of the IMAT analysis machine. The "Reset -all" button resets all these settings to their factory defaults. Note -that the **Reset all** button currently requires **no confirmation**. -The **System** tab of the interface is currently a work in -progress and it may change significantly as required during -commissioning of IMAT. - -The tab *Visualization* has simple push buttons to browse the files -available from the local and remote locations, as well as any other -directory or folder selected by the user. The data for the different -experiments can be found under these locations. - -Running jobs remotely ---------------------- - -To be able to run jobs on a remote compute resource (cluster, supercomputer, etc.) - -* Log into the resource (in **Setup**) -* Then in **Run** select the compute resource and setup one - reconstruction tool -* Use the *Reconstruct* button in the **Run** tab of the interface - -You can monitor the status of the jobs currently running (and recently -run) on remote compute resources in the same tab. - -Setting common parameters for the reconstruction jobs ------------------------------------------------------ - -Before any reconstruction job is started several pre-/post-processing -options would normally need to be fine tuned for the sample data to be -processed correctly. The region of interest and the "air" region (or -region for normalization) can be set visually in the *ROI etc* tab. All -other pre- and post-processing settings are defined in the *Filters* tab. - -Regions -~~~~~~~ - -Several parameters can be set in the **ROI etc.** tab. These -parameters will be used for all the reconstruction jobs, regardless of -the tool and/or reconstruction method used. - -* Region of interest (ROI) for the analysis -* Area for normalization (open beam, not blocked by sample) -* Center of rotation, for tomographic reconstruction - -.. figure:: /images/tomo_tab3_ROI_etc.png - :align: center - :scale: 60% - -Stacks of images can be opened by using the browse button located at -the top of the interface. You can point the interface to a folder -(directory) containing directories for sample, dark, and flat images, -or alternatively to a folder containing images. The interface will -pick all the files recognized as images. - -At any stage during the process of selecting the regions it is also -possible to see how the selections fit different images by sliding -through the images of the stack (using the slider or scroll bar). - -The angle of the image can be changed by changing the Rotate(clockwise) -option. This will affect how the image is displayed locally and reconstructed. - -The center of rotation can be selected interactively by clicking on -the select button and then clicking on an image pixel. To select the -regions of interest or the area of normalization, just click on the -respective "Select" button and then click and drag with the mouse to -select a rectangle. The precise coordinates of the center and regions -can be set via the boxes of the right panel as well. - -Once you have selected or set one of the regions, or the center, they -can be selected again by pushing the respective "Select" buttons -and/or editing their coordinates manually. - -There is also the option to change the ColorMap that is used to show -the images ONLY **locally**. This can be done by **double** clicking -the ColorBar on the side and selecting a different ColorMap file. -The changes are only local and will NOT affect the reconstruction. - -The default values, set in principle when a new stack of images is -loaded, are as follows. The rotate angle is set to 0 degrees, -the region of interest is set to cover all the images. The region -of normalization is not set (empty), and the center of rotation is -set to the center of the image. The option to find the center of -rotation automatically is disabled at present. - -While selecting a region, if the mouse is moved outside of the images, -it is possible to continue the selection of the region (second corner) -by clicking again inside the image. Alternatively, any selection can -be reset at any point by using the "Reset" buttons. - -When loading a stack of images, note that when the images are loaded -from the folder(s) (directorie(s)) any files with unrecognized -extension or type (for example .txt) will be ignored. Normally a -warning about this will be shown in the Mantid logs. Image files with -the string **_SummedImg** at the end of their names will be skipped as -well, as this is a convention used by some detectors/control software -to generate summed images. - -Pre-/post-processing -~~~~~~~~~~~~~~~~~~~~ - -The **Filters** tab can be used to set up the pre- and post-processing -steps. These are applied regardless of the particular tomographic -reconstruction tool and algorithm used when running reconstruction -jobs. Pre-processing filters are applied on the raw input images -before the reconstruction algorithm is run. Post-processing steps are -applied on the reconstructed volume produced by the algorithm. - -.. figure:: /images/tomo_tab4_pre_post_proc_filters.png - :align: center - :scale: 60% - -Among other options, normalization by flat and/or dark images can be -enabled here. Note that this setting is global and will be effective -for any input dataset. In the **Setup** tab it is possible to -enable or disable them specifically for the dataset being processed. - -The tab also shows options to define what outputs should be produced -in addition to the reconstructed volume. - -The settings are remembered between sessions. It is possible to reset -all the settings to their original defaults by clicking on the reset -button. - -Results from reconstruction jobs --------------------------------- - -The results are written into the output paths selected in the -interface (in the *Setup* tab). For every reconstructed -volume a sequence of images (slices along the vertical axis) are -written. In addition, two complementary outputs are generated in the -same location: - -* A *readme* file with detailed information on the reconstruction and - settings (0.README_reconstruction.txt), including paths, algorithms, - filters and parameters used. - -* A compressed package file that contains the scripts and subpackages - used for the reconstruction job, for reproducibility and to make it - easier to track down potential issues. This file is written as - 0.reconstruction_scripts.zip - -Running jobs locally --------------------- - -You can run local reconstructions as well, however that requires properly setting up the: - -* External python interpretor path, for example: - - - `C:/Anaconda/python.exe for Windows` - - `~/Anaconda2/bin/python for Linux` - -* PYTHONPATH environment variable should contain the Python directories - that have the installed plugins for the supported tools - -* (Optional) Scripts directory - - By default this will be properly setup from the Mantid installation - -Visualization -------------- - -.. warning:: The interface is being extended to have integration with - third party tools for 3D visualization and segmentation. - This is work in progress. - -The **Visualization** tab can be used to browse the local and remote -locations where results are stored. It is also possible to open these -results in third party visualization applications. **NB**: ParaView is -currently supported and additional tools are being integrated. - -.. figure:: /images/tomo_tab5_send_to_viz.png - :align: center - :scale: 60% - -Energy bands ------------- - -.. warning:: The interface is being extended to provide different methods - of combining energy bands from energy selective experiments. - This is work in progress. - -Here it is possible to aggregate stacks of images normally acquired as -energy/wavelength selective data. This interface is based on the -algorithm :ref:`ImggAggregateWavelengths <algm-ImggAggregateWavelengths>` which -supports different ways of aggregating the input images. In the -simplest case, a number of output bands can be produced by aggregating -the input bands split into uniform segments. This is called "uniform -bands". When the number of uniform bands is one, all the wavelengths -are aggregated into a single output stack. It is also possible to -specify a list of boundaries or ranges of image indices. For example -if an input dataset consists of 1000 images per projection angle (here -indexed from 0 to 999), three partially (50%) overlapping output bands -could by produced by specifying the ranges as "0-499, 250-749, -500-999". In principle it is also possible to aggregate images by time -of flight ranges, based on specific extension headers that must be -included in the input (FITS) images. This option is disabled at the -moment. Please refer to the documentation of :ref:`ImggAggregateWavelengths -<algm-ImggAggregateWavelengths>` for lower level details on how the -algorithm processes the input directories and files. - -.. figure:: /images/tomo_tab7_energy_bands.png - :align: center - :scale: 60% - -Convert image formats ---------------------- - -.. figure:: /images/tomo_tab6_formats_convert.png - :align: center - :scale: 60% - -This interface provides a simple way of converting stacks of images -between diferent formats. This is for convenience and interoperability -with third party tools that for example may not be able to load FITS -images but require them in TIFF format. All the images found under the -input path (directory) will be converted from the input format -selected into the output format. The output images will be created -under the output path (directory) with the same tree structure as the -input images. - -The conversion process will look for images recursively inside the -input directory. That is, it will process all its subdirectories and -the subdirectories of these up to a given maximum depth. To limit the -search depth. The usual default value is 3 which is sufficient for -stacks of images and sets of stacks of images from a series of samples -for an experiment, following the conventions for IMAT tomography -data. If higher depth values than the default are used we recommend to -take extreme care, making sure the input path given makes sense. This -process can be lengthy and demanding in terms of disk space when -processing more than one or a small number of experiments (RB -reference numbers), and especially so for wavelength dependent -experiments. - -System ------- - -.. figure:: /images/tomo_tab8_system_options.png - :align: center - :scale: 60% - -In the System tab you can specify the input folder names -for the sample, flat, and dark images, and also the names of the output folders. -The base paths for the SCARF file system can also be set here. Two options -are included. The first one specifies where the Tomography data is found in the -cluster, and the second specifies where the reconstruction tools and scripts -can be found. -The path can be changed to point to your own specific data and scripts on the -SCARF cluster, so it could be helpful to create different directories for -different scripts rather than changing the default script located in the default -directory. - -Example -------- - -TODO: there should be a worked out example using a small data set. - -TomoPy ------- - -TODO: how to use it. Hints. - -Astra Toolbox -------------- - -TODO: how to use it. Hints. - -MuhRec ------- - -TODO: how to use it. Hints. - -Savu ----- - -TODO: how to use it. Hints. - -Savu uses a specific file format developed by the Diamond Light -Source, the DLS NXTomo. A few examples can be found from `the savu -repository on GitHub -<https://github.com/DiamondLightSource/Savu/tree/master/test_data>`__. - -Pipeline configuration -~~~~~~~~~~~~~~~~~~~~~~ - -A Savu reconstruction pipeline is defined by a list of processing -steps (or plugins) and their parameters. In the Savu setup dialog this -list is built on the right panel (current configuration) by adding and -sorting available plugins available from the tree shown on the left -panel. From the file menu, different savu configurations can be saved for -later use and loaded from previously saved files. - -.. Leave this out for now. Not used at the moment. - .. interface:: Tomographic Reconstruction - :widget: savuConfigCentralWidget - :align: right - - -.. categories:: Interfaces Diffraction diff --git a/scripts/Imaging/IMAT/__init__.py b/scripts/Imaging/IMAT/__init__.py deleted file mode 100644 index 763e55451a6..00000000000 --- a/scripts/Imaging/IMAT/__init__.py +++ /dev/null @@ -1,23 +0,0 @@ -from __future__ import (absolute_import, division, print_function) -# Copyright © 2015 ISIS Rutherford Appleton Laboratory, NScD -# Oak Ridge National Laboratory & European Spallation Source -# -# This file is part of Mantid. -# Mantid is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3 of the License, or -# (at your option) any later version. -# -# Mantid is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see <http://www.gnu.org/licenses/>. -# -# File change history is stored at: <https://github.com/mantidproject/mantid>. -# Code Documentation is available at: <http://doxygen.mantidproject.org> -""" -3D Tomographic reconstruction being devepeloped for the IMAT instrument -""" diff --git a/scripts/Imaging/IMAT/agg_energy_bands.py b/scripts/Imaging/IMAT/agg_energy_bands.py deleted file mode 100644 index 44b39f203c8..00000000000 --- a/scripts/Imaging/IMAT/agg_energy_bands.py +++ /dev/null @@ -1,87 +0,0 @@ -""" -Command line tool to aggregate multiple bands from energy selective imaging experiments. -This simply provides a command line interface to prep.energy_bands_aggregator - -To print usage details: -ipython agg_energy_bands.py --help - -Usage example: -ipython -- agg_energy_bands.py --input-path=~/test/LARMOR/test_few_angles/ --output-path=out_stack_test - -ipython -- agg_energy_bands.py --input-path=~/test/LARMOR/test_few_angles/ --output-path=out_stack_test --energy-bands=100,299 --format=png - -""" -# Copyright © 2015 ISIS Rutherford Appleton Laboratory, NScD -# Oak Ridge National Laboratory & European Spallation Source -# -# This file is part of Mantid. -# Mantid is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3 of the License, or -# (at your option) any later version. -# -# Mantid is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see <http://www.gnu.org/licenses/>. -# -# File change history is stored at: <https://github.com/mantidproject/mantid>. -# Code Documentation is available at: <http://doxygen.mantidproject.org> - -import IMAT.prep.energy_bands_aggregator as eba -import argparse - - -def _indices_to_tuple(indices): - """ - See if we have energy band indices. Turn something like '100,200' to a tuple (100,200) - - @param indices :: indices given by the user - - Returns:: a tuple with the min and max indices - """ - tidx = None - if indices: - idxlist = indices.split(',') - if 2 != len(indices) or not isinstance(indices[0], int) or not isinstance(indices[1], int): - tidx = (int(idxlist[0]), int(idxlist[1])) - else: - raise ValueError("Wrong energy band indices given: {0}. " - "I expect two integers separated by a comma".format( - indices)) - return tidx - - -def agg_cli(): - """ - Provides a command line interface to the EnergyBandsAggregator - """ - arg_parser = argparse.ArgumentParser() - eb_agg = eba.EnergyBandsAggregator() - - arg_parser.add_argument("-i","--input-path", required=True, help="Input directory") - arg_parser.add_argument("-o","--output-path", help="Where to write the output stack of (aggregated) images. " - "If left empty a default '{0}' in the current working directory.". - format(eb_agg.default_out_path)) - arg_parser.add_argument("-b","--energy-bands", help="Energy band indices to aggregate into the outputs. " - "Must be given as two integer values separated by comma. " - "The indices start from 0. By default all bands are included.") - arg_parser.add_argument("-t","--agg-type", help="Type of aggregation. Supported: {0} ". - format(eb_agg.supported_aggs)) - - arg_parser.add_argument("-f","--format", help="Format of output files. Supported: {0}. Default: {1}.". - format(eb_agg.supported_out_formats, - eb_agg.default_out_format)) - - args = arg_parser.parse_args() - tidx = _indices_to_tuple(args.energy_bands) - - eb_agg.agg_angles(args.input_path, args.output_path, band_indices=tidx, agg_method=args.agg_type, - out_format=args.format) - - -if __name__=='__main__': - agg_cli() diff --git a/scripts/Imaging/IMAT/prep/__init__.py b/scripts/Imaging/IMAT/prep/__init__.py deleted file mode 100644 index b1f7f578082..00000000000 --- a/scripts/Imaging/IMAT/prep/__init__.py +++ /dev/null @@ -1,36 +0,0 @@ -# Copyright © 2014-2015 ISIS Rutherford Appleton Laboratory, NScD -# Oak Ridge National Laboratory & European Spallation Source -# -# This file is part of Mantid. -# Mantid is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3 of the License, or -# (at your option) any later version. -# -# Mantid is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see <http://www.gnu.org/licenses/>. -# -# File change history is stored at: <https://github.com/mantidproject/mantid>. -# Code Documentation is available at: <http://doxygen.mantidproject.org> -""" -Pre-processing operations and filters that are applied on stacks of images -or individual images. -""" - -ERR_MSG = ("Inconsistency found. Could not import {0} which " - "should be available in this package. Details: {1}") - -try: - from . import filters -except ImportError as exc: - raise ImportError(ERR_MSG.format('filters', exc)) - -try: - from . import filters_adv -except ImportError as exc: - raise ImportError(ERR_MSG.format('filters_adv', exc)) diff --git a/scripts/Imaging/IMAT/prep/energy_bands_aggregator.py b/scripts/Imaging/IMAT/prep/energy_bands_aggregator.py deleted file mode 100644 index a1f0a96a0db..00000000000 --- a/scripts/Imaging/IMAT/prep/energy_bands_aggregator.py +++ /dev/null @@ -1,365 +0,0 @@ -# Copyright © 2014-2015 ISIS Rutherford Appleton Laboratory, NScD -# Oak Ridge National Laboratory & European Spallation Source -# -# This file is part of Mantid. -# Mantid is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3 of the License, or -# (at your option) any later version. -# -# Mantid is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see <http://www.gnu.org/licenses/>. -# -# File change history is stored at: <https://github.com/mantidproject/mantid>. -# Code Documentation is available at: <http://doxygen.mantidproject.org> - -import glob -import os -import re -import sys -import time - -try: - from skimage import io as skio -except ImportError: - raise ImportError("Cannot find the package 'skimage.io' which is required to read/write image files in " - "TIFF and other formats") - -try: - from skimage import exposure -except ImportError: - raise ImportError("Unable to import package skimage.exposure which is required to write output image " - "files with correct range of values") - -# Ideally, use freeimage plugin. That provides good support for tiff, png, and more -# Backup solution: tifffile required for tiff format; skimage provides basic png, etc. support. -try: - skio.use_plugin('freeimage') -except RuntimeError: - FREEIMG_ERR_MSG = "Could not find the plugin 'freeimage' in skimage." - # Because tifffile is going to be imported later on (in skio.imsave()) - check that it can be imported - if not __package__: - try: - # it is unused here - it will be used by the tiff skio plugin - #pylint: disable=unused-import - import tifffile - _USING_PLUGIN_TIFFFILE = True - except ImportError: - raise ImportError("Cannot find the package 'tifffile' which is required to read/write TIFF image " - "files." + FREEIMG_ERR_MSG) - else: - try: - #pylint: disable=no-name-in-module - from . import tifffile - _USING_PLUGIN_TIFFFILE = True - except ImportError: - try: - import tifffile # noqa - _USING_PLUGIN_TIFFFILE = True - except ImportError: - raise ImportError("Cannot find the package 'tifffile' in the system or together with this " - "module. It is required to read/write TIFF image files. " + FREEIMG_ERR_MSG) - - -try: - import pyfits -except ImportError: - # In Anaconda python, the pyfits package is in a different place, and this is what you frequently - # find on windows. - try: - import astropy.io.fits as pyfits - except ImportError: - raise ImportError("Cannot find the package 'pyfits' which is required to read/write FITS image files") - -try: - import numpy as np -except ImportError: - raise ImportError("Cannot find the package 'numpy' which is required to calculate aggregated images") - -# alternative for when other plugins are not available. It can be distributed -# and copied on remote machines where there are no other options -_USING_PLUGIN_TIFFFILE = False - -#pylint: disable=too-many-instance-attributes - - -class EnergyBandsAggregator(object): - """ - Combines energy bands, producing stacks of images with one image per projection angle from - energy-banded stacks of images (in which there can be thousands of images per projection angle). - - Usage example: - eb_agg = Energy_Bands_Aggregator() - eb_agg.agg_angles("~/test/LARMOR/test_few_angles/", "output_stack_all_bands") - - where the input directory (first argument) is expected to have several directories like 'angle0', - 'angle1'... 'angle100', etc. - """ - - default_out_path = None - supported_aggs = None - supported_out_formats = None - default_out_format = None - - def __init__(self, out_format='tiff', out_type='uint16'): - """ - @param out_format :: format for the output image files. The list of supported format - is given in in the attribute supported_out_formats. Default: tiff - - @param out_type :: pixel type for the output image files. Default: 2 bytes integer - """ - # a default output path name for when the user doesn't provide any - self.default_out_path = 'out_agg_stack' - # types of aggregation across energy bands - self.supported_aggs = ['sum', 'average'] - # format of the output images. - self.supported_out_formats = ['tiff', 'png'] - # because tiff is the most common choice of third party tools - self.default_out_format = 'tiff' - # the default one - self._out_format = out_format - - # plain sum by default - self._default_agg_method = self.supported_aggs[0] - # default pixel type of output files. Only this one supported for now. - self._default_output_type = out_type - # to handle the image index when doing incremental calculations - self.__img_idx = 1 - - def _write_image(self, img_data, filename, img_format=None, dtype=None): - """ - Output image data to a file, in a given image format. - Assumes that the output directory exists (must be checked before). - - @param img_data :: image data in the usual numpy representation - @param filename :: file name, including directory and extension - @param img_format :: image file format - @param dtype :: can be used to force a pixel type, otherwise the type - of the input data is used - - Returns :: name of the file saved - """ - if not img_format: - img_format = self.default_out_format - filename = filename + '.' + img_format - - if dtype and img_data.dtype != dtype: - img_data = np.array(img_data, dtype=dtype) - - if img_format == 'tiff' and _USING_PLUGIN_TIFFFILE: - img_data = exposure.rescale_intensity(img_data, out_range='uint16') - skio.imsave(filename, img_data, plugin='tifffile') - else: - img_data = exposure.rescale_intensity(img_data, out_range='uint16') - skio.imsave(filename, img_data) - - return filename - - def _make_dirs_if_needed(self, dirname): - """ - Makes sure that the directory needed to save the file exists, or creates it - - @param dirname :: (output) directory to check - """ - absname = os.path.abspath(dirname) - if not os.path.exists(absname): - os.makedirs(absname) - - def _alphanum_key_split(self, path_str): - """ - From a string to a list of alphabetic and numeric elements. Intended to - be used for sequence number/natural sorting. In list.sort() the - key can be a list, so here we split the alpha/numeric fields into - a list. For example (in the final order after sort() would be applied): - - "angle4" -> ["angle", 4] - "angle31" -> ["angle", 31] - "angle42" -> ["angle", 42] - "angle101" -> ["angle", 101] - - Several variants compared here: - https://dave.st.germa.in/blog/2007/12/11/exception-handling-slow/ - """ - ALPHA_NUM_SPLIT_RE = re.compile('([0-9]+)') - return [ int(c) if c.isdigit() else c for c in ALPHA_NUM_SPLIT_RE.split(path_str) ] - - def _agg_img(self, acc, img_data, agg_method=None, index=1): - """ - Adds in data coming from a new image/hdu. Expects a numpy array of shape (N1, N2) where - N1 and N2 are the number of rows and columns of the images. - - @param acc :: aggregated value accumulated so far - @param img_data :: new image to add in - @param agg_method :: whether to sum, average, etc. See options supported. - @param index :: image index used when calculating incremental statistics like the average - - Returns :: result from aggregating (sum, average, etc.) the new image - """ - if agg_method is None: - agg_method = self._default_agg_method - - if 'sum' == agg_method: - acc = np.add(acc, img_data) - elif 'average' == agg_method: - acc = np.add((index-1)*acc/index, img_data/index) - - return acc - - #pylint: disable=too-many-arguments - def agg_indiv_angle(self, path_proj, band_indices=None, imgExt='fits', agg_method=None, - verbose=True, too_verbose=False): - """ - Aggregates (sum, average, etc.) all the energy bands selected for one projection angle and - returns it. The aggregation is done sequentially through the potentially thousands of energy - band images available for one projection angle. This requires memory for just two images at once. - It aggregates between given minimum and maximum indices. - - @param path_proj :: path to the angle/projection subdirectory (ex.: '~/test/IMAT/test1/angle10'). - - @param band_indices :: a typle with minimum and maximum indices of the energy bands/images - to aggregate. Empty implies all bands. Their validity must have been checked before/elsewhere. - - @param imgExt :: extension of image files. Only fits supported for now as this is the format - that we get from the intrument/cameras. - - @param agg_method :: whether to sum, average, etc. See options supported. - - Returns :: an aggregated image as a 2-dimensional numpy array with size number of image - rows x columns. - """ - img_files = glob.glob(os.path.join(path_proj, "*[0-9]." + imgExt)) - if len(img_files) <= 0: - raise RuntimeError("No image files found in " + path_proj) - - imgs = pyfits.open(img_files[0]) - if len(imgs) < 1: - raise RuntimeError( - "Could not load at least one image from path: {0}".format(path_proj)) - - data_dtype = imgs[0].data.dtype - # from fits files we usually get this, just change it to uint16 - if '>i2' == data_dtype: - data_dtype = np.uint16 - accum = np.zeros((imgs[0].shape[0], imgs[0].shape[1]), dtype=data_dtype) - - # filter, keep only the files between min and max indices given - if band_indices: - img_files = [f for idx,f in enumerate(img_files) if - idx >= band_indices[0] and idx <= band_indices[1] ] - - for ifile in img_files: - if too_verbose: - sys.stdout.write('.') - - hdu = None - try: - hdu = pyfits.open(ifile) - except IOError as exc: - print "Got I/O exception trying to open and load {0}: {1}. Ignoring and going on.".format( - ifile, str(exc)) - continue - - accum = self._agg_img(accum, hdu[0].data, agg_method=agg_method) - - if too_verbose: - sys.stdout.write('\n') - - if verbose: - print "Aggregated {0} images. Stats of result image. "\ - "Max : {1}, min: {2}, per-pixel-avg: {3:.3f}, all-sum: {4}".format( - len(img_files), np.amax(accum), np.amin(accum), np.average(accum), np.sum(accum)) - - return accum - - def _check_inputs_to_agg_angles(self, in_path, output_path, out_format, band_indices): - """ Checks relevant user inputs""" - if not in_path: - raise ValueError("The input path cannot be empty") - - if output_path is None: - output_path = self.default_out_path - - if out_format: - self._out_format = out_format - if not isinstance(self._out_format, str) or self._out_format not in self.supported_out_formats: - raise ValueError("Only the following output formats are supported: {0}. Format requested: {1}". - format(self.supported_out_formats, self._out_format)) - - if band_indices: - if 2 != len(band_indices) or not isinstance(band_indices[0], int) or\ - not isinstance(band_indices[1], int): - raise ValueError("Wrong min-max energy band indices given: {0}".format(band_indices)) - if band_indices[0] > band_indices[1]: - raise ValueError("The minimum energy band index must be lower than the maximum index") - - #pylint: disable=too-many-arguments - def agg_angles(self, in_path, output_path=None, band_indices=None, - agg_method='sum', out_format=None, angle_subdir_prefix='angle', - verbose=True, too_verbose=False, out_files_name_prefix='angle_agg_', zero_pad=6): - """ - Aggregate a stack, processing all the angles (projections) found. Produces an output stack with - one single image per projection into an output directory. Does not store all the images in - memory, only one at a time. - - @param in_path :: path to the multi-energy-band (energy selective) stack of images. It is - expected to have several directories with the prefix 'angle' and additional alphanumeric - characters (example: 'angle0', 'angle1', etc.) - - @param band_indices :: a typle with minimum and maximum indices of the energy bands/images - to aggregate. Empty implies all bands. This method checks the validity of the values (if) given. - - @param output_path :: where to write the output image files - - @param angle_subdir_prefix :: prefix for the individual angle subdirectories. For example, - 'angle', as used for IMAT data. Directories that do not match this are ignored. - - @param verbose :: write progress info and additional messages to the standard output - - @param too_verbose :: write more detailed progress information, for testing purposes - - @param zero_pad :: width (number of digits) to pad the index number to, in the output file - names - """ - self._check_inputs_to_agg_angles(in_path, output_path, out_format, band_indices) - - # in case they use '~' or similar - in_path = os.path.expanduser(in_path) - - # This is the big loop through every angle's of the order of 1000s individual energy bands - if verbose: - print "Looking for projection angles in {0}".format(in_path) - - angle_subdirs = glob.glob(os.path.join(in_path, "{0}*".format(angle_subdir_prefix))) - angle_subdirs.sort(key=self._alphanum_key_split) - - print "Found {0} projection (angle) subdirectories.".format(len(angle_subdirs)) - - # Prepare output directory - self._make_dirs_if_needed(output_path) - - start = time.time() - for idx, adir in enumerate(angle_subdirs): - print "Processing projection angle subdirectory: {0}".format(adir) - - # produce aggregated image - img_data = self.agg_indiv_angle(adir, band_indices, agg_method=agg_method, - verbose=verbose, too_verbose=too_verbose) - - # write into output image - if self._default_output_type != img_data.dtype: - img_data = img_data.astype(self._default_output_type) - - out_name = os.path.join(output_path, out_files_name_prefix + str(idx).zfill(zero_pad)) - - out_name = self._write_image(img_data=img_data, filename=out_name, - img_format=self._out_format, dtype=img_data.dtype) - - if verbose: - print "Output image written in: {0}".format(out_name) - tnow = time.time() - print "Time elapsed: {0:.3f}".format(tnow - start) diff --git a/scripts/Imaging/IMAT/prep/filters.py b/scripts/Imaging/IMAT/prep/filters.py deleted file mode 100644 index cb6c7eed719..00000000000 --- a/scripts/Imaging/IMAT/prep/filters.py +++ /dev/null @@ -1,208 +0,0 @@ -# Copyright © 2014-2015 ISIS Rutherford Appleton Laboratory, NScD -# Oak Ridge National Laboratory & European Spallation Source -# -# This file is part of Mantid. -# Mantid is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3 of the License, or -# (at your option) any later version. -# -# Mantid is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see <http://www.gnu.org/licenses/>. -# -# File change history is stored at: <https://github.com/mantidproject/mantid>. -# Code Documentation is available at: <http://doxygen.mantidproject.org> - -import numpy as np - - -def scale_down(data_vol, block_size, method='average'): - """ - Downscale to for example shrink 1Kx1K images to 512x512 - - @param data_vol :: 3d volume to downscale - @param block_size :: make block_size X block_size blocks to downscale - @param method :: either 'average' (default) or 'sum' to calculate average or sum of blocks - - Returns :: downscaled volume, with the dimensions implied by block_size, and the - same data type as the input data volume. - """ - if not isinstance(data_vol, np.ndarray) or 3 != len(data_vol.shape): - raise ValueError( - "Wrong data volume when trying to crop (expected a 3d numpy array): {0}". - format(data_vol)) - if block_size > data_vol.shape[1] or block_size > data_vol.shape[2]: - raise ValueError( - "Block size too large when trying to crop data volume. Block size: {0}, " - "data dimensions: {1}".format(block_size, data_vol.shape)) - - if 0 != np.mod(data_vol.shape[1], block_size) or 0 != np.mod( - data_vol.shape[2], block_size): - raise ValueError( - "The block size ({0}) must be an exact integer divisor of the sizes of the " - "x and y dimensions ({1} and {2} of the input data volume".format( - data_vol.shape[2], data_vol.shape[1], block_size)) - - supported_methods = ['average', 'sum'] - if method.lower() not in supported_methods: - raise ValueError( - "The method to combine pixels in blocks must be one of {0}. Got unknown " - "value: {1}".format(supported_methods, method)) - - rescaled_vol = np.zeros( - (data_vol.shape[0], data_vol.shape[1] // block_size, - data_vol.shape[2] // block_size), - dtype=data_vol.dtype) - # for block averages in every slice/image along the vertical/z axis - tmp_shape = rescaled_vol.shape[1], block_size, rescaled_vol.shape[ - 2], block_size - for vert_slice in range(len(rescaled_vol)): - vsl = data_vol[vert_slice, :, :] - if 'average' == method: - rescaled_vol[vert_slice, :, :] = vsl.reshape(tmp_shape).mean( - -1).mean(1) - elif 'sum' == method: - rescaled_vol[vert_slice, :, :] = vsl.reshape(tmp_shape).mean( - -1).mean(1) - - return rescaled_vol - - -def crop_vol(data_vol, coords): - """ - Crops a data volume by a rectangle defined by two corner - coordinates. Crops along the z axis (outermost numpy array index) - - @param data_vol :: 3D data volume - @param coords :: coordinates of the corners that define a rectangle box (crop to this - box, as when cropping to the regions of interest). - Returns :: cropped data volume - """ - # if nothing is provided make the user aware - if not isinstance(coords, list) or 4 != len(coords): - raise ValueError( - "Wrong coordinates object when trying to crop: {0}".format(coords)) - elif not isinstance(data_vol, np.ndarray) or 3 != len(data_vol.shape): - raise ValueError("Wrong data volume when trying to crop: {0}".format( - data_vol)) - # move into named variables for ease of use - left = coords[0] - top = coords[1] - right = coords[2] - bottom = coords[3] - - cropped_data = None - if not any(coords) or top > bottom or left > right: - # skip if for example: 0, 0, 0, 0 (empty selection) - print(" ! No coordinates given, not cropping the images") - return data_vol - elif not all(isinstance(crd, int) for crd in coords): - raise ValueError( - "Cannot use non-integer coordinates to crop images. Got " - "these coordinates: {0}".format(coords)) - else: - cropped_data = data_vol[:, top:bottom, left:right] - - return cropped_data - - -def remove_stripes_ring_artifacts(data_vol, method='wavelet-fourier'): - """ - Removal of stripes in sinograms / ring artifacts in reconstructed - volume. - - This is an unimplemented stub at the moment. - As first step it should implement one methods: the combined wavelet-Fourier method - (Muench et al. 2009, Opt Express, 17(10), 8567-91), as implemented also in tomopy. - - @param data_vol :: stack of projection images as 3d data (dimensions z, y, x), with - z different projections angles, and y and x the rows and columns of individual images. - - @param method :: 'wf': Wavelet-Fourier based method - - Returns :: filtered data hopefully without stripes which should dramatically decrease - ring artifacts after reconstruction and the effect of these on post-processing tasks - such as segmentation of the reconstructed 3d data volume. - """ - supported_methods = ['wavelet-fourier'] - - if not isinstance(data_vol, np.ndarray) or 3 != len(data_vol.shape): - raise ValueError( - "Wrong data volume when trying to filter stripes/ring artifacts: {0}". - format(data_vol)) - - if method.lower() not in supported_methods: - raise ValueError( - "The method to remove stripes and ring artifacts must be one of {0}. " - "Got unknown value: {1}".format(supported_methods, method)) - - try: - import tomopy - stripped_vol = tomopy.prep.stripe.remove_stripe_fw(data_vol) - except ImportError: - stripped_vol = remove_sino_stripes_rings_wf(data_vol) - - return stripped_vol - - -def remove_sino_stripes_rings_wf(data_vol, wv_levels=None): - if not wv_levels: - max_len = np.max(data_vol.shape) - wv_levels = int(np.ceil(np.log2(max_len))) - - from . import filters_adv - return filters_adv.remove_sino_stripes_rings_wf(data_vol, wv_levels) - - -def circular_mask(data_vol, ratio=1.0, mask_out_val=0.0): - """ - Applies a circular mask on a 3D volume. The mask is applied along the z axis (first - dimension of the numpy shape) - - @param data_vol :: 3D data volume - @param ratio :: radius of the mask relative to the radius of the smallest from the - x and y dimensions/edges - @param mask_out_val :: value to use when masking out pixels outside of the mask radius - - Returns :: masked volume - """ - if not isinstance(data_vol, np.ndarray) or 3 != len(data_vol.shape): - raise ValueError( - "Wrong data volume when trying to apply a circular mask: {0}". - format(data_vol)) - - edge_z, edge_y, edge_x = data_vol.shape - mask_in = _calc_mask(edge_y, edge_x, ratio) - for idx in range(edge_z): - data_vol[idx, ~mask_in] = mask_out_val - - return data_vol - - -def _calc_mask(ydim, xdim, ratio): - """ - Prepare a mask object. - - @param ydim :: size/length of the y dimension (image rows) - @param xdim :: size/length of the x dimension (innermost, image columns) - @param ratio :: ratio in [0,1] relative to the smaller dimension - - Returns :: mask as a numpy array of boolean values (in/out-side mask) - """ - radius_y = ydim / 2.0 - radius_x = xdim / 2.0 - if ydim < xdim: - small_radius2 = radius_y * radius_y - else: - small_radius2 = radius_x * radius_x - - y_mask, x_mask = np.ogrid[0.5 - radius_y:0.5 + radius_y, 0.5 - radius_x:0.5 - + radius_x] - - small_radius2 *= ratio * ratio - return (y_mask * y_mask + x_mask * x_mask) < (small_radius2) diff --git a/scripts/Imaging/IMAT/prep/filters_adv.py b/scripts/Imaging/IMAT/prep/filters_adv.py deleted file mode 100644 index 54c6bff5f1c..00000000000 --- a/scripts/Imaging/IMAT/prep/filters_adv.py +++ /dev/null @@ -1,135 +0,0 @@ -# Copyright © 2014-2015 ISIS Rutherford Appleton Laboratory, NScD -# Oak Ridge National Laboratory & European Spallation Source -# -# This file is part of Mantid. -# Mantid is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3 of the License, or -# (at your option) any later version. -# -# Mantid is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see <http://www.gnu.org/licenses/>. -# -# File change history is stored at: <https://github.com/mantidproject/mantid>. -# Code Documentation is available at: <http://doxygen.mantidproject.org> - -import numpy as np - -# The code of the 'Wavelet-Fourier' stripe removal method is heavily based on -# the implementation of this method in tomopy -# The original code from Tomopy is: -# ######################################################################### -# Copyright (c) 2015, UChicago Argonne, LLC. All rights reserved. # -# # -# Copyright 2015. UChicago Argonne, LLC. This software was produced # -# under U.S. Government contract DE-AC02-06CH11357 for Argonne National # -# Laboratory (ANL), which is operated by UChicago Argonne, LLC for the # -# U.S. Department of Energy. The U.S. Government has rights to use, # -# reproduce, and distribute this software. NEITHER THE GOVERNMENT NOR # -# UChicago Argonne, LLC MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR # -# ASSUMES ANY LIABILITY FOR THE USE OF THIS SOFTWARE. If software is # -# modified to produce derivative works, such modified software should # -# be clearly marked, so as not to confuse it with the version available # -# from ANL. # -# # -# Additionally, redistribution and use in source and binary forms, with # -# or without modification, are permitted provided that the following # -# conditions are met: # -# # -# * Redistributions of source code must retain the above copyright # -# notice, this list of conditions and the following disclaimer. # -# # -# * Redistributions in binary form must reproduce the above copyright # -# notice, this list of conditions and the following disclaimer in # -# the documentation and/or other materials provided with the # -# distribution. # -# # -# * Neither the name of UChicago Argonne, LLC, Argonne National # -# Laboratory, ANL, the U.S. Government, nor the names of its # -# contributors may be used to endorse or promote products derived # -# from this software without specific prior written permission. # -# # -# THIS SOFTWARE IS PROVIDED BY UChicago Argonne, LLC AND CONTRIBUTORS # -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS # -# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL UChicago # -# Argonne, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, # -# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, # -# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # -# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER # -# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN # -# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # -# POSSIBILITY OF SUCH DAMAGE. # -# ######################################################################### - - -def remove_sino_stripes_rings_wf(data_vol, wv_levels, wavelet_name='db5', sigma=2, pad=True): - """ - Removes horizontal stripes in sinograms (reducing ring artifacts in the reconstructed volume). - Implements a combined Wavelet-Fourier filter (wf) as described in: - - Muench B, Trtrik P, Marone F, and Stampanoni M. 2009. Optics Express, 17(10):8567-8591. - Stripe and ring artifact removal with combined wavelet-fourier filtering. 2009. - - This implementation is heavily based on the implementation from tomopy. This is not parallel - at the moment. - """ - try: - import pywt - except ImportError as exc: - raise ImportError("Could not import the package pywt. Details: {0}".format(exc)) - - dimx = data_vol.shape[0] - n_x = dimx - if pad: - n_x = dimx + dimx / 8 - xshift = int((n_x - dimx) / 2.) - - for sino_idx in range(0, data_vol.shape[1]): - sli = np.zeros((n_x, data_vol.shape[2]), dtype='float32') - sli[xshift:dimx + xshift] = data_vol[:, sino_idx, :] - - # Wavelet decomposition - c_H, c_V, c_D = [], [], [] - for _ in range(wv_levels): - sli, (cHt, cVt, cDt) = pywt.dwt2(sli, wavelet_name) - c_H.append(cHt) - c_V.append(cVt) - c_D.append(cDt) - - c_V = ft_horizontal_bands(c_V, wv_levels, sigma) - - # Wavelet reconstruction - for nlvl in range(wv_levels)[::-1]: - sli = sli[0:c_H[nlvl].shape[0], 0:c_H[nlvl].shape[1]] - sli = pywt.idwt2((sli, (c_H[nlvl], c_V[nlvl], c_D[nlvl])), - wavelet_name) - data_vol[:, sino_idx, :] = sli[xshift:dimx + xshift, 0:data_vol.shape[2]] - - return data_vol - - -def ft_horizontal_bands(c_V, wv_levels, sigma): - """ - Fourier transform of horizontal frequency bands - """ - for nlvl in range(wv_levels): - # FT - fcV = np.fft.fftshift(np.fft.fft(c_V[nlvl], axis=0)) - m_y, m_x = fcV.shape - - # Damping of ring artifact information - y_hat = (np.arange(-m_y, m_y, 2, dtype='float32') + 1) / 2 - damp = 1 - np.exp(-np.power(y_hat, 2) / (2 * np.power(sigma, 2))) - fcV = np.multiply(fcV, np.transpose(np.tile(damp, (m_x, 1)))) - - # Inverse FT - c_V[nlvl] = np.real(np.fft.ifft(np.fft.ifftshift(fcV), axis=0)) - - return c_V diff --git a/scripts/Imaging/IMAT/tomo_reconstruct.py b/scripts/Imaging/IMAT/tomo_reconstruct.py deleted file mode 100644 index 5cf75e478cb..00000000000 --- a/scripts/Imaging/IMAT/tomo_reconstruct.py +++ /dev/null @@ -1,411 +0,0 @@ -from __future__ import (absolute_import, division, print_function) -# Copyright © 2014,2015 ISIS Rutherford Appleton Laboratory, NScD -# Oak Ridge National Laboratory & European Spallation Source -# -# This file is part of Mantid. -# Mantid is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3 of the License, or -# (at your option) any later version. -# -# Mantid is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see <http://www.gnu.org/licenses/>. -# -# File change history is stored at: <https://github.com/mantidproject/mantid>. -# Code Documentation is available at: <http://doxygen.mantidproject.org> -""" -Do a tomographic reconstruction, including: -- Pre-processing of input raw images, -- 3d volume reconstruction using a third party tomographic reconstruction tool -- Post-processing of reconstructed volume -- Saving reconstruction results (and pre-processing results, and self-save this script and subpackages) - -This command line script and the classes and packages that it uses are prepared so that -they can be run from Mantid, locally (as a process) or remotely (through the tomographic reconstruction -GUI remote job submission, or the remote algorithms). - -Example command lines: - -ipython -- tomo_reconstruct.py --help - -ipython -- scripts/Imaging/IMAT/tomo_reconstruct.py\ - --input-path=../tomography-tests/stack_larmor_metals_summed_all_bands/ --output-path=test_REMOVE_ME\ - --tool tomopy --algorithm gridrec --cor 123 --max-angle 360 --in-img-format=tiff\ - --region-of-interest='[5, 252, 507, 507]' --rotation=-1 - -ipython -- scripts/Imaging/IMAT/tomo_reconstruct.py\ - --input-path=../tomography-tests/stack_larmor_metals_summed_all_bands/ --output-path=test_REMOVE_ME\ - --tool tomopy --algorithm sirt --num-iter 10 --cor 123 --max-angle 360 --in-img-format=tiff\ - --out-img-format png --region-of-interest='[5, 252, 507, 507]' --rotation=-1 - -ipython -- scripts/Imaging/IMAT/tomo_reconstruct.py\ - --input-path=../tomography-tests/stack_larmor_metals_summed_all_bands/ --output-path=test_REMOVE_ME\ - --tool astra --algorithm FP3D_CUDA --num-iter 10 --cor 123 --max-angle 360 --in-img-format=tiff\ - --region-of-interest='[5, 252, 507, 507]' --rotation=-1 -""" - -# find first the package/subpackages in the path of this file. -import sys -import os -from os import path -# So insert in the path the directory that contains this file -sys.path.insert(0, os.path.split(path.dirname(__file__))[0]) # noqa - -from tomorec import reconstruction_command as tomocmd -import tomorec.configs as tomocfg - - -def setup_cmd_options(): - """ - Build an argument parser - - Returns :: Python ArgumentParser set up and ready to parse command line arguments - """ - - import argparse - - parser = argparse.ArgumentParser( - description='Run tomographic reconstruction via third party tools') - - grp_req = parser.add_argument_group('Mandatory/required options') - - grp_req.add_argument( - "-i", "--input-path", required=True, type=str, help="Input directory") - - grp_req.add_argument( - "-o", - "--output-path", - required=True, - type=str, - help="Where to write the output slice images (reconstructed volume)") - - grp_req.add_argument( - "-c", - "--cor", - required=False, - type=float, - help="Provide a pre-calculated centre of rotation. If one is not provided it will be automatically calculated" - ) - - grp_req.add_argument( - "-f", - "--find-cor", - action='store_true', - required=False, - help="Find the center of rotation (in pixels). rotation around y axis is assumed" - ) - - grp_recon = parser.add_argument_group('Reconstruction options') - - grp_recon.add_argument( - "-t", - "--tool", - required=False, - type=str, - help="Tomographic reconstruction tool to use") - - grp_recon.add_argument( - "-a", - "--algorithm", - required=False, - type=str, - help="Reconstruction algorithm (tool dependent)") - - grp_recon.add_argument( - "-n", - "--num-iter", - required=False, - type=int, - help="Number of iterations (only valid for iterative methods " - "(example: SIRT, ART, etc.).") - - grp_recon.add_argument( - "--max-angle", - required=False, - type=float, - help="Maximum angle (of the last projection), assuming first angle=0, and " - "uniform angle increment for every projection (note: this " - "is overriden by the angles found in the input FITS headers)") - - grp_pre = parser.add_argument_group( - 'Pre-processing of input raw images/projections') - - grp_pre.add_argument( - "--input-path-flat", - required=False, - default=None, - type=str, - help="Input directory for flat images") - - grp_pre.add_argument( - "--input-path-dark", - required=False, - default=None, - type=str, - help="Input directory for flat images") - - img_formats = ['tiff', 'fits', 'tif', 'fit', 'png'] - grp_pre.add_argument( - "--in-img-format", - required=False, - default='fits', - type=str, - help="Format/file extension expected for the input images. Supported: {0}". - format(img_formats)) - - grp_pre.add_argument( - "--out-img-format", - required=False, - default='tiff', - type=str, - help="Format/file extension expected for the input images. Supported: {0}". - format(img_formats)) - - grp_pre.add_argument( - "--region-of-interest", - required=False, - type=str, - help="Region of interest (crop original " - "images to these coordinates, given as comma separated values: x1,y1,x2,y2. If not " - "given, the whole images are used.") - - grp_pre.add_argument( - "--air-region", - required=False, - type=str, - help="Air region /region for normalization. " - "If not provided, the normalization against beam intensity fluctuations in this " - "region will not be performed") - - grp_pre.add_argument( - "--median-filter-size", - type=int, - required=False, - help="Size/width of the median filter (pre-processing") - - grp_pre.add_argument( - "--remove-stripes", - default='wf', - required=False, - type=str, - help="Methods supported: 'wf' (Wavelet-Fourier)") - - grp_pre.add_argument( - "--rotation", - required=False, - type=int, - help="Rotate images by 90 degrees a number of " - "times. The rotation is clockwise unless a negative number is given which indicates " - "rotation counterclocwise") - - grp_pre.add_argument( - "--scale-down", - required=False, - type=int, - help="Scale down factor, to reduce the size of " - "the images for faster (lower-resolution) reconstruction. For example a factor of 2 " - "reduces 1kx1k images to 512x512 images (combining blocks of 2x2 pixels into a single " - "pixel. The output pixels are calculated as the average of the input pixel blocks." - ) - - grp_pre.add_argument( - "--mcp-corrections", - default='yes', - required=False, - type=str, - help="Perform corrections specific to images taken with the MCP detector" - ) - - grp_post = parser.add_argument_group( - 'Post-processing of the reconstructed volume') - - grp_post.add_argument( - "--circular-mask", - required=False, - type=float, - default=0.94, - help="Radius of the circular mask to apply on the reconstructed volume. " - "It is given in [0,1] relative to the size of the smaller dimension/edge " - "of the slices. Empty or zero implies no masking.") - - grp_post.add_argument( - "--cut-off", - required=False, - type=float, - help="Cut off level (percentage) for reconstructed " - "volume. pixels below this percentage with respect to maximum intensity in the stack " - "will be set to the minimum value.") - - grp_post.add_argument( - "--out-median-filter", - required=False, - type=float, - help="Apply median filter (2d) on reconstructed volume with the given window size." - ) - - parser.add_argument( - "-v", - "--verbose", - action="count", - default=1, - help="Verbosity level. Default: 1. " - "User zero to supress outputs.") - - return parser - - -def grab_preproc_options(args): - """ - Get pre-proc options from the command line (through an argument parser) - - @param parser :: arguments parser already, set up with pre-processing options - - Returns:: a pre-processing config object set up according to the user inputs in the command line - """ - import ast - - pre_config = tomocfg.PreProcConfig() - pre_config.input_dir = args.input_path - pre_config.input_dir_flat = args.input_path_flat - pre_config.input_dir_dark = args.input_path_dark - - if args.in_img_format: - pre_config.in_img_format = args.in_img_format - - if args.out_img_format: - pre_config.out_img_format = args.out_img_format - - if args.max_angle: - pre_config.max_angle = float(args.max_angle) - - if args.rotation: - pre_config.rotation = int(args.rotation) - - if args.air_region: - coords = ast.literal_eval(args.air_region) - pre_config.normalize_air_region = [int(val) for val in coords] - - if args.air_region: - coords = ast.literal_eval(args.air_region) - pre_config.normalize_air_region = [int(val) for val in coords] - - if args.region_of_interest: - roi_coords = ast.literal_eval(args.region_of_interest) - pre_config.crop_coords = [int(val) for val in roi_coords] - - if 'yes' == args.mcp_corrections: - pre_config.mcp_corrections = True - - if args.median_filter_size: - if isinstance(args.median_filter_size, - str) and not args.median_filter_size.isdigit(): - raise RuntimeError( - "The median filter size/width must be an integer") - pre_config.median_filter_size = args.median_filter_size - - if 'wf' == args.remove_stripes: - pre_config.stripe_removal_method = 'wavelet-fourier' - - if args.cor: - pre_config.cor = int(args.cor) - - return pre_config - - -def grab_tool_alg_options(args): - """ - Get tool and algorithm options from the command line (through an argument parser) - - @param parser :: arguments parsed already, set up with algorithm/tool options - - Returns:: an algorithm config object set up according to the user inputs in the command line - """ - config = tomocfg.ToolAlgorithmConfig() - config.tool = args.tool - config.algorithm = args.algorithm - - if args.num_iter: - if isinstance(args.num_iter, str) and not args.num_iter.isdigit(): - raise RuntimeError("The number of iterations must be an integer") - config.num_iter = int(args.num_iter) - - return config - - -def grab_postproc_options(args): - """ - Get post-processing (on the reconstructed volume) options from the command line - (through an argument parser) - - @param parser :: arguments parsed already, set up with post-processing options - - Returns:: a post-processing object set up according to the user inputs in the command line - """ - config = tomocfg.PostProcConfig() - config.output_dir = args.output_path - - if args.circular_mask: - config.circular_mask = float(args.circular_mask) - - if args.cut_off: - config.cut_off_level = float(args.cut_off) - - if args.out_median_filter: - config.median_filter_size = float(args.out_median_filter) - - return config - - -def main_tomo_rec(): - # several dependencies (numpy, scipy) are too out-of-date in standard Python 2.6 - # distributions, as found for example on rhel6 - - vers = sys.version_info - if vers < (2, 7, 0): - raise RuntimeError( - "Not running this test as it requires Python >= 2.7. Version found: {0}". - format(vers)) - - import inspect - - import IMAT.tomorec.io as tomoio - - arg_parser = setup_cmd_options() - args = arg_parser.parse_args() - - # Grab and check pre-processing options + algorithm setup + post-processing options - preproc_config = grab_preproc_options(args) - alg_config = grab_tool_alg_options(args) - postproc_config = grab_postproc_options(args) - - cmd_line = " ".join(sys.argv) - cfg = tomocfg.ReconstructionConfig(preproc_config, alg_config, - postproc_config) - - # Does all the real work - cmd = tomocmd.ReconstructionCommand() - # start the whole execution timer - cmd.tomo_total_timer() - - if (args.find_cor): - cmd.tomo_print(" >>> Finding COR <<<") - cmd.find_center(cfg) - else: - # Save myself early. Save command this command line script and all packages/subpackages - tomoio.self_save_zipped_scripts( - args.output_path, - os.path.abspath(inspect.getsourcefile(lambda: 0))) - cmd.tomo_print(" >>> Running reconstruction <<<") - cmd.do_recon(cfg, cmd_line=cmd_line) - - # end the whole execution timer - cmd.tomo_total_timer() - - -if __name__ == '__main__': - main_tomo_rec() diff --git a/scripts/Imaging/IMAT/tomorec/__init__.py b/scripts/Imaging/IMAT/tomorec/__init__.py deleted file mode 100644 index ca06e379c16..00000000000 --- a/scripts/Imaging/IMAT/tomorec/__init__.py +++ /dev/null @@ -1,54 +0,0 @@ -# Copyright © 2014-2015 ISIS Rutherford Appleton Laboratory, NScD -# Oak Ridge National Laboratory & European Spallation Source -# -# This file is part of Mantid. -# Mantid is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3 of the License, or -# (at your option) any later version. -# -# Mantid is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see <http://www.gnu.org/licenses/>. -# -# File change history is stored at: <https://github.com/mantidproject/mantid>. -# Code Documentation is available at: <http://doxygen.mantidproject.org> -""" -A collection of scripts for neutron imaging. Includes -pre-processing/preparation steps, reconstruction via third party -tools, and post-processing steps, in addition to input/output and -format conversion routines. - -""" - -IMPORT_ERR_MSG = ("Inconsistency found. Could not import {0} which should be " - "available in this package. Details/reason: {1}") -try: - import io -except ImportError as exc: - raise ImportError( - IMPORT_ERR_MSG.format("'io' (input/output routines)", exc)) - -try: - import configs -except ImportError as exc: - raise ImportError( - IMPORT_ERR_MSG.format("'configs' (tomographic reconstruction " - "configuration definitions)", exc)) - -try: - import tool_imports -except ImportError as exc: - raise ImportError( - IMPORT_ERR_MSG.format("'tool_imports' (for third party " - "tools such as Tomopy and Astra)", exc)) -try: - import reconstruction_command -except ImportError as exc: - raise ImportError( - IMPORT_ERR_MSG.format("'reconstruction_command' (tomographic " - "reconstruction command)", exc)) diff --git a/scripts/Imaging/IMAT/tomorec/configs.py b/scripts/Imaging/IMAT/tomorec/configs.py deleted file mode 100644 index 8f3cc189c75..00000000000 --- a/scripts/Imaging/IMAT/tomorec/configs.py +++ /dev/null @@ -1,195 +0,0 @@ -# Copyright © 2014,2015 ISIS Rutherford Appleton Laboratory, NScD -# Oak Ridge National Laboratory & European Spallation Source -# -# This file is part of Mantid. -# Mantid is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3 of the License, or -# (at your option) any later version. -# -# Mantid is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see <http://www.gnu.org/licenses/>. -# -# File change history is stored at: <https://github.com/mantidproject/mantid>. -# Code Documentation is available at: <http://doxygen.mantidproject.org> -""" -Classes to handle a tomographic reconstruction configuration, including -pre-processing, reconstruction, and post-processing -""" - -import os - -#pylint: disable=too-few-public-methods - - -class ToolAlgorithmConfig(object): - """ - Reconstruction algorithm specific configuration. Required for any reconstruction: - a tool that implements the method/algorithm, - the algorithm name, - (only for the iterative algorithms) the number of iterations - (only for some algorithms) a regularization/smoothing parameter - """ - - DEF_TOOL = 'tomopy' - DEF_ALGORITHM = 'gridrec' - - def __init__(self): - self.tool = self.DEF_TOOL - self.algorithm = self.DEF_ALGORITHM - self.num_iter = None - self.regularization = None - - def __str__(self): - mystr = "Tool: {0}\n".format(self.tool) - mystr += "Algorithm: {0}\n".format(self.algorithm) - if self.num_iter: - mystr += "Number of algorith iterations: {0}\n".format( - self.num_iter) - else: - mystr += "(Algorithm iterations: not defined)\n" - if self.regularization: - mystr += "Regularization parameter: {0}\n".format( - self.regularization) - else: - mystr += "(Regularization parameter: not defined)\n" - - return mystr - - -#pylint: disable=too-many-instance-attributes -class PreProcConfig(object): - """ - All pre-processing options required to run a tomographic reconstruction. - - Options like the stripe removal, MCP correction, or even the median filter would - better be handled as plugins. For the time being we just have a panel with a fixed - set of options to enable/disable/configure - """ - - DEF_NUM_ITER = 5 - - def __init__(self): - # defaults that look sensible for the MCP detector: - # median_filter=3, rotate=-1, crop=[0, 252, 0, 512], MCP correction: on - self.input_dir = None - self.input_dir_flat = None - self.input_dir_dark = None - self.in_img_format = 'tiff' - self.out_img_format = 'tiff' - self.max_angle = 360 - # Rotation 90 degrees clockwise (positive) or counterclockwise (negative) - # Example: -1 => (-90 degrees == 90 degrees counterclockwise) - self.rotation = -1 - self.normalize_flat_dark = True - # list with coordinates of the region for normalization / "air" / not blocked by any object - self.normalize_air_region = None - self.normalize_proton_charge = False - # region of interest - self.crop_coords = None - self.cut_off_level = 0 - self.mcp_corrections = True - self.scale_down = 0 - self.median_filter_size = 3 - self.line_projection = True - self.stripe_removal_method = 'wavelet-fourier' - # Center of rotation - self.cor = None - self.save_preproc_imgs = True - - def __str__(self): - - mystr = "Input path (relative): {0}\n".format(self.input_dir) - if self.input_dir: - mystr += "Input path (absolute): {0}\n".format( - os.path.abspath(self.input_dir)) - else: - mystr += "Input path (absolute): {0}\n".format( - 'cannot find because the input ' - 'path has not been set') - mystr += "Input path for flat (open beam) images (relative): {0}\n".format( - self.input_dir_flat) - mystr += "Input path for dark images (relative): {0}\n".format( - self.input_dir_dark) - mystr += "Input image format: {0}\n".format(self.in_img_format) - mystr += "Output image format: {0}\n".format(self.out_img_format) - mystr += "Maximum angle:: {0}\n".format(self.max_angle) - mystr += "Center of rotation: {0}\n".format(self.cor) - mystr += "Region of interest (crop coordinates): {0}\n".format( - self.crop_coords) - mystr += "Normalize by flat/dark images: {0}\n".format( - self.normalize_flat_dark) - mystr += "Normalize by air region: {0}\n".format( - self.normalize_air_region) - mystr += "Normalize by proton charge: {0}\n".format( - self.normalize_proton_charge) - mystr += "Cut-off on normalized images: {0}\n".format( - self.cut_off_level) - mystr += "Corrections for MCP detector: {0}\n".format( - self.mcp_corrections) - mystr += "Scale down factor for images: {0}\n".format(self.scale_down) - mystr += "Median filter width: {0}\n".format(self.median_filter_size) - mystr += "Rotation: {0}\n".format(self.rotation) - mystr += "Line projection (line integral/log re-scale): {0}\n".format( - 1) - mystr += "Sinogram stripes removal: {0}".format( - self.stripe_removal_method) - - return mystr - - -class PostProcConfig(object): - """ - All pre-processing options required to run a tomographic reconstruction - """ - - def __init__(self): - """ - Builds a default post-processing configuration with a sensible choice of parameters - """ - self.output_dir = None - self.circular_mask = 0.94 - self.cut_off_level = 0 - self.gaussian_filter_par = 0 - self.median_filter_size = 0 - self.median_filter3d_size = 0 - - def __str__(self): - - mystr = "Output path (relative): {0}\n".format(self.output_dir) - if self.output_dir: - mystr += "Output path (absolute): {0}\n".format( - os.path.abspath(self.output_dir)) - else: - mystr += "Output path (absolute): {0}\n".format( - 'cannot find because the input ' - 'path has not been set') - mystr += "Circular mask: {0}\n".format(self.circular_mask) - mystr += "Cut-off on reconstructed volume: {0}\n".format( - self.cut_off_level) - mystr += "Gaussian filter: {0}\n".format(self.gaussian_filter_par) - mystr += "Median filter size:: {0}\n".format(self.median_filter_size) - mystr += "Median filter (3d) size:: {0}\n".format( - self.median_filter3d_size) - - return mystr - - -class ReconstructionConfig(object): - """ - Full configuration (pre-proc + tool/algorithm + post-proc. - """ - - def __init__(self, preproc_cfg, alg_cfg, postproc_cfg): - self.preproc_cfg = preproc_cfg - self.alg_cfg = alg_cfg - self.postproc_cfg = postproc_cfg - - def __str__(self): - return str(self.preproc_cfg) + str(self.alg_cfg) + str( - self.postproc_cfg) diff --git a/scripts/Imaging/IMAT/tomorec/io.py b/scripts/Imaging/IMAT/tomorec/io.py deleted file mode 100644 index 29c8fa057c6..00000000000 --- a/scripts/Imaging/IMAT/tomorec/io.py +++ /dev/null @@ -1,578 +0,0 @@ -from __future__ import (absolute_import, division, print_function) -# Copyright © 2014-2015 ISIS Rutherford Appleton Laboratory, NScD -# Oak Ridge National Laboratory & European Spallation Source -# -# This file is part of Mantid. -# Mantid is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3 of the License, or -# (at your option) any later version. -# -# Mantid is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see <http://www.gnu.org/licenses/>. -# -# File change history is stored at: <https://github.com/mantidproject/mantid>. -# Code Documentation is available at: <http://doxygen.mantidproject.org> -""" -Input/output functionality for stacks of images. For example: load -a stack of images in different formats (.tif, FITS). Includes handling -of paths, sample, flat, and dark images, file name prefixes, etc. - -""" - -import glob -import os -import re - -import numpy as np - - -def _import_pyfits(): - """ - To import pyfits optionally only when it is/can be used - """ - try: - import pyfits - except ImportError: - # In Anaconda python, the pyfits package is in a different place, and this is what you frequently - # find on windows. - try: - import astropy.io.fits as pyfits - except ImportError: - raise ImportError( - "Cannot find the package 'pyfits' which is required to read/write FITS image files" - ) - - return pyfits - - -def _import_skimage_io(): - """ - To import skimage io only when it is/can be used - """ - try: - from skimage import io as skio - skio.use_plugin('freeimage') - except ImportError as exc: - raise ImportError( - "Could not find the package skimage, its subpackage " - "io and the pluging freeimage which are required to support " - "several image formats. Error details: {0}".format(exc)) - return skio - - -def make_dirs_if_needed(dirname): - """ - Makes sure that the directory needed (for example to save a file) - exists, otherwise creates it. - - @param dirname :: (output) directory to check - - """ - absname = os.path.abspath(dirname) - if not os.path.exists(absname): - os.makedirs(absname) - - -#pylint: disable=too-many-arguments - - -def write_image(img_data, - min_pix, - max_pix, - filename, - img_format=None, - dtype=None, - rescale_intensity=False): - """ - Output image data, given as a numpy array, to a file, in a given image format. - Assumes that the output directory exists (must be checked before). The pixel - values are rescaled in the range [min_pix, max_pix] which would normally be set - to the minimum/maximum values found in a stack of images. - - @param img_data :: image data in the usual numpy representation - - @param min_pix :: minimum reference value to rescale data (may be local to an - image or global for a stack of images) - @param max_pix :: maximum reference value to rescale data (may be local to an - image or global for a stack of images) - - @param filename :: file name, including directory and extension - @param img_format :: image file format - @param dtype :: can be used to force a pixel type, otherwise the type - of the input data is used - - Returns:: name of the file saved - """ - if not img_format: - img_format = 'png' - filename = filename + '.' + img_format - - # The special case dtype = 'uint8' could be handled with bytescale: - # img_data = scipy.misc.bytescale(img_data) - - # from bigger to smaller type, example: float32 => uint16 - if dtype and img_data.dtype != dtype: - old_img_data = img_data - img_data = np.zeros(old_img_data.shape, dtype='float32') - pix_range = max_pix - float(min_pix) - scale_factor = (np.iinfo(dtype).max - np.iinfo(dtype).min) / pix_range - - too_verbose = False - if too_verbose: - print("pix min: {0}, max: {1}, scale_factor: {2}".format( - min_pix, max_pix, scale_factor)) - img_data = scale_factor * (old_img_data - min_pix) - img_data = img_data.astype(dtype=dtype) - - # this rescale intensity would ignore the range of other images in the stack - # in addition, it clips if the original values are below/above the destination type limits - if rescale_intensity: - try: - from skimage import exposure - except ImportError as exc: - raise ImportError( - "Could not find the exposure package (in skimage) " - "Error details: {0}".format(exc)) - img_data = exposure.rescale_intensity( - img_data, out_range=dtype) #'uint16') - - skio = _import_skimage_io() - # Without this plugin tiff files don't seem to be generated correctly for some - # bit depths (especially relevant for uint16), but you still need to load the - # freeimage plugin with use_plugin! - _USING_PLUGIN_TIFFFILE = True - if img_format == 'tiff' and _USING_PLUGIN_TIFFFILE: - # compression option intentionally not used: compress=6, 3rd party tools have - # issues loading compressed tiff files) - skio.imsave(filename, img_data, plugin='tifffile') - else: - skio.imsave(filename, img_data, plugin='freeimage') - - return filename - - -def avg_image_files(path, - base_path, - file_prefix=None, - file_extension=None, - agg_method='average'): - """ - Reads files from a directory, assuming they are images from a - stack, and calculates the average image. - - @param base_path :: path that can be used as base path if the path to the images - to average is relative (for example a dark images path relative to the samples - path) - """ - path = None - if os.path.isabs(base_path): - path = base_path - else: - os.path.join(base_path, path) - - path = os.path.expanduser(path) - - img_files = glob.glob( - os.path.join(path, "{0}*.{1}".format(file_prefix, file_extension))) - - if len(img_files) <= 0: - raise RuntimeError("No image files found in " + path) - - pyfits = _import_pyfits() - - imgs = pyfits.open(img_files[0]) - if len(imgs) < 1: - raise RuntimeError("Could not load at least one image from path: {0}". - format(base_path)) - - data_dtype = imgs[0].data.dtype - # from fits files we usually get this, just change it to uint16 - if '>i2' == data_dtype: - data_dtype = np.uint16 - - accum = np.zeros((imgs[0].shape[0], imgs[0].shape[1]), dtype=data_dtype) - - for ifile in img_files: - hdu = None - try: - hdu = pyfits.open(ifile) - except IOError as exc: - print( - "Got I/O exception trying to open and load {0}: {1}. Ignoring and going on.". - format(ifile, str(exc))) - continue - - accum = _agg_img(accum, hdu[0].data, agg_method=agg_method) - - return accum - - -def _agg_img(acc, img_data, agg_method=None, index=1): - """ - Adds in (with average, median, etc.) data coming from a new - image/hdu. Expects a numpy array of shape (N1, N2) where N1 and N2 - are the number of rows and columns of the images. - - @param acc :: aggregated value accumulated so far - @param img_data :: new image to add in - @param agg_method :: whether to sum, average, etc. See options supported. - @param index :: image index used when calculating incremental statistics like the average - - Returns :: result from aggregating (sum, average, etc.) the new image - - """ - if agg_method is None: - agg_method = 'sum' - - if 'sum' == agg_method: - acc = np.add(acc, img_data) - elif 'average' == agg_method: - acc = np.add((index - 1) * acc / index, img_data / index) - - return acc - - -def _alphanum_key_split(path_str): - """ - From a string to a list of alphabetic and numeric elements. Intended to - be used for sequence number/natural sorting. In list.sort() the - key can be a list, so here we split the alpha/numeric fields into - a list. For example (in the final order after sort() would be applied): - - "angle4" -> ["angle", 4] - "angle31" -> ["angle", 31] - "angle42" -> ["angle", 42] - "angle101" -> ["angle", 101] - - Several variants compared here: - https://dave.st.germa.in/blog/2007/12/11/exception-handling-slow/ - """ - ALPHA_NUM_SPLIT_RE = re.compile('([0-9]+)') - return [ - int(c) if c.isdigit() else c - for c in ALPHA_NUM_SPLIT_RE.split(path_str) - ] - - -def _read_img(filename, file_extension=None): - """ - Read one image and return it as a 2d numpy array - - @param filename :: name of the image file, can be relative or absolute path - @param file_extension :: extension and effectively format to use ('tiff', 'fits') - """ - if file_extension in ['fits', 'fit']: - pyfits = _import_pyfits() - imgs = pyfits.open(filename) - if len(imgs) < 1: - raise RuntimeError( - "Could not load at least one FITS image/table file from: {0}". - format(filename)) - - # Input fits files always contain a single image - img_arr = imgs[0].data - - elif file_extension in ['tiff', 'tif', 'png']: - skio = _import_skimage_io() - img_arr = skio.imread(filename) - - else: - raise ValueError( - "Don't know how to load a file with this extension: {0}".format( - file_extension)) - - return img_arr - - -def _read_listed_files(files, slice_img_shape, file_extension, dtype): - """ - Read several images in a row into a 3d numpy array. Useful when reading all the sample - images, or all the flat or dark images. - - @param files :: list of image file paths given as strings - @param slice_img_shape :: shape of every image - @param file_extension :: file name extension if fixed (to set the expected image format) - @param dtype :: data type for the output numpy array - - Returns:: a 3d data volume with the size of the first (outermost) dimension equal - to the number of files, and the sizes of the second and third dimensions equal to - the sizes given in the input slice_img_shape - """ - data = np.zeros( - (len(files), slice_img_shape[0], slice_img_shape[1]), dtype=dtype) - for idx, in_file in enumerate(files): - try: - data[idx, :, :] = _read_img(in_file, file_extension) - except IOError as exc: - raise RuntimeError("Could not load file {0}. Error details: {2}". - format(in_file, str(exc))) - - return data - - -def get_flat_dark_stack(field_path, field_prefix, file_prefix, file_extension, - img_shape, data_dtype): - """ - Load the images of the flat/dark/other field and calculate an average of them. - - @param field_path :: path to the images - @param field_prefix :: prefix for the images of the flat/dark/other field images (filter). - example: OB, DARK, WHITE, etc. - - @param file_extension :: extension string to look for file names - @param img_shape :: shape that every image should have - @param data_dtype :: output data type - - Returns :: numpy array with an average (pixel-by-pixel) of the flat/dark/other field images - """ - avg = None - if field_prefix: - if not file_prefix: - file_prefix = '' - files_match = glob.glob( - os.path.join(field_path, "{0}*.{1}".format(field_prefix, - file_extension))) - if len(files_match) <= 0: - print( - "Could not find any flat field / open beam image files in: {0}". - format(field_prefix)) - else: - imgs_stack = _read_listed_files(files_match, img_shape, - file_extension, data_dtype) - avg = np.mean(imgs_stack, axis=0) - - return avg - - -# This could become a command class. There's already many parameters and it's -# likely that there will be more. - - -def read_stack_of_images(sample_path, - flat_field_path=None, - dark_field_path=None, - file_extension='tiff', - file_prefix=None, - flat_field_prefix=None, - dark_field_prefix=None, - verbose=True): - """ - Reads a stack of images into memory, assuming dark and flat images - are in separate directories. - - If several files are found in the same directory (for example you - give image0001.fits and there's also image0002.fits, - image0003.fits) these will also be loaded as the usual convention - in ImageJ and related imaging tools, using the last digits to sort - the images in the stack. - - @param sample_path :: path to sample images. Can be a file or directory - - @param flat_field_path :: (optional) path to open beam / white image(s). - Can be a file or directory - - @param dark_field_path :: (optional) path to dark field image(s). - Can be a file or directory - - @param file_extension :: file extension (typically 'tiff', 'tif', 'fits', - or 'fit' (not including the dot) - - @param file_prefix :: prefix for the image files (example: IMAT00), to filter - files that may be in the same directories but should not be loaded - - @param flat_field_prefix :: prefix for the flat field image files - - @param dark_field_prefix :: prefix for the dark field image files - - @param verbose :: verbose (some) output - - Returns :: 3 numpy arrays: input data volume (3d), average of flatt images (2d), - average of dark images(2d) - """ - SUPPORTED_EXTS = ['tiff', 'tif', 'fits', 'fit', 'png'] - - if file_extension not in SUPPORTED_EXTS: - raise ValueError( - "File extension not supported: {0}. Supported extensions: {1}". - format(file_extension, SUPPORTED_EXTS)) - - sample_path = os.path.expanduser(sample_path) - - print(" * Loading stack of images from {0}".format(sample_path)) - - if not file_prefix: - file_prefix = '' - files_match = glob.glob( - os.path.join(sample_path, "{0}*.{1}".format(file_prefix, - file_extension))) - if len(files_match) <= 0: - raise RuntimeError( - "Could not find any image files in {0}, with prefix: {1}, extension: {2}". - format(sample_path, file_prefix, file_extension)) - - files_match.sort(key=_alphanum_key_split) - - print(" * Found {0} image files in {1}".format( - len(files_match), sample_path)) - - # It is assumed that all images have the same size and properties as the first. - try: - first_img = _read_img(files_match[0], file_extension) - except RuntimeError as exc: - raise RuntimeError( - "Could not load at least one image file from: {0}. Details: {1}". - format(sample_path, str(exc))) - - data_dtype = first_img.dtype - # usual type in fits with 16-bit pixel depth - if '>i2' == data_dtype: - data_dtype = np.uint16 - - img_shape = first_img.shape - sample_data = _read_listed_files(files_match, img_shape, file_extension, - data_dtype) - - flat_avg = get_flat_dark_stack(flat_field_path, flat_field_prefix, - flat_field_prefix, file_extension, - img_shape, data_dtype) - - dark_avg = get_flat_dark_stack(dark_field_path, flat_field_prefix, - dark_field_prefix, file_extension, - img_shape, data_dtype) - - return sample_data, flat_avg, dark_avg - - -def save_recon_as_vertical_slices(recon_data, - output_dir, - img_format='tiff', - name_prefix='out_recon_slice', - zero_fill=6): - """ - Save reconstructed volume (3d) into a series of slices along the Z axis (outermost numpy dimension) - - @param data :: data as images/slices stores in numpy array - @param output_dir :: where to save the files - @param name_prefix :: prefix for the names of the images - an index is appended to this prefix - @param zero_fill :: number of zeros to pad the image/slice index number - """ - make_dirs_if_needed(output_dir) - min_pix = np.amin(recon_data) - max_pix = np.amax(recon_data) - for idx in range(0, recon_data.shape[0]): - write_image( - recon_data[idx, :, :], - min_pix, - max_pix, - os.path.join(output_dir, name_prefix + str(idx).zfill(zero_fill)), - img_format=img_format, - dtype='uint16') - - -def save_recon_as_horizontal_slices(recon_data, - out_horiz_dir, - img_format='tiff', - name_prefix='out_recon_horiz_slice', - zero_fill=6): - """ - Save reconstructed volume (3d) into a series of slices along the Y axis (second numpy dimension) - - @param data :: data as images/slices stores in numpy array - @param output_dir :: where to save the files - @param name_prefix :: prefix for the names of the images throughout the horizontal axis - @param zero_fill :: number of zeros to pad the image/slice index number. This index is appended to - the prefix - """ - make_dirs_if_needed(out_horiz_dir) - for idx in range(0, recon_data.shape[1]): - write_image( - recon_data[:, idx, :], - np.amin(recon_data), - np.amax(recon_data), - os.path.join(out_horiz_dir, - name_prefix + str(idx).zfill(zero_fill)), - img_format=img_format, - dtype='uint16') - - -def save_recon_netcdf(recon_data, output_dir, filename='tomo_recon_vol.nc'): - """ - A netCDF, for compatibility/easier interoperation with other tools - - @param recon_data :: reconstructed data volume. A sequence of images will be saved from this - @param output_dir :: where the outputs are being saved - @param filename :: name for the NetCDF file - """ - try: - from scipy.io import netcdf_file - except ImportError as exc: - print(" WARNING: could not save NetCDF file. Import error: {0}".format( - exc)) - - xsize = recon_data.shape[0] - ysize = recon_data.shape[1] - zsize = recon_data.shape[2] - - nc_path = os.path.join(output_dir, filename) - ncfile = netcdf_file(nc_path, 'w') - ncfile.createDimension('x', xsize) - ncfile.createDimension('y', ysize) - ncfile.createDimension('z', zsize) - print(" Creating netCDF volume data variable") - dtype = 'int16' - data = ncfile.createVariable('data', np.dtype(dtype).char, ('x', 'y', 'z')) - print(" Data shape: {0}".format(data.shape)) - print(" Loading/assigning data...") - - # handle differences in pixel type - save_data = recon_data - if recon_data.dtype != dtype: - save_data = np.zeros(recon_data.shape, dtype='float32') - max_vol = np.amax(recon_data) - min_vol = np.amin(recon_data) - vol_range = max_vol - min_vol - scale_factor = (np.iinfo(dtype).max - np.iinfo(dtype).min) / vol_range - save_data = scale_factor * (recon_data - min_vol) - save_data = save_data.astype(dtype=dtype) - - data[:, :, :] = save_data[0:xsize, 0:ysize, 0:zsize] - print(" Closing netCDF file: {0}".format(nc_path)) - ncfile.close() - - -def self_save_zipped_scripts(output_path, this_path): - """ - Self-save a python file and its subpackages. - - @param output_path :: path where to save - @param this_path :: full path to 'this' file, the file that wants to self-save itself. - """ - - def _zipdir(path, ziph): - # ziph is zipfile handle - for root, _, files in os.walk(path): - for indiv_file in files: - # Write all files, with the exception of the pyc's - exclude_extensions = ['pyc'] - if not indiv_file.endswith(tuple(exclude_extensions)): - ziph.write(os.path.join(root, indiv_file)) - - scripts_path = os.path.dirname(this_path) - - make_dirs_if_needed(output_path) - print("Saving myself (reconstruction scripts) from: {0} in: {1}".format( - scripts_path, os.path.abspath(output_path))) - import zipfile - # os.path.join(output_path, ... ) - RECON_SCRIPTS_PKG_NAME = '0.reconstruction_scripts.zip' - with zipfile.ZipFile( - os.path.join(output_path, RECON_SCRIPTS_PKG_NAME), 'w', - zipfile.ZIP_DEFLATED) as zip_scripts: - # To write just this file: zipscr.write(this_path) - _zipdir(scripts_path, zip_scripts) diff --git a/scripts/Imaging/IMAT/tomorec/reconstruction_command.py b/scripts/Imaging/IMAT/tomorec/reconstruction_command.py deleted file mode 100644 index 1bf9de103df..00000000000 --- a/scripts/Imaging/IMAT/tomorec/reconstruction_command.py +++ /dev/null @@ -1,1365 +0,0 @@ -from __future__ import (absolute_import, division, print_function) -# Copyright © 2014,2015 ISIS Rutherford Appleton Laboratory, NScD -# Oak Ridge National Laboratory & European Spallation Source -# -# This file is part of Mantid. -# Mantid is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3 of the License, or -# (at your option) any later version. -# -# Mantid is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see <http://www.gnu.org/licenses/>. -# -# File change history is stored at: <https://github.com/mantidproject/mantid>. -# Code Documentation is available at: <http://doxygen.mantidproject.org> - -import os -import time -import numpy as np - -# For 3d median filter -try: - import scipy - print( - scipy.__file__, - "< this is the directory of where scipy was imported from. If this is a Mantid " - "directory, then the scipy that fails to import here is older and/or missing ndimage than " - "the one I have locally") -except ImportError: - raise ImportError( - "Could not find the package scipy which is required for image pre-/post-processing" - ) - -try: - # for some reason ndimage is not found here. reason unknown? - import scipy.ndimage - print( - scipy.ndimage.__file__, - "< this is the directory of where scipy was imported from. If this is a Mantid " - "directory, then the scipy that fails to import here is older and/or missing ndimage than " - "the one I have locally") -except ImportError: - raise ImportError( - "Could not find the subpackage scipy.ndimage, required for image pre-/post-processing" - ) - -from . import io as tomoio -from . import configs as tomocfg - - -class ReconstructionCommand(object): - """ - Run a tomographic reconstruction command, which can be a local process or a job on a - remote machine/scheduler. This class provides functionality to pre-process a raw dataset, - run a reconstruction (from pre-processed data to reconstructed volume), and post-process - a reconstructed volume. - """ - - def __init__(self): - self._PREPROC_IMGS_SUBDIR_NAME = 'pre_processed' - self._OUT_README_FNAME = '0.README_reconstruction.txt' - self._OUT_SLICES_FILENAME_PREFIX = 'out_recon_slice' - self._OUT_HORIZ_SLICES_SUBDIR = 'out_recon_horiz_slice' - - self.preproc_cfg = tomocfg.PreProcConfig() - self.alg_cfg = tomocfg.ToolAlgorithmConfig - self.postproc_cfg = tomocfg.PostProcConfig() - - self._timer_running = False - self._whole_exec_timer = False - - # whether to crop before applying normalization steps. If True, the air region cannot be - # outside of the region of interest. Leaving as False by default, and not exposing this option. - self.__class__.crop_before_normaliz = False - - def _debug_print_memory_usage_linux(self, message=""): - try: - # Windows doesn't seem to have resouce package, so this will silently fail - import resource - print(" >> Memory usage", - resource.getrusage(resource.RUSAGE_SELF).ru_maxrss, "KB, ", - int(resource.getrusage(resource.RUSAGE_SELF).ru_maxrss) / - 1024, "MB", message) - except Exception: - pass - - def tomo_print(self, message, priority=1): - """ - TODO currently the priority parameter is ignored - Verbosity levels: - 0 -> debug, print everything - 1 -> information, print information about progress - 2 -> print only major progress information, i.e data loaded, recon started, recon finished - - Print only messages that have priority >= config verbosity level - - :param message: Message to be printed - :param priority: Importance level depending on which messages will be printed - :return: - """ - - # should be moved in the configs somewhere - temp_verbosity = 0 - if priority >= temp_verbosity: - print(message) - - def tomo_print_timed_start(self, message, priority=1): - """ - On every second call this will terminate and print the timer - TODO currently the priority parameter is ignored - - Verbosity levels: - 0 -> debug, print everything - 1 -> information, print information about progress - 2 -> print only major progress information, i.e data loaded, recon started, recon finished - - Print only messages that have priority >= config verbosity level - - :param message: Message to be printed - :param priority: Importance level depending on which messages will be printed - :return: - """ - - import time - - # should be moved in the configs somewhere - temp_verbosity = 1 - print_string = "" - - if not self._timer_running: - self._timer_running = True - self._timer_start = time.time() - print_string = message - - if priority >= temp_verbosity: - print(print_string) - - def tomo_print_timed_stop(self, message, priority=1): - """ - On every second call this will terminate and print the timer. This will append ". " to the string - TODO currently the priority parameter is ignored - - Verbosity levels: - 0 -> debug, print everything - 1 -> information, print information about progress - 2 -> print only major progress information, i.e data loaded, recon started, recon finished - - Print only messages that have priority >= config verbosity level - - :param message: Message to be printed - :param priority: Importance level depending on which messages will be printed - :return: - """ - - import time - - # should be moved in the configs somewhere - temp_verbosity = 1 - print_string = "" - - if self._timer_running: - self._timer_running = False - timer_string = str(time.time() - self._timer_start) - print_string = message + " Elapsed time: " + timer_string + " sec" - - if priority >= temp_verbosity: - print(print_string) - - def tomo_total_timer(self, message="Total execution time was "): - """ - This will ONLY be used to time the WHOLE execution time. - The first call to this will be in tomo_reconstruct.py and it will start it.abs - The last call will be at the end of find_center or do_recon. - """ - import time - - if not self._whole_exec_timer: - # change type from bool to timer - self._whole_exec_timer = time.time() - else: - # change from timer to string - self._whole_exec_timer = str(time.time() - self._whole_exec_timer) - print(message + self._whole_exec_timer + " sec") - - def _check_paths_integrity(self, cfg): - if not cfg or not isinstance(cfg, tomocfg.ReconstructionConfig): - raise ValueError( - "Cannot run a reconstruction without a valid configuration") - - if not cfg.preproc_cfg.input_dir: - raise ValueError( - "Cannot run a reconstruction without setting the input path") - - if not cfg.postproc_cfg.output_dir: - raise ValueError( - "Cannot run a reconstruction without setting the output path") - - def do_recon(self, cfg, cmd_line=None): - """ - Run a reconstruction using a particular tool, algorithm and setup - - @param preproc_cfg :: configuration (pre-processing + tool+algorithm + post-processing) - - @param cmd_line :: command line text if running from the CLI. When provided it will - be written in the output readme file(s) for reference. - """ - self._check_paths_integrity(cfg) - - if not cfg or not isinstance(cfg, tomocfg.ReconstructionConfig): - raise ValueError( - "Cannot run a reconstruction without a valid configuration") - - if not cfg.preproc_cfg.input_dir: - raise ValueError( - "Cannot run a reconstruction without setting the input path") - - if not cfg.postproc_cfg.output_dir: - raise ValueError( - "Cannot run a reconstruction without setting the output path") - - # First step import the tool - self.tomo_print_timed_start(" * Importing tool " + cfg.alg_cfg.tool) - # import tool - import tomorec.tool_imports as tti - reconstruction_tool = tti.import_tomo_tool(cfg.alg_cfg.tool) - - self.tomo_print_timed_stop(" * Tool loaded.") - - # ---------------------------------------------------------------- - - self.tomo_print_timed_start(" * Generating reconstruction script...") - readme_fullpath = os.path.join(cfg.postproc_cfg.output_dir, - self._OUT_README_FNAME) - tstart = self.gen_readme_summary_begin(readme_fullpath, cfg, cmd_line) - self.tomo_print_timed_stop(" * Finished generating script.") - - # ---------------------------------------------------------------- - - self.tomo_print_timed_start(" * Loading data...") - data, white, dark = self.read_in_stack( - cfg.preproc_cfg.input_dir, cfg.preproc_cfg.in_img_format, - cfg.preproc_cfg.input_dir_flat, cfg.preproc_cfg.input_dir_dark) - self.tomo_print_timed_stop( - " * Data loaded. Shape of raw data: {0}, dtype: {1}.".format( - data.shape, data.dtype)) - - # ---------------------------------------------------------------- - - preproc_data = self.apply_all_preproc(data, cfg.preproc_cfg, white, - dark) - - # ---------------------------------------------------------------- - - # Save pre-proc images, print inside - self.save_preproc_images(cfg.postproc_cfg.output_dir, preproc_data, - cfg.preproc_cfg) - - # ---------------------------------------------------------------- - - # Reconstruction - # for file readme summary - t_recon_start = time.time() - recon_data = self.run_reconstruct_3d(preproc_data, cfg.preproc_cfg, - cfg.alg_cfg, reconstruction_tool) - t_recon_end = time.time() - - # ---------------------------------------------------------------- - - # Post-processing - self.apply_postproc_filters(recon_data, cfg.postproc_cfg) - - # Save output from the reconstruction - self.save_recon_output(recon_data, cfg) - - # turned off for now, as it can't be opened from ParaView so it's a waste - save_netcdf_vol = False - if save_netcdf_vol: - self.tomo_print_timed_start( - " * Saving reconstructed volume as NetCDF...") - tomoio.save_recon_netcdf(recon_data, cfg.postproc_cfg.output_dir) - self.tomo_print_timed_stop( - " * Finished saving reconstructed volume as NetCDF.") - - self.gen_readme_summary_end(readme_fullpath, - (data, preproc_data, recon_data), tstart, - t_recon_end - t_recon_start) - - def gen_readme_summary_begin(self, filename, cfg, cmd_line): - """ - To write configuration, settings, etc. early on. As early as possible, before any failure - can happen. - - @param filename :: name of the readme/final report file - @param cfg :: full reconstruction configuration - @param cmd_line :: command line originally used to run this reconstruction, when running - from the command line - - Returns :: time now (begin of run) in number of seconds since epoch (time() time) - """ - tstart = time.time() - - # generate file with dos/windows line end for windoze users' convenience - with open(filename, 'w') as oreadme: - file_hdr = ( - 'Tomographic reconstruction. Summary of inputs, settings and outputs.\n' - 'Time now (run begin): ' + time.ctime(tstart) + '\n') - oreadme.write(file_hdr) - - alg_hdr = ("\n" - "--------------------------\n" - "Tool/Algorithm\n" - "--------------------------\n") - oreadme.write(alg_hdr) - oreadme.write(str(cfg.alg_cfg)) - oreadme.write("\n") - - preproc_hdr = ("\n" - "--------------------------\n" - "Pre-processing parameters\n" - "--------------------------\n") - oreadme.write(preproc_hdr) - oreadme.write(str(cfg.preproc_cfg)) - oreadme.write("\n") - - postproc_hdr = ("\n" - "--------------------------\n" - "Post-processing parameters\n" - "--------------------------\n") - oreadme.write(postproc_hdr) - oreadme.write(str(cfg.postproc_cfg)) - oreadme.write("\n") - - cmd_hdr = ("\n" - "--------------------------\n" - "Command line\n" - "--------------------------\n") - oreadme.write(cmd_hdr) - oreadme.write(cmd_line) - oreadme.write("\n") - - return tstart - - def gen_readme_summary_end(self, filename, data_stages, tstart, - t_recon_elapsed): - """ - Write last part of report in the output readme/report file. This should be used whenever a - reconstruction runs correctly. - - @param filename :: name of the readme/final report file - @param data_stages :: tuple with data in three stages (raw, pre-processed, reconstructed) - @param tstart :: time at the beginning of the job/reconstruction, when the first part of the - readme file was written - @param t_recon_elapsed :: reconstruction time - """ - # append to a readme/report that should have been pre-filled with the initial configuration - with open(filename, 'a') as oreadme: - - run_hdr = ("\n" - "--------------------------\n" - "Run/job details:\n" - "--------------------------\n") - oreadme.write(run_hdr) - (raw_data, preproc_data, recon_data) = data_stages - - oreadme.write("Dimensions of raw input sample data: {0}\n".format( - raw_data.shape)) - oreadme.write("Dimensions of pre-processed sample data: {0}\n". - format(preproc_data.shape)) - oreadme.write("Dimensions of reconstructed volume: {0}\n".format( - recon_data.shape)) - - oreadme.write("Raw input pixel type: {0}\n".format(raw_data.dtype)) - oreadme.write("Output pixel type: {0}\n".format('uint16')) - oreadme.write("Time elapsed in reconstruction: {0:.3f}s\r\n". - format(t_recon_elapsed)) - tend = time.time() - oreadme.write("Total time elapsed: {0:.3f}s\r\n".format(tend - - tstart)) - oreadme.write('Time now (run end): ' + time.ctime(tend)) - - def apply_all_preproc(self, data, preproc_cfg, white, dark): - """ - Do all the pre-processing. This does all that is needed between a) - loading the input data, and b) starting a reconstruction - run/job. From raw inputs to pre-proc data that is ready to go for - reconstruction. - - @param data :: raw data (sample projection images) - @param preproc_cfg :: pre-processing configuration - @param white :: white / flat / open-beam image for normalization in some of the first - pre-processing steps - @param dark :: dark image for normalization - - Returns :: pre-processed data. - - """ - self._check_data_stack(data) - - self.tomo_print(" * Beginning pre-processing with pixel data type: " + - str(data.dtype)) - preproc_data = self.apply_prep_filters(data, preproc_cfg, white, dark) - preproc_data = self.apply_line_projection(preproc_data, preproc_cfg) - preproc_data = self.apply_final_preproc_corrections(preproc_data, - preproc_cfg) - - return preproc_data - - def apply_prep_filters(self, data, cfg, white, dark): - """ - Apply the normal initial pre-processing filters, including simple - operations as selecting/cropping to the region-of-interest, - normalization, etc. If the images need to be rotated this is - done as a first step (so all intermediate pre-processed - results will be rotated as required). - - @param data :: projection images data, as 3d numpy array, with images along outermost (z) - dimension - - @param cfg :: pre-processing configuration - @param white :: white/flat/open-beam image for normalization - @param dark :: dark image for normalization - - Returns :: process/filtered data (sizes can change (cropped) and data can be rotated) - - """ - self._check_data_stack(data) - - if 'float64' == data.dtype: - # this is done because tomoio.write has problems with float64 to int16 - data = data.astype(dtype='float32') - # print with top priority - self.tomo_print( - " * Note: pixel data type changed to: " + data.dtype, - priority=2) - - data, white, dark = self.rotate_stack(data, cfg, white, dark) - - if self.crop_before_normaliz: - data = self.crop_coords(data, cfg) - - data = self.normalize_flat_dark(data, cfg, white, dark) - data = self.normalize_air_region(data, cfg) - - if not self.crop_before_normaliz: - data = self.crop_coords(data, cfg) - - data = self.apply_cut_off_and_others(data, cfg) - - return data - - def apply_line_projection(self, imgs_angles, preproc_cfg): - """ - Transform pixel values as $- ln (Is/I0)$, where $Is$ is the pixel (intensity) value and $I0$ is a - reference value (pixel/intensity value for open beam, or maximum in the stack or the image). - - This produces a projection image, $ p(s) = -ln\\frac{I(s)}{I(0)} $, - with $ I(s) = I(0) e^{-\\int_0^s \\mu(x)dx} $ - where: - $p(s)$ represents the sum of the density of objects along a line (pixel) of the beam - I(0) initital intensity of netron beam (white images) - I(s) neutron count measured by detector/camera - - The integral is the density along the path through objects. - This is required for example when pixels have neutron count values. - - @param imgs_angles :: stack of images (angular projections) as 3d numpy array. Every image will be - processed independently, using as reference intensity the maximum pixel value found across all the - images. - - @param preproc_cfg :: pre-processing configuration set up for a reconstruction - - Returns :: projected data volume (image stack) - """ - self._check_data_stack(imgs_angles) - - if not preproc_cfg.line_projection: - self.tomo_print( - " * Note: NOT applying line projection.", priority=2) - return imgs_angles - - self.tomo_print_timed_start( - " * Starting to apply line projection on {0} images...".format( - imgs_angles.shape[0])) - imgs_angles = imgs_angles.astype('float32') - for idx in range(0, imgs_angles.shape[0]): - max_img = np.amax(imgs_angles[idx, :, :]) - to_log = np.true_divide(imgs_angles[idx, :, :], max_img) - if False: - print( - " Initial image max: {0}. Transformed to log scale, min: {1}, max: {2}.". - format(max_img, np.amin(to_log), np.amax(to_log))) - imgs_angles[idx, :, :] = -np.log(to_log + 1e-6) - - self.tomo_print_timed_start( - " * Finished applying line projection on {0} images. ".format( - imgs_angles.shape[0])) - - return imgs_angles - - def apply_final_preproc_corrections(self, preproc_data, cfg): - """ - Apply additional, optional, pre-processing steps/filters. - - @param preproc_data :: input data as a 3d volume (projection images) - @param cfg :: pre-processing configuration - - Returns :: filtered data (stack of images) - """ - self._check_data_stack(preproc_data) - - import tomorec.tool_imports as tti - tomopy = tti.import_tomo_tool(cfg.alg_cfg.tool) - - # Remove stripes in sinograms / ring artefacts in reconstructed volume - if cfg.stripe_removal_method: - import prep as iprep - if 'wavelet-fourier' == cfg.stripe_removal_method.lower(): - self.tomo_print_timed_start( - " * Starting removal of stripes/ring artifacts using the method '{0}'...". - format(cfg.stripe_removal_method)) - - #preproc_data = tomopy.prep.stripe.remove_stripe_fw(preproc_data) - preproc_data = iprep.filters.remove_stripes_ring_artifacts( - preproc_data, 'wavelet-fourier') - - self.tomo_print_timed_start( - " * Finished removal of stripes/ring artifacts.") - - elif 'titarenko' == cfg.stripe_removal_method.lower(): - self.tomo_print_timed_start( - " * Starting removal of stripes/ring artifacts, using the method '{0}'...". - format(cfg.stripe_removal_method)) - - preproc_data = tomopy.prep.stripe.remove_stripe_ti( - preproc_data) - - self.tomo_print_timed_stop( - " * Finished removal of stripes/ring artifacts.") - else: - self.tomo_print( - " * WARNING: stripe removal method '{0}' is unknown. Not applying it.". - format(cfg.stripe_removal_method), - priority=2) - else: - self.tomo_print( - " * Note: NOT applying stripe removal.", priority=2) - - # Experimental options, disabled and not present in the config objects for now - # These and related algorithms needs more evaluation/benchmarking - if False: - self.tomo_print_timed_start(" * Starting adjust range...") - preproc_data = tomopy.misc.corr.adjust_range(preproc_data) - self.tomo_print_timed_stop(" * Finished adjusting range.") - - if False: - self.tomo_print_timed_start( - " * Starting background normalisation...") - - preproc_data = tomopy.prep.normalize.normalize_bg( - preproc_data, air=5) - self.tomo_print_timed_stop(" * Finished background normalisation.") - - return preproc_data - - def normalize_air_region(self, data, pre_cfg): - """ - TODO move to filters.py - Normalize by beam intensity. This is not directly about proton - charg - not using the proton charge field as usually found in - experiment/nexus files. This uses an area of normalization, if - provided in the pre-processing configuration. TODO: much - of this method should be moved into filters. - - @param data :: stack of images as a 3d numpy array - @param pre_cfg :: pre-processing configuration - - Returns :: filtered data (stack of images) - - """ - self._check_data_stack(data) - - if not pre_cfg or not isinstance(pre_cfg, tomocfg.PreProcConfig): - raise ValueError( - "Cannot normalize by air region without a valid pre-processing configuration" - ) - - if pre_cfg.normalize_air_region: - if not isinstance(pre_cfg.normalize_air_region, list) or\ - 4 != len(pre_cfg.normalize_air_region): - raise ValueError( - "Wrong air region coordinates when trying to use them to normalize images: {0}". - format(pre_cfg.normalize_air_region)) - - if not all( - isinstance(crd, int) - for crd in pre_cfg.normalize_air_region): - raise ValueError( - "Cannot use non-integer coordinates to use the normalization region " - "(air region). Got these coordinates: {0}".format( - pre_cfg.normalize_air_region)) - - right = pre_cfg.normalize_air_region[2] # why do we add 1? - top = pre_cfg.normalize_air_region[1] - left = pre_cfg.normalize_air_region[0] - bottom = pre_cfg.normalize_air_region[3] - - # skip if for example: 0, 0, 0, 0 (empty selection) - if top >= bottom or left >= right: - self.tomo_print( - " * NOTE: NOT applying Normalise by Air Region. Reason: Empty Selection" - ) - return data - - self.tomo_print_timed_start( - " * Starting normalization by air region. Statistics of values in the air region..." - ) - air_sums = [] - for idx in range(0, data.shape[0]): - air_data_sum = data[idx, top:bottom, left:right].sum() - air_sums.append(air_data_sum) - - air_sums = np.true_divide(air_sums, np.amax(air_sums)) - - self.tomo_print( - " Air region sums (relative to maximum): " + air_sums, - priority=0) - - for idx in range(0, data.shape[0]): - data[idx, :, :] = np.true_divide(data[idx, :, :], - air_sums[idx]) - - avg = np.average(air_sums) - self.tomo_print_timed_stop( - " * Finished normalization by air region. Statistics of values in the air region, " - "average: {0}, max ratio: {1}, min ratio: {2}.".format( - avg, np.max(air_sums) / avg, np.min(air_sums) / avg)) - - else: - self.tomo_print( - " * Note: NOT normalizing by air region", priority=2) - - return data - - def crop_coords(self, data, cfg): - """ - Crop stack of images to a region (region of interest or similar), image by image - - @param data :: stack of images as a 3d numpy array - @param cfg :: pre-processing configuration - - Returns :: filtered data (stack of images) - """ - self._check_data_stack(data) - - # list with first-x, first-y, second-x, second-y - if cfg.crop_coords: - try: - self.tomo_print_timed_start( - " * Starting image cropping step, with pixel data type: {0}, coordinates: {1}. ...". - format(data.dtype, cfg.crop_coords)) - import prep as iprep - data = iprep.filters.crop_vol(data, cfg.crop_coords) - self.tomo_print_timed_stop( - " * Finished image cropping step, with pixel data type: {0}, coordinates: {1}. " - "Resulting shape: {2}.".format(data.dtype, cfg.crop_coords, - data.shape)) - - except ValueError as exc: - print( - "Error in crop (region of interest) parameter (expecting a list with four integers. " - "Got: {0}. Error details: ".format(cfg.crop_coords), exc) - else: - self.tomo_print( - " * Note: NOT applying cropping to region of interest.", - priority=2) - - return data - - def normalize_flat_dark(self, data, cfg, norm_flat_img, norm_dark_img): - """ - Normalize by flat and dark images - - @param data :: image stack as a 3d numpy array - @param cfg :: pre-processing configuration - @param norm_flat_img :: flat (open beam) image to use in normalization - @param norm_dark_img :: dark image to use in normalization - - Returns :: filtered data (stack of images) - """ - self._check_data_stack(data) - - if not cfg or not isinstance(cfg, tomocfg.PreProcConfig): - raise ValueError( - "Cannot normalize by flat/dark images without a valid pre-processing " - "configuration") - - if not cfg.normalize_flat_dark: - self.tomo_print( - " * Note: NOT applying normalization by flat/dark images.", - priority=2) - return data - - if isinstance(norm_flat_img, np.ndarray): - if 2 != len(norm_flat_img. - shape) or norm_flat_img.shape != data.shape[1:]: - raise ValueError( - "Incorrect shape of the flat image ({0}) which should match the " - "shape of the sample images ({1})".format( - norm_flat_img.shape, data[0].shape)) - self.tomo_print_timed_start( - " * Starting normalization by flat/dark images with pixel data type: {0}...". - format(data.dtype)) - norm_divide = None - if norm_dark_img: - norm_divide = norm_flat_img - norm_dark_img - else: - norm_divide = norm_flat_img - - if self.crop_before_normaliz and cfg.crop_coords: - norm_divide = norm_divide[:, cfg.crop_coords[ - 1]:cfg.crop_coords[3] + 1, cfg.crop_coords[0]: - cfg.crop_coords[2] + 1] - # prevent divide-by-zero issues - norm_divide[norm_divide == 0] = 1e-6 - - if not norm_dark_img: - norm_dark_img = 0 - for idx in range(0, data.shape[0]): - data[idx, :, :] = np.true_divide( - data[idx, :, :] - norm_dark_img, norm_divide) - # true_divide produces float64, we assume that precision not needed (definitely not - # for 16-bit depth output images as we usually have). - self.tomo_print_timed_stop( - " * Finished normalization by flat/dark images with pixel data type: {0}.". - format(data.dtype)) - else: - self.tomo_print( - " * Note: cannot apply normalization by flat/dark images because no valid flat image has been " - "provided in the inputs. Flat image given: {0}".format( - norm_flat_img), - priority=2) - - return data - - def apply_cut_off_and_others(self, data, cfg): - """ - Applies several pre-processing steps meant to be applied before - the line projection transformation and final pre-processing on - it. This includes at the moment: cut-off, and median - filter. TODO: MCP corrections, scaling down, others. - - Returns :: filtered data (stack of images) - - """ - self._check_data_stack(data) - - if not cfg or not isinstance(cfg, tomocfg.PreProcConfig): - raise ValueError( - "Cannot apply cut-off without a valid pre-processing configuration" - ) - - # Apply cut-off for the normalization? - if cfg.cut_off_level and cfg.cut_off_level: - self.tomo_print_timed_start( - "* Applying cut-off with level: {0}".format(cfg.cut_off_level)) - dmin = np.amin(data) - dmax = np.amax(data) - rel_cut_off = dmin + cfg.cut_off_level * (dmax - dmin) - data[data < rel_cut_off] = dmin - self.tomo_print_timed_stop( - " * Finished cut-off step, with pixel data type: {0}.".format( - data.dtype)) - else: - self.tomo_print(" * Note: NOT applying cut-off.", priority=2) - - if cfg.mcp_corrections: - self.tomo_print( - " * MCP corrections not implemented in this version", - priority=2) - - if cfg.scale_down: - self.tomo_print( - " * Scale down not implemented in this version", priority=2) - - if cfg.median_filter_size and cfg.median_filter_size > 1: - self.tomo_print_timed_start( - " * Starting noise filter / median, with pixel data type: {0}, filter size/width: {1}.". - format(data.dtype, cfg.median_filter_size)) - for idx in range(0, data.shape[0]): - data[idx] = scipy.ndimage.median_filter( - data[idx], cfg.median_filter_size, mode='mirror') - #, mode='nearest') - self.tomo_print_timed_stop( - " * Finished noise filter / median, with pixel data type: {0}, filter size/width: {1}.". - format(data.dtype, cfg.median_filter_size)) - else: - self.tomo_print( - " * Note: NOT applying noise filter /median.", priority=2) - - return data - - def rotate_stack(self, data, cfg, white=None, dark=None): - """ - Rotates a stack (sample, white and dark images). - This funciton is usually used on the whole picture, which is a square. - If the picture is cropped first, the ROI coordinates - have to be adjusted separately to be pointing at the NON ROTATED image! - - @param data :: stack of sample images - @param cfg :: pre-processing configuration - @param white :: stack of white images - @param white :: stack of dark images - - Returns :: rotated images - """ - if not cfg or not isinstance(cfg, tomocfg.PreProcConfig): - raise ValueError( - "Cannot rotate images without a valid pre-processing configuration" - ) - - if not cfg.rotation or cfg.rotation < 0: - self.tomo_print( - " * Note: NOT rotating the input images.", priority=2) - return data, white, dark - - self.tomo_print_timed_start( - " * Starting rotation step ({0} degrees clockwise), with pixel data type: {1}...". - format(cfg.rotation * 90, data.dtype)) - - data = self._rotate_imgs(data, cfg) - if white: - white = self._rotate_imgs(white, cfg) - if dark: - dark = self._rotate_imgs(dark, cfg) - - self.tomo_print_timed_stop( - " * Finished rotation step ({0} degrees clockwise), with pixel data type: {1}.". - format(cfg.rotation * 90, data.dtype)) - - return (data, white, dark) - - def _rotate_imgs(self, data, cfg): - """ - Rotate every image of a stack - - @param data :: image stack as a 3d numpy array - @param cfg :: pre-processing configuration - - Returns :: rotated data (stack of images) - """ - - self._check_data_stack(data) - self._debug_print_memory_usage_linux("before rotation.") - - for idx in range(0, data.shape[0]): - # rot90 rotates counterclockwise; cfg.rotation rotates clockwise - counterclock_rotations = 4 - cfg.rotation - data[idx, :, :] = np.rot90(data[idx, :, :], counterclock_rotations) - - self._debug_print_memory_usage_linux("after rotation.") - - return data - - def run_reconstruct_3d(self, - proj_data, - preproc_cfg, - alg_cfg, - reconstruction_tool=None): - """ - A 3D reconstruction - - @param proj_data :: Input projected images - @param tool :: reconstruction tool to call/use - - Returns :: reconstructed volume - """ - self._check_data_stack(proj_data) - - num_proj = proj_data.shape[0] - inc = float(preproc_cfg.max_angle) / (num_proj - 1) - - proj_angles = np.arange(0, num_proj * inc, inc) - # For tomopy - proj_angles = np.radians(proj_angles) - - if 'astra' == alg_cfg.tool: - # run_reconstruct_3d_astra(proj_data, algorithm, cor, proj_angles=proj_angles) - return self.run_reconstruct_3d_astra_simple( - proj_data, proj_angles, alg_cfg, preproc_cfg.cor, - reconstruction_tool) - - self.tomo_print(" * Using center of rotation: {0}".format( - preproc_cfg.cor)) - if 'tomopy' == alg_cfg.tool and 'gridrec' != alg_cfg.algorithm and 'fbp' != alg_cfg.algorithm: - if not alg_cfg.num_iter: - reconstruction_tool.cfg_num_iter = tomocfg.PreProcConfig.DEF_NUM_ITER - # For ref, some typical run times with 4 cores: - # 'bart' with num_iter=20 => 467.640s ~= 7.8m - # 'sirt' with num_iter=30 => 698.119 ~= 11.63 - self.tomo_print_timed_start( - " * Starting iterative method with TomoPy. Algorithm: {0}, " - "number of iterations: {1}...".format(alg_cfg.algorithm, - alg_cfg.num_iter)) - rec = reconstruction_tool.recon( - tomo=proj_data, - theta=proj_angles, - center=preproc_cfg.cor, - algorithm=alg_cfg.algorithm, - num_iter=alg_cfg.num_iter) #, filter_name='parzen') - - else: - self.tomo_print_timed_start( - " * Starting non-iterative reconstruction algorithm with TomoPy. " - "Algorithm: {0}...".format(alg_cfg.algorithm)) - rec = reconstruction_tool.recon( - tomo=proj_data, - theta=proj_angles, - center=preproc_cfg.cor, - algorithm=alg_cfg.algorithm) - - self.tomo_print_timed_stop( - " * Reconstructed 3D volume. Shape: {0}, and pixel data type: {1}.". - format(rec.shape, rec.dtype)) - - return rec - - # def astra_reconstruct3d(self, sinogram, angles, depth, alg_cfg): - # """ - # Run a reconstruction with astra - - # @param sinogram :: sinogram data - # @param angles :: angles of the image projections - # @param depth :: number of rows in images/sinograms - # @param alg_cfg :: tool/algorithm configuration - # """ - # # Some of these have issues depending on the GPU setup - # algs_avail = "[FP3D_CUDA], [BP3D_CUDA]], [FDK_CUDA], [SIRT3D_CUDA], [CGLS3D_CUDA]" - - # if alg_cfg.algorithm.upper() not in algs_avail: - # raise ValueError( - # "Invalid algorithm requested for the Astra package: {0}. " - # "Supported algorithms: {1}".format(alg_cfg.algorithm, - # algs_avail)) - # det_rows = sinogram.shape[0] - # det_cols = sinogram.shape[2] - - # vol_geom = astra.create_vol_geom(sinograms.shape[0], depth, - # sinogram.shape[2]) - # proj_geom = astra.create_proj_geom('parallel3d', 1.0, 1.0, det_cols, - # det_rows, np.deg2rad(angles)) - - # sinogram_id = astra.data3d.create("-sino", proj_geom, sinogram) - # # Create a data object for the reconstruction - # rec_id = astra.data3d.create('-vol', vol_geom) - - # cfg = astra.astra_dict(alg_cfg.algorithm) - # cfg['ReconstructionDataId'] = rec_id - # cfg['ProjectionDataId'] = sinogram_id - - # # Create the algorithm object from the configuration structure - # alg_id = astra.algorithm.create(cfg) - # # This will have a runtime in the order of 10 seconds. - # astra.algorithm.run(alg_id, alg_cfg.num_iter) - # # This could be used to check the norm of the difference between the projection data - # # and the forward projection of the reconstruction. - # # if "CUDA" in cfg_alg.algorithm and "FBP" not cfg_alg.algorithm: - # # self.norm_diff += astra.algorithm.get_res_norm(alg_id)**2 - # # print math.sqrt(self.norm_diff) - - # # Get the result - # rec = astra.data3d.get(rec_id) - - # astra.algorithm.delete(alg_id) - # astra.data3d.delete(rec_id) - # astra.data3d.delete(sinogram_id) - - # return rec - - # def run_reconstruct_3d_astra(self, proj_data, proj_angles, alg_cfg): - # """ - # Run a reconstruction with astra, approach based on swpapping axes - - # @param proj_data :: projection images - # @param proj_angles :: angles corresponding to the projection images - # @param alg_cfg :: tool/algorithm configuration - # """ - - # def get_max_frames(algorithm): - # frames = 8 if "3D" in algorithm else 1 - # return frames - - # nSinos = get_max_frames(alg_cfg.algorithm) - # iterations = alg_cfg.num_iter - # print(" astra recon - doing {0} iterations".format(iterations)) - - # swaps outermost dimensions so it is sinogram layout - # sinogram = proj_data - # sinogram = np.swapaxes(sinogram, 0, 1) - - # Needs to be figured out better - #ctr = cor - #width = sinogram.shape[1] - #pad = 50 - - #sino = np.nan_to_num(1./sinogram) - - # pad the array so that the centre of rotation is in the middle - #alen = ctr - #blen = width - ctr - #mid = width / 2.0 - - #if ctr > mid: - #plow = pad - #phigh = (alen - blen) + pad - #else: - #plow = (blen - alen) + pad - #phigh = pad - - #logdata = np.log(sino+1) - - # sinogram = np.tile(sinogram.reshape((1, ) + sinogram.shape), (8, 1, 1)) - - # rec = self.astra_reconstruct3d( - # sinogram, proj_angles, depth=nSinos, alg_cfg=alg_cfg) - - # return rec - - def run_reconstruct_3d_astra_simple(self, - proj_data, - proj_angles, - alg_cfg, - cor=None, - reconstruction_tool=None): - """ - Run a reconstruction with astra, simple handling of projected data/images - - @param proj_data :: projection images - @param alg_cfg :: tool/algorithm configuration - @param cor :: center of rotation - @param proj_angles :: angles corresponding to the projection images - """ - import tomorec.tool_imports as tti - astra = tti.import_tomo_tool('astra') - sinograms = proj_data - - sinograms = np.swapaxes(sinograms, 0, 1) - - plow = (proj_data.shape[2] - cor * 2) - phigh = 0 - - # minval = np.amin(sinograms) - sinograms = np.pad(sinograms, ((0, 0), (0, 0), (plow, phigh)), - mode='reflect') - - proj_geom = astra.create_proj_geom('parallel3d', .0, 1.0, - proj_data.shape[1], - sinograms.shape[2], proj_angles) - sinogram_id = astra.data3d.create('-sino', proj_geom, sinograms) - - vol_geom = astra.create_vol_geom( - proj_data.shape[1], sinograms.shape[2], proj_data.shape[1]) - recon_id = astra.data3d.create('-vol', vol_geom) - alg_cfg = astra.astra_dict(alg_cfg.algorithm) - alg_cfg['ReconstructionDataId'] = recon_id - alg_cfg['ProjectionDataId'] = sinogram_id - alg_id = astra.algorithm.create(alg_cfg) - - number_of_iters = 100 - astra.algorithm.run(alg_id, number_of_iters) - recon = astra.data3d.get(recon_id) - - astra.algorithm.delete(alg_id) - astra.data3d.delete(recon_id) - astra.data3d.delete(sinogram_id) - - return recon - - def apply_postproc_filters(self, recon_data, cfg): - """ - Apply all post-processing steps/filters/transformations on a reconstructed volume - - @param cfg :: post-processing configuration - - Returns :: filtered data (reconstructed 3d volume) - """ - import prep as iprep - - if cfg.circular_mask: - self.tomo_print_timed_start( - " * Applying circular mask on reconstructed volume...") - recon_data = iprep.filters.circular_mask( - recon_data, ratio=cfg.circular_mask) - self.tomo_print_timed_stop( - " * Finished applying circular mask on reconstructed volume") - else: - self.tomo_print( - " * Note: NOT applied circular mask on reconstructed volume", - priority=2) - - if cfg.cut_off_level and cfg.cut_off_level > 0.0: - self.tomo_print_timed_start( - " * Starting to apply cut-off: {0}".format(cfg.cut_off)) - dmin = np.amin(recon_data) - dmax = np.amax(recon_data) - rel_cut_off = dmin + cfg.cut_off * (dmax - dmin) - recon_data[recon_data < rel_cut_off] = dmin - self.tomo_print_timed_stop(" * Finished applying cut-off.") - - if cfg.gaussian_filter_par: - self.tomo_print(" * Gaussian filter not implemented", priority=2) - - if cfg.median_filter_size and cfg.median_filter_size > 1: - self.tomo_print_timed_start( - " * Applying median_filter on reconstructed volume, with filtersize: {0}". - format(cfg.median_filter_size)) - - recon_data = scipy.ndimage.median_filter(recon_data, - cfg.median_filter_size) - - self.tomo_print_timed_stop( - " * Finished applying median_filter on reconstructed volume, with filtersize: {0}". - format(cfg.median_filter_size)) - else: - self.tomo_print( - " * Note: NOT applied median_filter on reconstructed volume", - priority=2) - - if cfg.median_filter3d_size and cfg.median_filter3d_size > 1: - kernel_size = 3 - - self.tomo_print_timed_start( - " * Applying N-dimensional median filter on reconstructed volume, with filter size: {0} ". - format(kernel_size)) - - # Note this can be extremely slow - recon_data = scipy.signal.medfilt( - recon_data, kernel_size=kernel_size) - - self.tomo_print_timed_stop( - " * Finished applying N-dimensional median filter on reconstructed volume, with filter size: {0} ". - format(kernel_size)) - else: - self.tomo_print( - " * Note: NOT applied N-dimensional median filter on reconstructed volume" - ) - - def read_in_stack(self, - sample_path, - img_format, - flat_field_path=None, - dark_field_path=None): - """ - Loads a stack, including sample, white and dark images. - - @param sample_path :: path to sample images - - @param img_format :: image format to expect/use (as a filename extension) - - @param flat_field_path :: (optional) path to open beam / white image(s). - Can be a file or directory - - @param dark_field_path :: (optional) path to dark field image(s). - Can be a file or directory - - Returns :: stack of images as a 3-elements tuple: numpy array with sample images, white image, - and dark image. - """ - # Note, not giving prefix. It will load all the files found. - # Example prefixes are prefix = 'tomo_', prefix = 'LARMOR00', prefix = 'angle_agg' - - sample, white, dark = tomoio.read_stack_of_images( - sample_path, - flat_field_path=flat_field_path, - dark_field_path=dark_field_path, - file_extension=img_format) - - if not isinstance(sample, np.ndarray) or not sample.shape \ - or not isinstance(sample.shape, tuple) or 3 != len(sample.shape): - raise RuntimeError( - "Error reading sample images. Could not produce a 3-dimensional array " - "of data from the sample images. Got: {0}".format(sample)) - - return (sample, white, dark) - - def save_recon_output(self, recon_data, cfg, save_horiz_slices=False): - """ - Save output reconstructed volume in different forms. - - @param recon_data :: reconstructed data volume. A sequence of images will be saved from this - @param cfg :: configuration of the reconstruction, including output paths and formats - @param save_horiz_slices :: Save images along the horizontal axis in addition to the vertical - slices saved by defult. Useful for testing - some tools - """ - # slices along the vertical (z) axis - # output_dir = 'output_recon_tomopy' - output_dir = cfg.postproc_cfg.output_dir - out_recon_dir = os.path.join(output_dir, 'reconstructed') - self.tomo_print_timed_start( - " * Starting saving slices of the reconstructed volume in: {0}...". - format(out_recon_dir)) - tomoio.save_recon_as_vertical_slices( - recon_data, - out_recon_dir, - name_prefix=self._OUT_SLICES_FILENAME_PREFIX, - img_format=cfg.preproc_cfg.out_img_format) - - # Sideways slices: - save_horiz_slices = False - if save_horiz_slices: - out_horiz_dir = os.path.join(output_dir, 'horiz_slices') - print("* Saving horizontal slices in: {0}".format(out_horiz_dir)) - tomoio.save_recon_as_horizontal_slices( - recon_data, - out_horiz_dir, - name_prefix=self._OUT_HORIZ_SLICES_SUBDIR, - img_format=cfg.preproc_cfg.out_img_format) - - self.tomo_print_timed_stop( - " * Finished saving slices of the reconstructed volume in: {0}". - format(out_recon_dir)) - - def save_preproc_images(self, - output_dir, - preproc_data, - preproc_cfg, - out_dtype='uint16'): - """ - Save (pre-processed) images from a data array to image files. - - @param output_dir :: where results are being saved, including the pre-proc images/slices - @param preproc_data :: data volume with pre-processed images - @param preproc_cfg :: pre-processing configuration set up for a reconstruction - @param out_dtype :: dtype used for the pixel type/depth in the output image files - """ - - min_pix = np.amin(preproc_data) - max_pix = np.amax(preproc_data) - # DEBUG message - # print(" with min_pix: {0}, max_pix: {1}".format(min_pix, max_pix)) - if preproc_cfg.save_preproc_imgs: - preproc_dir = os.path.join(output_dir, - self._PREPROC_IMGS_SUBDIR_NAME) - self.tomo_print_timed_start( - " * Saving all pre-processed images (preproc_data) into {0} dtype: {1}". - format(preproc_dir, preproc_data.dtype)) - tomoio.make_dirs_if_needed(preproc_dir) - for idx in range(0, preproc_data.shape[0]): - # rescale_intensity has issues with float64=>int16 - tomoio.write_image( - preproc_data[idx, :, :], - min_pix, - max_pix, - os.path.join(preproc_dir, - 'out_preproc_proj_image' + str(idx).zfill(6)), - img_format=preproc_cfg.out_img_format, - dtype=out_dtype) - self.tomo_print_timed_stop( - " * Saving pre-processed images finished.") - else: - self.tomo_print(" * NOTE: NOT saving pre-processed images...") - - def _check_data_stack(self, data): - if not isinstance(data, np.ndarray): - raise ValueError( - "Invalid stack of images data. It is not a numpy array: {0}". - format(data)) - - if 3 != len(data.shape): - raise ValueError( - "Invalid stack of images data. It does not have 3 dimensions. Shape: {0}". - format(data.shape)) - - def find_center(self, cfg): - self._check_paths_integrity(cfg) - - self.tomo_print_timed_start(" * Importing tool " + cfg.alg_cfg.tool) - # import tool - import tomorec.tool_imports as tti - tomopy = tti.import_tomo_tool(cfg.alg_cfg.tool) - self.tomo_print_timed_stop(" * Tool loaded.") - - self.tomo_print_timed_start(" * Loading data...") - # load in data - sample, white, dark = self.read_in_stack( - cfg.preproc_cfg.input_dir, cfg.preproc_cfg.in_img_format, - cfg.preproc_cfg.input_dir_flat, cfg.preproc_cfg.input_dir_dark) - self.tomo_print_timed_stop( - " * Data loaded. Shape of raw data: {0}, dtype: {1}.".format( - sample.shape, sample.dtype)) - - # rotate - sample, white, dark = self.rotate_stack(sample, cfg.preproc_cfg) - - # crop the ROI, this is done first, so beware of what the correct ROI coordinates are - sample = self.crop_coords(sample, cfg.preproc_cfg) - - # sanity check - self.tomo_print(" * Sanity check on data", 0) - self._check_data_stack(sample) - - num_projections = sample.shape[0] - inc = float(cfg.preproc_cfg.max_angle) / (num_projections - 1) - - self.tomo_print(" * Calculating projection angles") - proj_angles = np.arange(0, num_projections * inc, inc) - # For tomopy - self.tomo_print(" * Calculating radians for TomoPy") - proj_angles = np.radians(proj_angles) - - size = int(num_projections) - - # depending on the number of COR projections it will select different slice indices - cor_num_checked_projections = 6 - cor_proj_slice_indices = [] - cor_slice_index = 0 - - if cor_num_checked_projections < 2: - # this will give us the middle slice - cor_slice_index = int(size / 2) - cor_proj_slice_indices.append(cor_slice_index) - else: - for c in range(cor_num_checked_projections): - cor_slice_index += int(size / cor_num_checked_projections) - cor_proj_slice_indices.append(cor_slice_index) - - calculated_cors = [] - - self.tomo_print_timed_start( - " * Starting COR calculation for " + - str(cor_num_checked_projections) + " out of " + - str(sample.shape[0]) + " projections", 2) - - cropCoords = cfg.preproc_cfg.crop_coords[0] - imageWidth = sample.shape[2] - - # if crop corrds match with the image width then the full image was selected - pixelsFromLeftSide = cropCoords if cropCoords - imageWidth <= 1 else 0 - - for slice_idx in cor_proj_slice_indices: - tomopy_cor = tomopy.find_center( - tomo=sample, theta=proj_angles, ind=slice_idx, emission=False) - print(" ** COR for slice", str(slice_idx), ".. REL to CROP ", - str(tomopy_cor), ".. REL to FULL ", - str(tomopy_cor + pixelsFromLeftSide)) - calculated_cors.append(tomopy_cor) - - self.tomo_print_timed_stop(" * Finished COR calculation.", 2) - - averageCORrelativeToCrop = sum(calculated_cors) / len(calculated_cors) - averageCORrelativeToFullImage = sum(calculated_cors) / len( - calculated_cors) + pixelsFromLeftSide - - # we add the pixels cut off from the left, to reflect the full image in Mantid - self.tomo_print(" * Printing average COR in relation to cropped image " - + str(cfg.preproc_cfg.crop_coords) + ":", 2) - print(str(round(averageCORrelativeToCrop))) - self.tomo_print(" * Printing average COR in relation to FULL image:", - 2) - print(str(round(averageCORrelativeToFullImage))) diff --git a/scripts/Imaging/IMAT/tomorec/tool_imports.py b/scripts/Imaging/IMAT/tomorec/tool_imports.py deleted file mode 100644 index 066d8c266ab..00000000000 --- a/scripts/Imaging/IMAT/tomorec/tool_imports.py +++ /dev/null @@ -1,69 +0,0 @@ -from __future__ import (absolute_import, division, print_function) -# Copyright © 2014-2015 ISIS Rutherford Appleton Laboratory, NScD -# Oak Ridge National Laboratory & European Spallation Source -# -# This file is part of Mantid. -# Mantid is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3 of the License, or -# (at your option) any later version. -# -# Mantid is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see <http://www.gnu.org/licenses/>. -# -# File change history is stored at: <https://github.com/mantidproject/mantid>. -# Code Documentation is available at: <http://doxygen.mantidproject.org> - - -def _import_tool_tomopy(): - try: - import tomopy - import tomopy.prep - import tomopy.recon - import tomopy.misc - import tomopy.io - - except ImportError as exc: - raise ImportError("Could not import the tomopy package and its subpackages. Details: {0}". - format(exc)) - - return tomopy - - -def _import_tool_astra(): - # current astra distributions install here, so check there by default - ASTRA_LOCAL_PATH = '/usr/local/python/' - import sys - sys.path.append(ASTRA_LOCAL_PATH) - try: - import astra - except ImportError as exc: - raise ImportError("Cannot find and import the astra toolbox package: {0}". - format(exc)) - - MIN_ASTRA_VERSION = 106 - vers = astra.astra.version() - if isinstance(vers, int) and vers >= MIN_ASTRA_VERSION: - print("Imported astra successfully. Version: {0}".format(astra.astra.version())) - else: - raise RuntimeError("Could not find the required version of astra. Found version: {0}".format(vers)) - - print("Astra using cuda: {0}". format(astra.astra.use_cuda())) - return astra - - -def import_tomo_tool(tool): - if not tool or not isinstance(tool, str): - raise ValueError("The name of a reconstruction tool is required as a string. Got: {0}". - format(tool)) - if 'tomopy' == tool: - return _import_tool_tomopy() - elif 'astra' == tool: - return _import_tool_astra() - else: - raise ValueError("Internal inconsistency. Tried to import unknown tool: {0}".format(tool)) -- GitLab