Re: Dynamically Update Dataset?

356 views
Skip to first unread message

Timo

unread,
Dec 18, 2012, 4:43:47 PM12/18/12
to guidata...@googlegroups.com
Hello Brian,

I am no expert, but from my understanding you have to make the proper call to .get() and .set() of the DataEditGroupBox.

So if you modify your processing Call back to

def processingCallback(self):

print ""

print "Callback"

self.expBox.set() # Update data item values from layout content

print self.expBox.dataset


it should do what you want.

The .get() does exactly the opposite: it updates the display of the widgets in the layout with the values of the DataItems.


It took me quite a while to understand this behavior :-)


Best regards from the today not so sunny San Diego,


Timo







Am Dienstag, 18. Dezember 2012 13:09:14 UTC-8 schrieb Brian Clowers:
First thank you for both spyder and guidata.  I find them quite useful and am trying to expand to a more complex application and am running into a problem when I embed the datasets into a gui.  Specifically, it seems overly complex to have to click on each apply button to register changes to the dataset.  Granted there is the following thread (https://groups.google.com/d/topic/guidata_guiqwt/9qk0TPGLMzk/discussion), however, it is still not clear how to make sure the dataset is updated using an external button. 

I've attached an example in which there are a few parameters that I would like to change and then move straight to the processing button.  You'll that the following example allows me to connect the button clicks to events, however, I cannot seem to find a way to accept all changes to a dataset without explicitly clicking on the "Apply" button.  Am I emitting the wrong SIGNAL? 

Any help would be appreciated.

Cheers,

Brian




################
# -*- coding: utf-8 -*-
import os
import tempfile, atexit, shutil
import numpy as np


from guidata.dataset.datatypes import (DataSet, BeginTabGroup, EndTabGroup,
                                       BeginGroup, EndGroup, ObjectItem)
from guidata.dataset.dataitems import (FloatItem, IntItem, BoolItem, ChoiceItem,
                             MultipleChoiceItem, ImageChoiceItem, FilesOpenItem,
                             StringItem, TextItem, ColorItem, FileSaveItem,
                             FileOpenItem, DirectoryItem, FloatArrayItem, ButtonItem)


from guidata.configtools import get_icon
from guidata.qthelpers import create_action, add_actions, get_std_icon

from guidata.qt.QtGui import QMainWindow, QSplitter, QPushButton, QGridLayout, QGroupBox
from guidata.qt.QtCore import SIGNAL, Qt

from guidata.dataset.qtwidgets import DataSetEditLayout, DataSetShowLayout, DataSetShowGroupBox, DataSetEditGroupBox
from guidata.dataset.qtitemwidgets import DataSetWidget


def dummyCall(a = None, b = None, c = None, d = None):
    print ""
    #~ print a
    #~ print b
    #~ print c
    #~ print d   
   
class ProcessParams(DataSet):
    '''
    Note that the None for the callback MUST be replaced or ignored
    '''
    #This is position 1
    floatArray = FloatArrayItem("Float array", default=np.ones( (5,5), float),
                                format=" %.2e ").set_pos(col=0)
    #This is position 2
    processButton = ButtonItem("Process Data", dummyCall).set_pos(col = 1, colspan = 1)
   
    btnPos = 2
   
    def __init__(self, title=None, comment=None, icon=''):
        super(ProcessParams, self).__init__(title, comment, icon)
        self.mainWindow = None

    def setMainWindow(self, mainWindow):
        self.mainWindow = mainWindow      

class ExperimentParams(DataSet):
    '''
    Experimental Parameters
    '''
    analyteID = StringItem("Analyte ID", "Biotin").set_pos(col=0, colspan = 1)
    analyteConc = FloatItem("Analyte Concentration (ppm)", default = 10.0, min = 0.000005, max = 100000, step = 0.5).set_pos(col=1, colspan = 1)
    humidity = FloatItem("Humidity (ppm)", default = 100.0, min = 1, max = 10000, step = 0.5).set_pos(col=0, colspan = 1)
    waterBool = BoolItem("Water Spike?").set_pos(col=1, colspan=1)

    def __init__(self, title=None, comment=None, icon=''):
        super(ExperimentParams, self).__init__(title, comment, icon)
        self.mainWindow = None

    def setMainWindow(self, mainWindow):
        self.mainWindow = mainWindow
                                                                         
       
class MainWindow(QMainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()
        self.setWindowIcon(get_icon('python.png'))
        self.setWindowTitle("Application example")
       
        # Instantiate dataset-related widgets:

       
        self.expBox = DataSetEditGroupBox("Experimental Parameters",
                                          ExperimentParams, comment='')
        self.expBox.dataset.setMainWindow(self)#link to MainWindow instance
       
        self.processingBox = DataSetEditGroupBox("Processing Parameters",
                                                 ProcessParams, comment = '')
        self.processingBox.dataset.setMainWindow(self)#link to MainWindow instance
       
        self.groupList = []
        self.groupList.append(self.expBox)
        self.groupList.append(self.processingBox)                                        
                                                
        btnPos = self.processingBox.dataset.btnPos
        self.processBtn = self.processingBox.children()[btnPos]
        self.connect(self.processBtn, SIGNAL('clicked()'), self.processingCallback)
        vsplitter = QSplitter(Qt.Vertical, self)

        vsplitter.addWidget(self.expBox)
        vsplitter.addWidget(self.processingBox)
        self.setCentralWidget(vsplitter)
        self.setContentsMargins(10, 5, 10, 5)
       
       
        self.connect(self.expBox, SIGNAL("apply_button_clicked()"),
                     self.updateExperimentBox)
   
    def emitApply(self):
        self.processingBox.emit(SIGNAL("apply_button_clicked()"))#This updates the variables (you hope)
        self.expBox.emit(SIGNAL("apply_button_clicked()"))

    def updateExperimentBox(self, extra = None):
        print "Exp Box Apply Clicked"
        print self.expBox.dataset

    def processingCallback(self):
        print ""
        print "Callback"
        print self.emitApply()
        print self.expBox.dataset
        #~ print self.processingBox.dataset
          
               
   
if __name__ == "__main__":
    from guidata.qt.QtGui import QApplication
    import sys
    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec_())
   

Brian Clowers

unread,
Dec 18, 2012, 5:21:22 PM12/18/12
to guidata...@googlegroups.com
Timo,

Thanks a bunch.  I can't believe I missed that and am glad it was so simple.  Any chance you know how to register a custom matplotlib instance to work with guidata?

Cheers,

Brian

--Should we ever cross paths remember that I owe you a beer.

Timo

unread,
Dec 18, 2012, 8:07:35 PM12/18/12
to guidata...@googlegroups.com
Hi Brian,

Your are welcome.
As I said I am not an expert and I still do not understand why changing the values of a DatasetItem works in the examples (e.g. all_features.py of the guidata.tests suite) without the need of a .get() or .set() call  but not in your or my code. In principle that is something one could look into and than maybe file a bug report (or patch) but my python projects are currently very low priority :-)

I am not sure what you mean by registering a custom matplotlib instance with guidata. For my own application (mainly a tool to read and analyze the mass-spec data from our thermal desorption setup) I simply use the guiqwt plot components.

Timo

p.s. I can only join your thanks to the developers of spyder, guidata and guiqwt as these tools simplify developing small gui programs considerably.

Brian Clowers

unread,
Dec 19, 2012, 11:47:26 PM12/19/12
to guidata...@googlegroups.com
I am just now looking at the quiqwt library and was simply hoping that a matplotlib canvas could easily be adapted as a guidata widget. Seeing as I am mostly familiar with matplotlib I went ahead and embedded a matplotlib canvas as a QWidget, which seems to work just fine. 

However, there is another problem that I keep running into regarding the ability to make sure that when I call the "set_prop" function of a given item that the new value actually is displayed in the gui.  For example if I create a new IntItem with a slider there is a time when I want to update the maximum value.  It appears as though when I update the "max" property I have to close the edit dialog and reopen it before the change take effect.  Is there a way to do this on the fly and simply repaint the item? 

Initial:

newIntSlider = IntItem("Scan Index", default=5, min=1, max=25, slider=True)

Later in the code:

newIntSlider.set_prop("display", max = 40)#this doesn't seem to work unless you close/reopen the interface

###########

I'd also like to do this for a FloatArrayItem and am having an even bigger problem there.  It appears that even if I set the default to a new value and close/reopen the dataset the new array is not applied.  Any ideas?

floatArray = FloatArrayItem("Data Array", default=N.ones((5,10), float), format=" %.2e ")

Later:

floatArray.set_prop("display", default = N.arange((5,50), float))

##########

Cheers,

Brian

Neal Gordon

unread,
Sep 28, 2014, 12:30:11 AM9/28/14
to guidata...@googlegroups.com
great post. thanks!
Reply all
Reply to author
Forward
0 new messages