def __init__(self, data, time_axis, freq_axis, start, end, t_init=None, t_delt=None, t_label="Time", f_label="Frequency", content="", instruments=None): if t_delt is None: t_delt = min_delt(freq_axis) super(LinearTimeSpectrogram, self).__init__( data, time_axis, freq_axis, start, end, t_init, t_label, f_label, content, instruments ) self.t_delt = t_delt
def __init__(self, arr, delt=None): self.arr = arr if delt is None: # Nyquist–Shannon sampling theorem delt = min_delt(arr.freq_axis) / 2. self.delt = delt midpoints = (self.arr.freq_axis[:-1] + self.arr.freq_axis[1:]) / 2 self.midpoints = np.concatenate([midpoints, arr.freq_axis[-1:]]) self.max_mp_delt = np.min(delta(self.midpoints)) self.freq_axis = np.arange(self.arr.freq_axis[0], self.arr.freq_axis[-1], -self.delt) self.time_axis = self.arr.time_axis self.shape = (len(self), arr.shape[1])
def __init__(self, arr, delt=None): self.arr = arr if delt is None: # Nyquist–Shannon sampling theorem delt = min_delt(arr.freq_axis) / 2. self.delt = delt midpoints = (self.arr.freq_axis[:-1] + self.arr.freq_axis[1:]) / 2 self.midpoints = np.concatenate([midpoints, arr.freq_axis[-1:]]) self.max_mp_delt = np.min(delta(self.midpoints)) self.freq_axis = np.arange( self.arr.freq_axis[0], self.arr.freq_axis[-1], -self.delt ) self.time_axis = self.arr.time_axis self.shape = (len(self), arr.shape[1])
def __init__(self, data, time_axis, freq_axis, start, end, t_init=None, t_delt=None, t_label="Time", f_label="Frequency", content="", instruments=None): if t_delt is None: t_delt = min_delt(freq_axis) super(LinearTimeSpectrogram, self).__init__(data, time_axis, freq_axis, start, end, t_init, t_label, f_label, content, instruments) self.t_delt = t_delt
def linearize_freqs(self, delta_freq=None): """ Rebin frequencies so that the frequency axis is linear. Parameters ---------- delta_freq : float Difference between consecutive values on the new frequency axis. Defaults to half of smallest delta in current frequency axis. Compare Nyquist-Shannon sampling theorem. """ if delta_freq is None: # Nyquist–Shannon sampling theorem delta_freq = min_delt(self.freq_axis) / 2. nsize = (self.freq_axis.max() - self.freq_axis.min()) / delta_freq + 1 new = np.zeros((nsize, self.shape[1]), dtype=self.dtype) freqs = self.freq_axis - self.freq_axis.max() freqs = freqs / delta_freq midpoints = np.round((freqs[:-1] + freqs[1:]) / 2) fillto = np.concatenate( [midpoints - 1, np.round([freqs[-1]]) - 1] ) fillfrom = np.concatenate( [np.round([freqs[0]]), midpoints - 1] ) fillto = np.abs(fillto) fillfrom = np.abs(fillfrom) for row, from_, to_ in izip(self, fillfrom, fillto): new[from_: to_] = row vrs = self._get_params() vrs.update({ 'freq_axis': np.linspace( self.freq_axis.max(), self.freq_axis.min(), nsize ) }) return self.__class__(new, **vrs)
def linearize_freqs(self, delta_freq=None): """ Rebin frequencies so that the frequency axis is linear. Parameters ---------- delta_freq : float Difference between consecutive values on the new frequency axis. Defaults to half of smallest delta in current frequency axis. Compare Nyquist-Shannon sampling theorem. """ if delta_freq is None: # Nyquist–Shannon sampling theorem delta_freq = min_delt(self.freq_axis) / 2. nsize = (self.freq_axis.max() - self.freq_axis.min()) / delta_freq + 1 new = np.zeros((nsize, self.shape[1]), dtype=self.dtype) freqs = self.freq_axis - self.freq_axis.max() freqs = freqs / delta_freq midpoints = np.round((freqs[:-1] + freqs[1:]) / 2) fillto = np.concatenate([midpoints - 1, np.round([freqs[-1]]) - 1]) fillfrom = np.concatenate([np.round([freqs[0]]), midpoints - 1]) fillto = np.abs(fillto) fillfrom = np.abs(fillfrom) for row, from_, to_ in izip(self, fillfrom, fillto): new[from_:to_] = row vrs = self._get_params() vrs.update({ 'freq_axis': np.linspace(self.freq_axis.max(), self.freq_axis.min(), nsize) }) return self.__class__(new, **vrs)
def plot(self, figure=None, overlays=[], colorbar=True, min_=None, max_=None, linear=True, showz=True, yres=DEFAULT_YRES, max_dist=None, **matplotlib_args): """ Plot spectrogram onto figure. Parameters ---------- figure : matplotlib.figure.Figure Figure to plot the spectrogram on. If None, new Figure is created. overlays : list List of overlays (functions that receive figure and axes and return new ones) to be applied after drawing. colorbar : bool Flag that determines whether or not to draw a colorbar. If existing figure is passed, it is attempted to overdraw old colorbar. min_ : float Clip intensities lower than min_ before drawing. max_ : float Clip intensities higher than max_ before drawing. linear : bool If set to True, "stretch" image to make frequency axis linear. showz : bool If set to True, the value of the pixel that is hovered with the mouse is shown in the bottom right corner. yres : int or None To be used in combination with linear=True. If None, sample the image with half the minimum frequency delta. Else, sample the image to be at most yres pixels in vertical dimension. Defaults to 1080 because that's a common screen size. max_dist : float or None If not None, mask elements that are further than max_dist away from actual data points (ie, frequencies that actually have data from the receiver and are not just nearest-neighbour interpolated). """ # [] as default argument is okay here because it is only read. # pylint: disable=W0102,R0914 if linear: delt = yres if delt is not None: delt = max( (self.freq_axis[0] - self.freq_axis[-1]) / (yres - 1), min_delt(self.freq_axis) / 2. ) delt = float(delt) data = _LinearView(self.clip_values(min_, max_), delt) freqs = np.arange( self.freq_axis[0], self.freq_axis[-1], -data.delt ) else: data = np.array(self.clip_values(min_, max_)) freqs = self.freq_axis newfigure = figure is None if figure is None: figure = plt.figure(frameon=True, FigureClass=SpectroFigure) axes = figure.add_subplot(111) else: if figure.axes: axes = figure.axes[0] else: axes = figure.add_subplot(111) params = { 'origin': 'lower', 'aspect': 'auto', } params.update(matplotlib_args) if linear and max_dist is not None: toplot = ma.masked_array(data, mask=data.make_mask(max_dist)) else: toplot = data im = axes.imshow(toplot, **params) xa = axes.get_xaxis() ya = axes.get_yaxis() xa.set_major_formatter( FuncFormatter(self.time_formatter) ) if linear: # Start with a number that is divisible by 5. init = (self.freq_axis[0] % 5) / data.delt nticks = 15. # Calculate MHz difference between major ticks. dist = (self.freq_axis[0] - self.freq_axis[-1]) / nticks # Round to next multiple of 10, at least ten. dist = max(round(dist, -1), 10) # One pixel in image space is data.delt MHz, thus we can convert # our distance between the major ticks into image space by dividing # it by data.delt. ya.set_major_locator( IndexLocator( dist / data.delt, init ) ) ya.set_minor_locator( IndexLocator( dist / data.delt / 10, init ) ) def freq_fmt(x, pos): # This is necessary because matplotlib somehow tries to get # the mid-point of the row, which we do not need here. x = x + 0.5 return self.format_freq(self.freq_axis[0] - x * data.delt) else: freq_fmt = _list_formatter(freqs, self.format_freq) ya.set_major_locator(MaxNLocator(integer=True, steps=[1, 5, 10])) ya.set_major_formatter( FuncFormatter(freq_fmt) ) axes.set_xlabel(self.t_label) axes.set_ylabel(self.f_label) # figure.suptitle(self.content) figure.suptitle( ' '.join([ get_day(self.start).strftime("%d %b %Y"), 'Radio flux density', '(' + ', '.join(self.instruments) + ')', ]) ) for tl in xa.get_ticklabels(): tl.set_fontsize(10) tl.set_rotation(30) figure.add_axes(axes) figure.subplots_adjust(bottom=0.2) figure.subplots_adjust(left=0.2) if showz: figure.gca().format_coord = self._mk_format_coord( data, figure.gca().format_coord) if colorbar: if newfigure: figure.colorbar(im).set_label("Intensity") else: if len(figure.axes) > 1: Colorbar(figure.axes[1], im).set_label("Intensity") for overlay in overlays: figure, axes = overlay(figure, axes) for ax in figure.axes: ax.autoscale() figure._init(self, freqs) return figure
def plot(self, figure=None, overlays=[], colorbar=True, min_=None, max_=None, linear=True, showz=True, yres=DEFAULT_YRES, max_dist=None, **matplotlib_args): """ Plot spectrogram onto figure. Parameters ---------- figure : matplotlib.figure.Figure Figure to plot the spectrogram on. If None, new Figure is created. overlays : list List of overlays (functions that receive figure and axes and return new ones) to be applied after drawing. colorbar : bool Flag that determines whether or not to draw a colorbar. If existing figure is passed, it is attempted to overdraw old colorbar. min_ : float Clip intensities lower than min_ before drawing. max_ : float Clip intensities higher than max_ before drawing. linear : bool If set to True, "stretch" image to make frequency axis linear. showz : bool If set to True, the value of the pixel that is hovered with the mouse is shown in the bottom right corner. yres : int or None To be used in combination with linear=True. If None, sample the image with half the minimum frequency delta. Else, sample the image to be at most yres pixels in vertical dimension. Defaults to 1080 because that's a common screen size. max_dist : float or None If not None, mask elements that are further than max_dist away from actual data points (ie, frequencies that actually have data from the receiver and are not just nearest-neighbour interpolated). """ # [] as default argument is okay here because it is only read. # pylint: disable=W0102,R0914 if linear: delt = yres if delt is not None: delt = max( (self.freq_axis[0] - self.freq_axis[-1]) / (yres - 1), min_delt(self.freq_axis) / 2.) delt = float(delt) data = _LinearView(self.clip_values(min_, max_), delt) freqs = np.arange(self.freq_axis[0], self.freq_axis[-1], -data.delt) else: data = np.array(self.clip_values(min_, max_)) freqs = self.freq_axis newfigure = figure is None if figure is None: figure = plt.figure(frameon=True, FigureClass=SpectroFigure) axes = figure.add_subplot(111) else: if figure.axes: axes = figure.axes[0] else: axes = figure.add_subplot(111) params = { 'origin': 'lower', 'aspect': 'auto', } params.update(matplotlib_args) if linear and max_dist is not None: toplot = ma.masked_array(data, mask=data.make_mask(max_dist)) else: toplot = data im = axes.imshow(toplot, **params) xa = axes.get_xaxis() ya = axes.get_yaxis() xa.set_major_formatter(FuncFormatter(self.time_formatter)) if linear: # Start with a number that is divisible by 5. init = (self.freq_axis[0] % 5) / data.delt nticks = 15. # Calculate MHz difference between major ticks. dist = (self.freq_axis[0] - self.freq_axis[-1]) / nticks # Round to next multiple of 10, at least ten. dist = max(round(dist, -1), 10) # One pixel in image space is data.delt MHz, thus we can convert # our distance between the major ticks into image space by dividing # it by data.delt. ya.set_major_locator(IndexLocator(dist / data.delt, init)) ya.set_minor_locator(IndexLocator(dist / data.delt / 10, init)) def freq_fmt(x, pos): # This is necessary because matplotlib somehow tries to get # the mid-point of the row, which we do not need here. x = x + 0.5 return self.format_freq(self.freq_axis[0] - x * data.delt) else: freq_fmt = _list_formatter(freqs, self.format_freq) ya.set_major_locator(MaxNLocator(integer=True, steps=[1, 5, 10])) ya.set_major_formatter(FuncFormatter(freq_fmt)) axes.set_xlabel(self.t_label) axes.set_ylabel(self.f_label) # figure.suptitle(self.content) figure.suptitle(' '.join([ get_day(self.start).strftime("%d %b %Y"), 'Radio flux density', '(' + ', '.join(self.instruments) + ')', ])) for tl in xa.get_ticklabels(): tl.set_fontsize(10) tl.set_rotation(30) figure.add_axes(axes) figure.subplots_adjust(bottom=0.2) figure.subplots_adjust(left=0.2) if showz: figure.gca().format_coord = self._mk_format_coord( data, figure.gca().format_coord) if colorbar: if newfigure: figure.colorbar(im).set_label("Intensity") else: if len(figure.axes) > 1: Colorbar(figure.axes[1], im).set_label("Intensity") for overlay in overlays: figure, axes = overlay(figure, axes) for ax in figure.axes: ax.autoscale() figure._init(self, freqs) return figure