source: sasview/src/sas/qtgui/Perspectives/Inversion/DMaxExplorerWidget.py @ c6fb57c

ESS_GUIESS_GUI_DocsESS_GUI_batch_fittingESS_GUI_bumps_abstractionESS_GUI_iss1116ESS_GUI_iss879ESS_GUI_iss959ESS_GUI_openclESS_GUI_orderingESS_GUI_sync_sascalc
Last change on this file since c6fb57c was 0261bc1, checked in by Piotr Rozyczko <rozyczko@…>, 7 years ago

Added unit tests for recent functionality

  • Property mode set to 100644
File size: 5.0 KB
Line 
1# -*- coding: utf-8 -*-
2"""
3Dialog panel to explore the P(r) inversion results for a range
4of D_max value. User picks a number of points and a range of
5distances, then can toggle between inversion outputs and see
6their distribution as a function of D_max.
7"""
8
9# global
10import sys
11import os
12import logging
13import numpy as np
14from PyQt5 import QtCore
15from PyQt5 import QtGui
16from PyQt5 import QtWidgets
17
18from twisted.internet import threads
19
20# sas-global
21from sas.qtgui.Plotting.PlotterData import Data1D
22from sas.qtgui.Plotting.Plotter import PlotterWidget
23import sas.qtgui.Utilities.GuiUtils as GuiUtils
24
25# local
26from .UI.DMaxExplorer import Ui_DmaxExplorer
27
28logger = logging.getLogger(__name__)
29
30from sas.qtgui.Utilities.GuiUtils import enum
31
32W = enum( 'NPTS',           #0
33          'DMIN',               #1
34          'DMAX',               #2
35          'VARIABLE',         #3
36)
37
38class DmaxWindow(QtWidgets.QDialog, Ui_DmaxExplorer):
39    # The controller which is responsible for managing signal slots connections
40    # for the gui and providing an interface to the data model.
41    name = "Dmax Explorer"  # For displaying in the combo box
42
43    def __init__(self, pr_state, nfunc, parent=None):
44        super(DmaxWindow, self).__init__()
45        self.setupUi(self)
46
47        self.setWindowTitle("Dₐₓ Explorer")
48
49        self.pr_state = pr_state
50        self.nfunc = nfunc
51        self.communicator = GuiUtils.Communicate()
52
53        self.plot = PlotterWidget(self, self)
54        self.hasPlot = None
55        self.verticalLayout.insertWidget(0, self.plot)
56
57        # Let's choose the Standard Item Model.
58        self.model = QtGui.QStandardItemModel(self)
59        self.mapper = None
60
61        # # Connect buttons to slots.
62        # # Needs to be done early so default values propagate properly.
63        self.setupSlots()
64
65        # Set up the model.
66        self.setupModel()
67
68        # # Set up the mapper
69        self.setupMapper()
70
71    def setupSlots(self):
72        self.closeButton.clicked.connect(self.close)
73
74        self.model.itemChanged.connect(self.modelChanged)
75
76    def setupModel(self):
77        self.model.setItem(W.NPTS, QtGui.QStandardItem(str(self.nfunc)))
78        self.model.setItem(W.DMIN, QtGui.QStandardItem(str(0.9*self.pr_state.d_max)))
79        self.model.setItem(W.DMAX, QtGui.QStandardItem(str(1.1*self.pr_state.d_max)))
80        self.model.setItem(W.VARIABLE, QtGui.QStandardItem( "χ²/dof"))
81
82    def setupMapper(self):
83        self.mapper = QtWidgets.QDataWidgetMapper(self)
84        self.mapper.setOrientation(QtCore.Qt.Vertical)
85        self.mapper.setModel(self.model)
86
87        self.mapper.addMapping(self.Npts, W.NPTS)
88        self.mapper.addMapping(self.minDist, W.DMIN)
89        self.mapper.addMapping(self.maxDist, W.DMAX)
90        self.mapper.addMapping(self.dependentVariable, W.VARIABLE)
91
92        self.mapper.toFirst()
93
94    def modelChanged(self, item):
95        if not self.mapper:
96            return
97
98        iq0 = []
99        rg = []
100        pos = []
101        pos_err = []
102        osc = []
103        bck = []
104        chi2 = []
105
106        xs = np.linspace(float(self.model.item(W.DMIN).text()),
107                         float(self.model.item(W.DMAX).text()),
108                         float(self.model.item(W.NPTS).text()))
109
110        original = self.pr_state.d_max
111        for x in xs:
112            self.pr_state.d_max = x
113            try:
114                out, cov = self.pr_state.invert(self.pr_state.nfunc)
115
116                iq0.append(self.pr_state.iq0(out))
117                rg.append(self.pr_state.rg(out))
118                pos.append(self.pr_state.get_positive(out))
119                pos_err.append(self.pr_state.get_pos_err(out, cov))
120                osc.append(self.pr_state.oscillations(out))
121                bck.append(self.pr_state.background)
122                chi2.append(self.pr_state.chi2)
123            except:
124                # This inversion failed, skip this D_max value
125                msg = "ExploreDialog: inversion failed "
126                msg += "for D_max=%s\n%s" % (str(x), sys.exc_info()[1])
127                print(msg)
128                logger.error(msg)
129
130        #Return the invertor to its original state
131        self.pr_state.d_max = original
132        try:
133            self.pr_state.invert(self.nfunc)
134        except RuntimeError as ex:
135            msg = "ExploreDialog: inversion failed "
136            msg += "for D_max=%s\n%s" % (str(x), sys.exc_info()[1])
137            print(msg)
138            logger.error(msg)
139
140        plotter = str(self.model.item(W.VARIABLE).text())
141        if plotter == "χ²/dof":
142            ys = chi2
143        elif plotter == "I(Q=0)":
144            ys = iq0
145        elif plotter == "Rg":
146            ys = rg
147        elif plotter == "Oscillation parameter":
148            ys = osc
149        elif plotter == "Background":
150            ys = bck
151        elif plotter == "Positive Fraction":
152            ys = pos
153        else:
154            ys = pos_err
155
156        data = Data1D(xs, ys)
157        if self.hasPlot:
158            self.plot.removePlot(None)
159        self.hasPlot = True
160        self.plot.plot(data=data, marker="-")
Note: See TracBrowser for help on using the repository browser.