def test_common_base(): """ This should return the base class common to each object in objs. """ class TestA(object): """Base test class.""" pass class TestB(TestA): """First inherited class.""" pass class TestC(TestA): """Second inherited class.""" pass inst_b = TestB() inst_c = TestC() objs = [inst_b, inst_c] assert util.common_base(objs) == TestA
def combine_frequencies(cls, specs): """ Return new spectrogram that contains frequencies from all the spectrograms in spec. Only returns time intersection of all of them. Parameters ---------- spec : list List of spectrograms of which to combine the frequencies into one. """ if not specs: raise ValueError("Need at least one spectrogram.") specs = cls.intersect_time(specs) one = specs[0] dtype_ = max(sp.dtype for sp in specs) fsize = sum(sp.shape[0] for sp in specs) new = np.zeros((fsize, one.shape[1]), dtype=dtype_) freq_axis = np.zeros((fsize,)) for n, (data, row) in enumerate(merge( [ [(sp, n) for n in xrange(sp.shape[0])] for sp in specs ], key=lambda x: x[0].freq_axis[x[1]] )): new[n, :] = data[row, :] freq_axis[n] = data.freq_axis[row] params = { 'time_axis': one.time_axis, # Should be equal 'freq_axis': freq_axis, 'start': one.start, 'end': one.end, 't_delt': one.t_delt, 't_init': one.t_init, 't_label': one.t_label, 'f_label': one.f_label, 'content': one.content, 'instruments': _union(spec.instruments for spec in specs) } return common_base(specs)(new, **params)
def combine_frequencies(cls, specs): """ Return new spectrogram that contains frequencies from all the spectrograms in spec. Only returns time intersection of all of them. Parameters ---------- spec : list List of spectrograms of which to combine the frequencies into one. """ if not specs: raise ValueError("Need at least one spectrogram.") specs = cls.intersect_time(specs) one = specs[0] dtype_ = max(sp.dtype for sp in specs) fsize = sum(sp.shape[0] for sp in specs) new = np.zeros((fsize, one.shape[1]), dtype=dtype_) freq_axis = np.zeros((fsize, )) for n, (data, row) in enumerate( merge([[(sp, n) for n in xrange(sp.shape[0])] for sp in specs], key=lambda x: x[0].freq_axis[x[1]])): new[n, :] = data[row, :] freq_axis[n] = data.freq_axis[row] params = { 'time_axis': one.time_axis, # Should be equal 'freq_axis': freq_axis, 'start': one.start, 'end': one.end, 't_delt': one.t_delt, 't_init': one.t_init, 't_label': one.t_label, 'f_label': one.f_label, 'content': one.content, 'instruments': _union(spec.instruments for spec in specs) } return common_base(specs)(new, **params)
def join_many(cls, specs, mk_arr=None, nonlinear=False, maxgap=0, fill=JOIN_REPEAT): """ Produce new Spectrogram that contains spectrograms joined together in time. Parameters ---------- specs : list List of spectrograms to join together in time. nonlinear : bool If True, leave out gaps between spectrograms. Else, fill them with the value specified in fill. maxgap : float, int or None Largest gap to allow in second. If None, allow gap of arbitrary size. fill : float or int Value to fill missing values (assuming nonlinear=False) with. Can be LinearTimeSpectrogram.JOIN_REPEAT to repeat the values for the time just before the gap. mk_array: function Function that is called to create the resulting array. Can be set to LinearTimeSpectrogram.memap(filename) to create a memory mapped result array. """ # XXX: Only load header and load contents of files # on demand. mask = None if mk_arr is None: mk_arr = cls.make_array specs = sorted(specs, key=lambda x: x.start) freqs = specs[0].freq_axis if not all(np.array_equal(freqs, sp.freq_axis) for sp in specs): raise ValueError("Frequency channels do not match.") # Smallest time-delta becomes the common time-delta. min_delt = min(sp.t_delt for sp in specs) dtype_ = max(sp.dtype for sp in specs) specs = [sp.resample_time(min_delt) for sp in specs] size = sum(sp.shape[1] for sp in specs) data = specs[0] init = data.t_init start_day = data.start xs = [] last = data for elem in specs[1:]: e_init = ( SECONDS_PER_DAY * ( get_day(elem.start) - get_day(start_day) ).days + elem.t_init ) x = int((e_init - last.t_init) / min_delt) xs.append(x) diff = last.shape[1] - x if maxgap is not None and -diff > maxgap / min_delt: raise ValueError("Too large gap.") # If we leave out undefined values, we do not want to # add values here if x > t_res. if nonlinear: size -= max(0, diff) else: size -= diff last = elem # The non existing element after the last one starts after # the last one. Needed to keep implementation below sane. xs.append(specs[-1].shape[1]) # We do that here so the user can pass a memory mapped # array if they'd like to. arr = mk_arr((data.shape[0], size), dtype_) time_axis = np.zeros((size,)) sx = 0 # Amount of pixels left out due to nonlinearity. Needs to be # considered for correct time axes. sd = 0 for x, elem in izip(xs, specs): diff = x - elem.shape[1] e_time_axis = elem.time_axis if x > elem.shape[1]: if nonlinear: x = elem.shape[1] else: # If we want to stay linear, fill up the missing # pixels with placeholder zeros. filler = np.zeros((data.shape[0], diff)) if fill is cls.JOIN_REPEAT: filler[:, :] = elem[:, -1, np.newaxis] else: filler[:] = fill minimum = elem.time_axis[-1] e_time_axis = np.concatenate([ elem.time_axis, np.linspace( minimum + min_delt, minimum + diff * min_delt, diff ) ]) elem = np.concatenate([elem, filler], 1) arr[:, sx:sx + x] = elem[:, :x] if diff > 0: if mask is None: mask = np.zeros((data.shape[0], size), dtype=np.uint8) mask[:, sx + x - diff:sx + x] = 1 time_axis[sx:sx + x] = e_time_axis[:x] + data.t_delt * (sx + sd) if nonlinear: sd += max(0, diff) sx += x params = { 'time_axis': time_axis, 'freq_axis': data.freq_axis, 'start': data.start, 'end': specs[-1].end, 't_delt': data.t_delt, 't_init': data.t_init, 't_label': data.t_label, 'f_label': data.f_label, 'content': data.content, 'instruments': _union(spec.instruments for spec in specs), } if mask is not None: arr = ma.array(arr, mask=mask) if nonlinear: del params['t_delt'] return Spectrogram(arr, **params) return common_base(specs)(arr, **params)
def join_many(cls, specs, mk_arr=None, nonlinear=False, maxgap=0, fill=JOIN_REPEAT): """ Produce new Spectrogram that contains spectrograms joined together in time. Parameters ---------- specs : list List of spectrograms to join together in time. nonlinear : bool If True, leave out gaps between spectrograms. Else, fill them with the value specified in fill. maxgap : float, int or None Largest gap to allow in second. If None, allow gap of arbitrary size. fill : float or int Value to fill missing values (assuming nonlinear=False) with. Can be LinearTimeSpectrogram.JOIN_REPEAT to repeat the values for the time just before the gap. mk_array: function Function that is called to create the resulting array. Can be set to LinearTimeSpectrogram.memap(filename) to create a memory mapped result array. """ # XXX: Only load header and load contents of files # on demand. mask = None if mk_arr is None: mk_arr = cls.make_array specs = sorted(specs, key=lambda x: x.start) freqs = specs[0].freq_axis if not all(np.array_equal(freqs, sp.freq_axis) for sp in specs): raise ValueError("Frequency channels do not match.") # Smallest time-delta becomes the common time-delta. min_delt = min(sp.t_delt for sp in specs) dtype_ = max(sp.dtype for sp in specs) specs = [sp.resample_time(min_delt) for sp in specs] size = sum(sp.shape[1] for sp in specs) data = specs[0] init = data.t_init start_day = data.start xs = [] last = data for elem in specs[1:]: e_init = (SECONDS_PER_DAY * (get_day(elem.start) - get_day(start_day)).days + elem.t_init) x = int((e_init - last.t_init) / min_delt) xs.append(x) diff = last.shape[1] - x if maxgap is not None and -diff > maxgap / min_delt: raise ValueError("Too large gap.") # If we leave out undefined values, we do not want to # add values here if x > t_res. if nonlinear: size -= max(0, diff) else: size -= diff last = elem # The non existing element after the last one starts after # the last one. Needed to keep implementation below sane. xs.append(specs[-1].shape[1]) # We do that here so the user can pass a memory mapped # array if they'd like to. arr = mk_arr((data.shape[0], size), dtype_) time_axis = np.zeros((size, )) sx = 0 # Amount of pixels left out due to nonlinearity. Needs to be # considered for correct time axes. sd = 0 for x, elem in izip(xs, specs): diff = x - elem.shape[1] e_time_axis = elem.time_axis if x > elem.shape[1]: if nonlinear: x = elem.shape[1] else: # If we want to stay linear, fill up the missing # pixels with placeholder zeros. filler = np.zeros((data.shape[0], diff)) if fill is cls.JOIN_REPEAT: filler[:, :] = elem[:, -1, np.newaxis] else: filler[:] = fill minimum = elem.time_axis[-1] e_time_axis = np.concatenate([ elem.time_axis, np.linspace(minimum + min_delt, minimum + diff * min_delt, diff) ]) elem = np.concatenate([elem, filler], 1) arr[:, sx:sx + x] = elem[:, :x] if diff > 0: if mask is None: mask = np.zeros((data.shape[0], size), dtype=np.uint8) mask[:, sx + x - diff:sx + x] = 1 time_axis[sx:sx + x] = e_time_axis[:x] + data.t_delt * (sx + sd) if nonlinear: sd += max(0, diff) sx += x params = { 'time_axis': time_axis, 'freq_axis': data.freq_axis, 'start': data.start, 'end': specs[-1].end, 't_delt': data.t_delt, 't_init': data.t_init, 't_label': data.t_label, 'f_label': data.f_label, 'content': data.content, 'instruments': _union(spec.instruments for spec in specs), } if mask is not None: arr = ma.array(arr, mask=mask) if nonlinear: del params['t_delt'] return Spectrogram(arr, **params) return common_base(specs)(arr, **params)