diff --git a/Framework/Algorithms/src/PolarizationCorrectionFredrikze.cpp b/Framework/Algorithms/src/PolarizationCorrectionFredrikze.cpp index f62a0e248a5d07bebf5976341f88dbcce764e191..5c16cddec86d53f5df4a2fb97c492a62bd649e51 100644 --- a/Framework/Algorithms/src/PolarizationCorrectionFredrikze.cpp +++ b/Framework/Algorithms/src/PolarizationCorrectionFredrikze.cpp @@ -222,16 +222,16 @@ PolarizationCorrectionFredrikze::execPA(WorkspaceGroup_sptr inWS) { const auto alpha = this->getEfficiencyWorkspace(cAlphaLabel); const auto ap = this->getEfficiencyWorkspace(cApLabel); - const auto A0 = (Iaa * pp * ap) + (ap * Ipa * rho * pp) + - (ap * Iap * alpha * pp) + (Ipp * ap * alpha * rho * pp); - const auto A1 = pp * Iaa; - const auto A2 = pp * Iap; - const auto A3 = ap * Iaa; - const auto A4 = ap * Ipa; - const auto A5 = ap * alpha * Ipp; - const auto A6 = ap * alpha * Iap; - const auto A7 = pp * rho * Ipp; - const auto A8 = pp * rho * Ipa; + const auto A0 = (Iaa * pp * ap) + (Ipa * ap * rho * pp) + + (Iap * ap * alpha * pp) + (Ipp * ap * alpha * rho * pp); + const auto A1 = Iaa * pp; + const auto A2 = Iap * pp; + const auto A3 = Iaa * ap; + const auto A4 = Ipa * ap; + const auto A5 = Ipp * ap * alpha; + const auto A6 = Iap * ap * alpha; + const auto A7 = Ipp * pp * rho; + const auto A8 = Ipa * pp * rho; const auto D = pp * ap * (rho + alpha + 1.0 + (rho * alpha)); diff --git a/Framework/Algorithms/src/ReflectometryReductionOneAuto2.cpp b/Framework/Algorithms/src/ReflectometryReductionOneAuto2.cpp index 121483547287033697c04c27da6f79011723babf..6f3281a0fbf334a272c6acf93e46d805907823a8 100644 --- a/Framework/Algorithms/src/ReflectometryReductionOneAuto2.cpp +++ b/Framework/Algorithms/src/ReflectometryReductionOneAuto2.cpp @@ -793,7 +793,6 @@ bool ReflectometryReductionOneAuto2::processGroups() { alg->setProperty("FirstTransmissionRun", ""); alg->setProperty("SecondTransmissionRun", ""); alg->setProperty("CorrectionAlgorithm", "None"); - alg->setProperty("ThetaIn", Mantid::EMPTY_DBL()); alg->setProperty("ProcessingInstructions", "0"); for (size_t i = 0; i < group->size(); ++i) { const std::string IvsQName = outputIvsQ + "_" + std::to_string(i + 1); diff --git a/Framework/Algorithms/src/ReflectometrySumInQ.cpp b/Framework/Algorithms/src/ReflectometrySumInQ.cpp index 290260132aca37fc90cbce5d2a88aa0e163eff6b..dcc7a807b636c6ba4edaf19092421e8b95ed9d5b 100644 --- a/Framework/Algorithms/src/ReflectometrySumInQ.cpp +++ b/Framework/Algorithms/src/ReflectometrySumInQ.cpp @@ -269,8 +269,18 @@ std::map<std::string, std::string> ReflectometrySumInQ::validateInputs() { std::map<std::string, std::string> issues; API::MatrixWorkspace_sptr inWS; Indexing::SpectrumIndexSet indices; - std::tie(inWS, indices) = - getWorkspaceAndIndices<API::MatrixWorkspace>(Prop::INPUT_WS); + + // validateInputs is called on the individual workspaces when the algorithm + // is executed, it but may get called on a group from AlgorithmDialog. This + // isn't handled in getWorkspaceAndIndices. We should fix this properly but + // for now skip validation for groups to avoid an exception. See #22933 + try { + std::tie(inWS, indices) = + getWorkspaceAndIndices<API::MatrixWorkspace>(Prop::INPUT_WS); + } catch (std::runtime_error &) { + return issues; + } + const auto &spectrumInfo = inWS->spectrumInfo(); const int beamCentre = getProperty(Prop::BEAM_CENTRE); bool beamCentreFound{false}; diff --git a/buildconfig/dev-packages/deb/mantid-developer/ns-control b/buildconfig/dev-packages/deb/mantid-developer/ns-control index 11793d3cc34c7f37566012a3992dec1d661d5e5d..84b8050b8c26265cafef6228671e1d4e353fe716 100644 --- a/buildconfig/dev-packages/deb/mantid-developer/ns-control +++ b/buildconfig/dev-packages/deb/mantid-developer/ns-control @@ -3,7 +3,7 @@ Priority: optional Standards-Version: 3.9.2 Package: mantid-developer -Version: 1.3.6 +Version: 1.3.7 Maintainer: Mantid Project <mantid-tech@mantidproject.org> Priority: optional Architecture: all @@ -61,6 +61,7 @@ Depends: git, python-h5py, python-yaml, python-mock, + python-psutil, ipython-qtconsole (>=1.2.0), texlive, texlive-latex-extra, @@ -82,7 +83,8 @@ Depends: git, ipython3-qtconsole, python3-h5py, python3-yaml, - python3-mock + python3-mock, + python3-psutil Description: Installs all packages required for a Mantid developer A metapackage which requires all the dependencies and tools that are required for Mantid development. It works for Ubuntu 16.04. diff --git a/buildconfig/dev-packages/rpm/mantid-developer/mantid-developer.spec b/buildconfig/dev-packages/rpm/mantid-developer/mantid-developer.spec index e470bfbc2f93d87c0dcb25bcd3a39eb8cc4f3f93..64908d8e50390c36d9d96cfd3d7221837a43bb1c 100644 --- a/buildconfig/dev-packages/rpm/mantid-developer/mantid-developer.spec +++ b/buildconfig/dev-packages/rpm/mantid-developer/mantid-developer.spec @@ -5,7 +5,7 @@ %endif Name: mantid-developer -Version: 1.27 +Version: 1.28 Release: 1%{?dist} Summary: Meta Package to install dependencies for Mantid Development @@ -55,6 +55,7 @@ Requires: python-sphinx Requires: python2-sphinx-bootstrap-theme Requires: PyYAML Requires: python2-mock +Requires: python2-psutil Requires: qscintilla-devel Requires: qt-devel >= 4.6 Requires: qwt5-qt4-devel @@ -103,6 +104,7 @@ Requires: python3-matplotlib %{?fedora:Requires: python3-qtconsole} Requires: python3-PyYAML Requires: python3-mock +%{?fedora:Requires: python3-psutil} Requires: boost-python3-devel %endif @@ -128,6 +130,9 @@ required for Mantid development. %changelog +* Wed Jul 18 2018 Martyn Gigg <martyn.gigg@stfc.ac.uk> +- Added python-psutil + * Wed Apr 25 2018 Steven Hahn <hahnse@ornl.gov> - Add qt5-qtx11extras - remove RHEL6-specific packages diff --git a/docs/source/concepts/ConvFit.rst b/docs/source/concepts/ConvFit.rst new file mode 100644 index 0000000000000000000000000000000000000000..fe61f0c38b8756cabc97489c88f23bfb8a4088e3 --- /dev/null +++ b/docs/source/concepts/ConvFit.rst @@ -0,0 +1,80 @@ +.. _ConvFitConcept: + +Conv Fit +======== + +The measured data :math:`I(Q, \omega)` is proportional to the convolution of the +scattering law :math:`S(Q, \omega)` with the resolution function :math:`R(Q, +\omega)` of the spectrometer via :math:`I(Q, \omega) = S(Q, \omega) ⊗ R(Q, +\omega)`. The traditional method of analysis has been to fit the measured +:math:`I(Q, \omega)` with an appropriate set of functions related to the form of +:math:`S(Q, \omega)` predicted by theory. + +* In quasielastic scattering the simplest form is when both the :math:`S(Q, + \omega)` and the :math:`R(Q, \omega)` have the form of a Lorentzian - a + situation which is almost correct for reactor based backscattering + spectrometers such as IN10 & IN16 at ILL. The convolution of two Lorentzians + is itself a Lorentzian so that the spectrum of the measured and resolution + data can both just be fitted with Lorentzians. The broadening of the sample + spectrum is then just the difference of the two widths. +* The next easiest case is when both :math:`S(Q, \omega)` and :math:`R(Q, + \omega)` have a simple functional form and the convolution is also a function + containing the parameters of the :math:`S(Q, \omega)` and R(Q, \omega) functions. + The convoluted function may then be fitted to the data to provide the + parameters. An example would be the case where the :math:`S(Q, \omega)` is a + Lorentzian and the :math:`R(Q, \omega)` is a Gaussian. +* For diffraction, the shape of the peak in time is a convolution of a Gaussian + with a decaying exponential and this function can be used to fit the Bragg + peaks. +* The final case is where :math:`R(Q, \omega)` does not have a simple function + form so that the measured data has to be convoluted numerically with the + :math:`S(Q, \omega)` function to provide an estimate of the sample scattering. + The result is least-squares fitted to the measured data to provide values for + the parameters in the :math:`S(Q, \omega)` function. + +This latter form of peak fitting is provided by SWIFT. It employs a +least-squares algorithm which requires the derivatives of the fitting function +with respect to its parameters in order to be faster and more efficient than +those algorithms which calculate the derivatives numerically. To do this the +assumption is made that the derivative of a convolution is equal to the +convolution of the derivative-as the derivative and the convolution are +performed over different variables (function parameters and energy transfer +respectively) this should be correct. A flat background is subtracted from the +resolution data before the convolution is performed. + +Four types of sample function are available for :math:`S(Q, \omega)`: + +Quasielastic + This is the most common case and applies to both translational (diffusion) and + rotational modes, both of which have the form of a Lorentzian. The fitted + function is a set of Lorentzians centred at the origin in energy transfer. + +Elastic + Comprising a central elastic peak together with a set of quasi-elastic + Lorentzians also centred at the origin. The elastic peak is taken to be the + un-broadened resolution function. + +Shift + A central Lorentzian with pairs of energy shifted Lorentzians. This was + originally used for crystal field splitting data but more recently has been + applied to quantum tunnelling peaks. The fitting function assumes that the + peaks are symmetric about the origin in energy transfer both in position and + width. The widths of the central and side peaks may be different. + +Polymer + A single quasi-elastic peak with 3 different forms of shape. The theory behind + this is described elsewhere [1,2]. Briefly, polymer theory predicts 3 forms + of the :math:`I(Q,t)` in the form of :math:`exp(-at2/b)` where :math:`b` can + be 2, 3 or 4. The Full Width Half-Maximum (FWHM) then has a Q-dependence + (power law) of the form :math:`Qb`. The :math:`I(Q,t)` has been numerically + Fourier transformed into :math:`I(Q, \omega)` and the :math:`I(Q, \omega)` + have been fitted with functions of the form of a modified Lorentzian. These + latter functions are used in the energy fitting procedures. + +References: + +1. J S Higgins, R E Ghosh, W S Howells & G Allen, `JCS Faraday II 73 40 (1977) <http://dx.doi.org/10.1039/F29777300040>`_ +2. J S Higgins, G Allen, R E Ghosh, W S Howells & B Farnoux, `Chem Phys Lett 49 197 (1977) <http://dx.doi.org/10.1016/0009-2614(77)80569-1>`_ + + +.. categories:: Concepts diff --git a/docs/source/concepts/ProjectRecovery.rst b/docs/source/concepts/ProjectRecovery.rst index 0c31c3ad0795cc56b26081b0ac01ab19e659696f..2abd1948681e51f793662051779413462c28a13c 100644 --- a/docs/source/concepts/ProjectRecovery.rst +++ b/docs/source/concepts/ProjectRecovery.rst @@ -46,8 +46,9 @@ Caveats * Indirect analysis - project recovery does not work when performing fitting routines within the indirect analysis interface. * SANS - project recovery does not currently work with the SANS interface. -* Multi-line commands - * Currently if a workspace history contains any multi-line commands then the recovery script builder will fail. +* Dictionary properties + * Affects: SANS interface, SetSample algorithm + * Cause: Currently the history writer does not serialise Python dictionaries correctly. * If full project recovery does not work: * If the project recovery process has managed to create a script of the ordered workspace histories, this will appear in MantidPlot, it will have a red arrow beside the line where the process failed. In many cases it is possible to edit the script by hand to get it to run. @@ -68,4 +69,4 @@ Settings * **Regularity:** `projectRecovery.secondsBetween = 60` * **Number of backups to keep:** `projectRecovery.numberOfCheckpoints = 5` -.. categories:: Concepts \ No newline at end of file +.. categories:: Concepts diff --git a/docs/source/interfaces/Indirect Data Analysis.rst b/docs/source/interfaces/Indirect Data Analysis.rst index 143087606a562ead1aeed40684e5a2d3afe8c925..58b8966fbe60b39891d5594ea0a4867f3db0f832 100644 --- a/docs/source/interfaces/Indirect Data Analysis.rst +++ b/docs/source/interfaces/Indirect Data Analysis.rst @@ -7,20 +7,22 @@ Indirect Data Analysis Overview -------- -.. interface:: Data Analysis - :align: right - :width: 350 The Indirect Data Analysis interface is a collection of tools within MantidPlot for analysing reduced data from indirect geometry spectrometers, such as IRIS and OSIRIS. +.. interface:: Data Analysis + :width: 450 + The majority of the functions used within this interface can be used with both reduced files (*_red.nxs*) and workspaces (*_red*) created using the Indirect Data Reduction interface or using :math:`S(Q, \omega)` files (*_sqw.nxs*) and workspaces (*_sqw*) created using either the Indirect Data Reduction interface or taken from a bespoke algorithm or auto reduction. +Four of the available tabs are QENS fitting interfaces and share common features and layout. These common factors are documented in the :ref:`qens-fitting-features` section of this document. + These interfaces do not support GroupWorkspace as input. Action Buttons @@ -39,43 +41,13 @@ Manage Directories Opens the Manage Directories dialog allowing you to change your search directories and default save directory and enable/disable data archive search. -Bayesian --------- - -There is the option to perform Bayesian data analysis on the I(Q, t) Fit ConvFit -tabs on this interface by using the :ref:`FABADA` fitting minimizer, however in -order to to use this you will need to use better starting parameters than the -defaults provided by the interface. - -You may also experience issues where the starting parameters may give a reliable -fit on one spectra but not others, in this case the best option is to reduce -the number of spectra that are fitted in one operation. - -In both I(Q, t) Fit and ConvFit the following options are available when fitting -using FABADA: - -Output Chain - Select to enable output of the FABADA chain when using FABADA as the fitting - minimizer. - -Chain Length - Number of further steps carried out by fitting algorithm once parameters have - converged (see *ChainLength* is :ref:`FABADA` documentation) - -Convergence Criteria - The minimum variation in the cost function before the parameters are - considered to have converged (see *ConvergenceCriteria* in :ref:`FABADA` - documentation) - -Acceptance Rate - The desired percentage acceptance of new parameters (see *JumpAcceptanceRate* - in :ref:`FABADA` documentation) +Plot Current Preview + Takes the data currently plotted in the preview plot and puts it in a separate external plot + Elwin ----- -.. interface:: Data Analysis - :widget: tabElwin Provides an interface for the :ref:`ElasticWindow <algm-ElasticWindow>` algorithm, with the option of selecting the range to integrate over as well as @@ -86,6 +58,10 @@ Mantid data search paths that contains the sample environment information the ELF workspace can also be normalised to the lowest temperature run in the range of input files. +.. interface:: Data Analysis + :width: 450 + :widget: tabElwin + Options ~~~~~~~ @@ -123,17 +99,15 @@ Plot Result Save Result If enabled the result will be saved as a NeXus file in the default save directory. - + MSD Fit ------- -.. interface:: Data Analysis - :widget: tabMSD - -Given either a saved NeXus file or workspace generated using the ElWin tab, this -tab fits :math:`log(intensity)` vs. :math:`Q^{2}` with a straight line for each +Given either a saved NeXus file or workspace generated using the Elwin tab, this +tab fits :math:`log(intensity)` vs. :math:`Q` with a straight line for each run specified to give the Mean Square Displacement (MSD). It then plots the MSD -as function of run number. +as function of run number. This is done by means of the +:ref:`QENSFitSequential <algm-QENSFitSequential>` algorithm. MSDFit searches for the log files named <runnumber>_sample.txt in your chosen raw file directory (the name ‘sample’ is for OSIRIS). If they exist the @@ -142,46 +116,39 @@ exist the MSD is plotted versus run number (last 3 digits). The fitted parameters for all runs are in _msd_Table and the <u2> in _msd. To run the Sequential fit a workspace named <inst><first-run>_to_<last-run>_lnI is -created of :math:`ln(I)` v. :math:`Q^{2}` for all runs. A contour or 3D plot of +created of :math:`ln(I)` v. :math:`Q` for all runs. A contour or 3D plot of this may be of interest. A sequential fit is run by clicking the Run button at the bottom of the tab, a single fit can be done using the Fit Single Spectrum button underneath the preview plot. +.. interface:: Data Analysis + :width: 450 + :widget: tabMSD + Options ~~~~~~~ -Input File - A file that has been created using the Elwin tab with an :math:`x` axis of - :math:`Q^2`. - -StartX & EndX - The :math:`x` range to perform fitting over. - -Plot Spectrum - The spectrum shown in the preview plot and will be fitted by running Fit - Single Spectrum. +.. seealso:: Common options are detailled in the :ref:`qens-fitting-features` section. -Spectra Range - The spectra range over which to perform sequential fitting. +.. seealso:: Sequential fitting is available, options are detailed in the :ref:`sequential-fitting-section` section. -Plot Result - If enabled will plot the result as a spectra plot. +Sample + A file that has been created using the Elwin tab with an :math:`x` axis of + :math:`Q`. Alternatively, a workspace may be provided. -Save Result - If enabled the result will be saved as a NeXus file in the default save - directory. I(Q, t) ------- -.. interface:: Data Analysis - :widget: tabIqt - Given sample and resolution inputs, carries out a fit as per the theory detailed in the :ref:`TransformToIqt <algm-TransformToIqt>` algorithm. +.. interface:: Data Analysis + :width: 450 + :widget: tabIqt + Options ~~~~~~~ @@ -197,7 +164,7 @@ ELow, EHigh The rebiinning range. SampleBinning - The ratio at which to decrease the number of bins by through merging of + The ratio at which to decrease the number of bins by merging of intensities from neighbouring bins. Plot Result @@ -206,14 +173,18 @@ Plot Result Save Result If enabled the result will be saved as a NeXus file in the default save directory. + +Tiled Plot + Produces a tiled plot of the output workspaces generated. -Binning -~~~~~~~ +Monte Carlo Error Calculation - Number Of Iterations + The number of iterations to perform in the Monte Carlo routine for error + calculation in I(Q,t) -As a bin width that is a factor of the binning range is required for this -analysis the bin width is calculated automatically based on the binning range -and the number of desired bins in the output which is in turn calculated by -reducing the number of sample bins by a given factor. +A note on Binning +~~~~~~~~~~~~~~~~~ + +The bin width is determined by the binning range and the sample binning factor. The number of bins is automatically calculated based on the **SampleBinning** specified. The width is the determined by the width of the range divided by the number of bins. The calculated binning parameters are displayed alongside the binning options: @@ -230,111 +201,302 @@ ResolutionBins I(Q, t) Fit ----------- -.. interface:: Data Analysis - :widget: tabIqtFit I(Q, t) Fit provides a simplified interface for controlling various fitting functions (see the :ref:`Fit <algm-Fit>` algorithm for more info). The functions are also available via the fit wizard. + +.. interface:: Data Analysis + :width: 450 + :widget: tabIqtFit + +Options +~~~~~~~ + +.. seealso:: Common options are detailled in the :ref:`qens-fitting-features` section. + +.. seealso:: Sequential fitting is available, options are detailed in the :ref:`sequential-fitting-section` section. + +Sample + Either a file (*_iqt.nxs*) or workspace (*_iqt*) that has been created using + the Iqt tab. + +Constrain Intensities + Check to ensure that the sum of the background and intensities is always equal + to 1. + +Make Beta Global + Check to use a multi-domain fitting function with the value of beta + constrained - the :ref:`IqtFitSimultaneous <algm-IqtFitSimultaneous>` will be + used to perform this fit. + +Extract Members + If checked, each individual member of the fit (e.g. exponential functions), will + be extracted. + +Linear Background + Adds a linear background to the composite fit function. + +Conv Fit +-------- + +ConvFit provides a simplified interface for controlling +various fitting functions (see the :ref:`Fit <algm-Fit>` algorithm for more +info). The functions are also available via the fit wizard. + Additionally, in the bottom-right of the interface there are options for doing a sequential fit. This is where the program loops through each spectrum in the input workspace, using the fitted values from the previous spectrum as input values for fitting the next. This is done by means of the -:ref:`PlotPeakByLogValue <algm-PlotPeakByLogValue>` algorithm. +:ref:`ConvolutionFitSequential <algm-ConvolutionFitSequential>` algorithm. A sequential fit is run by clicking the Run button at the bottom of the tab, a single fit can be done using the Fit Single Spectrum button underneath the preview plot. +.. interface:: Data Analysis + :width: 450 + :widget: tabConvFit + Options ~~~~~~~ -Input - Either a file (*_iqt.nxs*) or workspace (*_iqt*) that has been created using - the Fury tab. +.. seealso:: Common options are detailed in the :ref:`qens-fitting-features` section. -Fit Type - The type of fitting to perform. +.. seealso:: Sequential fitting is available, options are detailed in the :ref:`sequential-fitting-section` section. -Constrain Intensities - Check to ensure that the sum of the background and intensities is always equal - to 1. +Sample + Either a reduced file (*_red.nxs*) or workspace (*_red*) or an :math:`S(Q, + \omega)` file (*_sqw.nxs*) or workspace (*_sqw*). -Constrain Beta over all Q - Check to use a multi-domain fitting function with the value of beta - constrained. +Resolution + Either a resolution file (_res.nxs) or workspace (_res) or an :math:`S(Q, + \omega)` file (*_sqw.nxs*) or workspace (*_sqw*). + +Use Delta Function + Found under 'Custom Function Groups'. Enables use of a delta function. + +Extract Members + If checked, each individual member of the fit (e.g. exponential functions), will + be extracted into a <result_name>_Members group workspace. + +Use Temperature Correction + Adds the custom user function for temperature correction to the fit function. + +Background Options + Flat Background: Adds a flat background to the composite fit function. Linear Background: Adds a linear background to the composite fit function. + +Theory +~~~~~~ + +For more on the theory of Conv Fit see the :ref:`ConvFitConcept` concept page. + +F(Q) Fit +-------- + +One of the models used to interpret diffusion is that of jump diffusion in which +it is assumed that an atom remains at a given site for a time :math:`\tau`; and +then moves rapidly, that is, in a time negligible compared to :math:`\tau`. + +This interface can be used for a jump diffusion fit as well as fitting across +EISF. This is done by means of the +:ref:`QENSFitSequential <algm-QENSFitSequential>` algorithm. + +.. interface:: Data Analysis + :width: 450 + :widget: tabJumpFit + + +Options +~~~~~~~ + +.. seealso:: Common options are detailled in the :ref:`qens-fitting-features` section. + +-Sample +- A sample workspace created with either ConvFit or Quasi. +- +-Fit Parameter +- Either 'Width' or 'EISF' can be selected here, determining whether a width or +- EISF parameter will be fit across. +- +-Width/EISF +- Next to the 'Fit Parameter' menu, will be either a 'Width' or 'EISF' menu, depending on +- which was selected. This menu can be used to select the specific width/EISF parameter to be fit. + + + .. _qens-fitting-features: + +QENS Fitting Interfaces Features +-------------------------------- + +There are four QENS fitting interfaces: + +* MSD Fit +* I(Q,t) Fit, +* Conv Fit +* F(Q) + +These fitting interfaces share common features, with a few unique options in each. + +Single & Multiple Input +~~~~~~~~~~~~~~~~~~~~~~~ + +Each interface provides the option to choose between selecting one or multiple data files to be fit. +The selected mode can be changed by clicking either the 'Single Input' tab or 'Multiple Input' tab at the the top +of the interface to switch between selecting one or multiple data files respectively. +Data may either be provided as a file, or selected from workspaces which have already been loaded. + +When selecting 'Multiple Input', a table along with two buttons 'Add Workspace' and 'Remove' will be displayed. +Clicking 'Add Workspace' will allow you to add a new data-set to be fit (this will bring up a menu allowing you +to select a file/workspace and the spectra to load). Once data has been loaded, it will be displayed in the table. +Highlighting data in the table and selecting 'Remove' will allow you to remove data from the fit. Above the preview +plots will be a drop-down menu with which you can select the active data-set, which will be shown in the plots. + +Custom Function Groups +~~~~~~~~~~~~~~~~~~~~~~ + +Under 'Custom Function Groups', you will find utility options for quick selection of common fit functions, specific +to each fitting interface. + +The 'Fit Type' drop-down menu will be available here in each of the QENS fitting interfaces -- which is useful for +selecting common fit functions but not mandatory. + +Fitting Range +~~~~~~~~~~~~~ + +Under 'Fitting Range', you may select the start and end :math:`x`-values ('StartX' and 'EndX') to be used in the fit. -Plot Guess - When checked a curve will be created on the plot window based on the bitting - parameters. +Functions +~~~~~~~~~ + +Under 'Functions', you can view the selected model and associated parameters as well as make modifications. +Right-clicking on 'Functions' and selecting 'Add Function' will allow you to add any function from Mantid's library +of fitting functions. It is also possible to right-click on a composite function and select 'Add Function' to add a +function to the composite. + +Parameters may be tied by right-clicking on a parameter and selecting either 'Tie > To Function' when creating a tie +to a parameter of the same name in a different function or by selecting 'Tie > Custom Tie' to tie to parameters of +different names and for providing mathematical expressions. Parameters can be constrained by right-clicking and +using the available options under 'Constrain'. + +Upon performing a fit, the parameter values will be updated here to display the result of the fit for the selected +spectrum. + +Settings +~~~~~~~~ + +Minimizer + The minimizer which will be used in the fit (defaults to Levenberg-Marquadt). + +Ignore invalid data + Whether to ignore invalid (infinity/NaN) values when performing the fit. + +Cost function + The cost function to be used in the fit (defaults to Least Squares). Max Iterations - The maximum number of iterations that can be carried out by the fitting - algorithm (automatically increased when FABADA is enabled). + The maximum number of iterations used to perform the fit of each spectrum. -StartX & EndX - The range of :math:`x` over which the fitting will be applied (blue lines on - preview plot). +Preview Plots +~~~~~~~~~~~~~ -Use FABADA - Select to enable use of the :ref:`FABADA` minimizer when performing the fit. +Two preview plots are included in each of the fitting interfaces. The top preview plot displays the sample, guess +and fit curves. The bottom preview plot displays the difference curve. -Linear Background A0 - The constant amplitude of the background (horizontal green line on the preview - plot). +The preview plots will display the curves for the selected spectrum ('Plot Spectrum') of the selected data-set +(when in multiple input mode, a drop-down menu will be available above the plots to select the active data-set). -Fitting Parameters - Depending on the Fit Type the parameters shown for each of the fit functions - will differ, for more information refer to the documentation pages for the fit - function in question. +The 'Plot Spectrum' option can be used to select the active/displayed spectrum. -Plot Spectrum - The spectrum shown in the preview plot and will be fitted by running Fit - Single Spectrum. +A button labelled 'Fit Single Spectrum' is found under the preview plots and can be used to perform a fit of the +selected specturm. -Spectra Range - The spectra range over which to perform sequential fitting. +'Plot Current Preview' can be used to plot the sample, fit and difference curves of the selected spectrum in +a separate plotting window. -Plot Output - Allows plotting spectra plots of fitting parameters, the options available - will depend on the type of fit chosen. +The 'Plot Guess' check-box can be used to enable/disable the guess curve in the top preview plot. -Save Result - If enabled the result will be saved as a NeXus file in the default save - directory. -Conv Fit --------- +Output +~~~~~~ -.. interface:: Data Analysis - :widget: tabConvFit +The results of the fit may be plot and saved under the 'Output' section of the fitting interfaces. -Similarly to FuryFit, ConvFit provides a simplified interface for controlling -various fitting functions (see the :ref:`Fit <algm-Fit>` algorithm for more -info). The functions are also available via the fit wizard. +Next to the 'Plot Output' label, you can select a parameter to plot and then click 'Plot' to plot it across the +fit spectra (if multiple data-sets have been used, a separate plot will be produced for each data-set). -Additionally, in the bottom-right of the interface there are options for doing a +Clicking the 'Save Result' button will save the result of the fit to your default save location. + + +Bayesian (FABADA minimizer) +--------------------------- + +There is the option to perform Bayesian data analysis on the I(Q, t) Fit ConvFit +tabs on this interface by using the :ref:`FABADA` fitting minimizer, however in +order to to use this you will need to use better starting parameters than the +defaults provided by the interface. + +You may also experience issues where the starting parameters may give a reliable +fit on one spectra but not others, in this case the best option is to reduce +the number of spectra that are fitted in one operation. + +In both I(Q, t) Fit and ConvFit the following options are available when fitting +using FABADA: + +Output Chain + Select to enable output of the FABADA chain when using FABADA as the fitting + minimizer. + +Chain Length + Number of further steps carried out by fitting algorithm once parameters have + converged (see *ChainLength* is :ref:`FABADA` documentation) + +Convergence Criteria + The minimum variation in the cost function before the parameters are + considered to have converged (see *ConvergenceCriteria* in :ref:`FABADA` + documentation) + +Acceptance Rate + The desired percentage acceptance of new parameters (see *JumpAcceptanceRate* + in :ref:`FABADA` documentation) + +.. _sequential-fitting-section: + +Sequential Fitting +------------------ + +Three of the fitting interfaces allow sequential fitting of several spectra: + +* MSD Fit +* I(Q, T) Fit +* ConvFit + +At the bottom of the interface there are options for doing a sequential fit. This is where the program loops through each spectrum in the input workspace, using the fitted values from the previous spectrum as input values for fitting the next. This is done by means of the -:ref:`PlotPeakByLogValue <algm-PlotPeakByLogValue>` algorithm. +:ref:`IqtFitSequential <algm-IqtFitSequential>` algorithm. A sequential fit is run by clicking the Run button at the bottom of the tab, a single fit can be done using the Fit Single Spectrum button underneath the preview plot. -The 'ExtractMembers' property, found represented as a checkbox in the properties -table of the ConvFit interface, can be used to extract the members of a fit, each -into their own workspace, which are subsequently grouped in a GroupWorkspace. Members -of a fit include the sample, calculated fit, difference, and any peak functions used -in the convolution fit such as Lorenztian or Delta functions. +Spectrum Selection +~~~~~~~~~~~~~~~~~~ + +Below the preview plots, the spectra to be fit can be selected. The 'Fit Spectra' drop-down menu allows for +selecting either 'Range' or 'String'. If 'Range' is selected, you are able to select a range of spectra to fit by +providing the upper and lower bounds. If 'String' is selected you can provide the spectra to fit in a text form. +When selecting spectra using text, you can use '-' to identify a range and ',' to separate each spectrum/range. +:math:`X`-Ranges may be excluded from the fit by selecting a spectrum next to the 'Mask Bins of Spectrum' label and +then providing a comma-separated list of pairs, where each pair designates a range to exclude from the fit. -Fitting Model -~~~~~~~~~~~~~ +ConvFit fitting model +--------------------- -The model used to perform fitting is described in the following tree, note that +The model used to perform fitting in ConvFit is described in the following tree, note that everything under the Model section is optional and determined by the *Fit Type* and *Use Delta Function* options in the interface. @@ -396,190 +558,7 @@ The Temperature Correction is a :ref:`UserFunction <func-UserFunction>` with the formula :math:`((x * 11.606) / T) / (1 - exp(-((x * 11.606) / T)))` where :math:`T` is the temperature in Kelvin. -Options -~~~~~~~ - -Sample - Either a reduced file (*_red.nxs*) or workspace (*_red*) or an :math:`S(Q, - \omega)` file (*_sqw.nxs*) or workspace (*_sqw*). - -Resolution - Either a resolution file (_res.nxs) or workspace (_res) or an :math:`S(Q, - \omega)` file (*_sqw.nxs*) or workspace (*_sqw*). - -Fit Type - The type of fitting to perform. - -Background - Select the background type, see options below. - -Plot Guess - When checked a curve will be created on the plot window based on the bitting - parameters. - -Max Iterations - The maximum number of iterations that can be carried out by the fitting - algorithm (automatically increased when FABADA is enabled). - -StartX & EndX - The range of :math:`x` over which the fitting will be applied (blue lines on - preview plot). -Use FABADA - Select to enable use of the :ref:`FABADA` minimizer when performing the fit. -A0 & A1 (background) - The A0 and A1 parameters as they appear in the LinearBackground fir function, - depending on the Fit Type selected A1 may not be shown. - -Delta Function - Enables use of a delta function. - -Fitting Parameters - Depending on the Fit Type the parameters shown for each of the fit functions - will differ, for more information refer to the documentation pages for the fit - function in question. - -Plot Spectrum - The spectrum shown in the preview plot and will be fitted by running Fit - Single Spectrum. - -Spectra Range - The spectra range over which to perform sequential fitting. - -Plot Output - Allows plotting spectra plots of fitting parameters, the options available - will depend on the type of fit chosen. - -Save Result - If enabled the result will be saved as a NeXus file in the default save - directory. - -Background Options -~~~~~~~~~~~~~~~~~~ - -Fixed Flat - The A0 parameter is applied to all points in the data. - -Fit Flat - Similar to Fixed Flat, however the A0 parameter is treated as an initial guess - and will be included as a parameter to the LinearBackground fit function with - the coefficient of the linear term fixed to 0. - -Fit Linear - The A0 and A1 parameters are used as parameters to the LinearBackground fit - function and the best possible fit will be used as the background. - -Theory -~~~~~~ - -The measured data :math:`I(Q, \omega)` is proportional to the convolution of the -scattering law :math:`S(Q, \omega)` with the resolution function :math:`R(Q, -\omega)` of the spectrometer via :math:`I(Q, \omega) = S(Q, \omega) ⊗ R(Q, -\omega)`. The traditional method of analysis has been to fit the measured -:math:`I(Q, \omega)` with an appropriate set of functions related to the form of -:math:`S(Q, \omega)` predicted by theory. - -* In quasielastic scattering the simplest form is when both the :math:`S(Q, - \omega)` and the :math:`R(Q, \omega)` have the form of a Lorentzian - a - situation which is almost correct for reactor based backscattering - spectrometers such as IN10 & IN16 at ILL. The convolution of two Lorentzians - is itself a Lorentzian so that the spectrum of the measured and resolution - data can both just be fitted with Lorentzians. The broadening of the sample - spectrum is then just the difference of the two widths. -* The next easiest case is when both :math:`S(Q, \omega)` and :math:`R(Q, - \omega)` have a simple functional form and the convolution is also a function - containing the parameters of the :math:`S(Q, \omega)` and R(Q, \omega) functions. - The convoluted function may then be fitted to the data to provide the - parameters. An example would be the case where the :math:`S(Q, \omega)` is a - Lorentzian and the :math:`R(Q, \omega)` is a Gaussian. -* For diffraction, the shape of the peak in time is a convolution of a Gaussian - with a decaying exponential and this function can be used to fit the Bragg - peaks. -* The final case is where :math:`R(Q, \omega)` does not have a simple function - form so that the measured data has to be convoluted numerically with the - :math:`S(Q, \omega)` function to provide an estimate of the sample scattering. - The result is least-squares fitted to the measured data to provide values for - the parameters in the :math:`S(Q, \omega)` function. - -This latter form of peak fitting is provided by SWIFT. It employs a -least-squares algorithm which requires the derivatives of the fitting function -with respect to its parameters in order to be faster and more efficient than -those algorithms which calculate the derivatives numerically. To do this the -assumption is made that the derivative of a convolution is equal to the -convolution of the derivative-as the derivative and the convolution are -performed over different variables (function parameters and energy transfer -respectively) this should be correct. A flat background is subtracted from the -resolution data before the convolution is performed. - -Four types of sample function are available for :math:`S(Q, \omega)`: - -Quasielastic - This is the most common case and applies to both translational (diffusion) and - rotational modes, both of which have the form of a Lorentzian. The fitted - function is a set of Lorentzians centred at the origin in energy transfer. - -Elastic - Comprising a central elastic peak together with a set of quasi-elastic - Lorentzians also centred at the origin. The elastic peak is taken to be the - un-broadened resolution function. - -Shift - A central Lorentzian with pairs of energy shifted Lorentzians. This was - originally used for crystal field splitting data but more recently has been - applied to quantum tunnelling peaks. The fitting function assumes that the - peaks are symmetric about the origin in energy transfer both in position and - width. The widths of the central and side peaks may be different. - -Polymer - A single quasi-elastic peak with 3 different forms of shape. The theory behind - this is described elsewhere [1,2]. Briefly, polymer theory predicts 3 forms - of the :math:`I(Q,t)` in the form of :math:`exp(-at2/b)` where :math:`b` can - be 2, 3 or 4. The Full Width Half-Maximum (FWHM) then has a Q-dependence - (power law) of the form :math:`Qb`. The :math:`I(Q,t)` has been numerically - Fourier transformed into :math:`I(Q, \omega)` and the :math:`I(Q, \omega)` - have been fitted with functions of the form of a modified Lorentzian. These - latter functions are used in the energy fitting procedures. - -References: - -1. J S Higgins, R E Ghosh, W S Howells & G Allen, `JCS Faraday II 73 40 (1977) <http://dx.doi.org/10.1039/F29777300040>`_ -2. J S Higgins, G Allen, R E Ghosh, W S Howells & B Farnoux, `Chem Phys Lett 49 197 (1977) <http://dx.doi.org/10.1016/0009-2614(77)80569-1>`_ - -JumpFit -------- - -.. interface:: Data Analysis - :widget: tabJumpFit - -One of the models used to interpret diffusion is that of jump diffusion in which -it is assumed that an atom remains at a given site for a time :math:`\tau`; and -then moves rapidly, that is, in a time negligible compared to :math:`\tau`; -hence ‘jump’. - -Options -~~~~~~~ - -Sample - A sample workspace created with either ConvFit or Quasi. - -Fit Funcion - Selects the model to be used for fitting. - -Width - Spectrum in the sample workspace to fit. - -QMin & QMax - The Q range to perform fitting within. - -Fitting Parameters - Provides the option to change the defautl fitting parameters passed to the - chosen function. - -Plot Result - Plots the result workspaces. - -Save Result - Saves the result in the default save directory. .. categories:: Interfaces Indirect diff --git a/docs/source/release/v3.13.0/ui.rst b/docs/source/release/v3.13.0/ui.rst index 6dd5dbad52f737b4d3732de3bb3f1e465e3c64dc..72c8cae6678767aa2e2afb01014ccb3ed14542b2 100644 --- a/docs/source/release/v3.13.0/ui.rst +++ b/docs/source/release/v3.13.0/ui.rst @@ -11,7 +11,7 @@ MantidPlot ---------- - MantidPlot's pyplot API has been removed. -- + .. figure:: ../../images/WorkspaceWidgetSortSize.png :class: screenshot :align: right @@ -68,6 +68,7 @@ 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 (as tested on Windows 10): + +------------+-----------+ | Instrument | Speedup | +============+===========+ diff --git a/qt/scientific_interfaces/Indirect/ISISEnergyTransfer.cpp b/qt/scientific_interfaces/Indirect/ISISEnergyTransfer.cpp index 10f1d75a203a5505c378e4337e15cf17f197ba32..679295fc2f5fbc19535cddbdf7f2be1bd4fd24bb 100644 --- a/qt/scientific_interfaces/Indirect/ISISEnergyTransfer.cpp +++ b/qt/scientific_interfaces/Indirect/ISISEnergyTransfer.cpp @@ -1,14 +1,54 @@ #include "ISISEnergyTransfer.h" +#include "../General/UserInputValidator.h" #include "MantidAPI/MatrixWorkspace.h" #include "MantidAPI/WorkspaceGroup.h" -#include "../General/UserInputValidator.h" #include <QFileInfo> using namespace Mantid::API; using MantidQt::API::BatchAlgorithmRunner; +namespace { + +std::string createRangeString(std::size_t from, std::size_t to) { + return std::to_string(from) + "-" + std::to_string(to); +} + +std::string createGroupString(std::size_t start, std::size_t size) { + return createRangeString(start, start + size - 1); +} + +std::string createGroupingString(std::size_t groupSize, + std::size_t numberOfGroups) { + auto groupingString = createRangeString(0, groupSize - 1); + for (auto i = groupSize; i < groupSize * numberOfGroups; i += groupSize) + groupingString += "," + createGroupString(i, groupSize); + return groupingString; +} + +std::string createDetectorGroupingString(std::size_t groupSize, + std::size_t numberOfGroups, + std::size_t numberOfDetectors) { + const auto groupingString = createGroupingString(groupSize, numberOfGroups); + const auto remainder = numberOfDetectors % numberOfGroups; + if (remainder == 0) + return groupingString; + return groupingString + "," + createRangeString(numberOfDetectors - remainder, + numberOfDetectors - 1); +} + +std::string createDetectorGroupingString(std::size_t numberOfDetectors, + std::size_t numberOfGroups) { + const auto groupSize = numberOfDetectors / numberOfGroups; + if (groupSize == 0) + return createRangeString(0, numberOfDetectors - 1); + return createDetectorGroupingString(groupSize, numberOfGroups, + numberOfDetectors); +} + +} // namespace + namespace MantidQt { namespace CustomInterfaces { //---------------------------------------------------------------------------------------------- @@ -457,7 +497,7 @@ ISISEnergyTransfer::createMapFile(const std::string &groupType) { return std::make_pair("File", groupFile.toStdString()); } else if (groupType == "Groups") - return std::make_pair("Custom", createDetectorGroupingString()); + return std::make_pair("Custom", getDetectorGroupingString()); else if (groupType == "Default") return std::make_pair("IPF", ""); else if (groupType == "Custom") @@ -469,25 +509,12 @@ ISISEnergyTransfer::createMapFile(const std::string &groupType) { } } -const std::string ISISEnergyTransfer::createDetectorGroupingString() { - +std::string ISISEnergyTransfer::getDetectorGroupingString() const { const unsigned int nGroups = m_uiForm.spNumberGroups->value(); const unsigned int nSpectra = - m_uiForm.spSpectraMax->value() - m_uiForm.spSpectraMin->value(); - const unsigned int groupSize = nSpectra / nGroups; - auto n = groupSize; - std::stringstream groupingString; - groupingString << "0-" << std::to_string(n); - for (auto i = 1u; i < nGroups; ++i) { - groupingString << ", " << std::to_string(n + 1) << "-"; - n += groupSize; - groupingString << std::to_string(n); - } - if (n != nSpectra) // add remainder as extra group - groupingString << ", " << std::to_string(n + 1) << "-" - << std::to_string(nSpectra); - - return groupingString.str(); + 1 + m_uiForm.spSpectraMax->value() - m_uiForm.spSpectraMin->value(); + return createDetectorGroupingString(static_cast<std::size_t>(nSpectra), + static_cast<std::size_t>(nGroups)); } /** @@ -575,6 +602,7 @@ void ISISEnergyTransfer::plotRaw() { if (m_uiForm.ckBackgroundRemoval->isChecked()) { MatrixWorkspace_sptr tempWs = AnalysisDataService::Instance().retrieveWS<MatrixWorkspace>(name); + const double minBack = tempWs->x(0)[0]; const double maxBack = tempWs->x(0)[tempWs->blocksize()]; @@ -744,4 +772,4 @@ void ISISEnergyTransfer::saveClicked() { } } // namespace CustomInterfaces -} // namespace Mantid +} // namespace MantidQt diff --git a/qt/scientific_interfaces/Indirect/ISISEnergyTransfer.h b/qt/scientific_interfaces/Indirect/ISISEnergyTransfer.h index 35d45304eb7bdabde3c35b33f5b5f02975f5a5a5..0d2e8792ea1a3df7ecceef09993ae9cb1de071b3 100644 --- a/qt/scientific_interfaces/Indirect/ISISEnergyTransfer.h +++ b/qt/scientific_interfaces/Indirect/ISISEnergyTransfer.h @@ -76,7 +76,7 @@ private: std::vector<std::string> m_outputWorkspaces; ///< get a vector of workspaces to plot QString validateDetectorGrouping(); - const std::string createDetectorGroupingString(); + std::string getDetectorGroupingString() const; }; } // namespace CustomInterfaces } // namespace Mantid diff --git a/qt/scientific_interfaces/Indirect/ISISEnergyTransfer.ui b/qt/scientific_interfaces/Indirect/ISISEnergyTransfer.ui index 1585025f02389920ccca2f28dac35263e3588dc2..8fea6d1d7f674e7f19714b8b8f18f00999340697 100644 --- a/qt/scientific_interfaces/Indirect/ISISEnergyTransfer.ui +++ b/qt/scientific_interfaces/Indirect/ISISEnergyTransfer.ui @@ -289,7 +289,11 @@ </widget> </item> <item> - <widget class="QSpinBox" name="spNumberGroups"/> + <widget class="QSpinBox" name="spNumberGroups"> + <property name="minimum"> + <number>1</number> + </property> + </widget> </item> <item> <spacer name="horizontalSpacer_5"> @@ -313,19 +317,19 @@ <property name="enabled"> <bool>true</bool> </property> - <property name="toolTip"> - <string>, allows you to specify additional indices. 1,2,4 will keep indices 1, 2 and 4 only. -: indicates a continuous range of indices. For example, 1:5 is the same as 1,2,3,4,5. -+ sums two spectra together. 7+9 will produce a single spectra listing the sum of 7 and 9, ignoring any others. -- sums a range of spectra together. For example, 3-8 is the same as 3+4+5+6+7+8. - </string> - </property> <property name="maximumSize"> <size> <width>16777215</width> <height>16777215</height> </size> </property> + <property name="toolTip"> + <string>, allows you to specify additional indices. 1,2,4 will keep indices 1, 2 and 4 only. +: indicates a continuous range of indices. For example, 1:5 is the same as 1,2,3,4,5. ++ sums two spectra together. 7+9 will produce a single spectra listing the sum of 7 and 9, ignoring any others. +- sums a range of spectra together. For example, 3-8 is the same as 3+4+5+6+7+8. + </string> + </property> <property name="layoutDirection"> <enum>Qt::LeftToRight</enum> </property> @@ -572,7 +576,16 @@ <property name="spacing"> <number>0</number> </property> - <property name="margin"> + <property name="leftMargin"> + <number>0</number> + </property> + <property name="topMargin"> + <number>0</number> + </property> + <property name="rightMargin"> + <number>0</number> + </property> + <property name="bottomMargin"> <number>0</number> </property> <item> @@ -580,7 +593,16 @@ <property name="spacing"> <number>6</number> </property> - <property name="margin"> + <property name="leftMargin"> + <number>6</number> + </property> + <property name="topMargin"> + <number>6</number> + </property> + <property name="rightMargin"> + <number>6</number> + </property> + <property name="bottomMargin"> <number>6</number> </property> <item> diff --git a/qt/widgets/common/src/FunctionBrowser.cpp b/qt/widgets/common/src/FunctionBrowser.cpp index 77ef44e614d27f6864b7ef851c8fbcc7c3fcebe4..105477a688858e4969e77db88f7b1de8d42012ee 100644 --- a/qt/widgets/common/src/FunctionBrowser.cpp +++ b/qt/widgets/common/src/FunctionBrowser.cpp @@ -1857,14 +1857,15 @@ void FunctionBrowser::removeConstraint() { QtProperty *prop = item->property(); if (!isConstraint(prop)) return; - removeProperty(prop); - if (isLocalParameterProperty(getParentParameterProperty(prop))) { - auto parName = getParameterName(prop); + auto paramProp = getParentParameterProperty(prop); + if (isLocalParameterProperty(paramProp)) { + auto parName = getParameterName(paramProp); checkLocalParameter(parName); auto &localValue = m_localParameterValues[parName][m_currentDataset]; localValue.lowerBound = ""; localValue.upperBound = ""; } + removeProperty(prop); } void FunctionBrowser::updateCurrentFunctionIndex() { diff --git a/qt/widgets/legacyqwt/inc/MantidQtWidgets/LegacyQwt/PreviewPlot.h b/qt/widgets/legacyqwt/inc/MantidQtWidgets/LegacyQwt/PreviewPlot.h index 601dc2e726b5ff56c2a46c357da383d84bde2687..727574dac7b7e9e36ce4656db2239ea94f678606 100644 --- a/qt/widgets/legacyqwt/inc/MantidQtWidgets/LegacyQwt/PreviewPlot.h +++ b/qt/widgets/legacyqwt/inc/MantidQtWidgets/LegacyQwt/PreviewPlot.h @@ -112,6 +112,8 @@ signals: void needToHardReplot(); /// Signals that the axis scale has been changed void axisScaleChanged(); + /// Signals that workspace has been removed + void workspaceRemoved(Mantid::API::MatrixWorkspace_sptr); public slots: void showLegend(bool show); @@ -158,6 +160,7 @@ private slots: void showContextMenu(QPoint position); void handleViewToolSelect(); void handleAxisTypeSelect(); + void removeWorkspace(Mantid::API::MatrixWorkspace_sptr ws); private: Ui::PreviewPlot m_uiForm; diff --git a/qt/widgets/legacyqwt/src/PreviewPlot.cpp b/qt/widgets/legacyqwt/src/PreviewPlot.cpp index 34ce548f09c727e8919c9bdc6901da220309b346..ed88adb5135d12d9b7ab8602eaaae6e73dfea54b 100644 --- a/qt/widgets/legacyqwt/src/PreviewPlot.cpp +++ b/qt/widgets/legacyqwt/src/PreviewPlot.cpp @@ -3,8 +3,8 @@ //------------------------------------------------------ #include "MantidQtWidgets/LegacyQwt/PreviewPlot.h" -#include "MantidAPI/AnalysisDataService.h" #include "MantidAPI/AlgorithmManager.h" +#include "MantidAPI/AnalysisDataService.h" #include <Poco/Notification.h> #include <Poco/NotificationCenter.h> @@ -22,7 +22,7 @@ using namespace Mantid::API; namespace { Mantid::Kernel::Logger g_log("PreviewPlot"); bool isNegative(double v) { return v <= 0.0; } -} +} // namespace PreviewPlot::PreviewPlot(QWidget *parent, bool init) : API::MantidWidget(parent), @@ -122,6 +122,9 @@ PreviewPlot::PreviewPlot(QWidget *parent, bool init) connect(this, SIGNAL(needToReplot()), this, SLOT(replot())); connect(this, SIGNAL(needToHardReplot()), this, SLOT(hardReplot())); + connect(this, SIGNAL(workspaceRemoved(Mantid::API::MatrixWorkspace_sptr)), + this, SLOT(removeWorkspace(Mantid::API::MatrixWorkspace_sptr)), + Qt::QueuedConnection); } /** @@ -562,23 +565,25 @@ void PreviewPlot::hardReplot() { } /** - * Handle a workspace being deleted from ADS. - * - * Removes it from the plot (via removeSpectrum). - * + * Handle a notifcation about a workspace being deleted from ADS. * @param pNf Poco notification */ void PreviewPlot::handleRemoveEvent(WorkspacePreDeleteNotification_ptr pNf) { - MatrixWorkspace_sptr ws = - boost::dynamic_pointer_cast<MatrixWorkspace>(pNf->object()); + auto ws = boost::dynamic_pointer_cast<MatrixWorkspace>(pNf->object()); - // Ignore non matrix worksapces - if (!ws) - return; + if (ws) + // emit a queued signal to the queued slot + emit workspaceRemoved(ws); +} - // Remove the workspace +/** + * Remove the spectrum & replot when a workspace is removed. + * + * @param ws the workspace that is being removed. + */ +void PreviewPlot::removeWorkspace(MatrixWorkspace_sptr ws) { + // Remove the workspace on the main GUI thread removeSpectrum(ws); - emit needToReplot(); } diff --git a/scripts/SANS/sans/gui_logic/presenter/run_tab_presenter.py b/scripts/SANS/sans/gui_logic/presenter/run_tab_presenter.py index db7891cdb74e1bebaf38bcf296456f0312bce587..c91fb093b448e200f3c4c3b868951e7b9f8914c7 100644 --- a/scripts/SANS/sans/gui_logic/presenter/run_tab_presenter.py +++ b/scripts/SANS/sans/gui_logic/presenter/run_tab_presenter.py @@ -964,29 +964,29 @@ class RunTabPresenter(object): row_entry = "SampleScatter:{},ssp:{},SampleTrans:{},stp:{},SampleDirect:{},sdp:{}," \ "CanScatter:{},csp:{},CanTrans:{},ctp:{}," \ "CanDirect:{},cdp:{},OutputName:{},User File:{}," \ - "Sample Thickness:{}".format(sample_scatter, - get_string_period(sample_scatter_period), - sample_transmission, - get_string_period(sample_transmission_period), - sample_direct, - get_string_period(sample_direct_period), - can_scatter, - get_string_period(can_scatter_period), - can_transmission, - get_string_period(can_transmission_period), - can_direct, - get_string_period(can_direct_period), - output_name, user_file, sample_thickness) + "Sample Thickness:{:.2f}".format(sample_scatter, + get_string_period(sample_scatter_period), + sample_transmission, + get_string_period(sample_transmission_period), + sample_direct, + get_string_period(sample_direct_period), + can_scatter, + get_string_period(can_scatter_period), + can_transmission, + get_string_period(can_transmission_period), + can_direct, + get_string_period(can_direct_period), + output_name, user_file, sample_thickness) else: row_entry = "SampleScatter:{},SampleTrans:{},SampleDirect:{}," \ "CanScatter:{},CanTrans:{}," \ - "CanDirect:{},OutputName:{},User File:{},Sample Thickness:{}".format(sample_scatter, - sample_transmission, - sample_direct, - can_scatter, - can_transmission, - can_direct, - output_name, user_file,sample_thickness) + "CanDirect:{},OutputName:{},User File:{},Sample Thickness:{:.2f}".format(sample_scatter, + sample_transmission, + sample_direct, + can_scatter, + can_transmission, + can_direct, + output_name, user_file,sample_thickness) self._view.add_row(row_entry) diff --git a/scripts/test/SANS/gui_logic/run_tab_presenter_test.py b/scripts/test/SANS/gui_logic/run_tab_presenter_test.py index ae753dee818e80f58627094510d0552c0bfe9303..4b995034717047d3c34542e01d3df663a9e0aefb 100644 --- a/scripts/test/SANS/gui_logic/run_tab_presenter_test.py +++ b/scripts/test/SANS/gui_logic/run_tab_presenter_test.py @@ -171,14 +171,15 @@ class RunTabPresenterTest(unittest.TestCase): self.assertEqual(view.add_row.call_count, 2) if use_multi_period: expected_first_row = "SampleScatter:SANS2D00022024,ssp:,SampleTrans:SANS2D00022048,stp:,SampleDirect:SANS2D00022048,sdp:," \ - "CanScatter:,csp:,CanTrans:,ctp:,CanDirect:,cdp:,OutputName:test_file,User File:user_test_file,Sample Thickness:1.0" + "CanScatter:,csp:,CanTrans:,ctp:,CanDirect:,cdp:,OutputName:test_file," \ + "User File:user_test_file,Sample Thickness:1.00" expected_second_row = "SampleScatter:SANS2D00022024,ssp:,SampleTrans:,stp:,SampleDirect:,sdp:," \ - "CanScatter:,csp:,CanTrans:,ctp:,CanDirect:,cdp:,OutputName:test_file2,User File:,Sample Thickness:1.0" + "CanScatter:,csp:,CanTrans:,ctp:,CanDirect:,cdp:,OutputName:test_file2,User File:,Sample Thickness:1.00" else: expected_first_row = "SampleScatter:SANS2D00022024,SampleTrans:SANS2D00022048,SampleDirect:SANS2D00022048," \ - "CanScatter:,CanTrans:,CanDirect:,OutputName:test_file,User File:user_test_file,Sample Thickness:1.0" + "CanScatter:,CanTrans:,CanDirect:,OutputName:test_file,User File:user_test_file,Sample Thickness:1.00" expected_second_row = "SampleScatter:SANS2D00022024,SampleTrans:,SampleDirect:," \ - "CanScatter:,CanTrans:,CanDirect:,OutputName:test_file2,User File:,Sample Thickness:1.0" + "CanScatter:,CanTrans:,CanDirect:,OutputName:test_file2,User File:,Sample Thickness:1.00" calls = [mock.call(expected_first_row), mock.call(expected_second_row)] view.add_row.assert_has_calls(calls) @@ -212,7 +213,7 @@ class RunTabPresenterTest(unittest.TestCase): self.assertEqual(view.set_multi_period_view_mode.call_count, 1) expected_row = "SampleScatter:SANS2D00022024,ssp:3,SampleTrans:,stp:,SampleDirect:,sdp:," \ - "CanScatter:,csp:,CanTrans:,ctp:,CanDirect:,cdp:,OutputName:test_file,User File:,Sample Thickness:1.0" + "CanScatter:,csp:,CanTrans:,ctp:,CanDirect:,cdp:,OutputName:test_file,User File:,Sample Thickness:1.00" calls = [mock.call(expected_row)] view.add_row.assert_has_calls(calls)