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

Source Code for Module qubx.ideal

  1  #!/usr/bin/env python 
  2   
  3  """ 
  4  Interface to the U{qubidl<http://www.qub.buffalo.edu/src/qub-express/api/qubfast/qubidl.h.html>} module (in the qubfast library) 
  5  for efficiently handling sequences of dwells. 
  6   
  7  An Idealization assigns each sample to one of a limited number of Classes, 
  8  then condenses this sequence of sampled Classes into a sequence of Dwells: 
  9  { which class; start sample index; end sample index (inclusive) } 
 10  Classes are numbered contiguously starting with 0. 
 11  This module keeps track of each Class's {mean amplitude; standard deviation}. 
 12   
 13  Previously, Idealizations had been stored as parallel arrays: 
 14   
 15  >>> int class[] 
 16  >>> int first[] 
 17  >>> int last[] 
 18  >>> (and/or float duration[]) 
 19   
 20   
 21  There were problems with this approach: 
 22     - editing a portion could change the number of dwells, 
 23       requiring shifts and/or reallocation 
 24     - to read the dwells for samples k through m, 
 25       we had to search for the first dwell, 
 26       since dwell index doesn't correlate with sample index 
 27   
 28  To address these, we use data structures with log(N) edits and seeks 
 29  (at the core, we use the STL map), 
 30  and move "chunks" of idealization between storage levels: 
 31      - in STL maps: efficient editing and seeking; biggest memory footprint 
 32      - in arrays:   no editing beyond full replacement; smaller memory footprint 
 33   
 34  The idealization is divided into chunks of QUB_IDLSEG_CHUNKSIZE samples: 
 35      - for lookup: dwells for sample k are in chunk (k >> QUB_IDLSEG_CHUNKSHIFT) 
 36      - for map traversal and editing: N events take N log N time, 
 37        but since there are only so many events per map, 
 38        it becomes N log M, where log M has a constant upper bound 
 39      - for multiple storage levels: only the relevant chunks need to be loaded 
 40        for reading, or upgraded to "map" for editing. 
 41   
 42  The chunk size has been experimentally tuned to handle fast data smoothly, 
 43  but maybe wants adjustment for newer hardware?; 
 44  adjust QUB_IDLSEG_CHUNKSHIFT (log2(_CHUNKSIZE)) in qubidl.cpp. 
 45   
 46  The IdlMaps object manages one or more chunks. 
 47   
 48  Every sample is said to belong to a class.  Un-idealized samples belong to dwells 
 49  of class -1. 
 50   
 51  .begin(), .find(), and .end() return iterator objects.  They don't necessarily iterate 
 52  over entire dwells; long dwells are broken at chunk boundaries, resulting in a string 
 53  of dwells of the same class -- to the user they should be represented as one dwell. 
 54   
 55  Copyright 2008-2012 Research Foundation State University of New York  
 56  This file is part of QUB Express.                                           
 57   
 58  QUB Express is free software; you can redistribute it and/or modify           
 59  it under the terms of the GNU General Public License as published by  
 60  the Free Software Foundation, either version 3 of the License, or     
 61  (at your option) any later version.                                   
 62   
 63  QUB Express is distributed in the hope that it will be useful,                
 64  but WITHOUT ANY WARRANTY; without even the implied warranty of        
 65  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         
 66  GNU General Public License for more details.                          
 67   
 68  You should have received a copy of the GNU General Public License,    
 69  named LICENSE.txt, in the QUB Express program directory.  If not, see         
 70  <http://www.gnu.org/licenses/>.                                       
 71   
 72   
 73  """ 
 74   
 75  # we use this ctypes mess to make a nice python/numpy wrapper (below) 
 76   
 77  from ctypes import cdll, c_void_p, c_int, c_uint, c_double, c_float, POINTER, byref 
 78  from qubx.fast.fast_utils import qubfast as qubidl 
 79  c_int_p = POINTER(c_int) 
 80  c_uint_p = POINTER(c_uint) 
 81  c_float_p = POINTER(c_float) 
 82  c_double_p = POINTER(c_double) 
 83   
 84  import numpy 
 85  import sys 
 86  from itertools import izip 
 87   
 88  qubidl.qubidl_create.argtypes = (c_double,) 
 89  qubidl.qubidl_create.restype = c_void_p 
 90  qubidl.qubidl_destroy.argtypes = (c_void_p,) 
 91  qubidl.qubidl_destroy.restype = None 
 92   
 93  qubidl.qubidl_get_sampling.argtypes = (c_void_p,) 
 94  qubidl.qubidl_get_sampling.restype = c_double 
 95  qubidl.qubidl_set_sampling.argtypes = (c_void_p, c_double) 
 96  qubidl.qubidl_set_sampling.restype = None 
 97   
 98  qubidl.qubidl_get_seg_count.argtypes = (c_void_p,) 
 99  qubidl.qubidl_get_seg_count.restype = c_int 
100  qubidl.qubidl_get_seg_first.argtypes = (c_void_p, c_int) 
101  qubidl.qubidl_get_seg_first.restype = c_int 
102  qubidl.qubidl_get_seg_last.argtypes = (c_void_p, c_int) 
103  qubidl.qubidl_get_seg_last.restype = c_int 
104   
105  qubidl.qubidl_count_dwells.argtypes = (c_void_p, c_int, c_int, c_int) 
106  qubidl.qubidl_count_dwells.restype = c_int 
107  qubidl.qubidl_get_dwells.argtypes = (c_void_p, c_int, c_int, c_int, c_int_p, c_int_p, c_int_p, c_float_p) 
108  qubidl.qubidl_get_dwells.restype = c_int 
109  qubidl.qubidl_set_dwells.argtypes = (c_void_p, c_int, c_int_p, c_int_p, c_int_p) 
110  qubidl.qubidl_set_dwells.restype = None 
111  qubidl.qubidl_sample_dwells.argtypes = (c_void_p, c_int, c_int, c_double_p, c_int, c_float_p, c_float_p) 
112  qubidl.qubidl_sample_dwells.restype = None 
113  qubidl.qubidl_sample_dwells_classes.argtypes = (c_void_p, c_int, c_int, c_double_p, c_int, c_float_p, c_float_p, c_uint_p) 
114  qubidl.qubidl_sample_dwells_classes.restype = None 
115  qubidl.qubidl_sample_dwells_std.argtypes = (c_void_p, c_int, c_int, c_float_p, c_float_p, c_int, c_float_p, c_float_p) 
116  qubidl.qubidl_sample_dwells_std.restype = None 
117  qubidl.qubidl_count_dwells_and_gaps.argtypes = (c_void_p, c_int, c_int) 
118  qubidl.qubidl_count_dwells_and_gaps.restype = c_int 
119  qubidl.qubidl_get_dwells_and_gaps.argtypes = (c_void_p, c_int, c_int, c_int_p, c_int_p, c_int_p, c_float_p) 
120  qubidl.qubidl_get_dwells_and_gaps.restype = c_int 
121   
122  qubidl.qubidl_clear.argtypes = (c_void_p,) 
123  qubidl.qubidl_clear.restype = None 
124  qubidl.qubidl_add_seg.argtypes = (c_void_p, c_int, c_int) 
125  qubidl.qubidl_add_seg.restype = None 
126  qubidl.qubidl_erase.argtypes = (c_void_p, c_int, c_int) 
127  qubidl.qubidl_erase.restype = None 
128  qubidl.qubidl_join.argtypes = (c_void_p, c_int, c_int) 
129  qubidl.qubidl_join.restype = None 
130   
131  qubidl.qubidl_begin.argtypes = (c_void_p,) 
132  qubidl.qubidl_begin.restype = c_void_p 
133  qubidl.qubidl_end.argtypes = (c_void_p,) 
134  qubidl.qubidl_end.restype = c_void_p 
135  qubidl.qubidl_find.argtypes = (c_void_p, c_int) 
136  qubidl.qubidl_find.restype = c_void_p 
137  qubidl.qubidl_iter_clone.argtypes = (c_void_p,) 
138  qubidl.qubidl_iter_clone.restype = c_void_p 
139  qubidl.qubidl_iter_destroy.argtypes = (c_void_p,) 
140  qubidl.qubidl_iter_destroy.restype = None 
141  qubidl.qubidl_iter_valid.argtypes = (c_void_p,) 
142  qubidl.qubidl_iter_valid.restype = c_int 
143  qubidl.qubidl_iter_equals.argtypes = (c_void_p, c_void_p) 
144  qubidl.qubidl_iter_equals.restype = c_int 
145  qubidl.qubidl_iter_segindex.argtypes = (c_void_p,) 
146  qubidl.qubidl_iter_segindex.restype = c_int 
147  qubidl.qubidl_iter_segfirst.argtypes = (c_void_p,) 
148  qubidl.qubidl_iter_segfirst.restype = c_int 
149  qubidl.qubidl_iter_read.argtypes = (c_void_p, c_int_p, c_int_p, c_int_p) 
150  qubidl.qubidl_iter_read.restype = None 
151  qubidl.qubidl_iter_next.argtypes = (c_void_p,) 
152  qubidl.qubidl_iter_next.restype = None 
153  qubidl.qubidl_iter_prev.argtypes = (c_void_p,) 
154  qubidl.qubidl_iter_prev.restype = None 
155   
156   
157 -class Idealization(object):
158 - def __init__(self, sampling):
159 """Creates a new zero-length Idealization. 160 @param sampling: shortest measured duration, usually in milliseconds 161 """ 162 self.idl = qubidl.qubidl_create(sampling)
163 - def __del__(self):
164 qubidl.qubidl_destroy(self.idl)
165 - def __getitem__(self, key):
166 """Returns the class at sample key.""" 167 iter = self.find(int(key)) 168 if iter: 169 return iter.read()[2] # cls at int(key) 170 else: 171 return -1
172 - def get_sampling(self):
173 """Returns sampling, usually in milliseconds.""" 174 return qubidl.qubidl_get_sampling(self.idl)
175 - def set_sampling(self, sampling):
176 """Sets sampling, usually in milliseconds.""" 177 qubidl.qubidl_set_sampling(self.idl, sampling)
178 sampling = property(lambda self: self.get_sampling(), lambda self, x: self.set_sampling(x))
179 - def get_seg_count(self):
180 """Returns the number of segments.""" 181 return qubidl.qubidl_get_seg_count(self.idl)
182 - def get_seg_first(self, i):
183 """Returns the first sample index in segment i.""" 184 return qubidl.qubidl_get_seg_first(self.idl, i)
185 - def get_seg_last(self, i):
186 """Returns the last sample index in segment i.""" 187 return qubidl.qubidl_get_seg_last(self.idl, i)
188 - def count_dwells(self, f, l, fragments):
189 """ 190 Returns the numer of dwells between sample f and sample l, inclusive. 191 If (not fragments): doesn't count dwells which extend beyond the bounds. 192 """ 193 return qubidl.qubidl_count_dwells(self.idl, f, l, fragments)
194 - def get_dwells_into(self, f, l, fragments, firsts, lasts, classes, durations):
195 """Copies the dwells between samples f and l, inclusive, into numpy arrays. 196 197 @type firsts: numpy.array(dtype=int32) 198 @type lasts: numpy.array(dtype=int32) 199 @type classes: numpy.array(dtype=int32) 200 @type durations: numpy.array(dtype=float32) or None 201 """ 202 qubidl.qubidl_get_dwells(self.idl, f, l, fragments, firsts, lasts, classes, durations)
203 - def get_dwells(self, f, l, fragments, get_durations=False):
204 """Returns the dwells between samples f and l, inclusive, as numpy arrays 205 @return: firsts, lasts, classes[, durations] 206 """ 207 count = self.count_dwells(f, l, fragments) 208 firsts = numpy.zeros(shape=(count,), dtype='int32') 209 lasts = numpy.zeros(shape=(count,), dtype='int32') 210 classes = numpy.zeros(shape=(count,), dtype='int32') 211 if get_durations: 212 durations = numpy.zeros(shape=(count,), dtype='float32') 213 self.get_dwells_into(f, l, fragments, firsts.ctypes.data_as(c_int_p), 214 lasts.ctypes.data_as(c_int_p), 215 classes.ctypes.data_as(c_int_p), 216 durations.ctypes.data_as(c_float_p)) 217 return firsts, lasts, classes, durations 218 else: 219 self.get_dwells_into(f, l, fragments, firsts.ctypes.data_as(c_int_p), 220 lasts.ctypes.data_as(c_int_p), 221 classes.ctypes.data_as(c_int_p), 222 c_float_p()) 223 return firsts, lasts, classes
224 - def count_dwells_and_gaps(self, f, l):
225 """ 226 Returns the numer of dwells between sample f and sample l, inclusive. 227 """ 228 return qubidl.qubidl_count_dwells_and_gaps(self.idl, f, l)
229 - def get_dwells_and_gaps_into(self, f, l, firsts, lasts, classes, durations):
230 """Copies the dwells between samples f and l, inclusive, into numpy arrays; cls=-1 between events. 231 232 @type firsts: numpy.array(dtype=int32) 233 @type lasts: numpy.array(dtype=int32) 234 @type classes: numpy.array(dtype=int32) 235 @type durations: numpy.array(dtype=float32) or None 236 """ 237 qubidl.qubidl_get_dwells_and_gaps(self.idl, f, l, firsts, lasts, classes, durations)
238 - def get_dwells_and_gaps(self, f, l, get_durations=False):
239 """Returns the dwells between samples f and l, inclusive, as numpy arrays 240 @return: firsts, lasts, classes[, durations] 241 """ 242 count = self.count_dwells_and_gaps(f, l) 243 firsts = numpy.zeros(shape=(count,), dtype='int32') 244 lasts = numpy.zeros(shape=(count,), dtype='int32') 245 classes = numpy.zeros(shape=(count,), dtype='int32') 246 if get_durations: 247 durations = numpy.zeros(shape=(count,), dtype='float32') 248 self.get_dwells_and_gaps_into(f, l, firsts.ctypes.data_as(c_int_p), 249 lasts.ctypes.data_as(c_int_p), 250 classes.ctypes.data_as(c_int_p), 251 durations.ctypes.data_as(c_float_p)) 252 return firsts, lasts, classes, durations 253 else: 254 self.get_dwells_and_gaps_into(f, l, firsts.ctypes.data_as(c_int_p), 255 lasts.ctypes.data_as(c_int_p), 256 classes.ctypes.data_as(c_int_p), 257 c_float_p()) 258 return firsts, lasts, classes
259 - def set_dwells(self, count, firsts, lasts, classes):
260 """Writes dwells to the idealization.""" 261 qubidl.qubidl_set_dwells(self.idl, count, firsts.ctypes.data_as(c_int_p), 262 lasts.ctypes.data_as(c_int_p), classes.ctypes.data_as(c_int_p))
263 - def sample_dwells(self, f, l, amps, Nsample, lows, highs, class_bits=None):
264 """ 265 Renders the dwells between samples f and l, inclusive, into resampled arrays lo and hi, suitable for display. 266 Samples with no dwells (all class < 0) are not modified, so if you fill lo or hi with a sentry value, you can skip blank samples. 267 class_bits[i] & (1 << c) if class c occurs during sample i 268 """ 269 qubidl.qubidl_sample_dwells_classes(self.idl, f, l, amps.ctypes.data_as(c_double_p), 270 Nsample, lows.ctypes.data_as(c_float_p), highs.ctypes.data_as(c_float_p), 271 (not (class_bits is None)) and class_bits.ctypes.data_as(c_uint_p) or None)
272 - def sample_dwells_std(self, f, l, amps, stds, Nsample, lows, highs):
273 """ 274 Renders the dwells between samples f and l, inclusive, into resampled arrays lo and hi, suitable for display. 275 Samples with no dwells (all class < 0) are not modified, so if you fill lo or hi with a sentry value, you can skip blank samples. 276 """ 277 qubidl.qubidl_sample_dwells_std(self.idl, f, l, amps.ctypes.data_as(c_float_p), stds.ctypes.data_as(c_float_p), 278 Nsample, lows.ctypes.data_as(c_float_p), highs.ctypes.data_as(c_float_p))
279 - def count_dwells_excluding(self, exclusion, excl_class, f, l):
280 """ 281 Returns the numer of dwells between sample f and sample l, inclusive; 282 unlike count_dwells, counts each un-idealized region as a dwell (of class -1). 283 @param exclusion: an L{Idealization} with the same segmentation 284 @param excl_class: class in exclusion marking where to overwrite output with class -2 285 """ 286 count = 0 287 for ef, el, ec in izip(*exclusion.get_dwells(f, l, True)): 288 if ec != excl_class: 289 count += qubidl.qubidl_count_dwells_and_gaps(self.idl, ef, el) 290 else: 291 count += 1 292 return count
293 - def get_dwells_excluding_into(self, exclusion, excl_class, f, l, firsts, lasts, classes, durations=None):
294 """ 295 Copies the dwells between samples f and l, inclusive, into numpy arrays; 296 unlike get_dwells_into, outputs un-idealized regions as class -1. 297 298 @param exclusion: an L{Idealization} with the same segmentation 299 @param excl_class: class in exclusion marking where to overwrite output with class -2 300 301 @type firsts: numpy.array(dtype=int32) 302 @type lasts: numpy.array(dtype=int32) 303 @type classes: numpy.array(dtype=int32) 304 @type durations: numpy.array(dtype=float32) or None 305 """ 306 count = 0 307 for ef, el, ec in izip(*exclusion.get_dwells(f, l, True)): 308 if ec != excl_class: 309 if not (durations is None): 310 durs = durations[count:].ctypes.data_as(c_float_p) 311 else: 312 durs = c_float_p() 313 count += qubidl.qubidl_get_dwells_and_gaps(self.idl, ef, el, 314 firsts[count:].ctypes.data_as(c_int_p), 315 lasts[count:].ctypes.data_as(c_int_p), 316 classes[count:].ctypes.data_as(c_int_p), 317 durs) 318 else: 319 firsts[count] = ef 320 lasts[count] = el 321 classes[count] = -2 322 count += 1 323 if not (durations is None): 324 durations[:] = self.get_sampling() * (lasts - firsts + 1)
325 - def get_dwells_excluding(self, exclusion, excl_class, f, l, get_durations=False):
326 """ 327 Returns the dwells between samples f and l, inclusive, as numpy arrays; 328 unlike get_dwells, outputs un-idealized regions as class -1. 329 330 @param exclusion: an L{Idealization} with the same segmentation 331 @param excl_class: class in exclusion marking where to overwrite output with class -2 332 @return: firsts, lasts, classes[, durations] 333 """ 334 count = self.count_dwells_excluding(exclusion, excl_class, f, l) 335 firsts = numpy.zeros(shape=(count,), dtype='int32') 336 lasts = numpy.zeros(shape=(count,), dtype='int32') 337 classes = numpy.zeros(shape=(count,), dtype='int32') 338 if get_durations: 339 durations = numpy.zeros(shape=(count,), dtype='float32') 340 self.get_dwells_excluding_into(exclusion, excl_class, f, l, firsts, lasts, classes, durations) 341 return firsts, lasts, classes, durations 342 else: 343 self.get_dwells_excluding_into(exclusion, excl_class, f, l, firsts, lasts, classes) 344 return firsts, lasts, classes
345 - def set_dwell(self, f, l, c):
346 """Overwrites the idealization between samples f and l, inclusive, with class c.""" 347 F = c_int(f) 348 L = c_int(l) 349 C = c_int(c) 350 qubidl.qubidl_set_dwells(self.idl, 1, byref(F), byref(L), byref(C))
351 - def clear(self):
352 """Clears all segments' idealization to class -1.""" 353 qubidl.qubidl_clear(self.idl)
354 - def add_seg(self, f, l):
355 """Adds a segment, with inclusive sample bounds. For best results, use f = total sample count so far; l = f+seg_length-1.""" 356 qubidl.qubidl_add_seg(self.idl, f, l)
357 - def erase(self, f, l):
358 """Clears all dwells (or fragments) between samples f and l inclusive, by setting them to class -1.""" 359 qubidl.qubidl_erase(self.idl, f, l)
360 - def join(self, f, l):
361 """Extends the class at sample f through to sample l.""" 362 qubidl.qubidl_join(self.idl, f, l)
363 - def begin(self):
364 """Returns an L{IdlIter} pointing to the first (partial) dwell.""" 365 return IdlIter(qubidl.qubidl_begin(self.idl))
366 - def end(self):
367 """Returns an L{IdlIter} pointing past the last (partial) dwell.""" 368 return IdlIter(qubidl.qubidl_end(self.idl))
369 - def find(self, f):
370 """Returns an L{IdlIter} pointing to the (partial) dwell at sample f.""" 371 return IdlIter(qubidl.qubidl_find(self.idl, f))
372
373 -class IdlIter(object):
374 __slots__ = ['iter', 'readinto']
375 - def __init__(self, iter):
376 """Creates an IdlIter; If iter is an IdlIter, this creates a clone.""" 377 if isinstance(iter, IdlIter): 378 self.iter = qubidl.qubidl_iter_clone(iter.iter) 379 else: 380 self.iter = iter 381 self.readinto = None
382 - def __del__(self):
383 qubidl.qubidl_iter_destroy(self.iter)
384 - def __nonzero__(self):
385 """bool(iter) is True if iter points to a (partial) dwell, not past the end.""" 386 return qubidl.qubidl_iter_valid(self.iter)
387 - def __cmp__(self, other):
388 """Returns 0 if other iterator points to the same (partial) dwell.""" 389 if qubidl.qubidl_iter_equals(self.iter, other.iter): 390 return 0 391 else: 392 return -1
393 - def segindex(self):
394 """Returns the segment index of the current dwell.""" 395 return qubidl.qubidl_iter_segindex(self.iter)
396 - def segfirst(self):
397 """Returns the first sample index in the current dwell's segment.""" 398 return qubidl.qubidl_iter_segfirst(self.iter)
399 - def read(self):
400 """Returns the first, last, and class indices of the current (partial) dwell.""" 401 if self.readinto is None: 402 f = c_int() 403 l = c_int() 404 c = c_int() 405 self.readinto = (f, l, c) 406 else: 407 f, l, c = self.readinto 408 qubidl.qubidl_iter_read(self.iter, byref(f), byref(l), byref(c)) 409 return (f.value, l.value, c.value)
410 - def next(self):
411 """Moves the iterator to the next (partial) dwell.""" 412 qubidl.qubidl_iter_next(self.iter)
413 - def prev(self):
414 """Moves the iterator to the previous (partial) dwell.""" 415 qubidl.qubidl_iter_prev(self.iter)
416
417 -class IdlFits(Idealization):
418 - def __init__(self, sampling):
419 Idealization.__init__(self, sampling) 420 self.segmentation = Idealization(self.sampling) 421 self.segmeans = [] 422 self.segstds = []
423 - def set_sampling(self, sampling):
424 Idealization.set_sampling(self, sampling) 425 self.segmentation.set_sampling(sampling)
426 - def clear(self, seg_ix=None):
427 if seg_ix is None: 428 for i in xrange(len(self.segmeans)): 429 self.clear(i) 430 else: 431 self.set_dwell(self.get_seg_first(seg_ix), self.get_seg_last(seg_ix), -1) 432 self.segmeans[seg_ix] = numpy.zeros(shape=(1,), dtype='float32') 433 self.segstds[seg_ix] = numpy.zeros(shape=(1,), dtype='float32')
434 - def add_seg(self, f, l):
435 Idealization.add_seg(self, f, l) 436 ix = len(self.segmeans) 437 self.segmentation.add_seg(f, l) 438 self.segmentation.set_dwell(f, l, ix) 439 self.segmeans.append(None) 440 self.segstds.append(None) 441 self.clear(ix) # set up segmeans, segstds
442 - def set_fit(self, firsts, lasts, means, stds=None):
443 if len(firsts) == 0: 444 return 445 seg_ix = self.segmentation[firsts[0]] 446 if seg_ix != self.segmentation[lasts[-1]]: 447 raise ValueError('All points must be in the same segment') 448 base = len(self.segmeans[seg_ix]) 449 self.segmeans[seg_ix] = numpy.hstack((self.segmeans[seg_ix], means)) 450 if not (stds is None): 451 self.segstds[seg_ix] = numpy.hstack((self.segstds[seg_ix], stds)) 452 else: 453 self.segstds[seg_ix] = numpy.hstack((self.segstds[seg_ix], numpy.zeros(shape=(len(means),), dtype='float32'))) 454 classes = numpy.arange(base, base+len(firsts), dtype='int32') 455 self.set_dwells(len(firsts), firsts, lasts, classes)
456 - def get_samples_into(self, first, last, arr, cls_values=None, arr_stds=None, cls_stds=None):
457 seg_ix = self.segmentation[first] 458 if seg_ix != self.segmentation[last]: 459 raise ValueError('All points must be in the same segment') 460 ff, ll, cc = self.get_dwells(first, last, True, False) 461 if not (cls_values is None): 462 means = cls_values 463 else: 464 means = self.segmeans[seg_ix] 465 if cls_stds is None: 466 stds = self.segstds[seg_ix] 467 else: 468 stds = cls_stds 469 for f, l, c in izip(ff, ll, cc): 470 arr[f-first:l-first+1] = means[c] 471 if not (arr_stds is None): 472 arr_stds[f-first:l-first+1] = stds[c]
473 474
475 -class IdlRecord(object):
476 - def __init__(self, **kw):
477 for k,v in kw.iteritems(): 478 self.__dict__[k] = v
479 # access missing field returns None instead of raising NameError
480 - def __getattr__(self, name):
481 try: 482 return self.__dict__[name] 483 except: 484 return None
485
486 -class IdlRecords(object):
487 - def __init__(self, sampling, construct_record=IdlRecord):
488 self.idl = Idealization(sampling) 489 self.__construct_record = construct_record 490 self.__next = 0 491 self.__last = -1 492 self.records = {-1 : construct_record()}
493 # may accumulate stale records, whose dwells were overwritten, until you erase() 494 sampling = property(lambda self: self.get_sampling(), lambda self, x: self.set_sampling(x))
495 - def __getitem__(self, key):
496 return self.records[self.idl[key]]
497 - def get_sampling(self):
498 return self.idl.sampling
499 - def set_sampling(self, sampling):
500 self.idl.set_sampling(sampling)
501 - def get_seg_first(self, i):
502 return self.idl.get_seg_first(i)
503 - def get_seg_last(self, i):
504 return self.idl.get_seg_last(i)
505 - def get_records(self, f, l, fragments=True):
506 ff, ll, cc = self.idl.get_dwells(f, l, fragments) 507 valid = [i for i,c in enumerate(cc) if (c >= 0)] 508 records = [self.records[cc[v]] for v in valid] 509 return records, [ff[v] for v in valid], [ll[v] for v in valid]
510 - def add_seg(self, f, l):
511 self.idl.add_seg(f, l) 512 self.__last = l
513 - def add_record(self, f, l):
514 ix = self.__next 515 while ix in self.records: 516 ix = (ix + 1) % 2147483648 517 self.__next = (ix + 1) % 2147483648 518 rec = self.__construct_record() 519 self.records[ix] = rec 520 self.idl.set_dwell(f, l, ix) 521 return rec
522 - def clear(self):
523 self.idl.clear() 524 self.records = {} 525 self.__next = 0
526 - def erase(self, f=0, l=None):
527 last = l 528 if last is None: last = self.__last 529 ff, ll, cc = self.idl.get_dwells(f, last, fragments=False) 530 for c in cc: 531 del self.records[c] 532 self.idl.erase(f, last)
533 - def begin(self):
534 return IdlRecordsIter(self.idl.begin())
535 - def end(self):
536 return IdlRecordsIter(self.idl.end())
537 - def find(self, f):
538 return IdlRecordsIter(self.idl.find(f))
539
540 -class IdlRecordsIter(object):
541 - def __init__(self, iter, idl_recs=None):
542 if isinstance(iter, IdlRecordsIter): 543 self.iter = IdlIter(iter.iter) 544 self.idl_recs = idl_recs or iter.idl_recs 545 else: 546 self.iter = iter 547 self.idl_recs = idl_recs 548 self.read()
549 - def __nonzero__(self):
550 bool(self.iter)
551 - def __cmp(self, other):
552 return cmp(self.iter, other.iter)
553 - def segindex(self):
554 return self.iter.segindex()
555 - def segfirst(self):
556 return self.iter.segfirst()
557 - def next(self):
558 self.iter.next() 559 self.read()
560 - def prev(self):
561 self.iter.prev() 562 self.read()
563 - def read(self):
564 f, l, c = self.iter.read() 565 self.record = self.idl_recs.records[c] 566 return self.record
567 568 if __name__ == '__main__': 569 import traceback 570 import linecache 571 import sys 572 573 #tracelog = open('/dev/shm/trace', 'w')
574 - def traceit(frame, event, arg):
575 if event == "line": 576 lineno = frame.f_lineno 577 filename = frame.f_globals["__file__"] 578 if filename == "<stdin>": 579 filename = "<stdin> " 580 if (filename.endswith(".pyc") or 581 filename.endswith(".pyo")): 582 filename = filename[:-1] 583 name = frame.f_globals["__name__"] 584 line = linecache.getline(filename, lineno) 585 tracelog.write("%s:%s: %s\n" % (name, lineno, line.rstrip())) 586 return traceit
587 #sys.settrace(traceit) 588 589 idl = Idealization(0.1) 590 idl.add_seg(0, 255) 591 idl.set_dwell(10, 20, 2) 592 iter = idl.begin() 593 while iter: 594 print iter.read() 595 iter.next() 596 print 597 598 excl = Idealization(0.1) 599 excl.add_seg(0, 255) 600 excl.set_dwell(0, 255, 1) 601 print 602 for f, l, c, d in izip(*idl.get_dwells_excluding(excl, 0, 0, 255, get_durations=True)): 603 print "%10i%10i%5i%16.9g" % (f,l,c,d) 604 print 605 excl.set_dwell(15, 24, 0) 606 for f, l, c, d in izip(*idl.get_dwells_excluding(excl, 0, 0, 255, get_durations=True)): 607 print "%10i%10i%5i%16.9g" % (f,l,c,d) 608 609 del excl 610 del iter 611 del idl 612