Source code for sas.qtgui.Perspectives.Inversion.InversionLogic

import math
import logging
import numpy as np

from sas.qtgui.Plotting.PlotterData import Data1D

PR_FIT_LABEL = r"$P_{fit}(r)$"
PR_LOADED_LABEL = r"$P_{loaded}(r)$"
IQ_DATA_LABEL = r"$I_{obs}(q)$"
IQ_FIT_LABEL = r"$I_{fit}(q)$"
IQ_SMEARED_LABEL = r"$I_{smeared}(q)$"
GROUP_ID_IQ_DATA = r"$I_{obs}(q)$"
GROUP_ID_PR_FIT = r"$P_{fit}(r)$"
PR_PLOT_PTS = 51

logger = logging.getLogger(__name__)


[docs]class InversionLogic(object): """ All the data-related logic. This class deals exclusively with Data1D/2D No QStandardModelIndex here. """
[docs] def __init__(self, data=None): self._data = data self.data_is_loaded = False if data is not None: self.data_is_loaded = True
@property def data(self): return self._data @data.setter def data(self, value): """ data setter """ self._data = value self.data_is_loaded = (self._data is not None)
[docs] def isLoadedData(self): """ accessor """ return self.data_is_loaded
[docs] def new1DPlot(self, out, pr, q=None): """ Create a new 1D data instance based on fitting results """ qtemp = pr.x if q is not None: qtemp = q # Make a plot maxq = max(qtemp) minq = min(qtemp) # Check for user min/max if pr.q_min is not None and maxq >= pr.q_min >= minq: minq = pr.q_min if pr.q_max is not None and maxq >= pr.q_max >= minq: maxq = pr.q_max x = np.arange(minq, maxq, maxq / 301.0) # Vectorised iq. y = pr.iq(out, x) err = np.sqrt(np.abs(y)) index = np.isnan(y) if index.any(): y[index] = err[index] = 1.0 logger.info("Could not compute I(q) for q =", list((x[index]))) new_plot = Data1D(x, y) new_plot.name = IQ_FIT_LABEL + f"[{self._data.name}]" new_plot.xaxis("\\rm{Q}", 'A^{-1}') new_plot.yaxis("\\rm{Intensity} ", "cm^{-1}") title = "I(q)" new_plot.title = title # If we have a group ID, use it if 'plot_group_id' in pr.info: new_plot.group_id = pr.info["plot_group_id"] new_plot.id = IQ_FIT_LABEL # If we have used slit smearing, plot the smeared I(q) too if pr.slit_width > 0 or pr.slit_height > 0: x = np.arange(minq, maxq, maxq / 301.0) # Vectorised iq_smeared. y = pr.get_iq_smeared(out, x) err = np.sqrt(np.abs(y)) index = np.isnan(y) if index.any(): y[index] = err[index] = 1.0 logger.info("Could not compute smeared I(q) for q =", list((x[index]))) new_plot = Data1D(x, y) new_plot.name = IQ_SMEARED_LABEL new_plot.xaxis("\\rm{Q}", 'A^{-1}') new_plot.yaxis("\\rm{Intensity} ", "cm^{-1}") # If we have a group ID, use it if 'plot_group_id' in pr.info: new_plot.group_id = pr.info["plot_group_id"] new_plot.id = IQ_SMEARED_LABEL new_plot.title = title new_plot.symbol = 'Line' new_plot.hide_error = True return new_plot
[docs] def newPRPlot(self, out, pr, cov=None): """ """ # Show P(r) x = np.arange(0.0, pr.d_max, pr.d_max / PR_PLOT_PTS) if cov is None: y = pr.pr(out, x) new_plot = Data1D(x, y) else: (y, dy) = pr.pr_err(out, cov, x) new_plot = Data1D(x, y, dy=dy) new_plot.name = PR_FIT_LABEL + f"[{self._data.name}]" new_plot.xaxis("\\rm{r}", 'A') new_plot.yaxis("\\rm{P(r)} ", "cm^{-3}") new_plot.title = "P(r) fit" new_plot.id = PR_FIT_LABEL new_plot.xtransform = "x" new_plot.ytransform = "y" new_plot.group_id = GROUP_ID_PR_FIT return new_plot
[docs] def add_errors(self, sigma=0.05): """ Adds errors to data set is they are not available. Uses $\Delta y = \sigma | y |$. """ self._data.dy = sigma * np.fabs(self._data.y)
[docs] def computeDataRange(self): """ Wrapper for calculating the data range based on local dataset """ return self.computeRangeFromData(self.data)
[docs] def computeRangeFromData(self, data): """ Compute the minimum and the maximum range of the data return the npts contains in data """ qmin, qmax = None, None if isinstance(data, Data1D): try: qmin = min(data.x) qmax = max(data.x) except (ValueError, TypeError): msg = "Unable to find min/max/length of \n data named %s" % \ self.data.filename raise ValueError(msg) else: qmin = 0 try: x = max(np.fabs(data.xmin), np.fabs(data.xmax)) y = max(np.fabs(data.ymin), np.fabs(data.ymax)) except (ValueError, TypeError): msg = "Unable to find min/max of \n data named %s" % \ self.data.filename raise ValueError(msg) qmax = np.sqrt(x * x + y * y) return qmin, qmax