source: sasview/src/sas/qtgui/Perspectives/Invariant/InvariantPerspective.py @ 4992ff2

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 4992ff2 was 4992ff2, checked in by Piotr Rozyczko <rozyczko@…>, 6 years ago

Initial, in-progress version. Not really working atm. SASVIEW-787

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