diff --git a/MantidPlot/src/ApplicationWindow.cpp b/MantidPlot/src/ApplicationWindow.cpp index ae9c8d1dd165c663bfc321c89444b2067ae7c24f..76c35b7c3516f895ae6eb2423fa13f4135c8f1a6 100644 --- a/MantidPlot/src/ApplicationWindow.cpp +++ b/MantidPlot/src/ApplicationWindow.cpp @@ -9774,6 +9774,7 @@ void ApplicationWindow::closeEvent(QCloseEvent *ce) { // Stop background saving thread, so it doesn't try to use a destroyed // resource m_projectRecovery.stopProjectSaving(); + m_projectRecovery.clearAllCheckpoints(); // Close the remaining MDI windows. The Python API is required to be active // when the MDI window destructor is called so that those references can be diff --git a/MantidPlot/src/ProjectRecovery.cpp b/MantidPlot/src/ProjectRecovery.cpp index a50feadef500666dab341a9718fb98b71f0593f8..39695bc429d249b513c24cdc2e39f754537a2934 100644 --- a/MantidPlot/src/ProjectRecovery.cpp +++ b/MantidPlot/src/ProjectRecovery.cpp @@ -5,8 +5,8 @@ #include "ProjectSerialiser.h" #include "ScriptingWindow.h" +#include "MantidAPI/AlgorithmManager.h" #include "MantidAPI/FileProperty.h" -#include "MantidAPI/FrameworkManager.h" #include "MantidKernel/ConfigService.h" #include "MantidKernel/Logger.h" #include "MantidKernel/UsageService.h" @@ -18,9 +18,9 @@ #include "Poco/Path.h" #include <QMessageBox> +#include <QMetaObject> #include <QObject> #include <QString> -#include <QMetaObject> #include <chrono> #include <condition_variable> @@ -99,7 +99,9 @@ Poco::Path getOutputPath() { std::vector<Poco::Path> getRecoveryFolderCheckpoints(const std::string &recoveryFolderPath) { Poco::Path recoveryPath; - if (!recoveryPath.tryParse(recoveryFolderPath)) { + + if (!recoveryPath.tryParse(recoveryFolderPath) || + !Poco::File(recoveryPath).exists()) { // Folder may not exist yet g_log.debug("Project Saving: Failed to get working folder whilst deleting " "checkpoints"); @@ -194,10 +196,28 @@ bool ProjectRecovery::attemptRecovery() { } } -bool ProjectRecovery::checkForRecovery() const { - const auto checkpointPaths = - getRecoveryFolderCheckpoints(getRecoveryFolder()); - return checkpointPaths.size() != 0; // Non zero indicates recovery is pending +bool ProjectRecovery::checkForRecovery() const noexcept { + try { + const auto checkpointPaths = + getRecoveryFolderCheckpoints(getRecoveryFolder()); + return checkpointPaths.size() != + 0; // Non zero indicates recovery is pending + } catch (...) { + g_log.warning("Project Recovery: Caught exception whilst attempting to " + "check for existing recovery"); + return false; + } +} + +bool ProjectRecovery::clearAllCheckpoints() const noexcept { + try { + deleteExistingCheckpoints(0); + return true; + } catch (...) { + g_log.warning("Project Recovery: Caught exception whilst attempting to " + "clear existing checkpoints."); + return false; + } } /// Returns a background thread with the current object captured inside it @@ -226,17 +246,13 @@ void ProjectRecovery::configKeyChanged( void ProjectRecovery::compileRecoveryScript(const Poco::Path &inputFolder, const Poco::Path &outputFile) { const std::string algName = "OrderWorkspaceHistory"; - auto *alg = - Mantid::API::FrameworkManager::Instance().createAlgorithm(algName, 1); - if (!alg) { - throw std::runtime_error("Could not get pointer to alg: " + algName); - } - + auto alg = + Mantid::API::AlgorithmManager::Instance().createUnmanaged(algName, 1); alg->initialize(); + alg->setChild(true); alg->setRethrows(true); alg->setProperty("RecoveryCheckpointFolder", inputFolder.toString()); alg->setProperty("OutputFilepath", outputFile.toString()); - alg->execute(); g_log.notice("Saved your recovery script to:\n" + outputFile.toString()); @@ -416,14 +432,11 @@ void ProjectRecovery::saveWsHistories(const Poco::Path &historyDestFolder) { Mantid::Kernel::UsageService::Instance().getStartTime().toISO8601String(); const std::string algName = "GeneratePythonScript"; - auto *alg = - Mantid::API::FrameworkManager::Instance().createAlgorithm(algName, 1); - - if (!alg) { - throw std::runtime_error("Could not get pointer to alg: " + algName); - } + auto alg = + Mantid::API::AlgorithmManager::Instance().createUnmanaged(algName, 1); + alg->setChild(true); + alg->setLogging(false); - for (const auto &ws : wsHandles) { std::string filename = ws->getName(); filename.append(".py"); diff --git a/MantidPlot/src/ProjectRecovery.h b/MantidPlot/src/ProjectRecovery.h index e7c3662d00197ef437e6c1007ed6562bc4e2063f..b1154dbb657f228db38fe983662bc40e9f764b5f 100644 --- a/MantidPlot/src/ProjectRecovery.h +++ b/MantidPlot/src/ProjectRecovery.h @@ -57,10 +57,10 @@ public: /// Attempts recovery of the most recent checkpoint bool attemptRecovery(); /// Checks if recovery is required - bool checkForRecovery() const; + bool checkForRecovery() const noexcept; /// Clears all checkpoints in the existing folder - void clearAllCheckpoints() const { deleteExistingCheckpoints(0); }; + bool clearAllCheckpoints() const noexcept; /// Starts the background thread void startProjectSaving(); diff --git a/docs/source/release/v3.13.0/diffraction.rst b/docs/source/release/v3.13.0/diffraction.rst index bc9725a87261a440339e8b2b19a268153d2968ec..2aa2024a226bc3082bcb2a861b5c9e7a38bf0cc6 100644 --- a/docs/source/release/v3.13.0/diffraction.rst +++ b/docs/source/release/v3.13.0/diffraction.rst @@ -12,6 +12,23 @@ Diffraction Changes Powder Diffraction ------------------ +New +### + +- :ref:`LoadILLDiffraction <algm-LoadILLDiffraction>` is extended to apply vertical and horizontal tube alignment for D2B, based on the IPF. +- :ref:`LoadILLDiffraction <algm-LoadILLDiffraction>` is modified to comply with the U-shape convention for tube numbering for D2B. +- :ref:`PowderDiffILLDetEffCorr <algm-PowderDiffILLDetEffCorr>` is extended to compute the detector efficiencies also for the 2-dimensional scanning diffractometer D2B at the ILL. +- :ref:`PowderDiffILLDetEffCorr <algm-PowderDiffILLDetEffCorr>` is extended to provide automatic masking of the pixels with spurious calibration constants. +- :ref:`PowderDiffILLDetEffCorr <algm-PowderDiffILLDetEffCorr>` will now ignore the last scan point data, if some of the input files have 26 points, instead of 25. +- :ref:`PowderDiffILLDetScanReduction <algm-PowderDiffILLDetScanReduction>` is extended to provide initial masking of the top and bottom parts of the tubes, and final masking of the 2D outputs. +- :ref:`WANDPowderReduction <algm-WANDPowderReduction>` performs powder diffraction data reduction for WAND² with calibration, monitor normalisation and background subtraction. +- New NOMAD instrument geometry for 2018 run cycle +- New POWGEN instrument geometry for 2018 run cycle +- New SNAP instrument geometry for 2018 run cycle with configuration for live data + +Improvements +############ + - Changing settings while running methods on the PEARL object no longer updates the default settings. Instead, initial settings are taken as the default, and any changes are reverted back to the @@ -23,24 +40,13 @@ Powder Diffraction - The ``.maud`` calibration file format, for conversion to d-spacing (uses a new algorithm :ref:`SaveGEMMAUDParamFile <algm-SaveGEMMAUDParamFile>` - :ref:`PDCalibration <algm-PDCalibration>` has major upgrades including making use of :ref:`FitPeaks <algm-FitPeaks>` for the individual peak fitting -- New NOMAD instrument geometry for 2018 run cycle -- New POWGEN instrument geometry for 2018 run cycle -- New SNAP instrument geometry for 2018 run cycle with configuration for live data - -New Features ------------- - -- :ref:`LoadILLDiffraction <algm-LoadILLDiffraction>` is extended to apply vertical and horizontal tube alignment for D2B, based on the IPF. -- :ref:`LoadILLDiffraction <algm-LoadILLDiffraction>` is modified to comply with the U-shape convention for tube numbering for D2B. -- :ref:`PowderDiffILLDetEffCorr <algm-PowderDiffILLDetEffCorr>` is extended to compute the detector efficiencies also for the 2-dimensional scanning diffractometer D2B at the ILL. -- :ref:`PowderDiffILLDetEffCorr <algm-PowderDiffILLDetEffCorr>` is extended to provide automatic masking of the pixels with spurious calibration constants. -- :ref:`PowderDiffILLDetEffCorr <algm-PowderDiffILLDetEffCorr>` will now ignore the last scan point data, if some of the input files have 26 points, instead of 25. -- :ref:`PowderDiffILLDetScanReduction <algm-PowderDiffILLDetScanReduction>` is extended to provide initial masking of the top and bottom parts of the tubes, and final masking of the 2D outputs. -- :ref:`WANDPowderReduction <algm-WANDPowderReduction>` performs powder diffraction data reduction for WAND² with calibration, monitor normalisation and background subtraction. Engineering Diffraction ----------------------- +Improvements +############ + - Improvements to the GSAS tab: - GSASIIRefineFitPeaks is now run asynchronously in the GUI, so the @@ -69,6 +75,8 @@ Engineering Diffraction Single Crystal Diffraction -------------------------- +New +### - New algorithm :ref:`LoadDNSSCD <algm-LoadDNSSCD>` to load multiple single crystal diffraction data files from the DNS instrument into MDEventWorkspace. diff --git a/docs/source/release/v3.13.0/direct_inelastic.rst b/docs/source/release/v3.13.0/direct_inelastic.rst index 0e897307217bd4839ec65acc9805b42e387ff08f..305e47d358629adbb85a8f90a2df5d10ac3773ba 100644 --- a/docs/source/release/v3.13.0/direct_inelastic.rst +++ b/docs/source/release/v3.13.0/direct_inelastic.rst @@ -13,8 +13,8 @@ Interfaces ---------- -New features -############ +New +### - Added the ability to manually specify a temperature for a set of runs in the TOFTOF reduction dialog. @@ -28,8 +28,8 @@ Improvements Algorithms ---------- -New features -############ +New +### - The *EPPWorkspace* input property has been removed from :ref:`DirectILLCollectData <algm-DirectILLCollectData>`. @@ -45,8 +45,8 @@ Improvements - all output workspaces are now converted to distributions, i.e. the histograms are divided by the bin width. - The default :math:`Q` binning has been revised. -Bug fixes -######### +Bugfixes +######## - Fixed a crash in :ref:`SofQW <algm-SofQW>`, :ref:`SofQWCentre <algm-SofQWCentre>`, :ref:`SofQWNormalisedPolygon <algm-SofQWNormalisedPolygon>` and :ref:`SofQWPolygon <algm-SofQWPolygon>` algorithms when they were supplied with energy or :math:`Q` binning params containing the bin width only. - Fixed a failure in the wavelength interpolation of :ref:`MonteCarloAbsorption <algm-MonteCarloAbsorption>` which occurred under certain input property combinations. @@ -69,6 +69,9 @@ Instrument Definitions Python ------ +Improvements +############ + - The plotting methods in the :ref:`directtools <Directtools Python module>` python module now support logarithmic scales. :ref:`Release 3.13.0 <v3.13.0>` diff --git a/docs/source/release/v3.13.0/framework.rst b/docs/source/release/v3.13.0/framework.rst index 663ef1d2a93c10304904a98fcb70dc7b15d9643d..b41bb85a368c5c56f8d7d241607904cec3e46714 100644 --- a/docs/source/release/v3.13.0/framework.rst +++ b/docs/source/release/v3.13.0/framework.rst @@ -23,19 +23,22 @@ Stability ``` ISISDAE.Timeout = 100 #seconds ``` +- The error reporter now catches hard crashes to desktop. Algorithms ---------- +New +### + New Features -############ +************ - A list of Related Algorithms has been added to each algorithm, and is displayed in the documentation page of each algorithm as part of it's summary. -- The error reporter now catches hard crashes to desktop. New Algorithms -############## +************** - :ref:`LoadSampleShape <algm-LoadSampleShape>` loads a shape into the sample in a workspace from an ASCII `STL <https://en.wikipedia.org/wiki/STL_(file_format)>`_ file, @@ -57,19 +60,21 @@ New Algorithms - :ref:`SaveGEMMAUDParamFile <algm-SaveGEMMAUDParamFile>`, which acts as a partner to :ref:`SaveGDA <algm-SaveGDA>`, saves a MAUD calibration file to convert the output of **SaveGDA** back to d-spacing -Improved -######## +- Algorithm :ref:`FitPeaks <algm-FitPeaks>` is implemented as a generalized multiple-spectrum multiple-peak fitting algorithm. + +Improvements +############ - :ref:`LoadMcStas <algm-LoadMcStas>` new alg property which controls the granularity of event data returned. - :ref:`Maxent <algm-Maxent>` when outputting the results of the iterations, it no longer pads with zeroes but returns as many items as iterations done for each spectrum, making the iterations easy to count. -- XError values (Dx) can now be treated by the following algorithms: :ref:`ConjoinXRuns <algm-ConjoinXRuns>`, :ref:`ConvertToHistogram <algm-ConvertToHistogram>`, :ref:`ConvertToPointData <algm-ConvertToPointData>`, :ref:`CreateWorkspace <algm-CreateWorkspace>`, :ref:`SortXAxis <algm-SortXAxis>`, :ref:`algm-Stitch1D` and :ref:`algm-Stitch1DMany` (both with repect to point data). +- XError values (Dx) can now be treated by the following algorithms: :ref:`ConjoinXRuns <algm-ConjoinXRuns>`, :ref:`ConvertToHistogram <algm-ConvertToHistogram>`, :ref:`ConvertToPointData <algm-ConvertToPointData>`, :ref:`CreateWorkspace <algm-CreateWorkspace>`, :ref:`SortXAxis <algm-SortXAxis>`, :ref:`algm-Stitch1D` and :ref:`algm-Stitch1DMany` (both with respect to point data). - :ref:`Stitch1D <algm-Stitch1D>` can treat point data. - The algorithm :ref:`SortXAxis <algm-SortXAxis>` has a new input option that allows ascending (default) and descending sorting. The documentation needed to be corrected in general. -- :ref:`LoadNexusMonitors <algm-LoadNexusMonitors>` has changed its properties for clarification. This has also propogated to :ref:`LoadEventNexus <algm-LoadEventNexus>` and :ref:`LoadEventAndCompress <algm-LoadEventAndCompress>` +- :ref:`LoadNexusMonitors <algm-LoadNexusMonitors>` has changed its properties for clarification. This has also propagated to :ref:`LoadEventNexus <algm-LoadEventNexus>` and :ref:`LoadEventAndCompress <algm-LoadEventAndCompress>` -Bug fixes -######### +Bugfixes +######## - In :ref:`LoadMcStas <algm-LoadMcStas>` internally reduce number of event workspaces created. If n mcstas event components now create n*(n-1) fewer. - The documentation of the algorithm :ref:`algm-CreateSampleWorkspace` did not match its implementation. The axis in beam direction will now be correctly described as Z instead of X. @@ -79,16 +84,11 @@ Bug fixes - Fixed :ref:`SumSpectra <algm-SumSpectra>` to avoid a crash when validation of inputs was called with a WorkspaceGroup. - Fixed a bug in TableWorkspaces where vector column data was set to 0 when the table was viewed - The output workspace of :ref:`LineProfile <algm-LineProfile>` now has correct sample logs, instrument and history. -- TimeSeriesProperty::splitByTimeVector's behavior on a boundary condition is changed. In the set of splitters toward a same target splitted workspace, if there is a splitter's beginning time is after the last entry of the TimeSeriesProperty to be split, then this last entry shall be included in its output TimeSeriesProperty. +- TimeSeriesProperty::splitByTimeVector's behavior on a boundary condition is changed. In the set of splitters toward a same target split workspace, if a splitter's beginning time is after the last entry of the TimeSeriesProperty to be split, then this last entry shall be included in its output TimeSeriesProperty. - Fixed a bug in :ref:`MergeRuns <algm-MergeRuns>` which could cause the runs to be merged in a different sequence than indicated in the *InputWorkspaces* property. - Fixed a bug where the values entered for basis vector properties in :ref:`BinMD <algm-BinMD>` were not being remembered. - Fixed a bug which prevented :ref:`Load <algm-Load>` and :ref:`LoadAndMerge <algm-Load>` from parsing advanced run ranges such as ``1-3+5-7+10+15-20``. -New -### - -- Algorithm :ref:`FitPeaks <algm-FitPeaks>` is implemented as a generalized multiple-spectra multiple-peak fitting algorithm. - Python ------ @@ -98,8 +98,8 @@ New - Added a new ``MDFrameValidator`` which can check that a MD workspace passed to a python algorithm has the expected MD frame (e.g. HKL, QLab, QSample etc.). -Improved -######## +Improvements +############ - Python fit functions that use from ``IPeakFunction`` as a base no longer require a ``functionDeriveLocal`` method to compute an analytical derivative. If the method is absent then a numerical derivative is calculate. @@ -109,15 +109,9 @@ Bugfixes - Checks on the structure of Python fit function classes have been improved to avoid scenarios, such as writing ``function1d`` rather than ``function1D``, which would previously have resulted in a hard crash. -- Fit functions defined in a python script can be used with the new fit function API right after sibscription. +- Fit functions defined in a python script can be used with the new fit function API right after subscription. - Child algorithms now respect their parent algorithm's ``EnableLogging`` setting when invoked using the function-style calling. Previously, some messages could appear in the log even though ``EnableLogging`` was set to ``False``. - -Python ------- - -Bug fixes -######### - - Fixed a bug in ``detectorSignedTwoTheta`` method in ``MatrixWorkspace`` where the sign of the angle depended on the axis pointing up, not on the actual theta-sing axis defined in the IDF. -:ref:`Release 3.13.0 <v3.13.0>` \ No newline at end of file + +:ref:`Release 3.13.0 <v3.13.0>` diff --git a/docs/source/release/v3.13.0/indirect_inelastic.rst b/docs/source/release/v3.13.0/indirect_inelastic.rst index 81f44729e57dbd0b7fcae3a371756941c414f9d6..023d053214282097744526bef46f9ef5f7b0d830 100644 --- a/docs/source/release/v3.13.0/indirect_inelastic.rst +++ b/docs/source/release/v3.13.0/indirect_inelastic.rst @@ -14,6 +14,9 @@ Indirect Inelastic Changes Data Reduction Interfaces ------------------------- +Improvements +############ + - Added 'Sum Files' checkbox to ISIS Calibration, to sum a specified range of input files on load. - Detector grouping in ISISEnergyTransfer: added custom grouping method to allow specific spectra or ranges, and the 'groups' method now includes all spectra including remainder. @@ -33,8 +36,8 @@ New - :ref:`algm-IqtFitSimultaneous` can be used to perform a QENS simultaneous fit over I(Q,t) data. -Improved -######## +Improvements +############ - :ref:`algm-ConvolutionFitSequential` and :ref:`algm-IqtFitSequential` can now accept multiple datasets as input, in the same format as that of :ref:`algm-PlotPeakByLogValue`. diff --git a/docs/source/release/v3.13.0/instrument_view.rst b/docs/source/release/v3.13.0/instrument_view.rst index fadb882e2b08d29dddf462d71fab4869629844a8..fc6de74b9c44411a4807b5b139eed42da75d7634 100644 --- a/docs/source/release/v3.13.0/instrument_view.rst +++ b/docs/source/release/v3.13.0/instrument_view.rst @@ -12,6 +12,9 @@ Instrument Visualization Instrument View --------------- +Improvements +############ + The `Instrument View <https://www.mantidproject.org/MantidPlot:_Instrument_View>`__ visualization tool in Mantid has undergone some major changes under-the-hood which has resulted in a smoother, more responsive interface. Instruments generally load faster as well. Below are a few noteworthy improvements to load times: @@ -33,4 +36,4 @@ Instruments generally load faster as well. Below are a few noteworthy improvemen Tested on Windows 10. -:ref:`Release 3.13.0 <v3.13.0>` \ No newline at end of file +:ref:`Release 3.13.0 <v3.13.0>` diff --git a/docs/source/release/v3.13.0/muon.rst b/docs/source/release/v3.13.0/muon.rst index 55d9ba95b53c821d2f28f2d9576808132aaa0c5f..3f770113774bbe5a0a0659bc2c928fd5230417de 100644 --- a/docs/source/release/v3.13.0/muon.rst +++ b/docs/source/release/v3.13.0/muon.rst @@ -13,12 +13,12 @@ Improvements - The updated :ref:`EstimateMuonAsymmetryFromCounts <algm-EstimateMuonAsymmetryFromCounts>` is used in Muon Analysis. - TF Asymmetry mode now uses :ref:`CalMuonDetectorPhases <algm-CalMuonDetectorPhases>` and the fitting function is updated to show the normalization. -Bug fixes -######### +Bugfixes +######## - Results table can now detect sequential fits. - Fit options are not disabled after changing tabs. -- The run number is now updated before the periods, preventing irrelevant warningsfrom being produced. +- The run number is now updated before the periods, preventing irrelevant warnings from being produced. - In single fit the workspace can be changed. - In multiple fitting the function can be replaced without causing a crash. @@ -33,8 +33,8 @@ Improvements ############ - :ref:`EstimateMuonAsymmetryFromCounts <algm-EstimateMuonAsymmetryFromCounts>` now updates a normalization table and produces unnormalized data. -Bug fixes -######### +Bugfixes +######## - :ref:`EstimateMuonAsymmetryFromCounts <algm-EstimateMuonAsymmetryFromCounts>` had a small numerical error in the denominator of the normalisation calculation. - :ref:`MuonMaxent <algm-MuonMaxent>` and :ref:`PhaseQuad <algm-PhaseQuad>` no longer include dead detectors (zero counts) when calculating the frequency spectrum. - :ref:`RemoveExpDecay <algm-RemoveExpDecay>` will not alter data from a dead detectors (zero counts). diff --git a/docs/source/release/v3.13.0/reflectometry.rst b/docs/source/release/v3.13.0/reflectometry.rst index 111cbe3676d0fd56d48ee9cf1007bc2d02953ad2..fd0736526830dff1a8a3a20d24826850eba1fd90 100644 --- a/docs/source/release/v3.13.0/reflectometry.rst +++ b/docs/source/release/v3.13.0/reflectometry.rst @@ -12,8 +12,8 @@ Reflectometry Changes ISIS Reflectometry Interface ---------------------------- -New features -############ +New +### - Fully-automatic processing has been added to the interface. Click ``Autoprocess`` to process all of the runs for an investigation and to start polling for new runs. Whenever new runs are found, they will automatically be added to the table and processed. - A new option has been added to the Settings tab to control whether partial bins should be included when summing in Q. @@ -21,8 +21,8 @@ New features Improvements ############ -Bug fixes -######### +Bugfixes +######## Features Removed ################ @@ -35,8 +35,8 @@ Algorithms * Removed version 1 of ``ReflectometryReductionOne`` and ``ReflectometryReductionOneAuto``. * Renamed algorithms ``PolarizationCorrection`` to ``PolarizationCorrectionFredrikze`` and ``PolarizationEfficiencyCor`` to ``PolarizationCorrectionWildes``. -New features -############ +New +### * Added algorithm ``PolarizationEfficiencyCor`` which calls ``PolarizationCorrectionFredrikze`` or ``PolarizationCorrectionWildes`` depending on chosen ``Method`` property. * Added algorithms that help create a matrix workspace with polarization efficiencies ready to be used with ``PolarizationEfficiencyCor`` @@ -50,7 +50,7 @@ New features - :ref:`algm-ReflectometryILLSumForeground` - :ref:`algm-ReflectometryILLPolarizationCor` - :ref:`algm-ReflectometryILLConvertToQ` -* A new algorithm :ref:`algm-ReflectometryMomentumTransfer` provides conversion to momentum transfer and :math:`Q_{z}` resolution calculation for relfectivity workspaces. +* A new algorithm :ref:`algm-ReflectometryMomentumTransfer` provides conversion to momentum transfer and :math:`Q_{z}` resolution calculation for reflectivity workspaces. * A new algorithm :ref:`ReflectometrySumInQ <algm-ReflectometrySumInQ>` is available for coherent summation of the reflected beam. - :ref:`algm-ReflectometryReductionOne` and :ref:`algm-ReflectometryReductionOneAuto` no longer include partial bins by default when summing in Q. A new property, `IncludePartialBins`, has been added to re-enable partial bins. @@ -58,8 +58,8 @@ New features Improvements ############ -Bug fixes -######### +Bugfixes +######## * Correct the angle to the value of ``ThetaIn`` property if summing in lambda in ``ReflectometryReductionOne-v2``. diff --git a/docs/source/release/v3.13.0/sans.rst b/docs/source/release/v3.13.0/sans.rst index 2d2b52e05968b3b6b247268109b2d2a69f33d2f3..351fe2e48ef14842d2829f643ecaa39735a5d289 100644 --- a/docs/source/release/v3.13.0/sans.rst +++ b/docs/source/release/v3.13.0/sans.rst @@ -11,8 +11,8 @@ SANS Changes ISIS SANS Interface ---------------------------- -New features -############ +New +### * A string of wavelength ranges can now be specified. A reduction is then done for each wavelength range. * :ref:`SANSMask <algm-SANSMask>` is extended to have a `MaskedWorkspace` property, to copy the mask from. @@ -28,11 +28,11 @@ Improvements * Updated the naming of workspace groups in a sliced reduction. * Updated old backend to mask by detector ID rather than spectrum number, improving reliability. -Bug fixes -######### +Bugfixes +######## * The beam stop arm is now masked on LOQ for the new backend. * Fixed a bug in the old backend where for LOQ the high angle bank was not being centered correctly in some cases. -* Userfiles specified in the batch file are now being loaded into the new GUI. +* User files specified in the batch file are now being loaded into the new GUI. * The new sans GUI will now save out all the outputs of a time sliced reduction. * Fixed a bug where save_format was not being specified if a user file was entered for a row. * Use gravity now defaulting to false. diff --git a/docs/source/release/v3.13.0/ui.rst b/docs/source/release/v3.13.0/ui.rst index 2a6d8d94cc7191628e2eb65aa173475b65e9030c..8991ae674ed4944dba8fd2e5e621e2f65dfe08fa 100644 --- a/docs/source/release/v3.13.0/ui.rst +++ b/docs/source/release/v3.13.0/ui.rst @@ -26,14 +26,21 @@ Bugfixes SliceViewer ----------- +Improvements +############ + +- A peaks workspace can now be overlaid on the slice viewer when the non-orthogonal view is displayed. + .. figure:: ../../images/NonOrthogonalPeaksSV.png :class: screenshot :align: center :figwidth: 70% -- A peaks workspace can now be overlayed on the slice viewer when the non-orthogonal view is displayed. DGS Planner ----------- +New +### + - DGSPlanner has an option to load the UB matrix from the Nexus file metadata diff --git a/scripts/Frequency_Domain_Analysis.py b/scripts/Frequency_Domain_Analysis.py index c8eefe082472f1bbfda9193831dbf26ff84ae6c8..fd35ff4ca14b2cb3d892c3196dffac8f1d860b03 100644 --- a/scripts/Frequency_Domain_Analysis.py +++ b/scripts/Frequency_Domain_Analysis.py @@ -5,27 +5,26 @@ import sys import PyQt4.QtGui as QtGui -from Muon import model_constructor -from Muon import transform_presenter -from Muon import transform_view -from Muon import view_constructor +from Muon.GUI.FrequencyDomainAnalysis.Transform.transform_widget import TransformWidget +from Muon.GUI.Common import load_utils +from Muon.GUI.Common import message_box class FrequencyDomainAnalysisGui(QtGui.QMainWindow): def __init__(self,parent=None): super(FrequencyDomainAnalysisGui,self).__init__(parent) - groupedViews = view_constructor.ViewConstructor(True,self) - groupedModels = model_constructor.ModelConstructor(True) - view =transform_view.TransformView(groupedViews,self) - self.presenter =transform_presenter.TransformPresenter(view,groupedModels) + load = load_utils.LoadUtils() + if not load.MuonAnalysisExists: + return + self.transform = TransformWidget(load = load, parent = self) - self.setCentralWidget(view) + self.setCentralWidget(self.transform.widget) self.setWindowTitle("Frequency Domain Analysis") # cancel algs if window is closed def closeEvent(self,event): - self.presenter.close() + self.transform.closeEvent(event) def qapp(): @@ -43,5 +42,4 @@ try: ex.show() app.exec_() except RuntimeError as error: - ex = QtGui.QWidget() - QtGui.QMessageBox.warning(ex,"Frequency Domain Analysis",str(error)) + message_box.warning(str(error)) diff --git a/scripts/Muon/GUI/dock/__init__.py b/scripts/Muon/GUI/Common/__init__.py similarity index 100% rename from scripts/Muon/GUI/dock/__init__.py rename to scripts/Muon/GUI/Common/__init__.py diff --git a/scripts/Muon/GUI/dummy/__init__.py b/scripts/Muon/GUI/Common/dock/__init__.py similarity index 100% rename from scripts/Muon/GUI/dummy/__init__.py rename to scripts/Muon/GUI/Common/dock/__init__.py diff --git a/scripts/Muon/GUI/dock/dock_view.py b/scripts/Muon/GUI/Common/dock/dock_view.py similarity index 100% rename from scripts/Muon/GUI/dock/dock_view.py rename to scripts/Muon/GUI/Common/dock/dock_view.py diff --git a/scripts/Muon/GUI/dummy_label/__init__.py b/scripts/Muon/GUI/Common/dummy/__init__.py similarity index 100% rename from scripts/Muon/GUI/dummy_label/__init__.py rename to scripts/Muon/GUI/Common/dummy/__init__.py diff --git a/scripts/Muon/GUI/dummy/dummy_presenter.py b/scripts/Muon/GUI/Common/dummy/dummy_presenter.py similarity index 100% rename from scripts/Muon/GUI/dummy/dummy_presenter.py rename to scripts/Muon/GUI/Common/dummy/dummy_presenter.py diff --git a/scripts/Muon/GUI/dummy/dummy_view.py b/scripts/Muon/GUI/Common/dummy/dummy_view.py similarity index 100% rename from scripts/Muon/GUI/dummy/dummy_view.py rename to scripts/Muon/GUI/Common/dummy/dummy_view.py diff --git a/scripts/Muon/GUI/dummy/dummy_widget.py b/scripts/Muon/GUI/Common/dummy/dummy_widget.py similarity index 77% rename from scripts/Muon/GUI/dummy/dummy_widget.py rename to scripts/Muon/GUI/Common/dummy/dummy_widget.py index 099436c505253174630787625d37ee15b5e6eb18..b3a3cfcb49ee44fbae42ce62dee7871477a4fef1 100644 --- a/scripts/Muon/GUI/dummy/dummy_widget.py +++ b/scripts/Muon/GUI/Common/dummy/dummy_widget.py @@ -1,8 +1,8 @@ from __future__ import (absolute_import, division, print_function) -from Muon.GUI.dummy.dummy_view import DummyView -from Muon.GUI.dummy.dummy_presenter import DummyPresenter +from Muon.GUI.Common.dummy.dummy_view import DummyView +from Muon.GUI.Common.dummy.dummy_presenter import DummyPresenter class DummyWidget(object): @@ -14,7 +14,7 @@ class DummyWidget(object): self.presenter = DummyPresenter(view,model) @property - def presneter(self): + def presenter(self): return self.presenter @property diff --git a/scripts/Muon/GUI/Common/dummy_label/__init__.py b/scripts/Muon/GUI/Common/dummy_label/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/scripts/Muon/GUI/dummy_label/dummy_label_presenter.py b/scripts/Muon/GUI/Common/dummy_label/dummy_label_presenter.py similarity index 100% rename from scripts/Muon/GUI/dummy_label/dummy_label_presenter.py rename to scripts/Muon/GUI/Common/dummy_label/dummy_label_presenter.py diff --git a/scripts/Muon/GUI/dummy_label/dummy_label_view.py b/scripts/Muon/GUI/Common/dummy_label/dummy_label_view.py similarity index 100% rename from scripts/Muon/GUI/dummy_label/dummy_label_view.py rename to scripts/Muon/GUI/Common/dummy_label/dummy_label_view.py diff --git a/scripts/Muon/GUI/dummy_label/dummy_label_widget.py b/scripts/Muon/GUI/Common/dummy_label/dummy_label_widget.py similarity index 75% rename from scripts/Muon/GUI/dummy_label/dummy_label_widget.py rename to scripts/Muon/GUI/Common/dummy_label/dummy_label_widget.py index be5ecff4d691829a8034f7b67d7d3d598287084c..f8b67d7fb6ac3e09361b82698e5c87a8375ae241 100644 --- a/scripts/Muon/GUI/dummy_label/dummy_label_widget.py +++ b/scripts/Muon/GUI/Common/dummy_label/dummy_label_widget.py @@ -1,7 +1,7 @@ from __future__ import (absolute_import, division, print_function) -from Muon.GUI.dummy_label.dummy_label_view import DummyLabelView -from Muon.GUI.dummy_label.dummy_label_presenter import DummyLabelPresenter +from Muon.GUI.Common.dummy_label.dummy_label_view import DummyLabelView +from Muon.GUI.Common.dummy_label.dummy_label_presenter import DummyLabelPresenter class DummyLabelWidget(object): diff --git a/scripts/Muon/load_utils.py b/scripts/Muon/GUI/Common/load_utils.py similarity index 100% rename from scripts/Muon/load_utils.py rename to scripts/Muon/GUI/Common/load_utils.py diff --git a/scripts/Muon/message_box.py b/scripts/Muon/GUI/Common/message_box.py similarity index 100% rename from scripts/Muon/message_box.py rename to scripts/Muon/GUI/Common/message_box.py diff --git a/scripts/Muon/GUI/Common/mock_widget.py b/scripts/Muon/GUI/Common/mock_widget.py new file mode 100644 index 0000000000000000000000000000000000000000..62fc5eed705f7732f84d4ab25d7b4d0d782c024a --- /dev/null +++ b/scripts/Muon/GUI/Common/mock_widget.py @@ -0,0 +1,10 @@ + +import PyQt4.QtGui as QtGui + + +def mockQapp(): + qapp = QtGui.QApplication.instance() + if qapp is None: + return QtGui.QApplication(['']) + else: + return qapp diff --git a/scripts/Muon/table_utils.py b/scripts/Muon/GUI/Common/table_utils.py similarity index 100% rename from scripts/Muon/table_utils.py rename to scripts/Muon/GUI/Common/table_utils.py diff --git a/scripts/Muon/thread_model.py b/scripts/Muon/GUI/Common/thread_model.py similarity index 97% rename from scripts/Muon/thread_model.py rename to scripts/Muon/GUI/Common/thread_model.py index 4008d79a9f5d8bfac51d28ce9cd25f602ad6a6b6..f3b616d6efbc5bb8ad1c7bfefd8c8dcff5f2a04f 100644 --- a/scripts/Muon/thread_model.py +++ b/scripts/Muon/GUI/Common/thread_model.py @@ -2,7 +2,7 @@ from __future__ import (absolute_import, division, print_function) from PyQt4.QtCore import QThread from PyQt4 import QtCore -from Muon import message_box +from Muon.GUI.Common import message_box class ThreadModel(QThread): diff --git a/scripts/Muon/GUI/FrequencyDomainAnalysis/FFT/__init__.py b/scripts/Muon/GUI/FrequencyDomainAnalysis/FFT/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/scripts/Muon/GUI/FrequencyDomainAnalysis/FFT/fft_model.py b/scripts/Muon/GUI/FrequencyDomainAnalysis/FFT/fft_model.py new file mode 100644 index 0000000000000000000000000000000000000000..d07c1060568831e608ecc3c403c25e241179ee57 --- /dev/null +++ b/scripts/Muon/GUI/FrequencyDomainAnalysis/FFT/fft_model.py @@ -0,0 +1,159 @@ +from __future__ import (absolute_import, division, print_function) + +from six import iteritems + +import mantid.simpleapi as mantid + + +class FFTWrapper(object): + + """ + A class to wrap the different parts + of the FFT and its preprocessing. + This keeps the main FFT class simple. + """ + + def __init__(self, FFT): + self.name = "FFT" + self.model = FFT + self.phaseTable = None + self.preRe = None + self.preIm = None + self.FFT = None + + def cancel(self): + self.model.cancel() + + def loadData(self, inputs): + """ + store the data in the wrapper for later + """ + if "phaseTable" in inputs: + self.phaseTable = inputs["phaseTable"] + else: + self.phaseTable = None + if "preRe" in inputs: + self.preRe = inputs["preRe"] + else: + self.preRe = None + if "preIm" in inputs: + self.preIm = inputs["preIm"] + else: + self.preIm = None + if "FFT" in inputs: + self.FFT = inputs["FFT"] + else: + self.FFT = None + self.model.setRun(inputs["Run"]) + + def execute(self): + """ + runs the relevant parts of the FFT and the preprocessing + """ + if self.phaseTable is not None: + if self.phaseTable["newTable"]: + self.model.makePhaseQuadTable(self.phaseTable) + self.model.PhaseQuad() + + if self.preRe is not None: + self.model.preAlg(self.preRe) + + if self.preIm is not None: + self.model.preAlg(self.preIm) + + if self.FFT is not None: + self.model.FFTAlg(self.FFT) + + def output(self): + return + + +class FFTModel(object): + + """ + A simple class which executes + the relevant algorithms for + the analysis. + """ + + def __init__(self): + self.name = "FFT" + self.alg = None + + def cancel(self): + if self.alg is not None: + self.alg.cancel() + + def setRun(self, run): + self.runName = run + + def preAlg(self, preInputs): + """ + PaddingAndApodization alg on the data + """ + self.alg = mantid.AlgorithmManager.create("PaddingAndApodization") + self.alg.initialize() + self.alg.setAlwaysStoreInADS(False) + for name, value in iteritems(preInputs): + self.alg.setProperty(name, value) + self.alg.execute() + mantid.AnalysisDataService.addOrReplace( + preInputs["OutputWorkspace"], + self.alg.getProperty("OutputWorkspace").value) + self.alg = None + + def FFTAlg(self, FFTInputs): + """ + Use the FFT alg + """ + self.alg = mantid.AlgorithmManager.create("FFT") + self.alg.initialize() + self.alg.setAlwaysStoreInADS(False) + for name, value in iteritems(FFTInputs): + self.alg.setProperty(name, value) + self.alg.execute() + mantid.AnalysisDataService.addOrReplace( + FFTInputs["OutputWorkspace"], + self.alg.getProperty("OutputWorkspace").value) + + ws = self.alg.getPropertyValue("OutputWorkspace") + group = mantid.AnalysisDataService.retrieve(self.runName) + group.add(ws) + self.alg = None + + def makePhaseQuadTable(self, inputs): + """ + generates a phase table from CalMuonDetectorPhases + """ + self.alg = mantid.AlgorithmManager.create("CalMuonDetectorPhases") + self.alg.initialize() + self.alg.setAlwaysStoreInADS(False) + + self.alg.setProperty("FirstGoodData", inputs["FirstGoodData"]) + self.alg.setProperty("LastGoodData", inputs["LastGoodData"]) + + self.alg.setProperty("InputWorkspace", "MuonAnalysis") + self.alg.setProperty("DetectorTable", "PhaseTable") + self.alg.setProperty("DataFitted", "fits") + self.alg.execute() + mantid.AnalysisDataService.addOrReplace( + "PhaseTable", + self.alg.getProperty("DetectorTable").value) + self.alg = None + + def PhaseQuad(self): + """ + do the phaseQuad algorithm + groups data into a single set + """ + self.alg = mantid.AlgorithmManager.create("PhaseQuad") + self.alg.initialize() + self.alg.setChild(False) + self.alg.setProperty("InputWorkspace", "MuonAnalysis") + self.alg.setProperty("PhaseTable", "PhaseTable") + self.alg.setProperty("OutputWorkspace", "__phaseQuad__") + self.alg.execute() + self.alg = None + + def getName(self): + return self.name diff --git a/scripts/Muon/fft_presenter.py b/scripts/Muon/GUI/FrequencyDomainAnalysis/FFT/fft_presenter.py similarity index 51% rename from scripts/Muon/fft_presenter.py rename to scripts/Muon/GUI/FrequencyDomainAnalysis/FFT/fft_presenter.py index 085c399f0c167dd592b8d60aee437ac34ea98579..f9929e1ffb9a5fb0c15953f719c18f10b84d3f41 100644 --- a/scripts/Muon/fft_presenter.py +++ b/scripts/Muon/GUI/FrequencyDomainAnalysis/FFT/fft_presenter.py @@ -3,25 +3,35 @@ from __future__ import (absolute_import, division, print_function) import mantid.simpleapi as mantid -from Muon import thread_model +from Muon.GUI.Common import thread_model class FFTPresenter(object): + """ This class links the FFT model to the GUI """ - def __init__(self,view,alg,load): - self.view=view - self.alg=alg - self.load=load + + def __init__(self, view, alg, load): + self.view = view + self.alg = alg + self.load = load self.thread = None # set data self.getWorkspaceNames() - #connect + # connect self.view.tableClickSignal.connect(self.tableClicked) self.view.buttonSignal.connect(self.handleButton) self.view.phaseCheckSignal.connect(self.phaseCheck) + def cancel(self): + if self.thread is not None: + self.thread.cancel() + + @property + def widget(self): + return self.view + # turn on button def activate(self): self.view.activateButton() @@ -31,21 +41,25 @@ class FFTPresenter(object): self.view.deactivateButton() def getWorkspaceNames(self): - final_options=self.load.getWorkspaceNames() + final_options = self.load.getWorkspaceNames() self.view.addItems(final_options) - #functions + # functions def phaseCheck(self): self.view.phaseQuadChanged() - #check if a phase table exists + # check if a phase table exists if mantid.AnalysisDataService.doesExist("PhaseTable"): self.view.setPhaseBox() - def tableClicked(self,row,col): - if row == self.view.getImBoxRow() and col == 1 and self.view.getWS() !="PhaseQuad": - self.view.changedHideUnTick(self.view.getImBox(),self.view.getImBoxRow()+1) - elif row == self.view.getShiftBoxRow() and col == 1: - self.view.changed(self.view.getShiftBox(),self.view.getShiftBoxRow()+1) + def tableClicked(self, row, col): + if row == self.view.getImBoxRow() and col == 1 and self.view.getWS() != "PhaseQuad": + self.view.changedHideUnTick( + self.view.getImBox(), + self.view.getImBoxRow() + 1) + elif row == self.view.getShiftBoxRow() and col == 1: + self.view.changed( + self.view.getShiftBox(), + self.view.getShiftBoxRow() + 1) def createThread(self): return thread_model.ThreadModel(self.alg) @@ -58,50 +72,49 @@ class FFTPresenter(object): self.getWorkspaceNames() return # put this on its own thread so not to freeze Mantid - self.thread=self.createThread() - self.thread.started.connect(self.deactivate) - self.thread.finished.connect(self.handleFinished) + self.thread = self.createThread() + self.thread.threadWrapperSetUp(self.deactivate,self.handleFinished) # make some inputs - inputs={} - inputs["Run"]=self.load.getRunName() + inputs = {} + inputs["Run"] = self.load.getRunName() - #do apodization and padding to real data + # do apodization and padding to real data - preInputs=self.view.initAdvanced() + preInputs = self.view.initAdvanced() if self.view.getWS() == "PhaseQuad": - phaseTable={} - phaseTable["newTable"]= self.view.isNewPhaseTable() - phaseTable["FirstGoodData"]=self.view.getFirstGoodData() - phaseTable["LastGoodData"]=self.view.getLastGoodData() - phaseTable["Instrument"]=self.load.getInstrument() - inputs["phaseTable"]=phaseTable + phaseTable = {} + phaseTable["newTable"] = self.view.isNewPhaseTable() + phaseTable["FirstGoodData"] = self.view.getFirstGoodData() + phaseTable["LastGoodData"] = self.view.getLastGoodData() + phaseTable["Instrument"] = self.load.getInstrument() + inputs["phaseTable"] = phaseTable self.view.RePhaseAdvanced(preInputs) else: self.view.ReAdvanced(preInputs) if self.view.isRaw(): - self.view.addRaw(preInputs,"InputWorkspace") - inputs["preRe"]=preInputs + self.view.addRaw(preInputs, "InputWorkspace") + inputs["preRe"] = preInputs - #do apodization and padding to complex data - if self.view.isComplex() and self.view.getWS()!="PhaseQuad": - ImPreInputs=self.view.initAdvanced() + # do apodization and padding to complex data + if self.view.isComplex() and self.view.getWS() != "PhaseQuad": + ImPreInputs = self.view.initAdvanced() self.view.ImAdvanced(ImPreInputs) if self.view.isRaw(): - self.view.addRaw(ImPreInputs,"InputWorkspace") - inputs["preIm"]=ImPreInputs + self.view.addRaw(ImPreInputs, "InputWorkspace") + inputs["preIm"] = ImPreInputs - #do FFT to transformed data + # do FFT to transformed data FFTInputs = self.get_FFT_input() - if self.view.getWS()=="PhaseQuad": + if self.view.getWS() == "PhaseQuad": self.view.getFFTRePhase(FFTInputs) if self.view.isComplex(): self.view.getFFTImPhase(FFTInputs) else: if self.view.isRaw(): - self.view.addRaw(FFTInputs,"OutputWorkspace") - inputs["FFT"]=FFTInputs + self.view.addRaw(FFTInputs, "OutputWorkspace") + inputs["FFT"] = FFTInputs try: self.thread.loadData(inputs) self.thread.start() @@ -112,13 +125,14 @@ class FFTPresenter(object): # kills the thread at end of execution def handleFinished(self): self.activate() + self.thread.threadWrapperTearDown(self.deactivate,self.handleFinished) self.thread.deleteLater() - self.thread=None + self.thread = None def get_FFT_input(self): - FFTInputs=self.view.initFFTInput() - if self.view.isAutoShift(): - FFTInputs["AutoShift"]=True + FFTInputs = self.view.initFFTInput() + if self.view.isAutoShift(): + FFTInputs["AutoShift"] = True else: self.view.addFFTShift(FFTInputs) if self.view.isComplex(): diff --git a/scripts/Muon/fft_view.py b/scripts/Muon/GUI/FrequencyDomainAnalysis/FFT/fft_view.py similarity index 52% rename from scripts/Muon/fft_view.py rename to scripts/Muon/GUI/FrequencyDomainAnalysis/FFT/fft_view.py index e57d107b55a6b19b5e6c4eccfcf0e7fbba30e13d..00fd76639c3897b7bc2946b34f622cc5d98ce9a6 100644 --- a/scripts/Muon/fft_view.py +++ b/scripts/Muon/GUI/FrequencyDomainAnalysis/FFT/fft_view.py @@ -4,119 +4,136 @@ from PyQt4 import QtCore, QtGui import mantid.simpleapi as mantid -from Muon import table_utils +from Muon.GUI.Common import table_utils class FFTView(QtGui.QWidget): + """ creates the layout for the FFT GUI """ # signals buttonSignal = QtCore.pyqtSignal() - tableClickSignal = QtCore.pyqtSignal(object,object) + tableClickSignal = QtCore.pyqtSignal(object, object) phaseCheckSignal = QtCore.pyqtSignal() - def __init__(self, parent = None): + def __init__(self, parent=None): super(FFTView, self).__init__(parent) self.grid = QtGui.QGridLayout(self) - #make table + # add splitter for resizing + splitter = QtGui.QSplitter(QtCore.Qt.Vertical) + + # make table self.FFTTable = QtGui.QTableWidget(self) self.FFTTable.resize(800, 800) self.FFTTable.setRowCount(9) self.FFTTable.setColumnCount(2) - self.FFTTable.setColumnWidth(0,300) - self.FFTTable.setColumnWidth(1,300) + self.FFTTable.setColumnWidth(0, 300) + self.FFTTable.setColumnWidth(1, 300) self.FFTTable.verticalHeader().setVisible(False) self.FFTTable.horizontalHeader().setStretchLastSection(True) - self.FFTTable.setHorizontalHeaderLabels(("FFT Property;Value").split(";")) + self.FFTTable.setHorizontalHeaderLabels( + ("FFT Property;Value").split(";")) # populate table options = ['test'] - table_utils.setRowName(self.FFTTable,0,"Workspace") - self.ws = table_utils.addComboToTable(self.FFTTable,0,options) + table_utils.setRowName(self.FFTTable, 0, "Workspace") + self.ws = table_utils.addComboToTable(self.FFTTable, 0, options) self.Im_box_row = 1 - table_utils.setRowName(self.FFTTable,self.Im_box_row,"Imaginary Data") - self.Im_box = table_utils.addCheckBoxToTable(self.FFTTable,True,self.Im_box_row) + table_utils.setRowName( + self.FFTTable, + self.Im_box_row, + "Imaginary Data") + self.Im_box = table_utils.addCheckBoxToTable( + self.FFTTable, True, self.Im_box_row) - table_utils.setRowName(self.FFTTable,2,"Imaginary Workspace") - self.Im_ws= table_utils.addComboToTable(self.FFTTable,2,options) + table_utils.setRowName(self.FFTTable, 2, "Imaginary Workspace") + self.Im_ws = table_utils.addComboToTable(self.FFTTable, 2, options) self.shift_box_row = 3 - table_utils.setRowName(self.FFTTable,self.shift_box_row,"Auto shift") - self.shift_box = table_utils.addCheckBoxToTable(self.FFTTable,True,self.shift_box_row) + table_utils.setRowName(self.FFTTable, self.shift_box_row, "Auto shift") + self.shift_box = table_utils.addCheckBoxToTable( + self.FFTTable, True, self.shift_box_row) - table_utils.setRowName(self.FFTTable,4,"Shift") - self.shift = table_utils.addDoubleToTable(self.FFTTable,0.0,4) + table_utils.setRowName(self.FFTTable, 4, "Shift") + self.shift = table_utils.addDoubleToTable(self.FFTTable, 0.0, 4) self.FFTTable.hideRow(4) - table_utils.setRowName(self.FFTTable,5,"Use Raw data") - self.Raw_box = table_utils.addCheckBoxToTable(self.FFTTable,True,5) + table_utils.setRowName(self.FFTTable, 5, "Use Raw data") + self.Raw_box = table_utils.addCheckBoxToTable(self.FFTTable, True, 5) - table_utils.setRowName(self.FFTTable,6,"First Good Data") - self.x0 = table_utils.addDoubleToTable(self.FFTTable,0.1,6) + table_utils.setRowName(self.FFTTable, 6, "First Good Data") + self.x0 = table_utils.addDoubleToTable(self.FFTTable, 0.1, 6) self.FFTTable.hideRow(6) - table_utils.setRowName(self.FFTTable,7,"Last Good Data") - self.xN = table_utils.addDoubleToTable(self.FFTTable,15.0,7) + table_utils.setRowName(self.FFTTable, 7, "Last Good Data") + self.xN = table_utils.addDoubleToTable(self.FFTTable, 15.0, 7) self.FFTTable.hideRow(7) - table_utils.setRowName(self.FFTTable,8,"Construct Phase Table") - self.phaseTable_box = table_utils.addCheckBoxToTable(self.FFTTable,True,8) + table_utils.setRowName(self.FFTTable, 8, "Construct Phase Table") + self.phaseTable_box = table_utils.addCheckBoxToTable( + self.FFTTable, True, 8) self.FFTTable.hideRow(8) self.FFTTable.resizeRowsToContents() - #make advanced table options + # make advanced table options self.advancedLabel = QtGui.QLabel("\n Advanced Options") self.FFTTableA = QtGui.QTableWidget(self) self.FFTTableA.resize(800, 800) self.FFTTableA.setRowCount(4) self.FFTTableA.setColumnCount(2) - self.FFTTableA.setColumnWidth(0,300) - self.FFTTableA.setColumnWidth(1,300) + self.FFTTableA.setColumnWidth(0, 300) + self.FFTTableA.setColumnWidth(1, 300) self.FFTTableA.verticalHeader().setVisible(False) self.FFTTableA.horizontalHeader().setStretchLastSection(True) - self.FFTTableA.setHorizontalHeaderLabels(("Advanced Property;Value").split(";")) - - table_utils.setRowName(self.FFTTableA,0,"Apodization Function") - options = ["None","Lorentz","Gaussian"] - self.apodization = table_utils.addComboToTable(self.FFTTableA,0,options) - - table_utils.setRowName(self.FFTTableA,1,"Decay Constant (micro seconds)") - self.decay = table_utils.addDoubleToTable(self.FFTTableA,1.4,1) - - table_utils.setRowName(self.FFTTableA,2,"Negative Padding") - self.negativePadding = table_utils.addCheckBoxToTable(self.FFTTableA,True,2) - - table_utils.setRowName(self.FFTTableA,3,"Padding") - self.padding = table_utils.addSpinBoxToTable(self.FFTTableA,1,3) + self.FFTTableA.setHorizontalHeaderLabels( + ("Advanced Property;Value").split(";")) + + table_utils.setRowName(self.FFTTableA, 0, "Apodization Function") + options = ["None", "Lorentz", "Gaussian"] + self.apodization = table_utils.addComboToTable( + self.FFTTableA, 0, options) + + table_utils.setRowName( + self.FFTTableA, + 1, + "Decay Constant (micro seconds)") + self.decay = table_utils.addDoubleToTable(self.FFTTableA, 1.4, 1) + + table_utils.setRowName(self.FFTTableA, 2, "Negative Padding") + self.negativePadding = table_utils.addCheckBoxToTable( + self.FFTTableA, True, 2) + + table_utils.setRowName(self.FFTTableA, 3, "Padding") + self.padding = table_utils.addSpinBoxToTable(self.FFTTableA, 1, 3) self.FFTTableA.resizeRowsToContents() - #make button + # make button self.button = QtGui.QPushButton('Calculate FFT', self) self.button.setStyleSheet("background-color:lightgrey") - #connects + # connects self.FFTTable.cellClicked.connect(self.tableClick) self.button.clicked.connect(self.buttonClick) self.ws.currentIndexChanged.connect(self.phaseCheck) # add to layout - self.FFTTable.setMinimumSize(40,158) - self.FFTTableA.setMinimumSize(40,127) + self.FFTTable.setMinimumSize(40, 158) + self.FFTTableA.setMinimumSize(40, 127) table_utils.setTableHeaders(self.FFTTable) table_utils.setTableHeaders(self.FFTTableA) - self.horizontalSpacer1 = QtGui.QSpacerItem(20, 94, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding) - self.horizontalSpacer2 = QtGui.QSpacerItem(20, 280, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding) # add to layout - self.grid.addWidget(self.FFTTable) - self.grid.addItem(self.horizontalSpacer1) - self.grid.addWidget(self.advancedLabel) - self.grid.addWidget(self.FFTTableA) - self.grid.addItem(self.horizontalSpacer2) + splitter.addWidget(self.FFTTable) + splitter.addWidget(self.advancedLabel) + splitter.addWidget(self.FFTTableA) + self.grid.addWidget(splitter) self.grid.addWidget(self.button) - # add data to view - def addItems(self,options): + def getLayout(self): + return self.grid + + # add data to view + def addItems(self, options): self.ws.clear() self.ws.addItems(options) self.ws.addItem("PhaseQuad") @@ -128,8 +145,8 @@ class FFTView(QtGui.QWidget): def phaseCheck(self): self.phaseCheckSignal.emit() - def tableClick(self,row,col): - self.tableClickSignal.emit(row,col) + def tableClick(self, row, col): + self.tableClickSignal.emit(row, col) def buttonClick(self): self.buttonSignal.emit() @@ -142,20 +159,20 @@ class FFTView(QtGui.QWidget): self.button.setEnabled(False) def setPhaseBox(self): - self.FFTTable.setRowHidden(8,self.getWS() != "PhaseQuad") + self.FFTTable.setRowHidden(8, self.getWS() != "PhaseQuad") - def changed(self,box,row ): - self.FFTTable.setRowHidden(row,box.checkState() == QtCore.Qt.Checked) + def changed(self, box, row): + self.FFTTable.setRowHidden(row, box.checkState() == QtCore.Qt.Checked) - def changedHideUnTick(self,box,row ): + def changedHideUnTick(self, box, row): self.FFTTable.setRowHidden(row, box.checkState() != QtCore.Qt.Checked) def phaseQuadChanged(self): - #show axis - self.FFTTable.setRowHidden(6,self.getWS() != "PhaseQuad") - self.FFTTable.setRowHidden(7,self.getWS() != "PhaseQuad") - #hide complex ws - self.FFTTable.setRowHidden(2,self.getWS() == "PhaseQuad") + # show axis + self.FFTTable.setRowHidden(6, self.getWS() != "PhaseQuad") + self.FFTTable.setRowHidden(7, self.getWS() != "PhaseQuad") + # hide complex ws + self.FFTTable.setRowHidden(2, self.getWS() == "PhaseQuad") # these are for getting inputs def getRunName(self): @@ -163,33 +180,34 @@ class FFTView(QtGui.QWidget): tmpWS = mantid.AnalysisDataService.retrieve("MuonAnalysis_1") else: tmpWS = mantid.AnalysisDataService.retrieve("MuonAnalysis") - return tmpWS.getInstrument().getName()+str(tmpWS.getRunNumber()).zfill(8) + return tmpWS.getInstrument().getName() + str(tmpWS.getRunNumber()).zfill(8) def initFFTInput(self): inputs = {} - inputs['InputWorkspace'] = "__ReTmp__"#str( self.ws.currentText()).replace(";","; ") - inputs['Real'] = 0 # always zero - out = str( self.ws.currentText()).replace(";","; ") - inputs['OutputWorkspace'] = self.getRunName()+";"+out+";FFT" + inputs[ + 'InputWorkspace'] = "__ReTmp__" # str( self.ws.currentText()).replace(";","; ") + inputs['Real'] = 0 # always zero + out = str(self.ws.currentText()).replace(";", "; ") + inputs['OutputWorkspace'] = self.getRunName() + ";" + out + ";FFT" inputs["AcceptXRoundingErrors"] = True return inputs - def addFFTComplex(self,inputs): + def addFFTComplex(self, inputs): inputs["InputImagWorkspace"] = "__ImTmp__" - inputs["Imaginary"] = 0 #always zero + inputs["Imaginary"] = 0 # always zero - def addFFTShift(self,inputs): + def addFFTShift(self, inputs): inputs['AutoShift'] = False inputs['Shift'] = float(self.shift.text()) - def addRaw(self,inputs,key): + def addRaw(self, inputs, key): inputs[key] += "_Raw" - def getFFTRePhase(self,inputs): + def getFFTRePhase(self, inputs): inputs['InputWorkspace'] = "__ReTmp__" - inputs['Real'] = 0 # always zero + inputs['Real'] = 0 # always zero - def getFFTImPhase(self,inputs): + def getFFTImPhase(self, inputs): inputs['InputImagWorkspace'] = "__ReTmp__" inputs['Imaginary'] = 1 @@ -201,21 +219,25 @@ class FFTView(QtGui.QWidget): inputs["Padding"] = int(self.padding.text()) return inputs - def ReAdvanced(self,inputs): - inputs['InputWorkspace'] = str( self.ws.currentText()).replace(";","; ") + def ReAdvanced(self, inputs): + inputs['InputWorkspace'] = str( + self.ws.currentText()).replace(";", + "; ") inputs['OutputWorkspace'] = "__ReTmp__" - def ImAdvanced(self,inputs): - inputs['InputWorkspace'] = str( self.Im_ws.currentText()).replace(";","; ") + def ImAdvanced(self, inputs): + inputs['InputWorkspace'] = str( + self.Im_ws.currentText()).replace(";", + "; ") inputs['OutputWorkspace'] = "__ImTmp__" - def RePhaseAdvanced(self,inputs): + def RePhaseAdvanced(self, inputs): inputs['InputWorkspace'] = "__phaseQuad__" inputs['OutputWorkspace'] = "__ReTmp__" # get methods (from the GUI) def getWS(self): - return str( self.ws.currentText()).replace(";","; ") + return str(self.ws.currentText()).replace(";", "; ") def isAutoShift(self): return self.shift_box.checkState() == QtCore.Qt.Checked diff --git a/scripts/Muon/GUI/FrequencyDomainAnalysis/FFT/fft_widget.py b/scripts/Muon/GUI/FrequencyDomainAnalysis/FFT/fft_widget.py new file mode 100644 index 0000000000000000000000000000000000000000..ab8bbaae54464549c888c11e313a9533f897ef3b --- /dev/null +++ b/scripts/Muon/GUI/FrequencyDomainAnalysis/FFT/fft_widget.py @@ -0,0 +1,30 @@ +from __future__ import (absolute_import, division, print_function) + +from Muon.GUI.FrequencyDomainAnalysis.FFT.fft_view import FFTView +from Muon.GUI.FrequencyDomainAnalysis.FFT.fft_presenter import FFTPresenter +from Muon.GUI.FrequencyDomainAnalysis.FFT.fft_model import FFTModel, FFTWrapper + +from PyQt4 import QtGui + + +class FFTWidget(QtGui.QWidget): + + def __init__(self, load, parent=None): + super(FFTWidget, self).__init__(parent) + view = FFTView(parent) + + fft = FFTModel() + model = FFTWrapper(fft) + + self._presenter = FFTPresenter(view=view, alg=model, load=load) + + @property + def presenter(self): + return self._presenter + + @property + def widget(self): + return self._presenter.widget + + def closeEvent(self, event): + self._presenter.cancel() diff --git a/scripts/Muon/GUI/FrequencyDomainAnalysis/MaxEnt/__init__.py b/scripts/Muon/GUI/FrequencyDomainAnalysis/MaxEnt/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/scripts/Muon/maxent_model.py b/scripts/Muon/GUI/FrequencyDomainAnalysis/MaxEnt/maxent_model.py similarity index 100% rename from scripts/Muon/maxent_model.py rename to scripts/Muon/GUI/FrequencyDomainAnalysis/MaxEnt/maxent_model.py diff --git a/scripts/Muon/maxent_presenter.py b/scripts/Muon/GUI/FrequencyDomainAnalysis/MaxEnt/maxent_presenter.py similarity index 97% rename from scripts/Muon/maxent_presenter.py rename to scripts/Muon/GUI/FrequencyDomainAnalysis/MaxEnt/maxent_presenter.py index 6b598a1ef9b9c836b2df04210509195e28823a13..37a04879f03bc3f14fba8b85003b7df3bedffb56 100644 --- a/scripts/Muon/maxent_presenter.py +++ b/scripts/Muon/GUI/FrequencyDomainAnalysis/MaxEnt/maxent_presenter.py @@ -2,7 +2,7 @@ from __future__ import (absolute_import, division, print_function) import math -from Muon import thread_model +from Muon.GUI.Common import thread_model class MaxEntPresenter(object): @@ -23,6 +23,10 @@ class MaxEntPresenter(object): self.view.cancelSignal.connect(self.cancel) self.view.phaseSignal.connect(self.handlePhase) + @property + def widget(self): + return self.view + # functions def getWorkspaceNames(self): final_options = self.load.getGroupedWorkspaceNames() diff --git a/scripts/Muon/maxent_view.py b/scripts/Muon/GUI/FrequencyDomainAnalysis/MaxEnt/maxent_view.py similarity index 94% rename from scripts/Muon/maxent_view.py rename to scripts/Muon/GUI/FrequencyDomainAnalysis/MaxEnt/maxent_view.py index 1a5b238206b38a4373394d2ec6ada6f68413cc3a..a082b6768d2f0604c2811354f20eab191247d9d0 100644 --- a/scripts/Muon/maxent_view.py +++ b/scripts/Muon/GUI/FrequencyDomainAnalysis/MaxEnt/maxent_view.py @@ -2,7 +2,7 @@ from __future__ import (absolute_import, division, print_function) from PyQt4 import QtCore, QtGui -from Muon import table_utils +from Muon.GUI.Common import table_utils class MaxEntView(QtGui.QWidget): @@ -19,6 +19,10 @@ class MaxEntView(QtGui.QWidget): def __init__(self, parent=None): super(MaxEntView, self).__init__(parent) self.grid = QtGui.QVBoxLayout(self) + + # add splitter for resizing + splitter = QtGui.QSplitter(QtCore.Qt.Vertical) + self.run = None # make table self.table = QtGui.QTableWidget(self) @@ -126,16 +130,7 @@ class MaxEntView(QtGui.QWidget): # this is if complex data is unhidden self.table.setMinimumSize(40, 203) self.tableA.setMinimumSize(40, 207) - self.horizontalSpacer1 = QtGui.QSpacerItem( - 20, - 30, - QtGui.QSizePolicy.Expanding, - QtGui.QSizePolicy.Expanding) - self.horizontalSpacer2 = QtGui.QSpacerItem( - 20, - 70, - QtGui.QSizePolicy.Expanding, - QtGui.QSizePolicy.Expanding) + # make buttons self.button = QtGui.QPushButton('Calculate MaxEnt', self) self.button.setStyleSheet("background-color:lightgrey") @@ -151,13 +146,15 @@ class MaxEntView(QtGui.QWidget): self.buttonLayout.addWidget(self.button) self.buttonLayout.addWidget(self.cancel) # add to layout - self.grid.addWidget(self.table) - self.grid.addItem(self.horizontalSpacer1) - self.grid.addWidget(self.advancedLabel) - self.grid.addWidget(self.tableA) - self.grid.addItem(self.horizontalSpacer2) + splitter.addWidget(self.table) + splitter.addWidget(self.advancedLabel) + splitter.addWidget(self.tableA) + self.grid.addWidget(splitter) self.grid.addLayout(self.buttonLayout) + def getLayout(self): + return self.grid + # add data to view def addItems(self, options): self.ws.clear() diff --git a/scripts/Muon/GUI/FrequencyDomainAnalysis/MaxEnt/maxent_widget.py b/scripts/Muon/GUI/FrequencyDomainAnalysis/MaxEnt/maxent_widget.py new file mode 100644 index 0000000000000000000000000000000000000000..246c76d9393b6363af7ff1c5d06accf4bc4db202 --- /dev/null +++ b/scripts/Muon/GUI/FrequencyDomainAnalysis/MaxEnt/maxent_widget.py @@ -0,0 +1,29 @@ +from __future__ import (absolute_import, division, print_function) + +from Muon.GUI.FrequencyDomainAnalysis.MaxEnt.maxent_view import MaxEntView +from Muon.GUI.FrequencyDomainAnalysis.MaxEnt.maxent_presenter import MaxEntPresenter +from Muon.GUI.FrequencyDomainAnalysis.MaxEnt.maxent_model import MaxEntModel, MaxEntWrapper + +from PyQt4 import QtGui + + +class MaxEntWidget(QtGui.QWidget): + + def __init__(self, load, parent=None): + super(MaxEntWidget, self).__init__(parent) + view = MaxEntView(parent) + + maxEnt = MaxEntModel() + model = MaxEntWrapper(maxEnt) + self._presenter = MaxEntPresenter(view, model, load) + + @property + def presenter(self): + return self._presenter + + @property + def widget(self): + return self._presenter.widget + + def closeEvent(self, event): + self._presenter.cancel() diff --git a/scripts/Muon/GUI/FrequencyDomainAnalysis/Transform/__init__.py b/scripts/Muon/GUI/FrequencyDomainAnalysis/Transform/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/scripts/Muon/transform_view.py b/scripts/Muon/GUI/FrequencyDomainAnalysis/Transform/transform_view.py similarity index 71% rename from scripts/Muon/transform_view.py rename to scripts/Muon/GUI/FrequencyDomainAnalysis/Transform/transform_view.py index 035e93920bfbfa0f9ec53a49d5b6ad4e7df05547..57449884ec25910b296949abcc4b67136d95d83d 100644 --- a/scripts/Muon/transform_view.py +++ b/scripts/Muon/GUI/FrequencyDomainAnalysis/Transform/transform_view.py @@ -4,19 +4,21 @@ from PyQt4 import QtGui class TransformView(QtGui.QWidget): + """ Creates the view for the transformation tab. At the top is the transform selection widget and below it is the selected GUI (FFT or MaxEnt) """ - def __init__(self,groupedViews,parent=None): - super(TransformView,self).__init__(parent) + + def __init__(self, selectorView, groupedViews, parent=None): + super(TransformView, self).__init__(parent) # set selector - self.selection = groupedViews.getTransformSelection() + self.selection = selectorView self.Layout = QtGui.QGridLayout() - self.Layout.addWidget(self.selection,1,0) + self.Layout.addWidget(self.selection, 1, 0) # add the transform widgets to the tab - self.methods = groupedViews.getTransformMethods() + self.methods = groupedViews for key in self.methods: self.Layout.addWidget(self.methods[key]) self.setLayout(self.Layout) @@ -24,6 +26,9 @@ class TransformView(QtGui.QWidget): methods = list(self.methods.keys()) self.show(methods[0]) + def getLayout(self): + return self.grid + def getMethods(self): return [key for key in self.methods] @@ -31,8 +36,8 @@ class TransformView(QtGui.QWidget): for key in self.methods: self.methods[key].hide() - def show(self,name): + def show(self, name): self.methods[name].show() - def getView(self,name): + def getView(self, name): return self.methods[name] diff --git a/scripts/Muon/GUI/FrequencyDomainAnalysis/Transform/transform_widget.py b/scripts/Muon/GUI/FrequencyDomainAnalysis/Transform/transform_widget.py new file mode 100644 index 0000000000000000000000000000000000000000..547b12d3904be4dda1d0bf7c8546e4abf5e4e33d --- /dev/null +++ b/scripts/Muon/GUI/FrequencyDomainAnalysis/Transform/transform_widget.py @@ -0,0 +1,45 @@ +from __future__ import (absolute_import, division, print_function) + +from Muon.GUI.FrequencyDomainAnalysis.Transform.transform_view import TransformView + +from Muon.GUI.FrequencyDomainAnalysis.FFT.fft_widget import FFTWidget +from Muon.GUI.FrequencyDomainAnalysis.MaxEnt.maxent_widget import MaxEntWidget +from Muon.GUI.FrequencyDomainAnalysis.TransformSelection.transform_selection_widget import TransformSelectionWidget + +from PyQt4 import QtGui + + +class TransformWidget(QtGui.QWidget): + def __init__(self, load, parent=None): + super(TransformWidget,self).__init__(parent) + self._fft = FFTWidget(load=load,parent=self) + self._maxent = MaxEntWidget(load=load,parent=self) + self._selector = TransformSelectionWidget(parent=self) + + groupedViews = self.getViews() + + self._view = TransformView(self._selector.widget, groupedViews,parent) + + self._selector.setSelectionConnection(self.updateDisplay) + + @property + def widget(self): + return self._view + + def mockWidget(self, mockView): + self._view = mockView + + def closeEvent(self,event): + self._selector.closeEvent(event) + self._fft.closeEvent(event) + self._maxent.closeEvent(event) + + def updateDisplay(self,method): + self._view.hideAll() + self._view.show(method) + + def getViews(self): + groupedViews = {} + groupedViews["FFT"] = self._fft.widget + groupedViews["MaxEnt"] = self._maxent.widget + return groupedViews diff --git a/scripts/Muon/GUI/FrequencyDomainAnalysis/TransformSelection/__init__.py b/scripts/Muon/GUI/FrequencyDomainAnalysis/TransformSelection/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/scripts/Muon/transform_selection_presenter.py b/scripts/Muon/GUI/FrequencyDomainAnalysis/TransformSelection/transform_selection_presenter.py similarity index 60% rename from scripts/Muon/transform_selection_presenter.py rename to scripts/Muon/GUI/FrequencyDomainAnalysis/TransformSelection/transform_selection_presenter.py index c3bff2f796a18a6cda7cc581d94a2bf8bb436420..ec565273c8a5622fd8de7d578047a95afcf382d5 100644 --- a/scripts/Muon/transform_selection_presenter.py +++ b/scripts/Muon/GUI/FrequencyDomainAnalysis/TransformSelection/transform_selection_presenter.py @@ -2,12 +2,18 @@ from __future__ import (absolute_import, division, print_function) class TransformSelectionPresenter(object): + """ The widget for selecting the widget shown in the transformation tab """ - def __init__(self,view): - self.view=view - def setMethodsCombo(self,options): + def __init__(self, view): + self.view = view + + @property + def widget(self): + return self.view + + def setMethodsCombo(self, options): self.view.setMethodsCombo(options) diff --git a/scripts/Muon/transform_selection_view.py b/scripts/Muon/GUI/FrequencyDomainAnalysis/TransformSelection/transform_selection_view.py similarity index 72% rename from scripts/Muon/transform_selection_view.py rename to scripts/Muon/GUI/FrequencyDomainAnalysis/TransformSelection/transform_selection_view.py index 5aa08de1ce173bf15e91efb15d86c8ae9e47284f..d07d510e5355f17902d7e39b2f942d5a7faa92fb 100644 --- a/scripts/Muon/transform_selection_view.py +++ b/scripts/Muon/GUI/FrequencyDomainAnalysis/TransformSelection/transform_selection_view.py @@ -4,6 +4,7 @@ from PyQt4 import QtCore, QtGui class TransformSelectionView(QtGui.QWidget): + """ Create the transformation selection widget's appearance """ @@ -15,15 +16,18 @@ class TransformSelectionView(QtGui.QWidget): self.grid = QtGui.QGridLayout(self) self.methods = QtGui.QComboBox() # default to FFT - options=["FFT"] + options = ["FFT", "MaxEnt"] self.methods.addItems(options) self.grid.addWidget(self.methods) self.methods.currentIndexChanged.connect(self.sendSignal) - # sets the methods in the selection widget - def setMethodsCombo(self,options): + def getLayout(self): + return self.grid + + # sets the methods in the selection widget + def setMethodsCombo(self, options): self.methods.clear() self.methods.addItems(options) - def sendSignal(self,index): - self.changeMethodSignal.emit(index) + def sendSignal(self): + self.changeMethodSignal.emit(self.methods.currentText()) diff --git a/scripts/Muon/GUI/FrequencyDomainAnalysis/TransformSelection/transform_selection_widget.py b/scripts/Muon/GUI/FrequencyDomainAnalysis/TransformSelection/transform_selection_widget.py new file mode 100644 index 0000000000000000000000000000000000000000..7a379289b10bd71c973280efbee5a0ba5da30798 --- /dev/null +++ b/scripts/Muon/GUI/FrequencyDomainAnalysis/TransformSelection/transform_selection_widget.py @@ -0,0 +1,26 @@ +from __future__ import (absolute_import, division, print_function) + +from Muon.GUI.FrequencyDomainAnalysis.TransformSelection.transform_selection_view import TransformSelectionView +from Muon.GUI.FrequencyDomainAnalysis.TransformSelection.transform_selection_presenter import TransformSelectionPresenter + +from PyQt4 import QtGui + + +class TransformSelectionWidget(QtGui.QWidget): + + def __init__(self, parent=None): + super(TransformSelectionWidget, self).__init__(parent) + view = TransformSelectionView(parent) + self._presenter = TransformSelectionPresenter(view) + + def setSelectionConnection(self, slot): + view = self.widget + view.changeMethodSignal.connect(slot) + + @property + def presenter(self): + return self._presenter + + @property + def widget(self): + return self._presenter.widget diff --git a/scripts/Muon/GUI/FrequencyDomainAnalysis/__init__.py b/scripts/Muon/GUI/FrequencyDomainAnalysis/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/scripts/Muon/GUI/MuonAnalysis/__init__.py b/scripts/Muon/GUI/MuonAnalysis/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/scripts/Muon/GUI/MuonAnalysis/dock/__init__.py b/scripts/Muon/GUI/MuonAnalysis/dock/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/scripts/Muon/GUI/dock/dock_widget.py b/scripts/Muon/GUI/MuonAnalysis/dock/dock_widget.py similarity index 88% rename from scripts/Muon/GUI/dock/dock_widget.py rename to scripts/Muon/GUI/MuonAnalysis/dock/dock_widget.py index 3866a008addb454228ac86392bb21ec3620f276b..28ccae93e6c9a7ad8be023ec493be2f6cf27a432 100644 --- a/scripts/Muon/GUI/dock/dock_widget.py +++ b/scripts/Muon/GUI/MuonAnalysis/dock/dock_widget.py @@ -2,9 +2,9 @@ from __future__ import (absolute_import, division, print_function) from PyQt4 import QtGui -from Muon.GUI.dummy.dummy_widget import DummyWidget -from Muon.GUI.dummy_label.dummy_label_widget import DummyLabelWidget -from Muon.GUI.dock.dock_view import DockView +from Muon.GUI.Common.dummy.dummy_widget import DummyWidget +from Muon.GUI.Common.dummy_label.dummy_label_widget import DummyLabelWidget +from Muon.GUI.Common.dock.dock_view import DockView class DockWidget(QtGui.QWidget): diff --git a/scripts/Muon/fft_model.py b/scripts/Muon/fft_model.py deleted file mode 100644 index 40b0d90d72b640ddead228cc4728b2d1e41cab49..0000000000000000000000000000000000000000 --- a/scripts/Muon/fft_model.py +++ /dev/null @@ -1,137 +0,0 @@ -from __future__ import (absolute_import, division, print_function) - -from six import iteritems - -import mantid.simpleapi as mantid - - -class FFTWrapper(object): - """ - A class to wrap the different parts - of the FFT and its preprocessing. - This keeps the main FFT class simple. - """ - def __init__(self,FFT): - self.name = "FFT" - self.model = FFT - - def loadData(self,inputs): - """ - store the data in the wrapper for later - """ - if "phaseTable" in inputs: - self.phaseTable = inputs["phaseTable"] - else: - self.phaseTable = None - if "preRe" in inputs: - self.preRe = inputs["preRe"] - else: - self.preRe = None - if "preIm" in inputs: - self.preIm = inputs["preIm"] - else: - self.preIm = None - if "FFT" in inputs: - self.FFT = inputs["FFT"] - else: - self.FFT = None - self.model.setRun(inputs["Run"]) - - def execute(self): - """ - runs the relevant parts of the FFT and the preprocessing - """ - try: - if self.phaseTable is not None: - if self.phaseTable["newTable"]: - self.model.makePhaseQuadTable(self.phaseTable) - self.model.PhaseQuad() - - if self.preRe is not None: - self.model.preAlg(self.preRe) - - if self.preIm is not None: - self.model.preAlg(self.preIm) - - if self.FFT is not None: - self.model.FFTAlg(self.FFT) - except: - pass - - def output(self): - return - - -class FFTModel(object): - """ - A simple class which executes - the relevant algorithms for - the analysis. - """ - def __init__(self): - self.name = "FFT" - - def setRun(self,run): - self.runName=run - - def preAlg(self,preInputs): - """ - PaddingAndApodization alg on the data - """ - preAlg = mantid.AlgorithmManager.create("PaddingAndApodization") - preAlg.initialize() - preAlg.setChild(True) - for name,value in iteritems(preInputs): - preAlg.setProperty(name,value) - preAlg.execute() - mantid.AnalysisDataService.addOrReplace(preInputs["OutputWorkspace"], preAlg.getProperty("OutputWorkspace").value) - - def FFTAlg(self,FFTInputs): - """ - Use the FFT alg - """ - alg = mantid.AlgorithmManager.create("FFT") - alg.initialize() - alg.setChild(True) - for name,value in iteritems(FFTInputs): - alg.setProperty(name,value) - alg.execute() - mantid.AnalysisDataService.addOrReplace(FFTInputs["OutputWorkspace"],alg.getProperty("OutputWorkspace").value) - - ws = alg.getPropertyValue("OutputWorkspace") - group = mantid.AnalysisDataService.retrieve(self.runName) - group.add(ws) - - def makePhaseQuadTable(self,inputs): - """ - generates a phase table from CalMuonDetectorPhases - """ - alg = mantid.AlgorithmManager.create("CalMuonDetectorPhases") - alg.initialize() - alg.setChild(True) - - alg.setProperty("FirstGoodData",inputs["FirstGoodData"]) - alg.setProperty("LastGoodData",inputs["LastGoodData"]) - - alg.setProperty("InputWorkspace","MuonAnalysis") - alg.setProperty("DetectorTable","PhaseTable") - alg.setProperty("DataFitted","fits") - alg.execute() - mantid.AnalysisDataService.addOrReplace("PhaseTable",alg.getProperty("DetectorTable").value) - - def PhaseQuad(self): - """ - do the phaseQuad algorithm - groups data into a single set - """ - phaseQuad = mantid.AlgorithmManager.create("PhaseQuad") - phaseQuad.initialize() - phaseQuad.setChild(False) - print (self.runName) - phaseQuad.setProperty("InputWorkspace","MuonAnalysis") - phaseQuad.setProperty("PhaseTable","PhaseTable") - phaseQuad.setProperty("OutputWorkspace","__phaseQuad__") - phaseQuad.execute() - - def getName(self): - return self.name diff --git a/scripts/Muon/model_constructor.py b/scripts/Muon/model_constructor.py deleted file mode 100644 index 91392d7a38867aecd4911d0590a6d106f23ac51e..0000000000000000000000000000000000000000 --- a/scripts/Muon/model_constructor.py +++ /dev/null @@ -1,30 +0,0 @@ -from __future__ import (absolute_import, division, print_function) -from Muon import maxent_model - -from Muon import fft_model - - -class ModelConstructor(object): - - """ - simple class to create a single object - containing all of the models. - Only need to pass a single object to all - presenters - """ - def __init__(self,includeTransform): - # construct transformation memebers - if includeTransform: - self.transformModels={} - # generate the models - MaxEnt =maxent_model.MaxEntModel() - MaxEntWrapper =maxent_model.MaxEntWrapper(MaxEnt) - FFT =fft_model.FFTModel() - FFTWrapper=fft_model.FFTWrapper(FFT) - # adds the models to the transformation tab - self.transformModels[MaxEnt.getName()]=MaxEntWrapper - self.transformModels[FFT.getName()]=FFTWrapper - - # gets the model - def getModel(self,name): - return self.transformModels[name] diff --git a/scripts/Muon/transform_presenter.py b/scripts/Muon/transform_presenter.py deleted file mode 100644 index 58511798914fb96e2f23c593fe0d0a24f2bc4d8a..0000000000000000000000000000000000000000 --- a/scripts/Muon/transform_presenter.py +++ /dev/null @@ -1,38 +0,0 @@ -from __future__ import (absolute_import, division, print_function) - -from Muon import fft_presenter -from Muon import load_utils -from Muon import maxent_presenter -from Muon import transform_selection_presenter - - -class TransformPresenter(object): - """ - The widget for controlling which method to display - in the transformation tab - """ - def __init__(self,view,model): - self.view=view - self.load=load_utils.LoadUtils() - if not self.load.MuonAnalysisExists(): - return - - # create presenters for the views - self.FFTPresenter=fft_presenter.FFTPresenter(self.view.getView("FFT"),model.getModel("FFT"),self.load) - self.MaxEntPresenter=maxent_presenter.MaxEntPresenter(self.view.getView("MaxEnt"),model.getModel("MaxEnt"),self.load) - # get the transform selection view - self.selectionPresenter=transform_selection_presenter.TransformSelectionPresenter(self.view.selection) - # gets a list of the views/methods - self.methodsList=self.view.getMethods() - # sets the transform selection view to have the correct options - self.selectionPresenter.setMethodsCombo(self.methodsList) - # connect - self.view.selection.changeMethodSignal.connect(self.updateDisplay) - - def close(self): - self.MaxEntPresenter.cancel() - - #switch the view - def updateDisplay(self,index): - self.view.hideAll() - self.view.show(self.methodsList[index]) diff --git a/scripts/Muon/view_constructor.py b/scripts/Muon/view_constructor.py deleted file mode 100644 index 44970df2b816b4ee3c2cbb18be5eb4bb65b7fdb1..0000000000000000000000000000000000000000 --- a/scripts/Muon/view_constructor.py +++ /dev/null @@ -1,29 +0,0 @@ -from __future__ import (absolute_import, division, print_function) - -from Muon import fft_view -from Muon import maxent_view -from Muon import transform_selection_view - - -class ViewConstructor(object): - """ - simple class to create a single object - containing all of the views. - Only need to pass a single object to all - presenters - """ - - def __init__(self,includeTransform,parent=None ): - # construct transformation memebers - if includeTransform: - self.transformMethods = {} - self.transformMethods["FFT"] = fft_view.FFTView(parent) - self.transformMethods["MaxEnt"] = maxent_view.MaxEntView(parent) - # create default transform selection widget - self.transformSelector = transform_selection_view.TransformSelectionView(parent) - - def getTransformMethods(self): - return self.transformMethods - - def getTransformSelection(self): - return self.transformSelector diff --git a/scripts/Muon_Analysis_2.py b/scripts/Muon_Analysis_2.py index a355cb5766d624248055c33c56b438065f883801..74284382f744613147277c229d202d0dd7f54b15 100644 --- a/scripts/Muon_Analysis_2.py +++ b/scripts/Muon_Analysis_2.py @@ -6,8 +6,8 @@ import sys import PyQt4.QtGui as QtGui import PyQt4.QtCore as QtCore -from Muon.GUI.dummy_label.dummy_label_widget import DummyLabelWidget -from Muon.GUI.dock.dock_widget import DockWidget +from Muon.GUI.Common.dummy_label.dummy_label_widget import DummyLabelWidget +from Muon.GUI.MuonAnalysis.dock.dock_widget import DockWidget class MuonAnalysis2Gui(QtGui.QMainWindow): diff --git a/scripts/test/Muon/CMakeLists.txt b/scripts/test/Muon/CMakeLists.txt index 5eb15b0b9eac3ad3ec99c39a1d61584062c62fe4..cf8bd05406a1a0e5e3b15b5f0b1fa3b9f4686e06 100644 --- a/scripts/test/Muon/CMakeLists.txt +++ b/scripts/test/Muon/CMakeLists.txt @@ -7,7 +7,7 @@ set ( TEST_PY_FILES FFTModel_test.py MaxEntPresenter_test.py MaxEntModel_test.py - transformPresenter_test.py + transformWidget_test.py ) check_tests_valid ( ${CMAKE_CURRENT_SOURCE_DIR} ${TEST_PY_FILES} ) diff --git a/scripts/test/Muon/FFTModel_test.py b/scripts/test/Muon/FFTModel_test.py index 68de091be30a4f90a68d6441819575fd993b1df9..0e6513e02357ee3a7e12c938a781f98916b37d34 100644 --- a/scripts/test/Muon/FFTModel_test.py +++ b/scripts/test/Muon/FFTModel_test.py @@ -1,6 +1,6 @@ import sys -from Muon import fft_model +from Muon.GUI.FrequencyDomainAnalysis.FFT import fft_model import unittest diff --git a/scripts/test/Muon/FFTPresenter_test.py b/scripts/test/Muon/FFTPresenter_test.py index 7d30be8b4f2e182600ab925e02ac5fad3594b619..846fd9886c1674570ac08b0205556035121c6b16 100644 --- a/scripts/test/Muon/FFTPresenter_test.py +++ b/scripts/test/Muon/FFTPresenter_test.py @@ -1,10 +1,10 @@ import sys -from Muon import load_utils -from Muon import fft_presenter -from Muon import fft_view -from Muon import fft_model -from Muon import thread_model +from Muon.GUI.Common import load_utils +from Muon.GUI.Common import thread_model +from Muon.GUI.FrequencyDomainAnalysis.FFT import fft_presenter +from Muon.GUI.FrequencyDomainAnalysis.FFT import fft_view +from Muon.GUI.FrequencyDomainAnalysis.FFT import fft_model import unittest diff --git a/scripts/test/Muon/MaxEntModel_test.py b/scripts/test/Muon/MaxEntModel_test.py index ebb0884d359efc70fd88461d78b37eb62d811cdd..80b0eb5ad54d50a6c2cadecbcff180ee8520e76c 100644 --- a/scripts/test/Muon/MaxEntModel_test.py +++ b/scripts/test/Muon/MaxEntModel_test.py @@ -1,6 +1,6 @@ import sys -from Muon import maxent_model +from Muon.GUI.FrequencyDomainAnalysis.MaxEnt import maxent_model import unittest diff --git a/scripts/test/Muon/MaxEntPresenter_test.py b/scripts/test/Muon/MaxEntPresenter_test.py index 73156d0ddb10409d486854c657b72216e2445e45..15e73d7830bb285d7d63e94848c7f8dfa2e51e75 100644 --- a/scripts/test/Muon/MaxEntPresenter_test.py +++ b/scripts/test/Muon/MaxEntPresenter_test.py @@ -2,11 +2,11 @@ from __future__ import (absolute_import, division, print_function) import sys -from Muon import load_utils -from Muon import maxent_presenter -from Muon import maxent_view -from Muon import maxent_model -from Muon import thread_model +from Muon.GUI.Common import load_utils +from Muon.GUI.Common import thread_model +from Muon.GUI.FrequencyDomainAnalysis.MaxEnt import maxent_presenter +from Muon.GUI.FrequencyDomainAnalysis.MaxEnt import maxent_view +from Muon.GUI.FrequencyDomainAnalysis.MaxEnt import maxent_model import unittest if sys.version_info.major == 3: diff --git a/scripts/test/Muon/transformPresenter_test.py b/scripts/test/Muon/transformPresenter_test.py deleted file mode 100644 index b184745a590a14e7b0f443af3332b3e371b93207..0000000000000000000000000000000000000000 --- a/scripts/test/Muon/transformPresenter_test.py +++ /dev/null @@ -1,43 +0,0 @@ -import sys - -import mantid #noqa -from Muon import fft_presenter -from Muon import load_utils -from Muon import transform_presenter -from Muon import transform_view -from Muon import transform_selection_view -from Muon import maxent_presenter -from Muon import model_constructor - -import unittest -if sys.version_info.major == 3: - from unittest import mock -else: - import mock - - -class FFTTransformTest(unittest.TestCase): - def setUp(self): - load_utils.LoadUtils=mock.Mock() - fft_presenter.FFTPresenter=mock.Mock() - maxent_presenter.MaxEntPresenter=mock.Mock() - self.view=mock.create_autospec(transform_view.TransformView,spec_set=False) - self.view.getView=mock.Mock() - self.view.getMethods=mock.Mock(return_value=["FFT","MaxEnt"]) - self.view.hideAll=mock.Mock() - self.view.show=mock.Mock() - self.view.selection=mock.create_autospec(transform_selection_view.TransformSelectionView,spec_set=True) - self.view.selection.changeMethodSignal=mock.Mock() - self.model=mock.create_autospec(model_constructor.ModelConstructor) - self.model.getModel=mock.Mock() - #set presenter - self.presenter=transform_presenter.TransformPresenter(self.view,self.model) - - def test_changeDisplay(self): - self.presenter.updateDisplay(1) - assert(self.view.hideAll.call_count==1) - assert(self.view.show.call_count==1) - - -if __name__ == '__main__': - unittest.main() diff --git a/scripts/test/Muon/transformWidget_test.py b/scripts/test/Muon/transformWidget_test.py new file mode 100644 index 0000000000000000000000000000000000000000..94c78456a0b014bf7f858b74453ef776cbe06b93 --- /dev/null +++ b/scripts/test/Muon/transformWidget_test.py @@ -0,0 +1,46 @@ +import sys + +from Muon.GUI.Common import mock_widget +from Muon.GUI.Common import load_utils +from Muon.GUI.FrequencyDomainAnalysis.FFT import fft_presenter +from Muon.GUI.FrequencyDomainAnalysis.Transform import transform_widget +from Muon.GUI.FrequencyDomainAnalysis.Transform import transform_view +from Muon.GUI.FrequencyDomainAnalysis.TransformSelection import transform_selection_view +from Muon.GUI.FrequencyDomainAnalysis.MaxEnt import maxent_presenter + + +# need to update this +import unittest +if sys.version_info.major == 3: + from unittest import mock +else: + import mock + +class FFTTransformTest(unittest.TestCase): + def setUp(self): + self._qapp = mock_widget.mockQapp() + self.load= mock.create_autospec( load_utils.LoadUtils,spec_set=True) + self.fft= mock.create_autospec( fft_presenter.FFTPresenter,spec_Set=True) + self.maxent=mock.create_autospec( maxent_presenter.MaxEntPresenter,spec_set=True) + + # create widget + self.widget=transform_widget.TransformWidget(self.load) + # create the view + self.view=mock.create_autospec(transform_view.TransformView,spec_set=False) + self.view.getView=mock.Mock() + self.view.getMethods=mock.Mock(return_value=["FFT","MaxEnt"]) + self.view.hideAll=mock.Mock() + self.view.show=mock.Mock() + self.view.selection=mock.create_autospec(transform_selection_view.TransformSelectionView,spec_set=True) + self.view.selection.changeMethodSignal=mock.Mock() + # set the mocked view to the widget + self.widget.mockWidget(self.view) + + def test_changeDisplay(self): + self.widget.updateDisplay(1) + assert(self.view.hideAll.call_count==1) + assert(self.view.show.call_count==1) + + +if __name__ == '__main__': + unittest.main()