source: sans/utils/bt5/bt5plot2/bt5plot2 @ 579

Last change on this file since 579 was 514, checked in by ajj, 13 years ago

Fixed filter bug whereby hitting refresh while a filter was applied would cause multiples of
the non-displayed (filtered out) entries. Fix is to re-filter the list with no filter, refresh, then
re-filter with the previously applied filter.

  • Property svn:executable set to *
File size: 10.6 KB
Line 
1#!/usr/bin/env python
2
3import sys
4import os
5import re
6import matplotlib
7import numpy
8matplotlib.use('GTK')
9
10from matplotlib.figure import Figure
11from matplotlib.axes import Subplot
12from matplotlib.backends.backend_gtk import FigureCanvasGTK, NavigationToolbar
13
14import usans
15from BT5DataSet import BT5DataSet
16
17try:
18    import pygtk
19    pygtk.require("2.0")
20   
21except:
22    pass
23
24try:
25    import gtk
26    import gtk.glade
27except:
28    sys.exit(1)
29
30class appGui:
31   
32    TARGETS = [('STRING', gtk.TARGET_SAME_APP, 0)]
33   
34    def __init__(self):
35       
36        gladefile = "bt5plot2.glade"
37        self.windowname = "win_Main"
38        self.wTree = gtk.glade.XML(gladefile, self.windowname)
39
40        event_dic = {"on_win_Main_destroy" : gtk.main_quit,
41                     "on_quit1_activate" : gtk.main_quit,
42                     "on_set_data_dir1_activate" : self.setdatadir,
43                     "on_xaxis_loglin_activate" : self.handle_xaxis_loglin,
44                     "on_yaxis_loglin_activate" : self.handle_yaxis_loglin,
45                     "on_plot_type_activate" : self.handle_plot_type_change,
46                     "on_btn_ClearPlot_clicked" : self.handle_clearplot,
47                     "on_btn_Refresh_clicked" : self.handle_refreshlist,
48                     "on_btn_Filter_clicked" : self.handle_filter}
49    #                 "on_tv_plotlist_key_press_event" : self.handle_plotlist_keypress}
50
51        #This is a bit clunky, but never mind.
52        #Set default plottype to rate. Glade definition sets that as default active button in menu
53        self.plottype = 'rate'
54       
55        self.wTree.signal_autoconnect(event_dic)
56
57        # Set up file list
58        self.filelistview = self.wTree.get_widget("tv_filelist")
59       
60        self.filelist = gtk.ListStore(str, 'gboolean', object)
61        self.filelist.set_sort_column_id(0, gtk.SORT_ASCENDING)
62
63        # Set up filtering of file list
64        self.filter_entry = self.wTree.get_widget("ent_filter")
65        self.filter_string = []
66        self.filter_string.append(self.filter_entry.get_text())
67        self.filelistfilter = self.filelist.filter_new()
68        self.filelistfilter.set_visible_func(self.filter_filelist,self.filter_string)
69
70        self.filelistview.set_model(self.filelistfilter)
71
72        self.cellrenderertoggle = gtk.CellRendererToggle()
73        self.cellrenderertoggle.set_property('activatable', True)
74        self.cellrenderertoggle.connect("toggled", self.handle_plot_toggle, self.filelistfilter)
75   
76        self.AddFileListColumns()
77
78        #fill the file list
79        if (len(sys.argv) > 1):
80                os.chdir(sys.argv[1])
81        self.FillFileList(usans.GetBT5DirList())
82
83        # Set up graphing widget to display xpeek data
84        self.figure = Figure(figsize=(4, 4), dpi=72)
85        self.axis = self.figure.add_subplot(111)
86        self.axis.set_yscale('log')
87        self.axis.set_aspect('auto')
88        self.axis.set_autoscale_on('True')
89        self.axis.set_xlabel('Motor position')
90        self.axis.set_ylabel('Counts')
91        self.axis.grid(True)
92       
93        self.canvas = FigureCanvasGTK(self.figure)
94        self.figure.canvas.mpl_connect('pick_event',self.handle_plot_click)
95        self.canvas.show()
96       
97        self.plotView = self.wTree.get_widget("vbox4")
98        self.plotView.pack_start(self.canvas, True, True)   
99       
100        self.metadataView = self.wTree.get_widget("tv_metadata")
101        self.mdlist = gtk.ListStore(str,str)
102       
103       
104    def AddFileListColumns(self):
105        """This function adds a column to the list view.
106        First it create the gtk.TreeViewColumn and then set
107        some needed properties"""
108                       
109        column = gtk.TreeViewColumn('Filename', gtk.CellRendererText(), text=0)
110        column.set_resizable(True)       
111        column.set_sort_column_id(0)
112        self.filelistview.append_column(column)
113
114        column = gtk.TreeViewColumn('', self.cellrenderertoggle, active=1)
115        self.filelistview.append_column(column)
116        return
117       
118   
119    def FillFileList(self, filenames):
120        self.filelist.clear()
121        for filename in filenames:
122                self.filelist.append([filename, 0, None])
123        return
124           
125    def RefreshFileList(self,filenames):       
126        #print len(filenames)
127       
128        deletelist = []
129        tempstr = self.filter_entry.get_text()
130        del self.filter_string[:]
131        self.filter_string.append("")
132        self.filelistfilter.refilter()
133       
134        treestore = self.filelistview.get_model()
135        treestore.foreach(self.filelist_match_filename, (filenames,deletelist))
136         
137        for filename in filenames:
138            self.filelist.append([filename, 0, None])
139       
140        deletelist.reverse()
141        for path in deletelist:
142            treestore.remove(treestore.get_iter(path))
143
144        del self.filter_string[:]
145        self.filter_string.append(tempstr)
146        self.filelistfilter.refilter()
147        return
148
149    def filelist_match_filename(self, model, path, iter, data):
150       
151        mval = model.get_value(iter,0)
152       
153        if mval in data[0]:
154            del data[0][data[0].index(mval)]
155        else:
156            data[1].append(path)
157           
158        return False
159   
160    def handle_refreshlist(self,widget):
161
162        self.RefreshFileList(usans.GetBT5DirList())
163       
164        return
165
166    def filter_filelist(self, model, iter, data):
167       
168        if model.get_value(iter,0):       
169            match = re.match(data[0],model.get_value(iter,0))
170        else:
171            match = None
172       
173        if match is None:
174            return False
175        else:
176            return True
177       
178    def handle_filter(self,widget):
179       
180        del self.filter_string[:]
181        self.filter_string.append(self.filter_entry.get_text())
182        #print self.filter_string[0]
183        self.filelistfilter.refilter()
184       
185        return
186
187    def setdatadir(self, widget):
188       
189        #Clear plot before selecting new folder
190        #This is a bit clunky, but it avoids a lot of pain for the moment
191       
192        self.clearplot()
193       
194        chooser = gtk.FileChooserDialog(title="Select Data Directory", action=gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER,
195                                  buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OPEN, gtk.RESPONSE_OK))
196        chooser.set_default_response(gtk.RESPONSE_OK)
197        chooser.set_current_folder(os.getcwd())
198        response = chooser.run()
199        if response == gtk.RESPONSE_OK:
200            os.chdir(chooser.get_filename())
201            self.FillFileList(usans.GetBT5DirList())
202        chooser.destroy()
203
204    def handle_plot_toggle(self, filter_cell, filter_path, filter_model):
205        model = filter_model.get_model()
206        path = filter_model.convert_path_to_child_path(filter_path)
207        model[path][1] = not model[path][1]
208
209        if model[path][1]:
210            #load data
211            model[path][2] = BT5DataSet(model[path][0])
212            #add plot
213            model[path][2].plot_dataset(self.axis,self.plottype)
214            self.rescale_and_redraw()
215        else:
216            #remove plot
217            model[path][2].remove_plot()
218            self.rescale_and_redraw()
219        return
220
221 
222    def handle_xaxis_loglin(self, widget):
223
224
225        if (self.axis.get_xscale() == "log"):
226            self.axis.set_xscale('linear')
227        else:
228            self.axis.set_xscale('log')       
229
230
231        self.rescale_and_redraw()
232       
233        return   
234
235    def handle_yaxis_loglin(self, widget):
236
237
238        if (self.axis.get_yscale() == "log"):
239            self.axis.set_yscale('linear')
240        else:
241            self.axis.set_yscale('log')       
242
243        self.rescale_and_redraw()
244        return
245       
246    def handle_plot_type_change(self,widget):
247               
248        if widget.get_active():
249                self.plottype = widget.get_name().split('_')[1]
250
251        model = self.filelistview.get_model().get_model()
252        iter = model.iter_children(None)
253        while iter:
254            path = model.get_path(iter)
255            if model[path][1] != 0:
256                model[path][2].remove_plot()
257                model[path][2].plot_dataset(self.axis,self.plottype)
258            iter = model.iter_next(iter)
259
260        self.rescale_and_redraw()
261               
262        return
263       
264    def handle_clearplot(self,widget):
265       
266        self.clearplot()
267       
268        return
269       
270   
271    def clearplot(self):
272        model = self.filelistview.get_model().get_model()
273        iter = model.iter_children(None)
274        while iter:
275            path = model.get_path(iter)
276            if model[path][1] != 0:
277                model[path][2].remove_plot()
278                model[path][1] = not model[path][1]
279            iter = model.iter_next(iter)
280       
281        self.canvas.draw()
282        return 
283       
284    def rescale_and_redraw(self):
285
286        xdata = []
287        ydata = []
288
289        if len(self.axis.lines) > 0:
290
291            for line in self.axis.lines:
292                if self.axis.get_xscale() == 'log':
293                        xdata.extend([xval for xval in line.get_xdata() if xval > 0])
294                else:
295                        xdata.extend(line.get_xdata())
296                if self.axis.get_yscale() == 'log':
297                        ydata.extend([xval for xval in line.get_ydata() if xval > 0])
298                else:
299                        ydata.extend(line.get_ydata())
300         
301            #set limits
302            xmin = float(min(xdata))
303            xmax = float(max(xdata))
304            ymin = float(min(ydata))
305            ymax = float(max(ydata))   
306   
307            #adjust for size of markers (sort of)
308            xmin = xmin - 0.1*abs(xmin)
309            xmax = xmax + 0.1*abs(xmax)
310            ymin = ymin - 0.1*abs(ymin)
311            ymax = ymax + 0.1*abs(ymax)
312                   
313            self.axis.set_xlim(xmin,xmax)
314            self.axis.set_ylim(ymin,ymax)
315       
316        #self.axis.autoscale_view()
317        self.canvas.draw()
318
319        return
320
321    def handle_plot_click(self,event):
322        model = self.filelistview.get_model().get_model()
323        iter = model.iter_children(None)
324
325
326        if isinstance(event.artist, matplotlib.lines.Line2D):
327            print "Clicked..."
328            pickedline = event.artist
329            ind = event.ind
330            xdata = pickedline.get_xdata()
331
332            while iter:
333                path = model.get_path(iter)
334                if model[path][1] != 0:
335                    for line in model[path][2].plot:
336                        if line == pickedline:
337                            model[path][2].calcAlignVals(xdata[ind])
338                            label = self.wTree.get_widget("lbl_alignvals")
339                            label.set_text(model[path][2].alignvalstring)
340                            break
341                iter = model.iter_next(iter)
342       
343
344           
345
346app = appGui()
347gtk.main()
Note: See TracBrowser for help on using the repository browser.