1 """Panel with live average of selections in active List.
2
3 Copyright 2008-2014 Research Foundation State University of New York
4 This file is part of QUB Express.
5
6 QUB Express is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
10
11 QUB Express is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License,
17 named LICENSE.txt, in the QUB Express program directory. If not, see
18 <http://www.gnu.org/licenses/>.
19
20 """
21
22 import cStringIO
23 import itertools
24 import os
25 import sys
26 import time
27 import traceback
28 import gobject
29 import cairo
30 import gtk
31 import qubx.settings
32 import qubx.GTK
33 import qubx.pyenv
34 import qubx.tree
35 import qubx.faces
36 import qubx.fit_space
37 import qubx.task
38 import qubx.dataGTK
39 import qubx.extract
40 import qubx.notebook
41 import qubx.notebookGTK
42 import qubx.toolspace
43
44 from gtk import gdk
45 from gtk import keysyms
46 from itertools import izip, count
47 from qubx.util_types import *
48 from qubx.accept import *
49 from qubx.GTK import pack_item, pack_space, pack_hsep, pack_vsep, pack_label, pack_button, pack_check, pack_radio, pack_scrolled, build_menuitem
50 from qubx.settings import Property, Propertied
51 from numpy import arange, array, zeros
52 from qubx.task import Tasks
53
54 GROUPS_IN_MENU = 16
55
56 @Propertied(Property('max_n', 2048, 'if there are more datapoints, they will be resampled to this many onscreen'))
57 -class ListAverageFace(qubx.faces.Face):
58 """
59
60 Panel showing live average of front List.
61
62 @ivar limit_group: None to use all selections, or integer group index to use only matching sels
63
64 """
65
66 __explore_featured = ['plot', 'sync', 'nbChart', 'nbPicture', 'subNotebook', 'nbParams', 'limit_group', 'update', 'robot_update']
67
68 - def __init__(self, name, global_name=""):
69 """@param name: caption for this panel's tab"""
70 qubx.faces.Face.__init__(self, name, global_name)
71 self.__ref = Reffer()
72 self.set_size_request(100, 70)
73 self.QubX = qubx.pyenv.env.globals['QubX']
74 self.QubX.OnQuit += self.__ref(lambda: self.plot.controls.robot.stop())
75 self.plot = pack_item(qubx.fit_space.FitSpace(label=name, global_name=global_name and ("%s.plot" % global_name)), self, expand=True)
76 self.plot.layerset = self.plot.controlsHidden
77 self.plot.caption = 'Average of all traces in List'
78 self.plot.controls.robot.OnException += self.__ref(self.__onException)
79 self.plot.data_rad = 0.0
80 self.subMaxN = qubx.toolspace.SubLayer_Label('Max N: %i' % self.max_n, -1, 1, x=-20, y=0, w=10, h=qubx.fit_space.LINE_EMS,
81 color=self.plot.controls.cText, action=self.__ref(self.__onClickMaxN))
82 self.plot.layBottomHidden.add_sublayer(self.subMaxN)
83 self.subExtract = qubx.toolspace.SubLayer_Label('Extract...', 0, 1, x=-30, y=0, w=10, h=qubx.fit_space.LINE_EMS,
84 color=self.plot.controls.cButton, action=self.__ref(self.__onClickExtract))
85 self.plot.layBottomHidden.add_sublayer(self.subExtract)
86 self.subGroup = qubx.toolspace.SubLayer_Label('Group: All', -1, 1, x=-40, y=0, w=10, h=qubx.fit_space.LINE_EMS,
87 color=self.plot.controls.cText, action=self.__ref(self.__onClickGroup))
88 self.plot.layBottomHidden.add_sublayer(self.subGroup)
89 self.mnuGroup = gtk.Menu()
90 self.itemGroupAll = build_menuitem('All', self.__ref(bind(self.__onClickGroupItem, None)), item_class=gtk.CheckMenuItem, active=True, menu=self.mnuGroup)
91 self.group_items = [build_menuitem(str(i), self.__ref(bind(self.__onClickGroupItem, i)), item_class=gtk.CheckMenuItem, menu=self.mnuGroup) for i in xrange(GROUPS_IN_MENU)]
92 build_menuitem('Other...', self.__ref(self.__onClickGroupOther), menu=self.mnuGroup)
93 self.__limit_group = None
94 self.__ignore_group_event = False
95 self.sync = self.plot.controls.robot.sync
96 self.serial = 0
97
98 self.propertied_connect_settings('ListAverage')
99
100 self.__datafile = None
101 self.QubX.Data.OnSwitch += self.__ref(self.__onSwitchData)
102 self.QubX.DataSource.OnChangeSignal += self.__ref(self.__onChangeSignal)
103
104 self.plot.controls.robot.OnStats += self.__ref(self.__onStats)
105 self.plot.controls.robot.OnEndFit += self.__ref(self.__onEndFit)
106 self.layNotebook = qubx.toolspace.Layer(x=1, y=-5.5-qubx.fit_space.LINE_EMS, w=2, h=2, cBG=qubx.toolspace.COLOR_CLEAR)
107 self.subNotebook = qubx.notebookGTK.SubLayer_Notebook(x=0, y=0, w=2, h=2)
108 self.layNotebook.add_sublayer(self.subNotebook)
109 self.plot.add_layer(self.layNotebook)
110 self.nbChart = qubx.notebook.NbChart('Chart', '%s.nbChart' % global_name, lambda: self.plot.caption,
111 self.plot.controls.nb_get_shape, self.plot.controls.nb_get_headers,
112 get_col=self.plot.controls.nb_get_col, get_type=lambda: float,
113 get_series=self.plot.nb_get_series)
114 self.subNotebook.items.append(self.nbChart)
115 self.nbPicture = qubx.notebookGTK.NbPicture('Picture', '%s.nbPicture' % global_name, self.plot.nb_picture_get_shape,
116 self.plot.nb_picture_draw)
117 self.subNotebook.items.append(self.nbPicture)
118 self.nbParams = qubx.notebook.NbDynText('Parameters', '%s.nbParams' % global_name, self.plot.controls.nb_get_param_text)
119 self.nbParams.std_err_est = None
120 self.subNotebook.items.append(self.nbParams)
121 qubx.notebook.Notebook.register_auto('%s.Parameters'%name, '%s Parameters, on Fit'%name, True)
122 qubx.notebook.Notebook.register_auto('%s.Results'%name, '%s Results, on Fit'%name, True)
123 qubx.notebook.Notebook.register_auto('%s.Chart'%name, '%s Chart, on Fit'%name)
124 qubx.notebook.Notebook.register_auto('%s.Picture'%name, '%s Picture, on Fit'%name, True)
125 self.__nb_next_stats = False
126 self.__onSwitchData(self.QubX.Data, self.QubX.Data.file)
133 if x == self.__limit_group:
134 return
135 self.__limit_group = x
136 if x is None:
137 self.subGroup.label = 'Group: All'
138 else:
139 self.subGroup.label = 'Group: %i' % x
140 self.update()
141 limit_group = property(lambda self: self.__limit_group, lambda self, x: self.set_limit_group(x))
143 new_val = qubx.pyenvGTK.prompt_entry('Max N (larger data will be resampled):', self.max_n, acceptIntGreaterThan(0))
144 if not (new_val is None):
145 self.propertied_on_user_set('max_n', new_val)
159 self.__ignore_group_event = True
160 g = self.__limit_group
161 self.itemGroupAll.set_active(g is None)
162 for i, item in enumerate(self.group_items):
163 item.set_active(g == i)
164 self.__ignore_group_event = False
165 self.mnuGroup.popup(None, None, None, 0, e.time)
172 g = self.__limit_group
173 if g is None:
174 g = 0
175 new_val = qubx.pyenvGTK.prompt_entry('Group:', g, acceptIntGreaterThan(0))
176 if not (new_val is None):
177 qubx.pyenv.env.OnScriptable('%s.limit_group = %s' % (self.global_name, new_val))
178 self.limit_group = new_val
198 self.__nb_next_stats = True
199 - def __onStats(self, correlation, is_pseudo, std_err_est, ssr, r2, runs_prob):
200 if self.__nb_next_stats:
201 self.__nb_next_stats = False
202 label = self.face_name
203 n = len(self.plot.controls.xx)
204 qubx.notebook.Notebook.send(qubx.notebook.NbText("""%(label)s fitting finished.
205 \tN: %(n)i
206 \tSSR: %(ssr).6g
207 \tR^2: %(r2).6g
208 \tWald-Wolfowitz runs probability: %(runs_prob).6g
209 \tCorrelation:
210 %(correlation)s
211 """ % locals()), auto_id='%s.Results'%self.face_name)
212 self.nbParams.std_err_est = std_err_est
213 qubx.notebook.Notebook.send(self.nbParams, auto_id='%s.Parameters'%self.face_name)
214 qubx.notebook.Notebook.send(self.nbChart, auto_id='%s.Chart'%self.face_name)
215 qubx.notebook.Notebook.send(self.nbPicture, auto_id='%s.Picture'%self.face_name)
216 self.nbParams.std_err_est = None
217
219 traceback.print_exception(typ, val, trace)
220 - def update(self, force=False):
221 """Requests that robot_update() be called in the robot thread."""
222 self.serial += 1
223 if self.showing or force:
224 self.plot.controls.robot.do(self.robot_try_update, self.serial)
226 """In robot thread, filters out duplicate (stale serial) requests and calls robot_update()"""
227
228 if serial == self.serial:
229 self.robot_update()
248