Package qubx :: Module ideal_tools
[hide private]
[frames] | no frames]

Source Code for Module qubx.ideal_tools

  1  """Panel to modify idealized data. 
  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 gobject 
 23  import gtk 
 24  from gtk import gdk 
 25  import numpy 
 26  import os 
 27  import qubx.chop 
 28  import qubx.data_types 
 29  import qubx.faces 
 30  import qubx.GTK 
 31  import qubx.notebook 
 32  import qubx.pyenv 
 33  import traceback 
 34  from itertools import izip, count 
 35  from qubx.accept import * 
 36  from qubx.GTK import pack_item, pack_space, pack_hsep, pack_vsep, pack_label, pack_button, pack_check, pack_radio, pack_scrolled 
 37  from qubx.settings import Property, Propertied 
 38  from qubx.util_types import WeakEvent, Reffer, bind, bind_with_args_before 
 39  from qubx.ulp_diff import fulpdiff 
 40   
 41  MAX_ULP_DIFF = 4 
 42   
 43   
 44  @Propertied(Property('stab_window', 50, 'number of events per chunk'), 
 45              Property('stab_overlap', 25, 'number of events overlapping in consecutive chunks'), 
 46              Property('stab_listname', 'Stability', 'name of output List'), 
 47              Property('list_events_class', 1, 'class index to be listed'), 
 48              Property('list_events_name', 'Events', 'output selection list name'), 
 49              Property('list_trans_from', 0, 'class index to be listed'), 
 50              Property('list_trans_to', 1, 'class index to be listed'), 
 51              Property('list_trans_pre', 5.0, 'msec of prior event to include in list sel'),  
 52              Property('list_trans_name', 'Transitions', 'output selection list name'), 
 53              # bw_ properties are used by menu in qubx.dataGTK for Baum-Welch (AMP) 
 54              Property('bw_auto_init', 0, 'True to spread initial amps evenly across [min(data)..max(data)]'), 
 55              Property('bw_auto_init_up', 1, 'False to auto-init classes from max to min'), 
 56              Property('bw_update_model', 1, 'True to update Classes:Amp and Std'), 
 57              Property('bw_show_ideal', 1, 'True to show results as idealized data')) 
58 -class IdlToolsFace(qubx.faces.Face):
59 __explore_featured = ['calc_stability', 'save_dwt', 'save_sampled', 'clear', 'apply_dead_time', 'change_class', 'fill_blanks', 60 'join_class', 'set_amp', 'list_events', 'list_transitions', 'get_segmentation_idl']
61 - def __init__(self, name='Idealization', global_name='QubX.Tools.Idealization'):
62 qubx.faces.Face.__init__(self, name, global_name) 63 self.propertied_connect_settings('IdlTools') 64 self.__ref = Reffer() 65 self.QubX = qubx.pyenv.env.globals['QubX'] 66 67 v = gtk.VBox() 68 self.scroll = pack_scrolled(v, self, with_vp=True, expand=True) 69 70 vh = pack_item(gtk.HBox(), v) 71 pack_label('Apply dead time:', vh) 72 self.txtDeadTime = pack_item(qubx.GTK.NumEntry(1.0, acceptFloatGreaterThan(0.0), '%.3g', width_chars=7), vh) 73 pack_label('ms', vh) 74 self.btnDeadTime = pack_button('Apply', vh, at_end=True, on_click=self.__onClickDeadTime) 75 76 vh = pack_item(gtk.HBox(), v) 77 pack_label('Change class', vh) 78 self.txtChangeFrom = pack_item(qubx.GTK.NumEntry(2, acceptIntGreaterThanOrEqualTo(0), width_chars=4), vh) 79 pack_label('events to class', vh) 80 self.txtChangeTo = pack_item(qubx.GTK.NumEntry(1, acceptIntGreaterThanOrEqualTo(0), width_chars=4), vh) 81 self.btnChangeClass = pack_button('Change', vh, at_end=True, on_click=self.__onClickChangeClass) 82 83 vh = pack_item(gtk.HBox(), v) 84 pack_label('Fill blanks with class', vh) 85 self.txtFillClass = pack_item(qubx.GTK.NumEntry(0, acceptIntGreaterThanOrEqualTo(0), width_chars=5), vh) 86 self.btnFillBlanks = pack_button('Fill blanks', vh, at_end=True, on_click=self.__onClickFillBlanks) 87 88 vh = pack_item(gtk.HBox(), v) 89 pack_label('Join class', vh) 90 self.txtJoinClass = pack_item(qubx.GTK.NumEntry(2, acceptIntGreaterThanOrEqualTo(0), width_chars=4), vh) 91 pack_label('events to the prior event', vh) 92 self.btnJoinClass = pack_button('Join', vh, at_end=True, on_click=self.__onClickJoinClass) 93 94 vh = pack_item(gtk.HBox(), v) 95 pack_label('Set amp of class', vh) 96 self.txtSetAmpClass = pack_item(qubx.GTK.NumEntry(2, acceptIntGreaterThanOrEqualTo(0), width_chars=4), vh) 97 pack_label('to', vh) 98 self.txtSetAmpTo = pack_item(qubx.GTK.NumEntry(0.0, acceptFloat, '%.4g', width_chars=8), vh) 99 self.btnSetAmp = pack_button('Set amp', vh, at_end=True, on_click=self.__onClickSetAmp) 100 101 vh = pack_item(gtk.HBox(), v) 102 pack_label('Calculate stats (e.g. occupancy):', vh) 103 self.btnIdlStatSeg = pack_button('of Segments', vh, at_end=True, on_click=self.__onClickIdlStatSeg) 104 self.btnIdlStatList = pack_button('of List', vh, at_end=True, on_click=self.__onClickIdlStatList) 105 106 vh = pack_item(gtk.HBox(), v) 107 pack_label('Calculate stability (stats over time):', vh) 108 self.btnStability = pack_button('Stability...', vh, at_end=True, on_click=self.onClickStability) 109 110 vh = pack_item(gtk.HBox(), v) 111 pack_label('Save as DWT:', vh) 112 self.btnSaveDWTStats = pack_button('With event stats...', vh, at_end=True, on_click=bind_with_args_before(self.onClickSaveDWT, True)) 113 self.btnSaveDWT = pack_button('Standard...', vh, at_end=True, on_click=bind_with_args_before(self.onClickSaveDWT, False)) 114 115 vh = pack_item(gtk.HBox(), v) 116 pack_label('Save as sampled text:', vh) 117 self.btnSaveSampledAmp = pack_button('by class amp...', vh, at_end=True, on_click=bind_with_args_before(self.onClickSaveSampled, True)) 118 self.btnSaveSampledIndex = pack_button('by class index...', vh, at_end=True, on_click=bind_with_args_before(self.onClickSaveSampled, False)) 119 120 vh = pack_item(gtk.HBox(), v) 121 pack_label('Clear idealization:', vh) 122 self.btnClearFile = pack_button('Whole file', vh, at_end=True, on_click=bind_with_args_before(self.onClickClear, True)) 123 self.btnClearScreen = pack_button('On-screen', vh, at_end=True, on_click=bind_with_args_before(self.onClickClear, False)) 124 125 vh = pack_item(gtk.HBox(), v) 126 pack_label('Make List:', vh) 127 self.btnChop = pack_button('of Bursts (Chop)', vh, at_end=True, on_click=self.onClickChop) 128 self.btnChop = pack_button('of Transitions', vh, at_end=True, on_click=self.onClickListTransitions) 129 self.btnChop = pack_button('of Events', vh, at_end=True, on_click=self.onClickListEvents) 130 131 qubx.notebook.Notebook.register_auto('IdealStat.Segments', 'Segments table, on idealize/get stats', True) 132 qubx.notebook.Notebook.register_auto('IdealStat.List', 'List table, on idealize/get stats', True)
133
134 - def __onClickIdlStatSeg(self, btn):
135 qubx.pyenv.env.OnScriptable('QubX.Data.view.measure_segments(QubX.DataSource.get_segmentation_file(), script_name="Idealized.py")') 136 self.QubX.Data.view.measure_segments(self.QubX.DataSource.get_segmentation(), script_name='Idealized.py') 137 self.QubX.Tables.show_table(self.QubX.Data.file.segments, show_tables=True)
138 - def __onClickIdlStatList(self, btn):
139 qubx.pyenv.env.OnScriptable('QubX.Data.view.measure_list(QubX.Data.file.list, script_name="Idealized.py")') 140 self.QubX.Data.view.measure_list(self.QubX.Data.file.list, script_name='Idealized.py', wait=False, 141 receiver=lambda tbl, off, ct: self.QubX.Tables.show_table(tbl, show_tables=True))
142 - def onClickStability(self, btn):
143 dlg = gtk.Dialog('Calculate stability...', self.parent_window, gtk.DIALOG_MODAL) 144 line = pack_item(gtk.HBox(), dlg.vbox) 145 pack_label('Builds a list of overlapping selections and measures them.', line) 146 line = pack_item(gtk.HBox(), dlg.vbox) 147 pack_label('Window size:', line) 148 txtWindow = pack_item(qubx.GTK.NumEntry(self.stab_window, acceptIntGreaterThan(0), width_chars=6), line) 149 pack_label('events', line) 150 line = pack_item(gtk.HBox(), dlg.vbox) 151 pack_label('Overlap:', line) 152 txtOverlap = pack_item(qubx.GTK.NumEntry(self.stab_overlap, acceptIntGreaterThan(0), width_chars=6), line) 153 pack_label('events', line) 154 line = pack_item(gtk.HBox(), dlg.vbox) 155 pack_label('Output list name:', line) 156 txtListName = pack_item(qubx.GTK.NumEntry(self.stab_listname), line, expand=True) 157 dlg.add_button('Cancel', gtk.RESPONSE_REJECT) 158 dlg.add_button('Run', gtk.RESPONSE_ACCEPT) 159 response = dlg.run() 160 window_size = txtWindow.value 161 overlap = txtOverlap.value 162 listname = txtListName.value or self.stab_listname 163 dlg.destroy() 164 165 if window_size != self.stab_window: 166 self.propertied_on_user_set('stab_window', window_size) 167 if overlap != self.stab_overlap: 168 self.propertied_on_user_set('stab_overlap', overlap) 169 if listname != self.stab_listname: 170 self.propertied_on_user_set('stab_listname', listname) 171 172 qubx.pyenv.env.OnScriptable('%s.calc_stability(window_size=%i, overlap=%i, listname=%s)' % (self.global_name, window_size, overlap, repr(listname))) 173 self.calc_stability(window_size, overlap, listname, wait=False)
174 - def calc_stability(self, window_size=None, overlap=None, listname=None, wait=True, receiver=lambda: None):
175 if wait: 176 return qubx.pyenv.call_async_wait(lambda rcv: self.calc_stability(window_size, overlap, listname, wait=False, receiver=rcv)) 177 self.btnStability.set_sensitive(False) 178 ws = self.stab_window if (window_size is None) else window_size 179 ol = self.stab_overlap if (overlap is None) else overlap 180 ln = self.stab_listname if (listname is None) else listname 181 QubX = qubx.global_namespace.QubX 182 segs = QubX.DataSource.get_segmentation() 183 idl = [seg.get_idealization(get_fragments=True) for seg in segs] # (ff, ll, cc) 184 lst = QubX.Data.file.lists.show_list(ln) 185 lst.clear() 186 task = StabilityTask(segs, idl, ws, ol, lst, receiver) 187 task.OnException += task_exception_to_console 188 task.start()
189 - def onClickSaveDWT(self, btn, with_stats):
190 qubx.GTK.SaveAs('Save DWT as...', self.QubX.Data.path, os.path.splitext(os.path.split(self.QubX.Data.file.path)[1])[0], 191 lambda fname: self.save_dwt_clicked(fname, with_stats), 192 filters=[('DWT files', '.dwt')], parent=self.parent_window)
193 - def save_dwt_clicked(self, fname, with_stats):
194 if not fname: return 195 self.QubX.Data.path = os.path.split(fname)[0] 196 if not os.path.splitext(fname)[1]: 197 fname = fname + '.dwt' 198 qubx.pyenv.env.OnScriptable('QubX.Tools.Idealization.save_dwt(%s, with_stats=%s)' % (repr(fname), repr(with_stats))) 199 self.save_dwt(fname, with_stats)
200 - def save_dwt(self, fname, with_stats):
201 self.busy_dwt_fname = fname 202 self.busy_dwt_stats = with_stats 203 dlg = qubx.GTK.BusyDialog('Saving %s...'%os.path.split(fname)[1], self.busy_save_dwt) 204 dlg.set_size_request(300, 75) 205 try: 206 dlg.run() 207 except Exception, e: 208 traceback.print_exc() 209 mdlg = gtk.MessageDialog(qubx.GTK.get_active_window(), buttons=gtk.BUTTONS_OK, flags=gtk.DIALOG_MODAL, 210 message_format=str(e)) 211 mdlg.run() 212 mdlg.destroy() 213 dlg.destroy()
214 - def busy_save_dwt(self, progress):
215 fname = self.busy_dwt_fname 216 with_stats = self.busy_dwt_stats 217 signal = self.QubX.DataSource.signal 218 segs = self.get_segmentation_idl(self.QubX.Data.view.get_segmentation_file()) 219 if not segs: return 220 fi = open(fname, "w") 221 points_f = segs[0].f 222 points_n = segs[-1].l - points_f + 1 223 for s, seg in enumerate(segs): 224 if not progress((seg.f - points_f) * 1.0 / points_n): 225 break 226 Nclass = numpy.max(seg.classes) + 1 227 amp = seg.file.ideal[signal].seg[seg.index].amp 228 std = seg.file.ideal[signal].seg[seg.index].std 229 fi.write("Segment: %d Dwells: %d Sampling(ms): %.10g Start(ms): %.10g ClassCount: %d" % (s+1, len(seg.firsts), seg.file.sampling*1e3, seg.start, Nclass)) 230 for c in xrange(Nclass): 231 a = amp[c] if c < len(amp) else 0.0 232 s = std[c] if c < len(std) else 0.0 233 fi.write(" %.10g %.10g" % (a, s)) 234 fi.write("\n") 235 if with_stats: 236 samples = seg.get_samples().samples 237 means = [samples[seg.firsts[i]-seg.f:seg.lasts[i]+1-seg.f].mean() for i in xrange(len(seg.firsts))] 238 stds = [samples[seg.firsts[i]-seg.f:seg.lasts[i]+1-seg.f].std() for i in xrange(len(seg.firsts))] 239 for i in xrange(len(seg.firsts)): 240 stats = with_stats and ("\t%.10g\t%.10g" % (means[i], stds[i])) or "" 241 fi.write("%d\t%.10g%s\n" % (seg.classes[i], seg.durations[i], stats))
242 # complain on zero events?
243 - def onClickSaveSampled(self, btn, lookup_amps):
244 qubx.GTK.SaveAs('Save Sampled idl as...', self.QubX.Data.path, os.path.splitext(os.path.split(self.QubX.Data.file.path)[1])[0], 245 lambda fname: self.save_sampled_clicked(fname, lookup_amps), 246 filters=[('Text files', '.txt')], parent=self.parent_window)
247 - def save_sampled_clicked(self, fname, lookup_amps):
248 if not fname: return 249 if not os.path.splitext(fname)[1]: 250 fname = fname + '.txt' 251 self.QubX.Data.path = os.path.split(fname)[0] 252 qubx.pyenv.env.OnScriptable('QubX.Tools.Idealization.save_sampled(%s, lookup_amps=%s)' % (repr(fname), repr(lookup_amps))) 253 self.save_sampled(fname, lookup_amps)
254 - def save_sampled(self, fname, lookup_amps):
255 self.busy_sam_fname = fname 256 self.busy_sam_amps = lookup_amps 257 dlg = qubx.GTK.BusyDialog('Saving %s...'%os.path.split(fname)[1], self.busy_save_sampled) 258 dlg.set_size_request(300, 75) 259 try: 260 dlg.run() 261 except Exception, e: 262 traceback.print_exc() 263 mdlg = gtk.MessageDialog(qubx.GTK.get_active_window(), buttons=gtk.BUTTONS_OK, flags=gtk.DIALOG_MODAL, 264 message_format=str(e)) 265 mdlg.run() 266 mdlg.destroy() 267 dlg.destroy()
268 - def busy_save_sampled(self, progress):
269 fname = self.busy_sam_fname 270 lookup_amps = self.busy_sam_amps 271 signal = self.QubX.DataSource.signal 272 segs = self.get_segmentation_idl(self.QubX.Data.view.get_segmentation_file()) 273 if not segs: return 274 sampling = segs[0].file.sampling 275 fi = open(fname, "w") 276 points_f = segs[0].f 277 points_n = segs[-1].l - points_f + 1 278 for s, seg in enumerate(segs): 279 if not progress((seg.f - points_f) * 1.0 / points_n): 280 break 281 if s: 282 fi.write('\n') 283 if lookup_amps: 284 amps = numpy.array(seg.file.ideal[signal].seg[seg.index].amp) 285 classes = amps[seg.classes] 286 else: 287 classes = seg.classes 288 t = seg.start * 1e-3 289 for i in xrange(len(seg.firsts)): 290 x = classes[i] 291 for j in xrange(seg.lasts[i] - seg.firsts[i] + 1): 292 fi.write("%f\t%s\n" % (t, x)) 293 t += sampling
294 - def onClickClear(self, btn, whole_file):
295 qubx.pyenv.env.OnScriptable('QubX.Tools.Idealization.clear(whole_file=%s)' % repr(whole_file)) 296 self.clear(whole_file)
297 - def clear(self, whole_file):
298 signal = self.QubX.DataSource.signal 299 file = self.QubX.Data.file 300 if whole_file: 301 file.ideal[signal].idl.clear() 302 else: 303 for seg in self.QubX.Data.view.get_segmentation_hires(): 304 file.ideal[signal].idl.set_dwell(seg.f, seg.l, -1) 305 file.OnChangeIdealization(file, signal)
306 - def __onClickDeadTime(self, btn):
307 qubx.pyenv.env.OnScriptable('QubX.Tools.Idealization.apply_dead_time(td_ms=%s)' % repr(self.txtDeadTime.value)) 308 self.apply_dead_time(self.txtDeadTime.value)
309 - def apply_dead_time(self, td_ms):
310 dlg = qubx.GTK.BusyDialog('Applying dead time', lambda progress: self.busy_dead_time(progress, td_ms)) 311 dlg.set_size_request(300, 75) 312 try: 313 dlg.run() 314 except Exception, e: 315 traceback.print_exc() 316 mdlg = gtk.MessageDialog(qubx.GTK.get_active_window(), buttons=gtk.BUTTONS_OK, flags=gtk.DIALOG_MODAL, 317 message_format=str(e)) 318 mdlg.run() 319 mdlg.destroy() 320 dlg.destroy()
321 - def busy_dead_time(self, progress, td_ms):
322 segs = self.get_segmentation_idl(self.QubX.DataSource.get_segmentation()) 323 if not segs: return 324 td_samples = td_ms / (1e3 * segs[0].file.sampling) 325 points_f = segs[0].f 326 points_n = segs[-1].l - points_f + 1 327 for seg in segs: 328 if not progress((seg.f - points_f) * 1.0 / points_n): 329 break 330 ff, ll, cc = seg.firsts, seg.lasts, seg.classes 331 n = len(ff) 332 i_in = 0 333 while i_in < n: 334 n_here = (ll[i_in] - ff[i_in] + 1) 335 if (n_here > td_samples) or (fulpdiff(n_here, td_samples) < MAX_ULP_DIFF): 336 break 337 i_in += 1 338 if i_in: 339 ll[0] = ll[i_in-1] 340 cc[0] = -1 341 i_out = 1 342 else: 343 i_out = 0 344 while i_in < n: 345 cls = cc[i_in] 346 dur = (ll[i_in] - ff[i_in] + 1) 347 if (cc[i_out] == cls) or ((dur < td_samples) and (fulpdiff(dur, td_samples) > MAX_ULP_DIFF)): 348 ll[i_out] = ll[i_in] 349 else: 350 i_out += 1 351 if i_out < n: 352 ff[i_out] = ff[i_in] 353 ll[i_out] = ll[i_in] 354 cc[i_out] = cls 355 i_in += 1 356 n = i_out + 1 357 seg.file.ideal[seg.signal].idl.set_dwells(n, ff, ll, cc) 358 segs[0].file.OnChangeIdealization(segs[0].file, segs[0].signal)
359 - def __onClickChangeClass(self, btn):
360 cls_from = self.txtChangeFrom.value 361 cls_to = self.txtChangeTo.value 362 qubx.pyenv.env.OnScriptable('QubX.Tools.Idealization.change_class(cls_from=%i, cls_to=%i)' % (cls_from, cls_to)) 363 self.change_class(cls_from, cls_to)
364 - def change_class(self, cls_from, cls_to):
365 dlg = qubx.GTK.BusyDialog('Changing class of events', lambda progress: self.busy_change_class(progress, cls_from, cls_to)) 366 dlg.set_size_request(300, 75) 367 try: 368 dlg.run() 369 except Exception, e: 370 traceback.print_exc() 371 mdlg = gtk.MessageDialog(qubx.GTK.get_active_window(), buttons=gtk.BUTTONS_OK, flags=gtk.DIALOG_MODAL, 372 message_format=str(e)) 373 mdlg.run() 374 mdlg.destroy() 375 dlg.destroy()
376 - def busy_change_class(self, progress, cls_from, cls_to):
377 segs = self.get_segmentation_idl(self.QubX.DataSource.get_segmentation()) 378 if not segs: return 379 points_f = segs[0].f 380 points_n = segs[-1].l - points_f + 1 381 for seg in segs: 382 if not progress((seg.f - points_f) * 1.0 / points_n): 383 break 384 ff, ll, cc = seg.firsts, seg.lasts, seg.classes 385 n = len(ff) 386 for i in xrange(n): 387 if cc[i] == cls_from: 388 cc[i] = cls_to 389 seg.file.ideal[seg.signal].idl.set_dwells(n, ff, ll, cc) 390 segs[0].file.OnChangeIdealization(segs[0].file, segs[0].signal)
391 - def __onClickFillBlanks(self, btn):
392 cls_fill = self.txtFillClass.value 393 qubx.pyenv.env.OnScriptable('QubX.Tools.Idealization.fill_blanks(cls_fill=%i)' % cls_fill) 394 self.fill_blanks(cls_fill)
395 - def fill_blanks(self, cls_fill):
396 dlg = qubx.GTK.BusyDialog('Filling blanks', lambda progress: self.busy_fill_blanks(progress, cls_fill)) 397 dlg.set_size_request(300, 75) 398 try: 399 dlg.run() 400 except Exception, e: 401 traceback.print_exc() 402 mdlg = gtk.MessageDialog(qubx.GTK.get_active_window(), buttons=gtk.BUTTONS_OK, flags=gtk.DIALOG_MODAL, 403 message_format=str(e)) 404 mdlg.run() 405 mdlg.destroy() 406 dlg.destroy()
407 - def busy_fill_blanks(self, progress, cls_fill):
408 segs = self.QubX.DataSource.get_segmentation() 409 if not segs: return 410 points_f = segs[0].f 411 points_n = segs[-1].l - points_f + 1 412 for seg in segs: 413 if not progress((seg.f - points_f) * 1.0 / points_n): 414 break 415 ff, ll, cc = seg.get_idealization(get_fragments=True) 416 n = len(ff) 417 for i in xrange(n): 418 if cc[i] < 0: 419 cc[i] = cls_fill 420 seg.file.ideal[seg.signal].idl.set_dwells(n, ff, ll, cc) 421 segs[0].file.OnChangeIdealization(segs[0].file, segs[0].signal)
422 - def __onClickJoinClass(self, btn):
423 cls_join = self.txtJoinClass.value 424 qubx.pyenv.env.OnScriptable('QubX.Tools.Idealization.join_class(cls_join=%i)' % cls_join) 425 self.join_class(cls_join)
426 - def join_class(self, cls_join):
427 dlg = qubx.GTK.BusyDialog('Joining events', lambda progress: self.busy_join_class(progress, cls_join)) 428 dlg.set_size_request(300, 75) 429 try: 430 dlg.run() 431 except Exception, e: 432 traceback.print_exc() 433 mdlg = gtk.MessageDialog(qubx.GTK.get_active_window(), buttons=gtk.BUTTONS_OK, flags=gtk.DIALOG_MODAL, 434 message_format=str(e)) 435 mdlg.run() 436 mdlg.destroy() 437 dlg.destroy()
438 - def busy_join_class(self, progress, cls_join):
439 segs = self.get_segmentation_idl(self.QubX.DataSource.get_segmentation()) 440 if not segs: return 441 points_f = segs[0].f 442 points_n = segs[-1].l - points_f + 1 443 for seg in segs: 444 if not progress((seg.f - points_f) * 1.0 / points_n): 445 break 446 ff, ll, cc = seg.firsts, seg.lasts, seg.classes 447 cls_last = seg.f and seg.file.ideal[seg.signal].idl[seg.f-1] or -1 448 n = len(ff) 449 for i in xrange(n): 450 if cc[i] == cls_join: 451 cc[i] = cls_last 452 else: 453 cls_last = cc[i] 454 seg.file.ideal[seg.signal].idl.set_dwells(n, ff, ll, cc) 455 segs[0].file.OnChangeIdealization(segs[0].file, segs[0].signal)
456 - def __onClickSetAmp(self, btn):
457 cls = self.txtSetAmpClass.value 458 amp = self.txtSetAmpTo.value 459 qubx.pyenv.env.OnScriptable('QubX.Tools.Idealization.set_amp(cls=%i, amp=%s)' % (cls, repr(amp))) 460 self.set_amp(cls, amp)
461 - def set_amp(self, cls, amp):
462 segs = self.QubX.DataSource.get_segmentation() 463 if not segs: return 464 for seg in segs: 465 amps = seg.file.ideal[seg.signal].seg[seg.index].amp 466 if (not (amps is None)) and (len(amps) > cls): 467 amps[cls] = amp 468 segs[0].file.OnChangeIdealization(segs[0].file, segs[0].signal)
469 - def onClickChop(self, btn):
470 qubx.chop.Chop(silent=False, chop=qubx.chop.CHOP_IDL)
471 - def onClickListEvents(self, btn):
472 response = qubx.GTK.PromptEntries([('List events in class:', self.list_events_class, acceptIntGreaterThanOrEqualTo(0), str), 473 ('Output list name:', self.list_events_name, str, str)], 474 'Make List of Events', self.parent_window) 475 if response and response[1]: 476 self.list_events_class = response[0] 477 self.list_events_name = response[1] 478 qubx.pyenv.env.OnScriptable('QubX.Tools.Idealization.list_events(class_index=%s, output_list_name=%s)' % (self.list_events_class, repr(self.list_events_name))) 479 self.list_events()
480 - def list_events(self, class_index=None, output_list_name=None):
481 cls = class_index 482 if cls is None: 483 cls = self.list_events_class 484 list_name = output_list_name or self.list_events_name 485 dlg = qubx.GTK.BusyDialog('Listing events...', lambda progress: self.busy_list_events(cls, list_name, progress)) 486 dlg.set_size_request(300, 75) 487 try: 488 dlg.run() 489 except Exception, e: 490 traceback.print_exc() 491 mdlg = gtk.MessageDialog(qubx.GTK.get_active_window(), buttons=gtk.BUTTONS_OK, flags=gtk.DIALOG_MODAL, 492 message_format=str(e)) 493 mdlg.run() 494 mdlg.destroy() 495 dlg.destroy()
496 - def busy_list_events(self, cls, list_name, progress):
497 lst = self.QubX.Data.file.lists.show_list(list_name) 498 lst.clear() 499 segs = self.QubX.DataSource.get_segmentation() 500 for s, seg in enumerate(segs): 501 if not progress( s * 1.0 / len(segs) ): return 502 for c, chunk in enumerate(seg.chunks): 503 if chunk.included: 504 ff, ll, cc = chunk.get_idealization(get_fragments=True, get_durations=False) 505 for i, f, l, c in izip(count(), ff, ll, cc): 506 if c == cls: 507 lst.insert_selection(f, l)
508 - def onClickListTransitions(self, btn):
509 response = qubx.GTK.PromptEntries([('List transitions from class:', self.list_trans_from, acceptIntGreaterThanOrEqualTo(0), str), 510 ('to class:', self.list_trans_to, acceptIntGreaterThanOrEqualTo(0), str), 511 ('msec before each transition:', self.list_trans_pre, acceptFloatGreaterThanOrEqualTo(0.0), '%.3g'), 512 ('Output list name:', self.list_trans_name, str, str)], 513 'Make List of Events', self.parent_window) 514 if response and response[3]: 515 self.list_trans_from, self.list_trans_to, self.list_trans_pre, self.list_trans_name = response 516 qubx.pyenv.env.OnScriptable('QubX.Tools.Idealization.list_transitions(class_from=%s, class_to=%s, msec_before=%s, output_list_name=%s)' % (self.list_trans_from, self.list_trans_to, self.list_trans_pre, repr(self.list_trans_name))) 517 self.list_transitions()
518 - def list_transitions(self, class_from=None, class_to=None, msec_before=None, output_list_name=None):
519 cls_from = class_from 520 if cls_from is None: 521 cls_from = self.list_trans_from 522 cls_to = class_to 523 if cls_to is None: 524 cls_to = self.list_trans_to 525 samples_pre = msec_before 526 if samples_pre is None: 527 samples_pre = self.list_trans_pre 528 samples_pre = int(round(samples_pre * 1e-3 / self.QubX.Data.file.sampling)) 529 list_name = output_list_name or self.list_trans_name 530 dlg = qubx.GTK.BusyDialog('Listing transitions...', lambda progress: self.busy_list_transitions(cls_from, cls_to, samples_pre, list_name, progress)) 531 dlg.set_size_request(300, 75) 532 try: 533 dlg.run() 534 except Exception, e: 535 traceback.print_exc() 536 mdlg = gtk.MessageDialog(qubx.GTK.get_active_window(), buttons=gtk.BUTTONS_OK, flags=gtk.DIALOG_MODAL, 537 message_format=str(e)) 538 mdlg.run() 539 mdlg.destroy() 540 dlg.destroy()
541 - def busy_list_transitions(self, cls_from, cls_to, samples_pre, list_name, progress):
542 lst = self.QubX.Data.file.lists.show_list(list_name) 543 lst.clear() 544 segs = self.QubX.DataSource.get_segmentation() 545 for s, seg in enumerate(segs): 546 if not progress( s * 1.0 / len(segs) ): return 547 for c, chunk in enumerate(seg.chunks): 548 if chunk.included: 549 ff, ll, cc = chunk.get_idealization(get_fragments=True, get_durations=False) 550 for i, f, l, c in izip(count(), ff, ll, cc): 551 if i == 0: continue 552 if (c == cls_to) and (cc[i-1] == cls_from): 553 lst.insert_selection(max(ff[i-1], f-samples_pre), l)
554 - def get_segmentation_idl(self, segs):
555 if not segs: return [] 556 # split into regions of cls >= 0 557 idlsegs = [] 558 for seg in segs: 559 seg.firsts, seg.lasts, seg.classes, seg.durations = seg.get_idealization(get_fragments=True, get_durations=True) 560 if numpy.any(seg.classes < 0): 561 ndwell = len(seg.lasts) 562 inext = 0 563 while inext < ndwell: 564 ifirst = inext 565 while (ifirst < ndwell) and (seg.classes[ifirst] < 0): 566 ifirst += 1 567 inext = ifirst + 1 568 while (inext < ndwell) and (seg.classes[inext] >= 0): 569 inext += 1 570 if ifirst < ndwell: 571 idlseg = qubx.data_types.SourceSeg(file=seg.file, signal=seg.signal, f=seg.firsts[ifirst], 572 l=seg.lasts[inext-1], index=seg.index, offset=seg.offset, 573 start=seg.start+(seg.firsts[ifirst]-seg.f)*1e3*seg.file.sampling, 574 latency=seg.latency, filter_Hz=seg.filter_Hz) 575 idlseg.firsts = numpy.array(seg.firsts[ifirst:inext]) 576 idlseg.lasts = numpy.array(seg.lasts[ifirst:inext]) 577 idlseg.classes = numpy.array(seg.classes[ifirst:inext]) 578 idlseg.durations = numpy.array(seg.durations[ifirst:inext]) 579 idlsegs.append(idlseg) 580 else: 581 idlsegs.append(seg) 582 return idlsegs
583
584 -def task_exception_to_console(task, typ, val, tb):
585 traceback.print_exception(typ, val, tb)
586
587 -class StabilityTask(qubx.task.Task):
588 - def __init__(self, segs, idl, window_size, overlap, lst, receiver):
589 qubx.task.Task.__init__(self, 'Stability') 590 self.segs = segs 591 self.idl = idl 592 self.window_size = window_size 593 self.overlap = overlap 594 self.lst = lst 595 self.receiver = receiver
596 - def run(self):
597 QubX = qubx.global_namespace.QubX 598 window_size = self.window_size 599 overlap = self.overlap 600 qubx.task.Tasks.add_task(self) 601 self.status = 'Running...' 602 try: 603 n = 0 604 done = 0 605 sels = [] 606 for ff, ll, cc in self.idl: 607 n += len(ff) 608 for ff, ll, cc in self.idl: 609 n_in_seg = len(ff) 610 for i in xrange(0, n_in_seg-window_size, overlap): 611 sels.append((ff[i], ll[min(n_in_seg, i+window_size)-1])) 612 if not (i % 20*overlap): 613 self.progress = (done + i) * 50.0 / n 614 done += n_in_seg 615 rcv = self.receiver 616 self.receiver = None # fill_and_measure will call it; avoid double-invocation in finally 617 gobject.idle_add(fill_and_measure_list, self.lst, sels, rcv) 618 finally: 619 try: 620 QubX.Tools.Idealization.btnStability.set_sensitive(True) 621 except: 622 pass 623 if self.receiver: 624 gobject.idle_add(self.receiver) 625 qubx.task.Tasks.remove_task(self)
626
627 -def fill_and_measure_list(lst, sels, receiver=lambda: None):
628 QubX = qubx.global_namespace.QubX 629 try: 630 for f, l in sels: 631 lst.insert_selection(f, l) 632 QubX.Data.view.measure_list(lst, script_name='Idealized.py') 633 QubX.Data.file.lists.show_list(lst.list_name) 634 finally: 635 gobject.idle_add(receiver)
636