source: sasview/src/sas/qtgui/Perspectives/Corfunc/CorfuncPerspective.py @ cadd595a

Last change on this file since cadd595a was cadd595a, checked in by Adam Washington <adam.washington@…>, 7 years ago

Everything into the model

  • Property mode set to 100644
File size: 10.4 KB
Line 
1# global
2import sys
3from PyQt4 import QtCore
4from PyQt4 import QtGui
5from PyQt4 import QtWebKit
6
7from twisted.internet import threads
8from twisted.internet import reactor
9
10# sas-global
11from sas.qtgui.Plotting.PlotterData import Data1D
12import sas.qtgui.Utilities.GuiUtils as GuiUtils
13from sas.sascalc.corfunc.corfunc_calculator import CorfuncCalculator
14
15# local
16from UI.CorfuncPanel import Ui_CorfuncDialog
17# from InvariantDetails import DetailsDialog
18from CorfuncUtils import WIDGETS as W
19
20from matplotlib.backends import qt_compat
21from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas
22from matplotlib.figure import Figure
23
24
25class MyMplCanvas(FigureCanvas):
26    """Ultimately, this is a QWidget (as well as a FigureCanvasAgg, etc.)."""
27    def __init__(self, model, parent=None, width=5, height=4, dpi=100):
28        self.model = model
29        self.fig = Figure(figsize=(width, height), dpi=dpi)
30        self.axes = self.fig.add_subplot(111)
31
32        FigureCanvas.__init__(self, self.fig)
33        # self.reparent(parent, QPoint(0, 0))
34
35        # FigureCanvas.setSizePolicy(self,
36        #                            QSizePolicy.Expanding,
37        #                            QSizePolicy.Expanding)
38        # FigureCanvas.updateGeometry(self)
39
40        self.data = None
41        self.extrap = None
42
43    def drawQSpace(self):
44        self.fig.clf()
45
46        self.qmin = None
47        self.qmax1 = None
48        self.qmax2 = None
49
50        self.axes = self.fig.add_subplot(111)
51        self.axes.set_xscale("log")
52        self.axes.set_yscale("log")
53
54        qmin = float(self.model.item(W.W_QMIN).text())
55        qmax1 = float(self.model.item(W.W_QMAX).text())
56        qmax2 = float(self.model.item(W.W_QCUTOFF).text())
57
58        if self.data:
59            self.axes.plot(self.data.x, self.data.y)
60            self.axes.axvline(qmin)
61            self.axes.axvline(qmax1)
62            self.axes.axvline(qmax2)
63            self.axes.set_xlim(min(self.data.x), max(self.data.x)*1.5-0.5*min(self.data.x))
64        if self.extrap:
65            self.axes.plot(self.extrap.x, self.extrap.y)
66
67        self.draw()
68
69    def drawRealSpace(self):
70        self.fig.clf()
71
72        self.axes = self.fig.add_subplot(111)
73        self.axes.set_xscale("linear")
74        self.axes.set_yscale("linear")
75
76        if self.data:
77            self.axes.plot(self.data.x, self.data.y)
78            self.axes.set_xlim(min(self.data.x), max(self.data.x)/4)
79
80        self.draw()
81
82
83    # def sizeHint(self):
84    #     w, h = self.get_width_height()
85    #     return QSize(w, h)
86
87    # def minimumSizeHint(self):
88    #     return QSize(10, 10)
89
90
91class CorfuncWindow(QtGui.QDialog, Ui_CorfuncDialog):
92    # The controller which is responsible for managing signal slots connections
93    # for the gui and providing an interface to the data model.
94    name = "Corfunc" # For displaying in the combo box
95    #def __init__(self, manager=None, parent=None):
96    def __init__(self, parent=None):
97        super(CorfuncWindow, self).__init__()
98        self.setupUi(self)
99
100        self.setWindowTitle("Corfunc Perspective")
101
102        self.model = QtGui.QStandardItemModel(self)
103        self.communicate = GuiUtils.Communicate()
104        self._calculator = CorfuncCalculator()
105
106        self._canvas = MyMplCanvas(self.model, self)
107        self._realplot = MyMplCanvas(self.model, self)
108        self.verticalLayout_7.insertWidget(0, self._canvas)
109        self.verticalLayout_7.insertWidget(1, self._realplot)
110
111        # Connect buttons to slots.
112        # Needs to be done early so default values propagate properly.
113        self.setupSlots()
114
115        # Set up the model.
116        self.setupModel()
117
118        # Set up the mapper
119        self.setupMapper()
120
121    def setupSlots(self):
122        self.extrapolateBtn.clicked.connect(self.extrapolate)
123        self.transformBtn.clicked.connect(self.transform)
124
125        self.calculateBgBtn.clicked.connect(self.calculateBackground)
126
127        self.model.itemChanged.connect(self.modelChanged)
128
129    def setupModel(self):
130        self.model.setItem(W.W_QMIN,
131                           QtGui.QStandardItem("0.01"))
132        self.model.setItem(W.W_QMAX,
133                           QtGui.QStandardItem("0.20"))
134        self.model.setItem(W.W_QCUTOFF,
135                           QtGui.QStandardItem("0.22"))
136        self.model.setItem(W.W_BACKGROUND,
137                           QtGui.QStandardItem("0"))
138        self.model.setItem(W.W_TRANSFORM,
139                           QtGui.QStandardItem("Fourier"))
140        self.model.setItem(W.W_GUINIERA,
141                           QtGui.QStandardItem("0.0"))
142        self.model.setItem(W.W_GUINIERB,
143                           QtGui.QStandardItem("0.0"))
144        self.model.setItem(W.W_PORODK,
145                           QtGui.QStandardItem("0.0"))
146        self.model.setItem(W.W_PORODSIGMA,
147                           QtGui.QStandardItem("0.0"))
148        self.model.setItem(W.W_CORETHICK, QtGui.QStandardItem(str(0)))
149        self.model.setItem(W.W_INTTHICK, QtGui.QStandardItem(str(0)))
150        self.model.setItem(W.W_HARDBLOCK, QtGui.QStandardItem(str(0)))
151        self.model.setItem(W.W_CRYSTAL, QtGui.QStandardItem(str(0)))
152        self.model.setItem(W.W_POLY, QtGui.QStandardItem(str(0)))
153        self.model.setItem(W.W_PERIOD, QtGui.QStandardItem(str(0)))
154
155    def modelChanged(self, item):
156        if item.row() == W.W_QMIN:
157            value = float(self.model.item(W.W_QMIN).text())
158            self._canvas.qmin = value
159        elif item.row() == W.W_QMAX or item.row() == W.W_QCUTOFF:
160            a = float(self.model.item(W.W_QMAX).text())
161            b = float(self.model.item(W.W_QCUTOFF).text())
162            self._canvas.qmax1 = a
163            self._canvas.qmax2 = b
164        else:
165            print("{} Changed".format(item))
166
167        self.mapper.toFirst()
168        self._canvas.drawQSpace()
169
170    def _update_calculator(self):
171        self._calculator.lowerq = float(self.model.item(W.W_QMIN).text())
172        qmax1 = float(self.model.item(W.W_QMAX).text())
173        qmax2 = float(self.model.item(W.W_QCUTOFF).text())
174        self._calculator.upperq = (qmax1, qmax2)
175        self._calculator.background = float(self.model.item(W.W_BACKGROUND).text())
176
177    def extrapolate(self):
178        self._update_calculator()
179        params, extrapolation = self._calculator.compute_extrapolation()
180
181        self.model.setItem(W.W_GUINIERA, QtGui.QStandardItem(str(params['A'])))
182        self.model.setItem(W.W_GUINIERB, QtGui.QStandardItem(str(params['B'])))
183        self.model.setItem(W.W_PORODK, QtGui.QStandardItem(str(params['K'])))
184        self.model.setItem(W.W_PORODSIGMA, QtGui.QStandardItem(str(params['sigma'])))
185
186        self._canvas.extrap = extrapolation
187        self._canvas.drawQSpace()
188
189
190    def transform(self):
191        if self.fourierBtn.isChecked():
192            method = "fourier"
193        elif self.hilbertBtn.isChecked():
194            method = "hilbert"
195
196        extrap = self._canvas.extrap
197        bg = float(self.model.item(W.W_BACKGROUND).text())
198        def updatefn(*args, **kwargs):
199            pass
200
201        def completefn(transform):
202            self._realplot.data = transform
203            self._realplot.drawRealSpace()
204            params = self._calculator.extract_parameters(transform)
205            self.model.setItem(W.W_CORETHICK, QtGui.QStandardItem(str(params['d0'])))
206            self.model.setItem(W.W_INTTHICK, QtGui.QStandardItem(str(params['dtr'])))
207            self.model.setItem(W.W_HARDBLOCK, QtGui.QStandardItem(str(params['Lc'])))
208            self.model.setItem(W.W_CRYSTAL, QtGui.QStandardItem(str(params['fill'])))
209            self.model.setItem(W.W_POLY, QtGui.QStandardItem(str(params['A'])))
210            self.model.setItem(W.W_PERIOD, QtGui.QStandardItem(str(params['max'])))
211
212        self._update_calculator()
213        self._calculator.compute_transform(extrap, method, bg, completefn, updatefn)
214
215
216    def setupMapper(self):
217        self.mapper = QtGui.QDataWidgetMapper(self)
218        self.mapper.setOrientation(QtCore.Qt.Vertical)
219        self.mapper.setModel(self.model)
220
221        self.mapper.addMapping(self.qMin, W.W_QMIN)
222        self.mapper.addMapping(self.qMax1, W.W_QMAX)
223        self.mapper.addMapping(self.qMax2, W.W_QCUTOFF)
224        self.mapper.addMapping(self.bg, W.W_BACKGROUND)
225
226        self.mapper.addMapping(self.guinierA, W.W_GUINIERA)
227        self.mapper.addMapping(self.guinierB, W.W_GUINIERB)
228        self.mapper.addMapping(self.porodK, W.W_PORODK)
229        self.mapper.addMapping(self.porodSigma, W.W_PORODSIGMA)
230
231        self.mapper.addMapping(self.avgCoreThick, W.W_CORETHICK)
232        self.mapper.addMapping(self.avgIntThick, W.W_INTTHICK)
233        self.mapper.addMapping(self.avgHardBlock, W.W_HARDBLOCK)
234        self.mapper.addMapping(self.polydisp, W.W_POLY)
235        self.mapper.addMapping(self.longPeriod, W.W_PERIOD)
236        self.mapper.addMapping(self.localCrystal, W.W_CRYSTAL)
237
238        self.mapper.toFirst()
239
240    def calculateBackground(self):
241        self._update_calculator()
242        bg = self._calculator.compute_background()
243        temp = QtGui.QStandardItem(str(bg))
244        self.model.setItem(W.W_BACKGROUND, temp)
245
246    def allowBatch(self):
247        """
248        We cannot perform corfunc analysis in batch at this time.
249        """
250        return False
251
252    def setData(self, data_item, is_batch=False):
253        """
254        Obtain a QStandardItem object and dissect it to get Data1D/2D
255        Pass it over to the calculator
256        """
257        if not isinstance(data_item, list):
258            msg = "Incorrect type passed to the Corfunc Perpsective"
259            raise AttributeError(msg)
260
261        if not isinstance(data_item[0], QtGui.QStandardItem):
262            msg = "Incorrect type passed to the Corfunc Perspective"
263            raise AttributeError(msg)
264
265        self._model_item = data_item[0]
266        data = GuiUtils.dataFromItem(self._model_item)
267        self._calculator.set_data(data)
268
269        self._canvas.data = data
270        self._canvas.drawQSpace()
271
272        # self.model.item(WIDGETS.W_FILENAME).setData(QtCoreQVariant(self._model_item.text()))
273
274    def setClosable(self, value=True):
275        """
276        Allow outsiders close this widget
277        """
278        assert isinstance(value, bool)
279
280        self._allow_close = value
281
282
283if __name__ == "__main__":
284    app = QtGui.QApplication([])
285    import qt4reactor
286    # qt4reactor.install()
287    # DO NOT move the following import to the top!
288    # (unless you know what you're doing)
289    from twisted.internet import reactor
290    dlg = CorfuncWindow(reactor)
291    print(dlg)
292    dlg.show()
293    # print(reactor)
294    # reactor.run()
295    sys.exit(app.exec_())
Note: See TracBrowser for help on using the repository browser.