source: sasview/src/sas/qtgui/Perspectives/Invariant/InvariantPerspective.py @ 29eb947

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 29eb947 was 0979dfb, checked in by Piotr Rozyczko <rozyczko@…>, 7 years ago

redesigned most important buttons to make the workflow more obvious

  • Property mode set to 100644
File size: 23.8 KB
Line 
1# global
2import sys
3import os
4from PyQt4 import QtCore
5from PyQt4 import QtGui
6from PyQt4 import QtWebKit
7
8from twisted.internet import threads
9from twisted.internet import reactor
10
11# sas-global
12from sas.sascalc.invariant import invariant
13from sas.sasgui.guiframe.dataFitting import Data1D
14#import GuiUtils
15import sas.qtgui.GuiUtils as GuiUtils
16
17# local
18from UI.TabbedInvariantUI import Ui_tabbedInvariantUI
19from InvariantDetails import DetailsDialog
20from InvariantUtils import WIDGETS
21
22# The minimum q-value to be used when extrapolating
23Q_MINIMUM = 1e-5
24# The maximum q-value to be used when extrapolating
25Q_MAXIMUM = 10
26# the ratio of maximum q value/(qmax of data) to plot the theory data
27Q_MAXIMUM_PLOT = 3
28
29
30class MyModel(object):
31    def __init__(self):
32        self._model = QtGui.QStandardItemModel(self)
33
34    def addItem(self, item):
35        item = QtGui.QStandardItem(str(item))
36        self._model.appendRow(item)
37
38class InvariantWindow(QtGui.QDialog, Ui_tabbedInvariantUI):
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 = "Invariant" # For displaying in the combo box
42    #def __init__(self, manager=None, parent=None):
43    def __init__(self, parent=None):
44        #super(InvariantWindow, self).__init__(parent)
45        super(InvariantWindow, self).__init__()
46        self.setupUi(self)
47
48        self.setWindowTitle("Invariant Perspective")
49
50        # initial input params
51        self._background = 0.0
52        self._scale = 1.0
53        self._contrast = 1.0
54        self._porod = 1.0
55        self._npoints_low = 10
56        self._npoints_high = 10
57        self._power_low = 4
58
59        self._manager = parent
60        #self._manager = manager
61        self._reactor = self._manager.reactor()
62        self._model_item = QtGui.QStandardItem()
63
64        self._helpView = QtWebKit.QWebView()
65        self.detailsDialog = DetailsDialog(self)
66
67        self._low_extrapolate = False
68        self._low_guinier  = True
69        self._low_fit  = True
70        self._high_extrapolate = False
71        self._high_power_value  = False
72
73        # no reason to have this widget resizable
74        self.setFixedSize(self.minimumSizeHint())
75
76        self.communicate = GuiUtils.Communicate()
77
78        self._data = None
79        self._path = ""
80
81        # Mask file selector
82        ###################################################
83        #self._path = "cyl_400_20.txt"
84        #from sas.sascalc.dataloader.loader import  Loader
85        #loader = Loader()
86        #try:
87        #    self._data = loader.load(self._path)
88        #except:
89        #    raise
90        ###################################################
91
92        self.lineEdit_8.setText(str(Q_MINIMUM))
93        self.lineEdit_9.setText(str(Q_MAXIMUM))
94
95        # Let's choose the Standard Item Model.
96        self.model = QtGui.QStandardItemModel(self)
97
98        # Connect buttons to slots.
99        # Needs to be done early so default values propagate properly.
100        self.setupSlots()
101
102        # Set up the model.
103        self.setupModel()
104
105        # Set up the mapper
106        self.setupMapper()
107
108    #def closeEvent(self, event):
109    #    """
110    #    Overwrite the default close method of QWidget
111    #    """
112    #    # No close on perspectives - one must always be active.
113    #    event.ignore()
114
115    def communicator(self):
116        """ Getter for the communicator """
117        return self.communicate
118
119    def updateFromModel(self):
120        """
121        update the globals based on the data in the model
122        """
123        self._background = float(self.model.item(WIDGETS.W_BACKGROUND).text())
124        self._contrast   = float(self.model.item(WIDGETS.W_CONTRAST).text())
125        self._scale      = float(self.model.item(WIDGETS.W_SCALE).text())
126
127        # High extrapolate
128        self._low_extrapolate = ( str(self.model.item(WIDGETS.W_ENABLE_LOWQ).text()) == 'true')
129        self._low_points = float(self.model.item(WIDGETS.W_NPTS_LOWQ).text())
130        self._low_guinier  = ( str(self.model.item(WIDGETS.W_LOWQ_GUINIER).text()) == 'true')
131        self._low_fit  = ( str(self.model.item(WIDGETS.W_LOWQ_FIT).text()) == 'true')
132        self._low_power_value  = float(self.model.item(WIDGETS.W_LOWQ_POWER_VALUE).text())
133
134        # High extrapolating
135        self._high_extrapolate = ( str(self.model.item(WIDGETS.W_ENABLE_HIGHQ).text()) == 'true')
136        self._high_points  = float(self.model.item(WIDGETS.W_NPTS_HIGHQ).text())
137        self._high_fit  = ( str(self.model.item(WIDGETS.W_HIGHQ_FIT).text()) == 'true')
138        self._high_power_value  = float(self.model.item(WIDGETS.W_HIGHQ_POWER_VALUE).text())
139
140    def calculateInvariant(self):
141        """
142        Use twisted to thread the calculations away.
143        """
144        # Find out if extrapolation needs to be used.
145        extrapolation = None
146        if self._low_extrapolate  and not self._high_extrapolate:
147            extrapolation = "low"
148        elif not self._low_extrapolate  and self._high_extrapolate:
149            extrapolation = "high"
150        elif self._low_extrapolate and self._high_extrapolate:
151            extrapolation = "both"
152        try:
153            # modify the Calculate button to indicate background process
154            self.pushButton.setText("Calculating...")
155            self.pushButton.setEnabled(False)
156            self.style = self.pushButton.styleSheet()
157            self.pushButton.setStyleSheet("background-color: rgb(255, 255, 0); color: rgb(0, 0, 0)")
158            # Send the calculations to separate thread.
159            d = threads.deferToThread(self.calculateThread, extrapolation)
160            # Add deferred callback for call return
161            d.addCallback(self.plotResult)
162        except Exception as ex:
163            # Set the button back to available
164            self.pushButton.setEnabled(True)
165            self.pushButton.setText("Calculate")
166            self.pushButton.setStyleSheet(self.style)
167
168
169    def plotResult(self, model):
170        """
171        """
172        self.model = model
173        self.mapper.toFirst()
174
175        # Set the button back to available
176        self.pushButton.setEnabled(True)
177        self.pushButton.setText("Calculate")
178        self.pushButton.setStyleSheet(self.style)
179
180        # Send the modified model item to DE for keeping in the model
181        self.communicate.updateModelFromPerspectiveSignal.emit(self._model_item)
182
183
184    def calculateThread(self, extrapolation):
185        """
186        Perform Invariant calculations.
187
188        TODO: Create a dictionary of results to be sent to DE on completion.
189        """
190        self.updateFromModel()
191
192        qstar_low = 0.0
193        qstar_low_err = 0.0
194        qstar_high = 0.0
195        qstar_high_err = 0.0
196        qstar_total = 0.0
197        qstar_total_low_err = 0.0
198
199        # Prepare the invariant object
200        inv = invariant.InvariantCalculator(data=self._data,
201                                            background = self._background,
202                                            scale = self._scale)
203
204        if self._low_extrapolate:
205            function_low = "power_law"
206            if self._low_guinier:
207                function_low = "guinier"
208            if self._low_fit:
209                self._low_power_value = None
210            inv.set_extrapolation(range="low",
211                                  npts=self._low_points,
212                                  function=function_low,
213                                  power=self._low_power_value)
214
215        if self._high_extrapolate:
216            function_low = "power_law"
217            inv.set_extrapolation(range="high",
218                                  npts=self._high_points,
219                                  function=function_low,
220                                  power=self._low_power_value)
221
222        #Compute invariant
223        # TODO: proper exception handling and logic -
224        # display info, update lineedits, don't run extrapolations etc.
225        calculation_failed = False
226        try:
227            qstar_total, qstar_total_error         = inv.get_qstar_with_error()
228        except Exception as ex:
229            calculation_failed = True
230            # Display relevant information
231            item = QtGui.QStandardItem("ERROR")
232            self.model.setItem(WIDGETS.W_INVARIANT, item)
233            item = QtGui.QStandardItem("ERROR")
234            self.model.setItem(WIDGETS.W_INVARIANT_ERR, item)
235        try:
236            volume_fraction, volume_fraction_error = \
237                inv.get_volume_fraction_with_error(self._contrast)
238        except Exception as ex:
239            calculation_failed = True
240            # Display relevant information
241            item = QtGui.QStandardItem("ERROR")
242            self.model.setItem(WIDGETS.W_VOLUME_FRACTION, item)
243            item = QtGui.QStandardItem("ERROR")
244            self.model.setItem(WIDGETS.W_VOLUME_FRACTION_ERR, item)
245        try:
246            surface, surface_error = \
247                inv.get_surface_with_error(self._contrast, self._porod)
248        except Exception as ex:
249            calculation_failed = True
250            # Display relevant information
251            item = QtGui.QStandardItem("ERROR")
252            self.model.setItem(WIDGETS.W_SPECIFIC_SURFACE, item)
253            item = QtGui.QStandardItem("ERROR")
254            self.model.setItem(WIDGETS.W_SPECIFIC_SURFACE_ERR, item)
255
256        if(calculation_failed):
257            # TODO: NOTIFY THE GUI MANAGER!!
258            self.mapper.toFirst()
259            return self.model
260
261        if self._low_extrapolate:
262            # for presentation in InvariantDetails
263            qstar_low, qstar_low_err = inv.get_qstar_low()
264            extrapolated_data = inv.get_extra_data_low(self._low_points)
265            power_low = inv.get_extrapolation_power(range='low')
266
267            #inv.data = extrapolated_data
268            #qstar_total, qstar_total_error = inv.get_qstar_with_error()
269
270            # Plot the chart
271            title = "Low-Q extrapolation"
272
273            # Convert the data into plottable
274            extrapolated_data = self._manager.createGuiData(extrapolated_data)
275            extrapolated_data.name = title
276            extrapolated_data.title = title
277
278            # Add the plot to the model item
279            # variant_item = QtCore.QVariant(self._plotter)
280            variant_item = QtCore.QVariant(extrapolated_data)
281
282            # This needs to run in the main thread
283            reactor.callFromThread(GuiUtils.updateModelItemWithPlot,
284                    self._model_item, variant_item, title)
285
286        if self._high_extrapolate:
287            # for presentation in InvariantDetails
288            qmax_plot = Q_MAXIMUM_PLOT * max(self._data.x)
289            if qmax_plot > Q_MAXIMUM:
290                qmax_plot = Q_MAXIMUM
291            qstar_high, qstar_high_err = inv.get_qstar_high()
292            power_high = inv.get_extrapolation_power(range='high')
293            high_out_data = inv.get_extra_data_high(q_end=qmax_plot, npts=500)
294
295            # Plot the chart
296            title = "High-Q extrapolation"
297
298            # Convert the data into plottable
299            high_out_data = self._manager.createGuiData(high_out_data)
300            high_out_data.name = title
301            high_out_data.title = title
302
303            # Add the plot to the model item
304            # variant_item = QtCore.QVariant(self._plotter)
305            variant_item = QtCore.QVariant(high_out_data)
306            # This needs to run in the main thread
307            reactor.callFromThread(GuiUtils.updateModelItemWithPlot,
308                    self._model_item, variant_item, title)
309
310        item = QtGui.QStandardItem(str(float('%.5g'% volume_fraction)))
311        self.model.setItem(WIDGETS.W_VOLUME_FRACTION, item)
312        item = QtGui.QStandardItem(str(float('%.5g'% volume_fraction_error)))
313        self.model.setItem(WIDGETS.W_VOLUME_FRACTION_ERR, item)
314        item = QtGui.QStandardItem(str(float('%.5g'% surface)))
315        self.model.setItem(WIDGETS.W_SPECIFIC_SURFACE, item)
316        item = QtGui.QStandardItem(str(float('%.5g'% surface_error)))
317        self.model.setItem(WIDGETS.W_SPECIFIC_SURFACE_ERR, item)
318        item = QtGui.QStandardItem(str(float('%.5g'% qstar_total)))
319        self.model.setItem(WIDGETS.W_INVARIANT, item)
320        item = QtGui.QStandardItem(str(float('%.5g'% qstar_total_error)))
321        self.model.setItem(WIDGETS.W_INVARIANT_ERR, item)
322
323        #item = QtGui.QStandardItem(str(float('%.5g'% qstar_total)))
324        #self.model.setItem(WIDGETS.D_TOTAL_QSTAR, item)
325        #item = QtGui.QStandardItem(str(float('%.5g'% qstar_total_err)))
326        #self.model.setItem(WIDGETS.D_TOTAL_QSTAR_ERR, item)
327        item = QtGui.QStandardItem(str(float('%.5g'% qstar_low)))
328        self.model.setItem(WIDGETS.D_LOW_QSTAR, item)
329        item = QtGui.QStandardItem(str(float('%.5g'% qstar_low_err)))
330        self.model.setItem(WIDGETS.D_LOW_QSTAR_ERR, item)
331        item = QtGui.QStandardItem(str(float('%.5g'% qstar_high)))
332        self.model.setItem(WIDGETS.D_HIGH_QSTAR, item)
333        item = QtGui.QStandardItem(str(float('%.5g'% qstar_high_err)))
334        self.model.setItem(WIDGETS.D_HIGH_QSTAR_ERR, item)
335
336        self.mapper.toFirst()
337
338        return self.model
339               
340    def title(self):
341        """
342        Perspective name
343        """
344        return "Invariant panel"
345
346    def status(self):
347        """
348        """
349        self.detailsDialog.setModel(self.model)
350        self.detailsDialog.showDialog()
351
352    def help(self):
353        """
354        """
355        _TreeLocation = self._manager.HELP_DIRECTORY_LOCATION + \
356            "/user/sasgui/perspectives/invariant/invariant_help.html"
357        self._helpView.load(QtCore.QUrl(_TreeLocation))
358        self._helpView.show()
359
360    def setupSlots(self):
361        self.pushButton.clicked.connect(self.calculateInvariant)
362        self.pushButton_2.clicked.connect(self.status)
363        self.pushButton_3.clicked.connect(self.help)
364
365        self.radioButton.toggled.connect(self.lowGuinierAndPowerToggle)
366        self.radioButton_8.toggled.connect(self.hiFitAndFixToggle)
367
368        self.radioButton_3.toggled.connect(self.lowFitAndFixToggle)
369
370        # Bug workaround for QDataWidgetMapper() not reacting to checkbox clicks.
371        # https://bugreports.qt.io/browse/QTBUG-1818
372        self.checkBox.clicked.connect(self.setFocus)
373        self.checkBox_2.clicked.connect(self.setFocus)
374
375        self.model.itemChanged.connect(self.modelChanged)
376
377    def modelChanged(self, item):
378        """
379        """
380        if item.row() == WIDGETS.W_ENABLE_LOWQ:
381            toggle = (str(item.text()) == 'true')
382            self._low_extrapolate = toggle
383            self.lowQToggle(toggle)
384        elif item.row() == WIDGETS.W_ENABLE_HIGHQ:
385            toggle = (str(item.text()) == 'true')
386            self._high_extrapolate = toggle
387            self.highQToggle(toggle)
388       
389    def lowGuinierAndPowerToggle(self, toggle):
390        """
391        """
392        self._low_guinier = toggle
393        toggle = not toggle
394        self.lineEdit_11.setEnabled(toggle)
395        self.radioButton_3.setEnabled(toggle)
396        self.radioButton_4.setEnabled(toggle)
397        self.lineEdit_11.setEnabled(toggle and (not self._low_fit))
398
399    def lowFitAndFixToggle(self, toggle):
400        """
401        """
402        self._low_fit = toggle
403        toggle = not toggle
404        self.lineEdit_11.setEnabled(toggle)
405
406    def hiFitAndFixToggle(self, toggle):
407        """
408        """
409        self.lineEdit_13.setEnabled(toggle)
410
411    def highQToggle(self, clicked):
412        """
413        Disable/enable High Q extrapolation
414        """
415        self.radioButton_7.setEnabled(clicked)
416        self.radioButton_8.setEnabled(clicked)
417        self.lineEdit_12.setEnabled(clicked)
418        self.lineEdit_13.setEnabled(clicked)
419
420    def lowQToggle(self, clicked):
421        """
422        Disable/enable Low Q extrapolation
423        """
424        self.radioButton.setEnabled(clicked)
425        self.radioButton_2.setEnabled(clicked)
426        self.lineEdit_11.setEnabled(clicked and not self._low_fit)
427
428        # Enable subelements
429        self.radioButton_3.setEnabled(clicked and not self._low_guinier)
430        self.radioButton_4.setEnabled(clicked and not self._low_guinier)
431        self.lineEdit_10.setEnabled(clicked and not self._low_guinier)
432
433    def setupModel(self):
434
435        # filename
436        item = QtGui.QStandardItem(self._path)
437        self.model.setItem(WIDGETS.W_FILENAME, item)
438
439        # add Q parameters to the model
440        #qmin = min(self._data.x)
441        qmin = 0.0
442        item = QtGui.QStandardItem(str(qmin))
443        self.model.setItem(WIDGETS.W_QMIN, item)
444        qmax = 0.0
445        item = QtGui.QStandardItem(str(qmax))
446        self.model.setItem(WIDGETS.W_QMAX, item)
447
448        # add custom input params
449        item = QtGui.QStandardItem(str(self._background))
450        self.model.setItem(WIDGETS.W_BACKGROUND, item)
451        item = QtGui.QStandardItem(str(self._contrast))
452        self.model.setItem(WIDGETS.W_CONTRAST, item)
453        item = QtGui.QStandardItem(str(self._scale))
454        self.model.setItem(WIDGETS.W_SCALE, item)
455       
456        # Dialog elements
457        itemf = QtGui.QStandardItem("false")
458        self.model.setItem(WIDGETS.W_ENABLE_HIGHQ, itemf)
459        itemf = QtGui.QStandardItem("false")
460        self.model.setItem(WIDGETS.W_ENABLE_LOWQ, itemf)
461
462        item = QtGui.QStandardItem(str(self._npoints_low))
463        self.model.setItem(WIDGETS.W_NPTS_LOWQ, item)
464        item = QtGui.QStandardItem(str(self._npoints_high))
465        self.model.setItem(WIDGETS.W_NPTS_HIGHQ, item)
466
467        itemt = QtGui.QStandardItem("true")
468        self.model.setItem(WIDGETS.W_LOWQ_GUINIER, itemt)
469
470        itemt = QtGui.QStandardItem("true")
471        self.model.setItem(WIDGETS.W_LOWQ_FIT, itemt)
472        item = QtGui.QStandardItem(str(self._power_low))
473        self.model.setItem(WIDGETS.W_LOWQ_POWER_VALUE, item)
474
475        itemt = QtGui.QStandardItem("true")
476        self.model.setItem(WIDGETS.W_HIGHQ_FIT, itemt)
477        item = QtGui.QStandardItem(str(self._power_low))
478        self.model.setItem(WIDGETS.W_HIGHQ_POWER_VALUE, item)
479
480
481    def setupMapper(self):
482        # Set up the mapper.
483        self.mapper = QtGui.QDataWidgetMapper(self)
484        self.mapper.setOrientation(QtCore.Qt.Vertical)
485        self.mapper.setModel(self.model)
486
487        # Set up the view on the model for testing
488        # self.tableView.setModel(self.model)
489
490        # Filename
491        self.mapper.addMapping(self.lineEdit, WIDGETS.W_FILENAME)
492        # Qmin/Qmax
493        self.mapper.addMapping(self.lineEdit_2, WIDGETS.W_QMIN)
494        self.mapper.addMapping(self.lineEdit_3, WIDGETS.W_QMAX)
495
496        # Background
497        self.mapper.addMapping(self.lineEdit_4, WIDGETS.W_BACKGROUND)
498        # Scale
499        self.mapper.addMapping(self.lineEdit_5, WIDGETS.W_SCALE)
500        # Contrast
501        self.mapper.addMapping(self.lineEdit_6, WIDGETS.W_CONTRAST)
502
503        # Lowq/Highq items
504        self.mapper.addMapping(self.checkBox, WIDGETS.W_ENABLE_LOWQ)
505        self.mapper.addMapping(self.checkBox_2, WIDGETS.W_ENABLE_HIGHQ)
506
507        self.mapper.addMapping(self.lineEdit_10, WIDGETS.W_NPTS_LOWQ)
508        self.mapper.addMapping(self.radioButton, WIDGETS.W_LOWQ_GUINIER)
509
510        self.mapper.addMapping(self.radioButton_3, WIDGETS.W_LOWQ_FIT)
511        self.mapper.addMapping(self.lineEdit_11, WIDGETS.W_LOWQ_POWER_VALUE)
512
513        self.mapper.addMapping(self.radioButton_7, WIDGETS.W_HIGHQ_FIT)
514        self.mapper.addMapping(self.lineEdit_13, WIDGETS.W_HIGHQ_POWER_VALUE)
515   
516        # Output
517        self.mapper.addMapping(self.lineEdit_14, WIDGETS.W_VOLUME_FRACTION)
518        self.mapper.addMapping(self.lineEdit_15, WIDGETS.W_VOLUME_FRACTION_ERR)
519        self.mapper.addMapping(self.lineEdit_16, WIDGETS.W_SPECIFIC_SURFACE)
520        self.mapper.addMapping(self.lineEdit_17, WIDGETS.W_SPECIFIC_SURFACE_ERR)
521        self.mapper.addMapping(self.lineEdit_19, WIDGETS.W_INVARIANT)
522        self.mapper.addMapping(self.lineEdit_18, WIDGETS.W_INVARIANT_ERR)
523
524        self.mapper.toFirst()
525
526    def setData(self, data_item):
527        """
528        Obtain a QStandardItem object and dissect it to get Data1D/2D
529        Pass it over to the calculator
530        """
531        if not isinstance(data_item, list):
532            msg = "Incorrect type passed to the Invariant Perspective"
533            raise AttributeError, msg
534
535        if not isinstance(data_item[0], QtGui.QStandardItem):
536            msg = "Incorrect type passed to the Invariant Perspective"
537            raise AttributeError, msg
538
539        self._model_item = data_item[0]
540
541        # Extract data on 1st child - this is the Data1D/2D component
542        data = GuiUtils.dataFromItem(self._model_item)
543        self.model.item(WIDGETS.W_FILENAME).setData(QtCore.QVariant(self._model_item.text()))
544
545        ##### DEBUG ####
546        # set data in the debug tree view window
547        self.treeView.setModel(self.model)
548
549        self.calculate(data_list=[data])
550       
551    def calculate(self, data_list=None):
552        """
553        receive a list of data and compute invariant
554
555        TODO: pass warnings/messages to log
556        """
557        msg = ""
558        data = None
559        if data_list is None:
560            data_list = []
561        if len(data_list) >= 1:
562            if len(data_list) == 1:
563                data = data_list[0]
564            else:
565                data_1d_list = []
566                data_2d_list = []
567                error_msg = ""
568                # separate data into data1d and data2d list
569                for data in data_list:
570                    if data is not None:
571                        if issubclass(data.__class__, Data1D):
572                            data_1d_list.append(data)
573                        else:
574                            error_msg += " %s  type %s \n" % (str(data.name),
575                                                              str(data.__class__.__name__))
576                            data_2d_list.append(data)
577                if len(data_2d_list) > 0:
578                    msg = "Invariant does not support the following data types:\n"
579                    msg += error_msg
580                if len(data_1d_list) == 0:
581                    # remake this as a qt event
582                    #wx.PostEvent(self.parent, StatusEvent(status=msg, info='error'))
583                    return
584
585                # TODO: add msgbox for data choice
586                #msg += "Invariant panel does not allow multiple data!\n"
587                #msg += "Please select one.\n"
588                #if len(data_list) > 1:
589                    #from invariant_widgets import DataDialog
590                    #dlg = DataDialog(data_list=data_1d_list, text=msg)
591                    #if dlg.ShowModal() == wx.ID_OK:
592                    #    data = dlg.get_data()
593                    #else:
594                    #    data = None
595                    #dlg.Destroy()
596
597            if data is None:
598                msg += "invariant receives no data. \n"
599                #wx.PostEvent(self.parent, StatusEvent(status=msg, info='error'))
600                return
601            if not issubclass(data.__class__, Data1D):
602                msg += "invariant cannot be computed for data of "
603                msg += "type %s\n" % (data.__class__.__name__)
604                #wx.PostEvent(self.parent, StatusEvent(status=msg, info='error'))
605                return
606            else:
607                #wx.PostEvent(self.parent, NewPlotEvent(plot=data, title=data.title))
608                try:
609                    self._data = data
610                    self._path = "unique path"
611                    self.calculateInvariant()
612                except:
613                    msg = "Invariant Set_data: " + str(sys.exc_value)
614                    #wx.PostEvent(self.parent, StatusEvent(status=msg, info="error"))
615        else:
616            msg = "invariant cannot be computed for data of "
617            msg += "type %s" % (data.__class__.__name__)
618            #wx.PostEvent(self.parent, StatusEvent(status=msg, info='error'))
619
620    def allowBatch(self):
621        """
622        Tell the caller that we don't accept multiple data instances
623        """
624        return False
625
626if __name__ == "__main__":
627    app = QtGui.QApplication([])
628    import qt4reactor
629    qt4reactor.install()
630    # DO NOT move the following import to the top!
631    # (unless you know what you're doing)
632    from twisted.internet import reactor
633    dlg = InvariantWindow(reactor)
634    dlg.show()
635    reactor.run()
Note: See TracBrowser for help on using the repository browser.