source: sasview/src/sas/qtgui/Perspectives/Invariant/InvariantPerspective.py @ 7fb471d

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

Update for unit tests and minor functionality quirks

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