コード例 #1
0
ファイル: audianJ.py プロジェクト: graslandschaft/audioJ3
class Playback():
    def __init__(self, main):
        self.main = main
        self.audio = PlayAudio()
        self.create_actions()

    def create_actions(self):

        # Playback
        self.main.actionPlay = QtGui.QAction('Play data chunk', self.main)
        self.main.actionPlay.setShortcut(Qt.Qt.Key_P)
        self.main.actionPlay.triggered.connect(self.play)
        self.main.addAction(self.main.actionPlay)

    def play(self):
        os.close(sys.stderr.fileno())  # block error messages
        data = self.main.data.get_data() / self.main.data.get_data().max()
        rate = self.main.data.audio.samplerate
        self.audio.play(data, rate, blocking=False)
        os.open(sys.stderr.fileno())  # unblock error messages

    def close(self):
        self.audio.close()
コード例 #2
0
ファイル: fishfinder.py プロジェクト: Aeapsu/thunderfish
    def __init__(self, data, samplingrate, unit, filename, channel, verbose, cfg):
        self.filename = filename
        self.channel = channel
        self.samplerate = samplingrate
        self.data = data
        self.unit = unit
        self.cfg = cfg
        self.verbose = verbose
        self.tmax = (len(self.data)-1)/self.samplerate
        self.toffset = 0.0
        self.twindow = 8.0
        if self.twindow > self.tmax:
            self.twindow = np.round(2 ** (np.floor(np.log(self.tmax) / np.log(2.0)) + 1.0))
        self.ymin = -1.0
        self.ymax = +1.0
        self.trace_artist = None
        self.spectrogram_artist = None
        self.fmin = 0.0
        self.fmax = 0.0
        self.decibel = True
        self.fresolution = self.cfg.value('frequencyResolution')
        self.deltaf = 1.0
        self.mains_freq = self.cfg.value('mainsFreq')
        self.power_label = None
        self.all_peaks_artis = None
        self.good_peaks_artist = None
        self.power_artist = None
        self.power_frequency_label = None
        self.peak_artists = []
        self.legend = True
        self.legendhandle = None
        self.help = self.cfg.value('displayHelp')
        self.helptext = []
        self.allpeaks = []
        self.fishlist = []
        self.mains = []
        self.peak_specmarker = []
        self.peak_annotation = []
        self.min_clip = self.cfg.value('minClipAmplitude')
        self.max_clip = self.cfg.value('maxClipAmplitude')
        self.colorrange, self.markerrange = colors_markers()

        # audio output:
        self.audio = PlayAudio()
        
        # set key bindings:
        plt.rcParams['keymap.fullscreen'] = 'ctrl+f'
        plt.rcParams['keymap.pan'] = 'ctrl+m'
        plt.rcParams['keymap.quit'] = 'ctrl+w, alt+q, q'
        plt.rcParams['keymap.yscale'] = ''
        plt.rcParams['keymap.xscale'] = ''
        plt.rcParams['keymap.grid'] = ''
        plt.rcParams['keymap.all_axes'] = ''

        # the figure:
        self.fig = plt.figure(figsize=(15, 9))
        self.fig.canvas.set_window_title(self.filename + ' channel {0:d}'.format(self.channel))
        self.fig.canvas.mpl_connect('key_press_event', self.keypress)
        self.fig.canvas.mpl_connect('button_press_event', self.buttonpress)
        self.fig.canvas.mpl_connect('pick_event', self.onpick)
        self.fig.canvas.mpl_connect('resize_event', self.resize)
        # trace plot:
        self.axt = self.fig.add_axes([0.1, 0.7, 0.87, 0.25])
        self.axt.set_ylabel('Amplitude [{:s}]'.format(self.unit))
        ht = self.axt.text(0.98, 0.05, '(ctrl+) page and arrow up, down, home, end: scroll', ha='right',
                           transform=self.axt.transAxes)
        self.helptext.append(ht)
        ht = self.axt.text(0.98, 0.15, '+, -, X, x: zoom in/out', ha='right', transform=self.axt.transAxes)
        self.helptext.append(ht)
        ht = self.axt.text(0.98, 0.25, 'y,Y,v,V: zoom amplitudes', ha='right', transform=self.axt.transAxes)
        self.helptext.append(ht)
        ht = self.axt.text(0.98, 0.35, 'p,P: play audio (display,all)', ha='right', transform=self.axt.transAxes)
        self.helptext.append(ht)
        ht = self.axt.text(0.98, 0.45, 'ctrl-f: full screen', ha='right', transform=self.axt.transAxes)
        self.helptext.append(ht)
        ht = self.axt.text(0.98, 0.55, 'w: plot waveform into png file', ha='right', transform=self.axt.transAxes)
        self.helptext.append(ht)
        ht = self.axt.text(0.98, 0.65, 's: save figure', ha='right', transform=self.axt.transAxes)
        self.helptext.append(ht)
        ht = self.axt.text(0.98, 0.75, 'S: save audiosegment', ha='right', transform=self.axt.transAxes)
        self.helptext.append(ht)
        ht = self.axt.text(0.98, 0.85, 'q: quit', ha='right', transform=self.axt.transAxes)
        self.helptext.append(ht)
        ht = self.axt.text(0.98, 0.95, 'h: toggle this help', ha='right', transform=self.axt.transAxes)
        self.helptext.append(ht)
        self.axt.set_xticklabels([])
        # spectrogram:
        self.axs = self.fig.add_axes([0.1, 0.45, 0.87, 0.25])
        self.axs.set_xlabel('Time [seconds]')
        self.axs.set_ylabel('Frequency [Hz]')
        # power spectrum:
        self.axp = self.fig.add_axes([0.1, 0.1, 0.87, 0.25])
        ht = self.axp.text(0.98, 0.9, 'r, R: frequency resolution', ha='right', transform=self.axp.transAxes)
        self.helptext.append(ht)
        ht = self.axp.text(0.98, 0.8, 'f, F: zoom', ha='right', transform=self.axp.transAxes)
        self.helptext.append(ht)
        ht = self.axp.text(0.98, 0.7, '(ctrl+) left, right: move', ha='right', transform=self.axp.transAxes)
        self.helptext.append(ht)
        ht = self.axp.text(0.98, 0.6, 'l: toggle legend', ha='right', transform=self.axp.transAxes)
        self.helptext.append(ht)
        ht = self.axp.text(0.98, 0.5, 'd: toggle decibel', ha='right', transform=self.axp.transAxes)
        self.helptext.append(ht)
        ht = self.axp.text(0.98, 0.4, 'm: toggle mains filter', ha='right', transform=self.axp.transAxes)
        self.helptext.append(ht)
        ht = self.axp.text(0.98, 0.3, 'left mouse: show peak properties', ha='right', transform=self.axp.transAxes)
        self.helptext.append(ht)
        ht = self.axp.text(0.98, 0.2, 'shift/ctrl + left/right mouse: goto previous/next harmonic', ha='right',
                           transform=self.axp.transAxes)
        self.helptext.append(ht)
        # plot:
        for ht in self.helptext:
            ht.set_visible(self.help)
        self.update_plots(False)
        plt.show()
コード例 #3
0
ファイル: fishfinder.py プロジェクト: Aeapsu/thunderfish
class SignalPlot:
    def __init__(self, data, samplingrate, unit, filename, channel, verbose, cfg):
        self.filename = filename
        self.channel = channel
        self.samplerate = samplingrate
        self.data = data
        self.unit = unit
        self.cfg = cfg
        self.verbose = verbose
        self.tmax = (len(self.data)-1)/self.samplerate
        self.toffset = 0.0
        self.twindow = 8.0
        if self.twindow > self.tmax:
            self.twindow = np.round(2 ** (np.floor(np.log(self.tmax) / np.log(2.0)) + 1.0))
        self.ymin = -1.0
        self.ymax = +1.0
        self.trace_artist = None
        self.spectrogram_artist = None
        self.fmin = 0.0
        self.fmax = 0.0
        self.decibel = True
        self.fresolution = self.cfg.value('frequencyResolution')
        self.deltaf = 1.0
        self.mains_freq = self.cfg.value('mainsFreq')
        self.power_label = None
        self.all_peaks_artis = None
        self.good_peaks_artist = None
        self.power_artist = None
        self.power_frequency_label = None
        self.peak_artists = []
        self.legend = True
        self.legendhandle = None
        self.help = self.cfg.value('displayHelp')
        self.helptext = []
        self.allpeaks = []
        self.fishlist = []
        self.mains = []
        self.peak_specmarker = []
        self.peak_annotation = []
        self.min_clip = self.cfg.value('minClipAmplitude')
        self.max_clip = self.cfg.value('maxClipAmplitude')
        self.colorrange, self.markerrange = colors_markers()

        # audio output:
        self.audio = PlayAudio()
        
        # set key bindings:
        plt.rcParams['keymap.fullscreen'] = 'ctrl+f'
        plt.rcParams['keymap.pan'] = 'ctrl+m'
        plt.rcParams['keymap.quit'] = 'ctrl+w, alt+q, q'
        plt.rcParams['keymap.yscale'] = ''
        plt.rcParams['keymap.xscale'] = ''
        plt.rcParams['keymap.grid'] = ''
        plt.rcParams['keymap.all_axes'] = ''

        # the figure:
        self.fig = plt.figure(figsize=(15, 9))
        self.fig.canvas.set_window_title(self.filename + ' channel {0:d}'.format(self.channel))
        self.fig.canvas.mpl_connect('key_press_event', self.keypress)
        self.fig.canvas.mpl_connect('button_press_event', self.buttonpress)
        self.fig.canvas.mpl_connect('pick_event', self.onpick)
        self.fig.canvas.mpl_connect('resize_event', self.resize)
        # trace plot:
        self.axt = self.fig.add_axes([0.1, 0.7, 0.87, 0.25])
        self.axt.set_ylabel('Amplitude [{:s}]'.format(self.unit))
        ht = self.axt.text(0.98, 0.05, '(ctrl+) page and arrow up, down, home, end: scroll', ha='right',
                           transform=self.axt.transAxes)
        self.helptext.append(ht)
        ht = self.axt.text(0.98, 0.15, '+, -, X, x: zoom in/out', ha='right', transform=self.axt.transAxes)
        self.helptext.append(ht)
        ht = self.axt.text(0.98, 0.25, 'y,Y,v,V: zoom amplitudes', ha='right', transform=self.axt.transAxes)
        self.helptext.append(ht)
        ht = self.axt.text(0.98, 0.35, 'p,P: play audio (display,all)', ha='right', transform=self.axt.transAxes)
        self.helptext.append(ht)
        ht = self.axt.text(0.98, 0.45, 'ctrl-f: full screen', ha='right', transform=self.axt.transAxes)
        self.helptext.append(ht)
        ht = self.axt.text(0.98, 0.55, 'w: plot waveform into png file', ha='right', transform=self.axt.transAxes)
        self.helptext.append(ht)
        ht = self.axt.text(0.98, 0.65, 's: save figure', ha='right', transform=self.axt.transAxes)
        self.helptext.append(ht)
        ht = self.axt.text(0.98, 0.75, 'S: save audiosegment', ha='right', transform=self.axt.transAxes)
        self.helptext.append(ht)
        ht = self.axt.text(0.98, 0.85, 'q: quit', ha='right', transform=self.axt.transAxes)
        self.helptext.append(ht)
        ht = self.axt.text(0.98, 0.95, 'h: toggle this help', ha='right', transform=self.axt.transAxes)
        self.helptext.append(ht)
        self.axt.set_xticklabels([])
        # spectrogram:
        self.axs = self.fig.add_axes([0.1, 0.45, 0.87, 0.25])
        self.axs.set_xlabel('Time [seconds]')
        self.axs.set_ylabel('Frequency [Hz]')
        # power spectrum:
        self.axp = self.fig.add_axes([0.1, 0.1, 0.87, 0.25])
        ht = self.axp.text(0.98, 0.9, 'r, R: frequency resolution', ha='right', transform=self.axp.transAxes)
        self.helptext.append(ht)
        ht = self.axp.text(0.98, 0.8, 'f, F: zoom', ha='right', transform=self.axp.transAxes)
        self.helptext.append(ht)
        ht = self.axp.text(0.98, 0.7, '(ctrl+) left, right: move', ha='right', transform=self.axp.transAxes)
        self.helptext.append(ht)
        ht = self.axp.text(0.98, 0.6, 'l: toggle legend', ha='right', transform=self.axp.transAxes)
        self.helptext.append(ht)
        ht = self.axp.text(0.98, 0.5, 'd: toggle decibel', ha='right', transform=self.axp.transAxes)
        self.helptext.append(ht)
        ht = self.axp.text(0.98, 0.4, 'm: toggle mains filter', ha='right', transform=self.axp.transAxes)
        self.helptext.append(ht)
        ht = self.axp.text(0.98, 0.3, 'left mouse: show peak properties', ha='right', transform=self.axp.transAxes)
        self.helptext.append(ht)
        ht = self.axp.text(0.98, 0.2, 'shift/ctrl + left/right mouse: goto previous/next harmonic', ha='right',
                           transform=self.axp.transAxes)
        self.helptext.append(ht)
        # plot:
        for ht in self.helptext:
            ht.set_visible(self.help)
        self.update_plots(False)
        plt.show()

    def __del(self):
        self.audio.close()

    def remove_peak_annotation(self):
        for fm in self.peak_specmarker:
            fm.remove()
        self.peak_specmarker = []
        for fa in self.peak_annotation:
            fa.remove()
        self.peak_annotation = []

    def annotate_peak(self, peak, harmonics=-1, inx=-1):
        # marker:
        if inx >= 0:
            m, = self.axs.plot([self.toffset + 0.01 * self.twindow], [peak[0]], linestyle='None',
                               color=self.colorrange[inx % len(self.colorrange)],
                               marker=self.markerrange[inx], ms=10.0, mec=None, mew=0.0, zorder=2)
        else:
            m, = self.axs.plot([self.toffset + 0.01 * self.twindow], [peak[0]], linestyle='None',
                               color='k', marker='o', ms=10.0, mec=None, mew=0.0, zorder=2)
        self.peak_specmarker.append(m)
        # annotation:
        fwidth = self.fmax - self.fmin
        pl = []
        if self.cfg.value('labelFrequency'):
            pl.append(r'$f=${:.1f} Hz'.format(peak[0]))
        if self.cfg.value('labelHarmonic') and harmonics >= 0:
            pl.append(r'$h=${:d}'.format(harmonics))
        if self.cfg.value('labelPower'):
            pl.append(r'$p=${:g}'.format(peak[1]))
        if self.cfg.value('labelWidth'):
            pl.append(r'$\Delta f=${:.2f} Hz'.format(peak[3]))
        if self.cfg.value('labelDoubleUse'):
            pl.append(r'dc={:.0f}'.format(peak[4]))
        self.peak_annotation.append(self.axp.annotate('\n'.join(pl), xy=(peak[0], peak[1]),
                                                      xytext=(peak[0] + 0.03 * fwidth, peak[1]),
                                                      bbox=dict(boxstyle='round', facecolor='white'),
                                                      arrowprops=dict(arrowstyle='-')))

    def annotate_fish(self, fish, inx=-1):
        self.remove_peak_annotation()
        for harmonic, freq in enumerate(fish[:, 0]):
            peak = self.allpeaks[np.abs(self.allpeaks[:, 0] - freq) < 0.8 * self.deltaf, :]
            if len(peak) > 0:
                self.annotate_peak(peak[0, :], harmonic, inx)
        self.fig.canvas.draw()

    def update_plots(self, draw=True):
        self.remove_peak_annotation()
        # trace:
        self.axt.set_xlim(self.toffset, self.toffset + self.twindow)
        t0 = int(np.round(self.toffset * self.samplerate))
        t1 = int(np.round((self.toffset + self.twindow) * self.samplerate))
        if t1>len(self.data):
            t1 = len(self.data)
        time = np.arange(t0, t1) / self.samplerate
        if self.trace_artist == None:
            self.trace_artist, = self.axt.plot(time, self.data[t0:t1])
        else:
            self.trace_artist.set_data(time, self.data[t0:t1])
        self.axt.set_ylim(self.ymin, self.ymax)

        # compute power spectrum:
        nfft, noverlap = nfft_noverlap(self.fresolution, self.samplerate, 0.5, 16)
        t00 = t0
        t11 = t1
        w = t11 - t00
        minw = nfft * (self.cfg.value('minPSDAverages') + 1) // 2
        if t11 - t00 < minw:
            w = minw
            t11 = t00 + w
        if t11 >= len(self.data):
            t11 = len(self.data)
            t00 = t11 - w
        if t00 < 0:
            t00 = 0
            t11 = w
        power, freqs = ml.psd(self.data[t00:t11], NFFT=nfft, noverlap=noverlap, Fs=self.samplerate, detrend=ml.detrend_mean)
        power = np.squeeze(power) # squeeze is necessary when nfft is to large with respect to the data
        self.deltaf = freqs[1] - freqs[0]
        # detect fish:
        h_kwargs = psd_peak_detection_args(self.cfg)
        h_kwargs.update(harmonic_groups_args(self.cfg))
        self.fishlist, fzero_harmonics, self.mains, self.allpeaks, peaks, lowth, highth, center = harmonic_groups(freqs, power, verbose=self.verbose, **h_kwargs)
        highth = center + highth - 0.5 * lowth
        lowth = center + 0.5 * lowth

        # spectrogram:
        t2 = t1 + nfft
        specpower, freqs, bins = ml.specgram(self.data[t0:t2], NFFT=nfft, Fs=self.samplerate, noverlap=nfft // 2,
                                             detrend=ml.detrend_mean)
        z = decibel(specpower)
        z = np.flipud(z)
        extent = self.toffset, self.toffset + np.amax(bins), freqs[0], freqs[-1]
        self.axs.set_xlim(self.toffset, self.toffset + self.twindow)
        if self.spectrogram_artist == None:
            self.fmax = np.round((freqs[-1] / 4.0) / 100.0) * 100.0
            min = highth
            min = np.percentile(z, 70.0)
            max = np.percentile(z, 99.9) + 30.0
            # cm = plt.get_cmap( 'hot_r' )
            cm = plt.get_cmap('jet')
            self.spectrogram_artist = self.axs.imshow(z, aspect='auto',
                                                      extent=extent, vmin=min, vmax=max,
                                                      cmap=cm, zorder=1)
        else:
            self.spectrogram_artist.set_data(z)
            self.spectrogram_artist.set_extent(extent)
        self.axs.set_ylim(self.fmin, self.fmax)

        # power spectrum:
        self.axp.set_xlim(self.fmin, self.fmax)
        if self.deltaf >= 1000.0:
            dfs = '%.3gkHz' % 0.001 * self.deltaf
        else:
            dfs = '%.3gHz' % self.deltaf
        tw = float(w) / self.samplerate
        if tw < 1.0:
            tws = '%.3gms' % (1000.0 * tw)
        else:
            tws = '%.3gs' % (tw)
        a = 2 * w // nfft - 1  # number of ffts
        m = ''
        if self.cfg.value('mainsFreq') > 0.0:
            m = ', mains=%.0fHz' % self.cfg.value('mainsFreq')
        if self.power_frequency_label == None:
            self.power_frequency_label = self.axp.set_xlabel(
                r'Frequency [Hz] (nfft={:d}, $\Delta f$={:s}: T={:s}/{:d}{:s})'.format(nfft, dfs, tws, a, m))
        else:
            self.power_frequency_label.set_text(
                r'Frequency [Hz] (nfft={:d}, $\Delta f$={:s}: T={:s}/{:d}{:s})'.format(nfft, dfs, tws, a, m))
        self.axp.set_xlim(self.fmin, self.fmax)
        if self.power_label == None:
            self.power_label = self.axp.set_ylabel('Power')
        if self.decibel:
            if len(self.allpeaks) > 0:
                self.allpeaks[:, 1] = decibel(self.allpeaks[:, 1])
            power = decibel(power)
            pmin = np.min(power[freqs < self.fmax])
            pmin = np.floor(pmin / 10.0) * 10.0
            pmax = np.max(power[freqs < self.fmax])
            pmax = np.ceil(pmax / 10.0) * 10.0
            doty = pmax - 5.0
            self.power_label.set_text('Power [dB]')
            self.axp.set_ylim(pmin, pmax)
        else:
            pmax = np.max(power[freqs < self.fmax])
            doty = pmax
            pmax *= 1.1
            self.power_label.set_text('Power')
            self.axp.set_ylim(0.0, pmax)
        if self.all_peaks_artis == None:
            self.all_peaks_artis, = self.axp.plot(self.allpeaks[:, 0],
                                                  np.zeros(len(self.allpeaks[:, 0])) + doty,
                                                  'o', color='#ffffff')
            self.good_peaks_artist, = self.axp.plot(peaks, np.zeros(len(peaks)) + doty,
                                                    'o', color='#888888')
        else:
            self.all_peaks_artis.set_data(self.allpeaks[:, 0],
                                          np.zeros(len(self.allpeaks[:, 0])) + doty)
            self.good_peaks_artist.set_data(peaks, np.zeros(len(peaks)) + doty)
        labels = []
        fsizes = [np.sqrt(np.sum(self.fishlist[k][:, 1])) for k in range(len(self.fishlist))]
        fmaxsize = np.max(fsizes) if len(fsizes) > 0 else 1.0
        for k in range(len(self.peak_artists)):
            self.peak_artists[k].remove()
        self.peak_artists = []
        for k in range(len(self.fishlist)):
            if k >= len(self.markerrange):
                break
            fpeaks = self.fishlist[k][:, 0]
            fpeakinx = [int(np.round(fp / self.deltaf)) for fp in fpeaks if fp < freqs[-1]]
            fsize = 7.0 + 10.0 * (fsizes[k] / fmaxsize) ** 0.5
            fishpoints, = self.axp.plot(fpeaks[:len(fpeakinx)], power[fpeakinx], linestyle='None',
                                        color=self.colorrange[k % len(self.colorrange)],
                                        marker=self.markerrange[k], ms=fsize,
                                        mec=None, mew=0.0, zorder=1)
            self.peak_artists.append(fishpoints)
            if self.deltaf < 0.1:
                labels.append('%4.2f Hz' % fpeaks[0])
            elif self.deltaf < 1.0:
                labels.append('%4.1f Hz' % fpeaks[0])
            else:
                labels.append('%4.0f Hz' % fpeaks[0])
        if len(self.mains) > 0:
            fpeaks = self.mains[:, 0]
            fpeakinx = np.array([np.round(fp / self.deltaf) for fp in fpeaks if fp < freqs[-1]], dtype=np.int)
            fishpoints, = self.axp.plot(fpeaks[:len(fpeakinx)],
                                        power[fpeakinx], linestyle='None',
                                        marker='.', color='k', ms=10, mec=None, mew=0.0, zorder=2)
            self.peak_artists.append(fishpoints)
            labels.append('%3.0f Hz mains' % self.cfg.value('mainsFreq'))
        ncol = (len(labels)-1) // 8 + 1
        self.legendhandle = self.axs.legend(self.peak_artists[:len(labels)], labels, loc='upper right', ncol=ncol)
        self.legenddict = dict()
        for legpoints, (finx, fish) in zip(self.legendhandle.get_lines(), enumerate(self.fishlist)):
            legpoints.set_picker(8)
            self.legenddict[legpoints] = [finx, fish]
        self.legendhandle.set_visible(self.legend)
        if self.power_artist == None:
            self.power_artist, = self.axp.plot(freqs, power, 'b', zorder=3)
        else:
            self.power_artist.set_data(freqs, power)
        if draw:
            self.fig.canvas.draw()

    def keypress(self, event):
        # print('pressed', event.key)
        if event.key in '+=X':
            if self.twindow * self.samplerate > 20:
                self.twindow *= 0.5
                self.update_plots()
        elif event.key in '-x':
            if self.twindow < len(self.data) / self.samplerate:
                self.twindow *= 2.0
                self.update_plots()
        elif event.key == 'pagedown':
            if self.toffset + 0.5 * self.twindow < len(self.data) / self.samplerate:
                self.toffset += 0.5 * self.twindow
                self.update_plots()
        elif event.key == 'pageup':
            if self.toffset > 0:
                self.toffset -= 0.5 * self.twindow
                if self.toffset < 0.0:
                    self.toffset = 0.0
                self.update_plots()
        elif event.key == 'a':
            if self.min_clip == 0.0 or self.max_clip == 0.0:
                self.min_clip, self.max_clip = clip_amplitudes(
                    self.data, **clip_args(self.cfg, self.samplerate))
            try:
                idx0, idx1, clipped = best_window_indices(
                    self.data, self.samplerate, min_clip=self.min_clip,
                    max_clip=self.max_clip, **best_window_args(self.cfg))
                if idx1 > 0:
                    self.toffset = idx0 / self.samplerate
                    self.twindow = (idx1 - idx0) / self.samplerate
                    self.twindow *= 2.0/(self.cfg.value('numberPSDWindows')+1.0)
                    self.update_plots()
            except UserWarning as e:
                if self.verbose > 0:
                    print(str(e))
        elif event.key == 'ctrl+pagedown':
            if self.toffset + 5.0 * self.twindow < len(self.data) / self.samplerate:
                self.toffset += 5.0 * self.twindow
                self.update_plots()
        elif event.key == 'ctrl+pageup':
            if self.toffset > 0:
                self.toffset -= 5.0 * self.twindow
                if self.toffset < 0.0:
                    self.toffset = 0.0
                self.update_plots()
        elif event.key == 'down':
            if self.toffset + self.twindow < len(self.data) / self.samplerate:
                self.toffset += 0.05 * self.twindow
                self.update_plots()
        elif event.key == 'up':
            if self.toffset > 0.0:
                self.toffset -= 0.05 * self.twindow
                if self.toffset < 0.0:
                    self.toffset = 0.0
                self.update_plots()
        elif event.key == 'home':
            if self.toffset > 0.0:
                self.toffset = 0.0
                self.update_plots()
        elif event.key == 'end':
            toffs = np.floor(len(self.data) / self.samplerate / self.twindow) * self.twindow
            if self.toffset < toffs:
                self.toffset = toffs
                self.update_plots()
        elif event.key == 'y':
            h = self.ymax - self.ymin
            c = 0.5 * (self.ymax + self.ymin)
            self.ymin = c - h
            self.ymax = c + h
            self.axt.set_ylim(self.ymin, self.ymax)
            self.fig.canvas.draw()
        elif event.key == 'Y':
            h = 0.25 * (self.ymax - self.ymin)
            c = 0.5 * (self.ymax + self.ymin)
            self.ymin = c - h
            self.ymax = c + h
            self.axt.set_ylim(self.ymin, self.ymax)
            self.fig.canvas.draw()
        elif event.key == 'v':
            t0 = int(np.round(self.toffset * self.samplerate))
            t1 = int(np.round((self.toffset + self.twindow) * self.samplerate))
            min = np.min(self.data[t0:t1])
            max = np.max(self.data[t0:t1])
            h = 0.5 * (max - min)
            c = 0.5 * (max + min)
            self.ymin = c - h
            self.ymax = c + h
            self.axt.set_ylim(self.ymin, self.ymax)
            self.fig.canvas.draw()
        elif event.key == 'V':
            self.ymin = -1.0
            self.ymax = +1.0
            self.axt.set_ylim(self.ymin, self.ymax)
            self.fig.canvas.draw()
        elif event.key == 'left':
            if self.fmin > 0.0:
                fwidth = self.fmax - self.fmin
                self.fmin -= 0.5 * fwidth
                self.fmax -= 0.5 * fwidth
                if self.fmin < 0.0:
                    self.fmin = 0.0
                    self.fmax = fwidth
                self.axs.set_ylim(self.fmin, self.fmax)
                self.axp.set_xlim(self.fmin, self.fmax)
                self.fig.canvas.draw()
        elif event.key == 'right':
            if self.fmax < 0.5 * self.samplerate:
                fwidth = self.fmax - self.fmin
                self.fmin += 0.5 * fwidth
                self.fmax += 0.5 * fwidth
                self.axs.set_ylim(self.fmin, self.fmax)
                self.axp.set_xlim(self.fmin, self.fmax)
                self.fig.canvas.draw()
        elif event.key == 'ctrl+left':
            if self.fmin > 0.0:
                fwidth = self.fmax - self.fmin
                self.fmin = 0.0
                self.fmax = fwidth
                self.axs.set_ylim(self.fmin, self.fmax)
                self.axp.set_xlim(self.fmin, self.fmax)
                self.fig.canvas.draw()
        elif event.key == 'ctrl+right':
            if self.fmax < 0.5 * self.samplerate:
                fwidth = self.fmax - self.fmin
                fm = 0.5 * self.samplerate
                self.fmax = np.ceil(fm / fwidth) * fwidth
                self.fmin = self.fmax - fwidth
                if self.fmin < 0.0:
                    self.fmin = 0.0
                    self.fmax = fwidth
                self.axs.set_ylim(self.fmin, self.fmax)
                self.axp.set_xlim(self.fmin, self.fmax)
                self.fig.canvas.draw()
        elif event.key in 'f':
            if self.fmax < 0.5 * self.samplerate or self.fmin > 0.0:
                fwidth = self.fmax - self.fmin
                if self.fmax < 0.5 * self.samplerate:
                    self.fmax = self.fmin + 2.0 * fwidth
                elif self.fmin > 0.0:
                    self.fmin = self.fmax - 2.0 * fwidth
                    if self.fmin < 0.0:
                        self.fmin = 0.0
                        self.fmax = 2.0 * fwidth
                self.axs.set_ylim(self.fmin, self.fmax)
                self.axp.set_xlim(self.fmin, self.fmax)
                self.fig.canvas.draw()
        elif event.key in 'F':
            if self.fmax - self.fmin > 1.0:
                fwidth = self.fmax - self.fmin
                self.fmax = self.fmin + 0.5 * fwidth
                self.axs.set_ylim(self.fmin, self.fmax)
                self.axp.set_xlim(self.fmin, self.fmax)
                self.fig.canvas.draw()
        elif event.key in 'r':
            if self.fresolution < 1000.0:
                self.fresolution *= 2.0
                self.update_plots()
        elif event.key in 'R':
            if 1.0 / self.fresolution < self.tmax:
                self.fresolution *= 0.5
                self.update_plots()
        elif event.key in 'd':
            self.decibel = not self.decibel
            self.update_plots()
        elif event.key in 'm':
            if self.cfg.value('mainsFreq') == 0.0:
                self.cfg.set('mainsFreq', self.mains_freq)
            else:
                self.cfg.set('mainsFreq', 0.0)
            self.update_plots()
        elif event.key in 't':
            t_diff = self.cfg.value('highThresholdFactor') - self.cfg.value('lowThresholdFactor')
            self.cfg.set('lowThresholdFactor', self.cfg.value('lowThresholdFactor') - 0.1)
            if self.cfg.value('lowThresholdFactor') < 0.1:
                self.cfg.set('lowThresholdFactor', 0.1)
            self.cfg.set('highThresholdFactor', self.cfg.value('lowThresholdFactor') + t_diff)
            print('lowThresholdFactor =', self.cfg.value('lowThresholdFactor'))
            self.update_plots()
        elif event.key in 'T':
            t_diff = self.cfg.value('highThresholdFactor') - self.cfg.value('lowThresholdFactor')
            self.cfg.set('lowThresholdFactor', self.cfg.value('lowThresholdFactor') + 0.1)
            if self.cfg.value('lowThresholdFactor') > 20.0:
                self.cfg.set('lowThresholdFactor', 20.0)
            self.cfg.set('highThresholdFactor', self.cfg.value('lowThresholdFactor') + t_diff)
            print('lowThresholdFactor =', self.cfg.value('lowThresholdFactor'))
            self.update_plots()
        elif event.key == 'escape':
            self.remove_peak_annotation()
            self.fig.canvas.draw()
        elif event.key in 'h':
            self.help = not self.help
            for ht in self.helptext:
                ht.set_visible(self.help)
            self.fig.canvas.draw()
        elif event.key in 'l':
            self.legend = not self.legend
            self.legendhandle.set_visible(self.legend)
            self.fig.canvas.draw()
        elif event.key in 'w':
            self.plot_waveform()
        elif event.key in 'p':
            self.play_segment()
        elif event.key in 'P':
            self.play_all()
        elif event.key in '1' :
            self.play_tone('c3')
        elif event.key in '2' :
            self.play_tone('a3')
        elif event.key in '3' :
            self.play_tone('e4')
        elif event.key in '4' :
            self.play_tone('a4')
        elif event.key in '5' :
            self.play_tone('c5')
        elif event.key in '6' :
            self.play_tone('e5')
        elif event.key in '7' :
            self.play_tone('g5')
        elif event.key in '8' :
            self.play_tone('a5')
        elif event.key in '9' :
            self.play_tone('c6')
        elif event.key in 'S':
            self.save_segment()

    def buttonpress( self, event ) :
        # print('mouse pressed', event.button, event.key, event.step)
        if event.inaxes == self.axp:
            if event.key == 'shift' or event.key == 'control':
                # show next or previous harmonic:
                if event.key == 'shift':
                    if event.button == 1:
                        ftarget = event.xdata / 2.0
                    elif event.button == 3:
                        ftarget = event.xdata * 2.0
                else:
                    if event.button == 1:
                        ftarget = event.xdata / 1.5
                    elif event.button == 3:
                        ftarget = event.xdata * 1.5
                foffs = event.xdata - self.fmin
                fwidth = self.fmax - self.fmin
                self.fmin = ftarget - foffs
                self.fmax = self.fmin + fwidth
                self.axs.set_ylim(self.fmin, self.fmax)
                self.axp.set_xlim(self.fmin, self.fmax)
                self.fig.canvas.draw()
            else:
                # put label on peak
                self.remove_peak_annotation()
                # find closest peak:
                fwidth = self.fmax - self.fmin
                peakdist = np.abs(self.allpeaks[:, 0] - event.xdata)
                inx = np.argmin(peakdist)
                if peakdist[inx] < 0.005 * fwidth:
                    peak = self.allpeaks[inx, :]
                    # find fish:
                    foundfish = False
                    for finx, fish in enumerate(self.fishlist):
                        if np.min(np.abs(fish[:, 0] - peak[0])) < 0.8 * self.deltaf:
                            self.annotate_fish(fish, finx)
                            foundfish = True
                            break
                    if not foundfish:
                        self.annotate_peak(peak)
                        self.fig.canvas.draw()
                else:
                    self.fig.canvas.draw()

    def onpick(self, event):
        # print('pick')
        legendpoint = event.artist
        finx, fish = self.legenddict[legendpoint]
        self.annotate_fish(fish, finx)

    def resize(self, event):
        # print('resized', event.width, event.height)
        leftpixel = 80.0
        rightpixel = 20.0
        xaxispixel = 50.0
        toppixel = 20.0
        timeaxis = 0.42
        left = leftpixel / event.width
        width = 1.0 - left - rightpixel / event.width
        xaxis = xaxispixel / event.height
        top = toppixel / event.height
        height = (1.0 - timeaxis - top) / 2.0
        if left < 0.5 and width < 1.0 and xaxis < 0.3 and top < 0.2:
            self.axt.set_position([left, timeaxis + height, width, height])
            self.axs.set_position([left, timeaxis, width, height])
            self.axp.set_position([left, xaxis, width, timeaxis - 2.0 * xaxis])

    def plot_waveform(self):
        fig = plt.figure()
        ax = fig.add_subplot(1, 1, 1)
        name = self.filename.split('.')[0]
        if self.channel > 0:
            ax.set_title('{filename} channel={channel:d}'.format(
                filename=self.filename, channel=self.channel))
            figfile = '{name}-{channel:d}-{time:.4g}s-waveform.png'.format(
                name=name, channel=self.channel, time=self.toffset)
        else:
            ax.set_title(self.filename)
            figfile = '{name}-{time:.4g}s-waveform.png'.format(
                name=name, time=self.toffset)
        t0 = int(np.round(self.toffset * self.samplerate))
        t1 = int(np.round((self.toffset + self.twindow) * self.samplerate))
        if t1>len(self.data):
            t1 = len(self.data)
        time = np.arange(t0, t1) / self.samplerate
        if self.twindow < 1.0:
            ax.set_xlabel('Time [ms]')
            ax.set_xlim(1000.0 * self.toffset,
                        1000.0 * (self.toffset + self.twindow))
            ax.plot(1000.0 * time, self.data[t0:t1])
        else:
            ax.set_xlabel('Time [s]')
            ax.set_xlim(self.toffset, self.toffset + self.twindow)
            ax.plot(time, self.data[t0:t1])
        ax.set_ylabel('Amplitude [{:s}]'.format(self.unit))
        fig.tight_layout()
        fig.savefig(figfile)
        fig.clear()
        plt.close(fig)
        print('saved waveform figure to', figfile)

    def play_segment(self):
        t0 = int(np.round(self.toffset * self.samplerate))
        t1 = int(np.round((self.toffset + self.twindow) * self.samplerate))
        playdata = 1.0 * self.data[t0:t1]
        fade(playdata, self.samplerate, 0.1)
        self.audio.play(playdata, self.samplerate, blocking=False)

    def save_segment(self):
        t0s = int(np.round(self.toffset))
        t1s = int(np.round(self.toffset + self.twindow))
        t0 = int(np.round(self.toffset * self.samplerate))
        t1 = int(np.round((self.toffset + self.twindow) * self.samplerate))
        savedata = 1.0 * self.data[t0:t1]
        filename = self.filename.split('.')[0]
        segmentfilename = '{name}-{time0:.4g}s-{time1:.4g}s.wav'.format(
                name=filename, time0=t0s, time1 = t1s)
        write_audio(segmentfilename, savedata, self.data.samplerate)
        print('saved segment to: ' , segmentfilename)
        
    def play_all(self):
        self.audio.play(self.data[:], self.samplerate, blocking=False)
        
    def play_tone( self, frequency ) :
        self.audio.beep(1.0, frequency)
コード例 #4
0
ファイル: songdetector.py プロジェクト: bendalab/audian
    def __init__(self, samplingrate, data, fdata, env, slowenv, envrate, threshs, onsets, offsets, unit, filename, path, cfg) :
        self.filepath = ''
        if platform.system() == 'Windows' :
            self.filepath = path
        self.filename = filename
        self.rate = samplingrate
        self.data = data
        self.unit = unit
        self.time = np.arange( 0.0, self.data.shape[0] )/self.rate
        self.toffset = 0.0
        self.twindow = 60.0
        if self.twindow > self.time[-1] :
            self.twindow = np.round( 2**(np.floor(np.log(self.time[-1]) / np.log(2.0)) + 1.0) )
        self.lowpassfreq = cfg.value('lowpassfreq')
        self.highpassfreq = cfg.value('highpassfreq')
        self.fdata = fdata
        self.channels = data.shape[1]
        self.envelopecutofffreq = cfg.value('envelopecutofffreq')
        self.envelopefilter = cfg.value('envelopefilter')
        self.envelope = env
        self.slowenvelope = slowenv
        self.envrate = envrate
        self.thresholdfac = cfg.value('thresholdfactor')
        self.thresholds = threshs
        self.min_duration = cfg.value('minduration')
        self.songonsets = onsets
        self.songoffsets = offsets
        self.trace_artists = []
        self.filtered_trace_artists = []
        self.envelope_artists = []
        self.slowenvelope_artists = []
        self.threshold_artists = []
        self.songonset_artists = []
        self.songoffset_artists = []
        self.highpass_label = None
        self.lowpass_label = None
        self.envelope_label = None
        self.max_pixel = cfg.value('maxpixel')
        self.show_traces = cfg.value('displayTraces')
        self.show_filtered_traces = cfg.value('displayFilteredTraces')
        self.show_envelope = cfg.value('displayEnvelope')
        self.show_slowenvelope = cfg.value('displaySlowEnvelope')
        self.show_thresholds = True
        self.show_songonsets = True
        self.show_songoffsets = True
        self.help = cfg.value('displayHelp')
        self.helptext = []
        self.analysis_file = None

        # audio output:
        self.audio = PlayAudio()

        # set key bindings:
        #plt.rcParams['keymap.fullscreen'] = 'ctrl+f'
        plt.rcParams['keymap.fullscreen'] = ''
        plt.rcParams['keymap.pan'] = 'ctrl+m'
        plt.rcParams['keymap.quit'] = 'ctrl+w, alt+q, q'
        plt.rcParams['keymap.save'] = 'alt+s'
        plt.rcParams['keymap.yscale'] = ''
        plt.rcParams['keymap.xscale'] = ''
        plt.rcParams['keymap.grid'] = ''
        plt.rcParams['keymap.all_axes'] = ''
        
        # the figure:
        self.fig = plt.figure( figsize=( 15, 9 ) )
        self.fig.canvas.set_window_title( 'SongDetector: ' + self.filename )
        self.fig.canvas.mpl_connect( 'key_press_event', self.keypress )
        
        # trace plots:
        ph = 0.9/self.channels
        self.axt = []
        self.ymin = []
        self.ymax = []
        for c in range(self.channels):
            self.ymin.append( -1.0 )
            self.ymax.append( +1.0 )
            if np.min(self.data[:, c]) < -1.0 or np.max(self.data[:, c]) > +1.0 :
                self.ymin[c] = -10.0
                self.ymax[c] = +10.0
            if c == 0 :
                self.axt.append( self.fig.add_axes( [ 0.08, 0.06+(self.channels-c-1)*ph, 0.89, ph ] ) )
                self.highpass_label = self.axt[0].text( 0.05, 0.9, 'highpass=%.1fkHz' % (0.001*self.highpassfreq), transform=self.axt[0].transAxes )
                self.lowpass_label = self.axt[0].text( 0.2, 0.9, 'lowpass=%.1fkHz' % (0.001*self.lowpassfreq), transform=self.axt[0].transAxes )
                self.envelope_label = self.axt[0].text( 0.35, 0.9, 'envelope=%.0fHz' % self.envelopecutofffreq, transform=self.axt[0].transAxes )
            else:
                self.axt.append( self.fig.add_axes( [ 0.08, 0.08+(self.channels-c-1)*ph, 0.89, ph ], sharex=self.axt[0] ) )
            self.axt[-1].set_ylabel( 'Amplitude [{:s}]'.format( self.unit ) )
        self.axt[-1].set_xlabel( 'Time [s]' )
        """
        ht = self.axt.text( 0.98, 0.05, '(ctrl+) page and arrow up, down, home, end: scroll', ha='right', transform=self.axt.transAxes )
        self.helptext.append( ht )
        ht = self.axt.text( 0.98, 0.15, '+, -, X, x: zoom in/out', ha='right', transform=self.axt.transAxes )
        self.helptext.append( ht )
        ht = self.axt.text( 0.98, 0.25, 'y,Y,v,V: zoom amplitudes', ha='right', transform=self.axt.transAxes )
        self.helptext.append( ht )
        ht = self.axt.text( 0.98, 0.35, 'p,P: play audio (display,all)', ha='right', transform=self.axt.transAxes )
        self.helptext.append( ht )
        ht = self.axt.text( 0.98, 0.45, 'ctrl-f: full screen', ha='right', transform=self.axt.transAxes )
        self.helptext.append( ht )
        ht = self.axt.text( 0.98, 0.65, 's: save figure', ha='right', transform=self.axt.transAxes )
        self.helptext.append( ht )
        ht = self.axt.text( 0.98, 0.75, 'q: quit', ha='right', transform=self.axt.transAxes )
        self.helptext.append( ht )
        ht = self.axt.text( 0.98, 0.85, 'h: toggle this help', ha='right', transform=self.axt.transAxes )
        self.helptext.append( ht )
        # plot:
        for ht in self.helptext :
            ht.set_visible( self.help )
        """
        self.update_plots( False )
        plt.show()
コード例 #5
0
ファイル: songdetector.py プロジェクト: bendalab/audian
class SignalPlot :
    def __init__(self, samplingrate, data, fdata, env, slowenv, envrate, threshs, onsets, offsets, unit, filename, path, cfg) :
        self.filepath = ''
        if platform.system() == 'Windows' :
            self.filepath = path
        self.filename = filename
        self.rate = samplingrate
        self.data = data
        self.unit = unit
        self.time = np.arange( 0.0, self.data.shape[0] )/self.rate
        self.toffset = 0.0
        self.twindow = 60.0
        if self.twindow > self.time[-1] :
            self.twindow = np.round( 2**(np.floor(np.log(self.time[-1]) / np.log(2.0)) + 1.0) )
        self.lowpassfreq = cfg.value('lowpassfreq')
        self.highpassfreq = cfg.value('highpassfreq')
        self.fdata = fdata
        self.channels = data.shape[1]
        self.envelopecutofffreq = cfg.value('envelopecutofffreq')
        self.envelopefilter = cfg.value('envelopefilter')
        self.envelope = env
        self.slowenvelope = slowenv
        self.envrate = envrate
        self.thresholdfac = cfg.value('thresholdfactor')
        self.thresholds = threshs
        self.min_duration = cfg.value('minduration')
        self.songonsets = onsets
        self.songoffsets = offsets
        self.trace_artists = []
        self.filtered_trace_artists = []
        self.envelope_artists = []
        self.slowenvelope_artists = []
        self.threshold_artists = []
        self.songonset_artists = []
        self.songoffset_artists = []
        self.highpass_label = None
        self.lowpass_label = None
        self.envelope_label = None
        self.max_pixel = cfg.value('maxpixel')
        self.show_traces = cfg.value('displayTraces')
        self.show_filtered_traces = cfg.value('displayFilteredTraces')
        self.show_envelope = cfg.value('displayEnvelope')
        self.show_slowenvelope = cfg.value('displaySlowEnvelope')
        self.show_thresholds = True
        self.show_songonsets = True
        self.show_songoffsets = True
        self.help = cfg.value('displayHelp')
        self.helptext = []
        self.analysis_file = None

        # audio output:
        self.audio = PlayAudio()

        # set key bindings:
        #plt.rcParams['keymap.fullscreen'] = 'ctrl+f'
        plt.rcParams['keymap.fullscreen'] = ''
        plt.rcParams['keymap.pan'] = 'ctrl+m'
        plt.rcParams['keymap.quit'] = 'ctrl+w, alt+q, q'
        plt.rcParams['keymap.save'] = 'alt+s'
        plt.rcParams['keymap.yscale'] = ''
        plt.rcParams['keymap.xscale'] = ''
        plt.rcParams['keymap.grid'] = ''
        plt.rcParams['keymap.all_axes'] = ''
        
        # the figure:
        self.fig = plt.figure( figsize=( 15, 9 ) )
        self.fig.canvas.set_window_title( 'SongDetector: ' + self.filename )
        self.fig.canvas.mpl_connect( 'key_press_event', self.keypress )
        
        # trace plots:
        ph = 0.9/self.channels
        self.axt = []
        self.ymin = []
        self.ymax = []
        for c in range(self.channels):
            self.ymin.append( -1.0 )
            self.ymax.append( +1.0 )
            if np.min(self.data[:, c]) < -1.0 or np.max(self.data[:, c]) > +1.0 :
                self.ymin[c] = -10.0
                self.ymax[c] = +10.0
            if c == 0 :
                self.axt.append( self.fig.add_axes( [ 0.08, 0.06+(self.channels-c-1)*ph, 0.89, ph ] ) )
                self.highpass_label = self.axt[0].text( 0.05, 0.9, 'highpass=%.1fkHz' % (0.001*self.highpassfreq), transform=self.axt[0].transAxes )
                self.lowpass_label = self.axt[0].text( 0.2, 0.9, 'lowpass=%.1fkHz' % (0.001*self.lowpassfreq), transform=self.axt[0].transAxes )
                self.envelope_label = self.axt[0].text( 0.35, 0.9, 'envelope=%.0fHz' % self.envelopecutofffreq, transform=self.axt[0].transAxes )
            else:
                self.axt.append( self.fig.add_axes( [ 0.08, 0.08+(self.channels-c-1)*ph, 0.89, ph ], sharex=self.axt[0] ) )
            self.axt[-1].set_ylabel( 'Amplitude [{:s}]'.format( self.unit ) )
        self.axt[-1].set_xlabel( 'Time [s]' )
        """
        ht = self.axt.text( 0.98, 0.05, '(ctrl+) page and arrow up, down, home, end: scroll', ha='right', transform=self.axt.transAxes )
        self.helptext.append( ht )
        ht = self.axt.text( 0.98, 0.15, '+, -, X, x: zoom in/out', ha='right', transform=self.axt.transAxes )
        self.helptext.append( ht )
        ht = self.axt.text( 0.98, 0.25, 'y,Y,v,V: zoom amplitudes', ha='right', transform=self.axt.transAxes )
        self.helptext.append( ht )
        ht = self.axt.text( 0.98, 0.35, 'p,P: play audio (display,all)', ha='right', transform=self.axt.transAxes )
        self.helptext.append( ht )
        ht = self.axt.text( 0.98, 0.45, 'ctrl-f: full screen', ha='right', transform=self.axt.transAxes )
        self.helptext.append( ht )
        ht = self.axt.text( 0.98, 0.65, 's: save figure', ha='right', transform=self.axt.transAxes )
        self.helptext.append( ht )
        ht = self.axt.text( 0.98, 0.75, 'q: quit', ha='right', transform=self.axt.transAxes )
        self.helptext.append( ht )
        ht = self.axt.text( 0.98, 0.85, 'h: toggle this help', ha='right', transform=self.axt.transAxes )
        self.helptext.append( ht )
        # plot:
        for ht in self.helptext :
            ht.set_visible( self.help )
        """
        self.update_plots( False )
        plt.show()

    def __del( self ) :
        if self.analysis_file != None :
            self.analysis_file.close()
        if self.audio is not None:
            self.audio.close()
            
    def update_plots( self, draw=True ) :
        # time window:
        t0 = int(np.round(self.toffset*self.rate))
        t1 = int(np.round((self.toffset+self.twindow)*self.rate))
        tstep = 1
        if self.max_pixel > 0 :
            tstep = int((t1-t0)//self.max_pixel)
            if tstep < 1 :
                tstep = 1
        for c in range(self.channels) :
            self.axt[c].set_xlim( self.toffset, self.toffset+self.twindow )
            self.axt[c].set_ylim( self.ymin[c], self.ymax[c] )
        # raw trace:
        if self.show_traces :
            append = len(self.trace_artists) == 0
            for c in range(self.channels) :
                if append :
                    ta, = self.axt[c].plot( self.time[t0:t1:tstep], self.data[t0:t1:tstep, c], 'b', zorder=0 )
                    self.trace_artists.append( ta )
                else :
                    self.trace_artists[c].set_data( self.time[t0:t1:tstep], self.data[t0:t1:tstep, c] )
                self.trace_artists[c].set_visible(True)
        else :
            for c in range(len(self.trace_artists)) :
                self.trace_artists[c].set_visible(False)
        # filtered trace:
        if self.show_filtered_traces :
            append = len(self.filtered_trace_artists) == 0
            for c in range(self.channels) :
                if append :
                    ta, = self.axt[c].plot( self.time[t0:t1:tstep], self.fdata[t0:t1:tstep, c], 'g', zorder=1 )
                    self.filtered_trace_artists.append( ta )
                else :
                    self.filtered_trace_artists[c].set_data( self.time[t0:t1:tstep], self.fdata[t0:t1:tstep, c] )
                self.filtered_trace_artists[c].set_visible(True)
        else :
            for c in range(len(self.filtered_trace_artists)) :
                self.filtered_trace_artists[c].set_visible(False)
        # fast envelope:
        if self.show_envelope :
            et0 = int(np.round(self.toffset*self.envrate))
            et1 = int(np.round((self.toffset+self.twindow)*self.envrate))
            etstep = int(np.round(tstep*self.rate/self.envrate))
            etime = self.time[t0:t1+etstep:etstep][:len(self.envelope[et0:et1:tstep, c])]
            append = len(self.envelope_artists) == 0
            for c in range(self.channels) :
                if append :
                    ta, = self.axt[c].plot( etime, self.envelope[et0:et1:tstep, c], 'r', lw=2, zorder=2 )
                    self.envelope_artists.append( ta )
                else :
                    self.envelope_artists[c].set_data( etime, self.envelope[et0:et1:tstep, c] )
                self.envelope_artists[c].set_visible(True)
        else :
            for c in range(len(self.envelope_artists)) :
                self.envelope_artists[c].set_visible(False)
        # slow envelope:
        if self.show_slowenvelope :
            et0 = int(np.round(self.toffset*self.envrate))
            et1 = int(np.round((self.toffset+self.twindow)*self.envrate))
            etstep = int(np.round(tstep*self.rate/self.envrate))
            etime = self.time[t0:t1+etstep:etstep][:len(self.slowenvelope[et0:et1:tstep, c])]
            append = len(self.slowenvelope_artists) == 0
            for c in range(self.channels) :
                if append :
                    ta, = self.axt[c].plot( etime, self.slowenvelope[et0:et1:tstep, c], 'c', lw=2, zorder=3 )
                    self.slowenvelope_artists.append( ta )
                else :
                    self.slowenvelope_artists[c].set_data( etime, self.slowenvelope[et0:et1:tstep, c] )
                self.slowenvelope_artists[c].set_visible(True)
        else :
            for c in range(len(self.slowenvelope_artists)) :
                self.slowenvelope_artists[c].set_visible(False)
        # thresholds:
        if self.show_thresholds :
            append = len(self.threshold_artists) == 0
            for c in range(self.channels) :
                tm = t1
                if tm >= len(self.time):
                    tm = len(self.time)-1
                if append :
                    ta, = self.axt[c].plot( [self.time[t0], self.time[tm]], [self.thresholds[c], self.thresholds[c]], 'k', zorder=4 )
                    self.threshold_artists.append( ta )
                else :
                    self.threshold_artists[c].set_data( [self.time[t0], self.time[tm]], [self.thresholds[c], self.thresholds[c]] )
                self.threshold_artists[c].set_visible(True)
        else :
            for c in range(len(self.threshold_artists)) :
                self.threshold_artists[c].set_visible(False)
        # song onsets:
        if self.show_songonsets :
            append = len(self.songonset_artists) == 0
            for c in range(self.channels) :
                if append :
                    ta, = self.axt[c].plot(self.songonsets[c]/self.envrate, self.thresholds[c]*np.ones(len(self.songonsets[c])), '.b', ms=10, zorder=5)
                    self.songonset_artists.append(ta)
                else :
                    self.songonset_artists[c].set_data(self.songonsets[c]/self.envrate, self.thresholds[c]*np.ones(len(self.songonsets[c])))
                self.songonset_artists[c].set_visible(True)
        else :
            for c in range(len(self.songonset_artists)) :
                self.songonset_artists[c].set_visible(False)
        # song offsets:
        if self.show_songoffsets :
            append = len(self.songoffset_artists) == 0
            for c in range(self.channels) :
                if append :
                    ta, = self.axt[c].plot(self.songoffsets[c]/self.envrate, self.thresholds[c]*np.ones(len(self.songoffsets[c])), '.b', ms=10, zorder=6)
                    self.songoffset_artists.append(ta)
                else :
                    self.songoffset_artists[c].set_data(self.songoffsets[c]/self.envrate, self.thresholds[c]*np.ones(len(self.songoffsets[c])))
                self.songoffset_artists[c].set_visible(True)
        else :
            for c in range(len(self.songoffset_artists)) :
                self.songoffset_artists[c].set_visible(False)
        
        if draw :
            self.fig.canvas.draw()
                 
    def keypress( self, event ) :
        if event.key in '+=X' :
            if self.twindow*self.rate > 20 :
                self.twindow *= 0.5
                self.update_plots()
        elif event.key in '-x' :
            if self.twindow < len( self.data )/self.rate :
                self.twindow *= 2.0
                self.update_plots()
        elif event.key == 'pagedown' :
            if self.toffset + 0.5*self.twindow < len( self.data )/self.rate :
                self.toffset += 0.5*self.twindow
                self.update_plots()
        elif event.key == 'pageup' :
            if self.toffset > 0 :
                self.toffset -= 0.5*self.twindow
                if self.toffset < 0.0 :
                    self.toffset = 0.0
                self.update_plots()
        elif event.key == 'ctrl+pagedown' :
            if self.toffset + 5.0*self.twindow < len( self.data )/self.rate :
                self.toffset += 5.0*self.twindow
                self.update_plots()
        elif event.key == 'ctrl+pageup' :
            if self.toffset > 0 :
                self.toffset -= 5.0*self.twindow
                if self.toffset < 0.0 :
                    self.toffset = 0.0
                self.update_plots()
        elif event.key == 'down' :
            if self.toffset + self.twindow < len( self.data )/self.rate :
                self.toffset += 0.05*self.twindow
                self.update_plots()
        elif event.key == 'up' :
            if self.toffset > 0.0 :
                self.toffset -= 0.05*self.twindow
                if self.toffset < 0.0 :
                    self.toffset = 0.0
                self.update_plots()
        elif event.key == 'home':
            if self.toffset > 0.0 :
                self.toffset = 0.0
                self.update_plots()
        elif event.key == 'end':
            toffs = np.floor( len( self.data )/self.rate / self.twindow ) * self.twindow
            if self.toffset < toffs :
                self.toffset = toffs
                self.update_plots()
        elif event.key == 'y':
            for c in range(self.channels):
                h = self.ymax[c] - self.ymin[c]
                v = 0.5*(self.ymax[c] + self.ymin[c])
                self.ymin[c] = v-h
                self.ymax[c] = v+h
                self.axt[c].set_ylim( self.ymin[c], self.ymax[c] )
            self.fig.canvas.draw()
        elif event.key == 'Y':
            for c in range(self.channels):
                h = 0.25*(self.ymax[c] - self.ymin[c])
                v = 0.5*(self.ymax[c] + self.ymin[c])
                self.ymin[c] = v-h
                self.ymax[c] = v+h
                self.axt[c].set_ylim( self.ymin[c], self.ymax[c] )
            self.fig.canvas.draw()
        elif event.key == 'v':
            for c in range(self.channels):
                fdmin = np.min( self.fdata[:, c] )
                fdmax = np.max( self.fdata[:, c] )
                #h = 0.5*(fdmax - fdmin)
                #v = 0.5*(fdmax + fdmin)
                #self.ymin[c] = v-h
                #self.ymax[c] = v+h
                m = max(-fdmin, fdmax)
                self.ymin[c] = -m
                self.ymax[c] = m
                self.axt[c].set_ylim( self.ymin[c], self.ymax[c] )
            self.fig.canvas.draw()
        elif event.key == 'V':
            for c in range(self.channels):
                self.ymin[c] = -1.0
                self.ymax[c] = +1.0
                self.axt[c].set_ylim( self.ymin[c], self.ymax[c] )
            self.fig.canvas.draw()
        elif event.key == 'ctrl+t' :
            self.show_traces = not self.show_traces
            if len(self.trace_artists) > 0 :
                for c in range(self.channels) :
                    self.trace_artists[c].set_visible( self.show_traces )
                self.fig.canvas.draw()
            else:
                self.update_plots()
        elif event.key == 'ctrl+f' :
            self.show_filtered_traces = not self.show_filtered_traces
            if len(self.filtered_trace_artists) > 0 :
                for c in range(self.channels) :
                    self.filtered_trace_artists[c].set_visible( self.show_filtered_traces )
                self.fig.canvas.draw()
            else:
                self.update_plots()
        elif event.key == 'ctrl+e' :
            self.show_envelope = not self.show_envelope
            if len(self.envelope_artists) > 0 :
                for c in range(self.channels) :
                    self.envelope_artists[c].set_visible( self.show_envelope )
                self.fig.canvas.draw()
            else:
                self.update_plots()
        elif event.key == 'h' :
            self.highpassfreq /= 1.5
            self.highpass_label.set_text('highpass=%.1fkHz' % (0.001*self.highpassfreq))
            self.fdata = bandpass_filter(self.data, self.rate, self.highpassfreq, self.lowpassfreq)
            self.update_plots()
        elif event.key == 'H' :
            self.highpassfreq * 1.5
            self.highpass_label.set_text('highpass=%.1fkHz' % (0.001*self.highpassfreq))
            self.fdata = bandpass_filter(self.data, self.rate, self.highpassfreq, self.lowpassfreq)
            self.update_plots()
        elif event.key == 'l' :
            self.lowpassfreq /= 1.5
            self.lowpass_label.set_text('lowpass=%.1fkHz' % (0.001*self.lowpassfreq))
            self.fdata = bandpass_filter(self.data, self.rate, self.highpassfreq, self.lowpassfreq)
            self.update_plots()
        elif event.key == 'L' :
            self.lowpassfreq * 1.5
            self.lowpass_label.set_text('lowpass=%.1fkHz' % (0.001*self.lowpassfreq))
            self.fdata = bandpass_filter(self.data, self.rate, self.highpassfreq, self.lowpassfreq)
            self.update_plots()
        elif event.key == 'e' :
            self.envelopecutofffreq /= 1.5
            self.envelope_label.set_text('envelope=%.0fHz' % self.envelopecutofffreq)
            self.envelope, self.envrate = envelope(self.fdata, self.rate, self.envelopecutofffreq)
            self.songonsets, self.songoffsets = detect_songs(self.slowenvelope, self.envrate, self.thresholds, min_duration=self.min_duration)
            self.songonsets, self.songoffsets = refine_detection(self.songonsets, self.songoffsets, self.envelope, self.envrate, self.thresholds, min_duration=self.min_duration, envelope_use_freq=self.envelopeusefreq)
            self.update_plots()
        elif event.key == 'E' :
            self.envelopecutofffreq *= 1.5
            self.envelope_label.set_text('envelope=%.0fHz' % self.envelopecutofffreq)
            self.envelope, self.envrate = envelope(self.fdata, self.rate, self.envelopecutofffreq)
            self.songonsets, self.songoffsets = detect_songs(self.slowenvelope, self.envrate, self.thresholds)
            self.songonsets, self.songoffsets = refine_detection(self.songonsets, self.songoffsets, self.envelope, self.envrate, self.thresholds, min_duration=self.min_duration, envelope_use_freq=self.envelopeusefreq)
            self.update_plots()
#        elif event.key in 'h' :
#            self.help = not self.help
#            for ht in self.helptext :
#                ht.set_visible( self.help )
#            self.fig.canvas.draw()
        elif event.key in 'w' :
            self.plot_waveform()
        elif event.key in 'p' :
            self.play_segment(self.fdata)
        elif event.key in 'P' :
            self.play_segment(self.data)
            #self.play_all()

    def plot_waveform( self ) :
        fig = plt.figure()
        ax = fig.add_subplot( 1, 1, 1 )
        name = os.path.splitext( self.filename )[0]
        ax.set_title( self.filename )
        figfile = '{name}-{time:.4g}s-waveform.png'.format( name=name, time=self.toffset )
        t0 = int(np.round(self.toffset*self.rate))
        t1 = int(np.round((self.toffset+self.twindow)*self.rate))
        if self.twindow < 1.0 :
            ax.set_xlabel( 'Time [ms]' )
            ax.set_xlim( 1000.0*self.toffset,
                         1000.0*(self.toffset+self.twindow) )
            ax.plot( 1000.0*self.time[t0:t1], self.data[t0:t1], 'b' )
            if self.show_envelope :
                ax.plot( 1000.0*self.time[t0:t1], self.envelope[t0:t1], 'r' )
        else :
            ax.set_xlabel( 'Time [s]' )
            ax.set_xlim( self.toffset, self.toffset+self.twindow )
            ax.plot( self.time[t0:t1], self.data[t0:t1], 'b' )
            if self.show_envelope :
                ax.plot( self.time[t0:t1], self.envelope[t0:t1], 'r' )
        ax.set_ylabel( 'Amplitude [{:s}]'.format( self.unit ) )
        fig.tight_layout()
        # on linux the following is not what you want! You want to save this into the current working directory!!!
        fig.savefig( os.path.join( self.filepath, figfile ) )
        fig.clear()
        plt.close( fig )
        print('saved waveform figure to %s' % figfile)

    def play_segment(self, data) :
        t0 = int(np.round(self.toffset*self.rate))
        t1 = int(np.round((self.toffset+self.twindow)*self.rate))
        playdata = 1.0*np.mean(data[t0:t1,:], axis=1)
        playdata -= np.mean(playdata)
        fade(playdata, self.rate, 0.1)
        self.audio.play(playdata, self.rate, blocking=False)
        
    def play_all(self) :
        playdata = np.mean(self.fdata, axis=1)
        playdata -= np.mean(playdata)
        self.audio.play(np.mean(self.data, axis=1), self.rate, blocking=False)
コード例 #6
0
ファイル: fishfinder.py プロジェクト: jfsehuanes/thunderfish
    def __init__(self, data, samplingrate, unit, filename, channel, cfg):
        self.filename = filename
        self.channel = channel
        self.samplerate = samplingrate
        self.data = data
        self.unit = unit
        self.cfg = cfg
        self.verbose = self.cfg['verboseLevel'][0]
        self.time = np.arange(0.0, len(self.data)) / self.samplerate
        self.toffset = 0.0
        self.twindow = 8.0
        if self.twindow > self.time[-1]:
            self.twindow = np.round(2 ** (np.floor(np.log(self.time[-1]) / np.log(2.0)) + 1.0))
        self.ymin = -1.0
        self.ymax = +1.0
        self.trace_artist = None
        self.spectrogram_artist = None
        self.fmin = 0.0
        self.fmax = 0.0
        self.decibel = True
        self.fresolution = self.cfg['initialFrequencyResolution'][0]
        self.deltaf = 1.0
        self.mains_freq = self.cfg['mainsFreq'][0]
        self.power_label = None
        self.all_peaks_artis = None
        self.good_peaks_artist = None
        self.power_artist = None
        self.power_frequency_label = None
        self.peak_artists = []
        self.legend = True
        self.legendhandle = None
        self.help = self.cfg['displayHelp'][0]
        self.helptext = []
        self.allpeaks = []
        self.fishlist = []
        self.mains = []
        self.peak_specmarker = []
        self.peak_annotation = []
        self.min_clip = self.cfg['minClipAmplitude'][0]
        self.max_clip = self.cfg['maxClipAmplitude'][0]
        self.generate_color_range()

        # audio output:
        self.audio = PlayAudio()

        # set key bindings:
        plt.rcParams['keymap.fullscreen'] = 'ctrl+f'
        plt.rcParams['keymap.pan'] = 'ctrl+m'
        plt.rcParams['keymap.quit'] = 'ctrl+w, alt+q, q'
        plt.rcParams['keymap.yscale'] = ''
        plt.rcParams['keymap.xscale'] = ''
        plt.rcParams['keymap.grid'] = ''
        plt.rcParams['keymap.all_axes'] = ''

        # the figure:
        self.fig = plt.figure(figsize=(15, 9))
        self.fig.canvas.set_window_title(self.filename + ' channel {0:d}'.format(self.channel))
        self.fig.canvas.mpl_connect('key_press_event', self.keypress)
        self.fig.canvas.mpl_connect('button_press_event', self.buttonpress)
        self.fig.canvas.mpl_connect('pick_event', self.onpick)
        self.fig.canvas.mpl_connect('resize_event', self.resize)
        # trace plot:
        self.axt = self.fig.add_axes([0.1, 0.7, 0.87, 0.25])
        self.axt.set_ylabel('Amplitude [{:s}]'.format(self.unit))
        ht = self.axt.text(0.98, 0.05, '(ctrl+) page and arrow up, down, home, end: scroll', ha='right',
                           transform=self.axt.transAxes)
        self.helptext.append(ht)
        ht = self.axt.text(0.98, 0.15, '+, -, X, x: zoom in/out', ha='right', transform=self.axt.transAxes)
        self.helptext.append(ht)
        ht = self.axt.text(0.98, 0.25, 'y,Y,v,V: zoom amplitudes', ha='right', transform=self.axt.transAxes)
        self.helptext.append(ht)
        ht = self.axt.text(0.98, 0.35, 'p,P: play audio (display,all)', ha='right', transform=self.axt.transAxes)
        self.helptext.append(ht)
        ht = self.axt.text(0.98, 0.45, 'ctrl-f: full screen', ha='right', transform=self.axt.transAxes)
        self.helptext.append(ht)
        ht = self.axt.text(0.98, 0.55, 'w: plot waveform into png file', ha='right', transform=self.axt.transAxes)
        self.helptext.append(ht)
        ht = self.axt.text(0.98, 0.65, 's: save figure', ha='right', transform=self.axt.transAxes)
        self.helptext.append(ht)
        ht = self.axt.text(0.98, 0.75, 'q: quit', ha='right', transform=self.axt.transAxes)
        self.helptext.append(ht)
        ht = self.axt.text(0.98, 0.85, 'h: toggle this help', ha='right', transform=self.axt.transAxes)
        self.helptext.append(ht)
        self.axt.set_xticklabels([])
        # spectrogram:
        self.axs = self.fig.add_axes([0.1, 0.45, 0.87, 0.25])
        self.axs.set_xlabel('Time [seconds]')
        self.axs.set_ylabel('Frequency [Hz]')
        # power spectrum:
        self.axp = self.fig.add_axes([0.1, 0.1, 0.87, 0.25])
        ht = self.axp.text(0.98, 0.9, 'r, R: frequency resolution', ha='right', transform=self.axp.transAxes)
        self.helptext.append(ht)
        ht = self.axp.text(0.98, 0.8, 'f, F: zoom', ha='right', transform=self.axp.transAxes)
        self.helptext.append(ht)
        ht = self.axp.text(0.98, 0.7, '(ctrl+) left, right: move', ha='right', transform=self.axp.transAxes)
        self.helptext.append(ht)
        ht = self.axp.text(0.98, 0.6, 'l: toggle legend', ha='right', transform=self.axp.transAxes)
        self.helptext.append(ht)
        ht = self.axp.text(0.98, 0.5, 'd: toggle decibel', ha='right', transform=self.axp.transAxes)
        self.helptext.append(ht)
        ht = self.axp.text(0.98, 0.4, 'm: toggle mains filter', ha='right', transform=self.axp.transAxes)
        self.helptext.append(ht)
        ht = self.axp.text(0.98, 0.3, 'left mouse: show peak properties', ha='right', transform=self.axp.transAxes)
        self.helptext.append(ht)
        ht = self.axp.text(0.98, 0.2, 'shift/ctrl + left/right mouse: goto previous/next harmonic', ha='right',
                           transform=self.axp.transAxes)
        self.helptext.append(ht)
        # plot:
        for ht in self.helptext:
            ht.set_visible(self.help)
        self.update_plots(False)
        plt.show()
コード例 #7
0
ファイル: fishfinder.py プロジェクト: jfsehuanes/thunderfish
class SignalPlot:
    def __init__(self, data, samplingrate, unit, filename, channel, cfg):
        self.filename = filename
        self.channel = channel
        self.samplerate = samplingrate
        self.data = data
        self.unit = unit
        self.cfg = cfg
        self.verbose = self.cfg['verboseLevel'][0]
        self.time = np.arange(0.0, len(self.data)) / self.samplerate
        self.toffset = 0.0
        self.twindow = 8.0
        if self.twindow > self.time[-1]:
            self.twindow = np.round(2 ** (np.floor(np.log(self.time[-1]) / np.log(2.0)) + 1.0))
        self.ymin = -1.0
        self.ymax = +1.0
        self.trace_artist = None
        self.spectrogram_artist = None
        self.fmin = 0.0
        self.fmax = 0.0
        self.decibel = True
        self.fresolution = self.cfg['initialFrequencyResolution'][0]
        self.deltaf = 1.0
        self.mains_freq = self.cfg['mainsFreq'][0]
        self.power_label = None
        self.all_peaks_artis = None
        self.good_peaks_artist = None
        self.power_artist = None
        self.power_frequency_label = None
        self.peak_artists = []
        self.legend = True
        self.legendhandle = None
        self.help = self.cfg['displayHelp'][0]
        self.helptext = []
        self.allpeaks = []
        self.fishlist = []
        self.mains = []
        self.peak_specmarker = []
        self.peak_annotation = []
        self.min_clip = self.cfg['minClipAmplitude'][0]
        self.max_clip = self.cfg['maxClipAmplitude'][0]
        self.generate_color_range()

        # audio output:
        self.audio = PlayAudio()

        # set key bindings:
        plt.rcParams['keymap.fullscreen'] = 'ctrl+f'
        plt.rcParams['keymap.pan'] = 'ctrl+m'
        plt.rcParams['keymap.quit'] = 'ctrl+w, alt+q, q'
        plt.rcParams['keymap.yscale'] = ''
        plt.rcParams['keymap.xscale'] = ''
        plt.rcParams['keymap.grid'] = ''
        plt.rcParams['keymap.all_axes'] = ''

        # the figure:
        self.fig = plt.figure(figsize=(15, 9))
        self.fig.canvas.set_window_title(self.filename + ' channel {0:d}'.format(self.channel))
        self.fig.canvas.mpl_connect('key_press_event', self.keypress)
        self.fig.canvas.mpl_connect('button_press_event', self.buttonpress)
        self.fig.canvas.mpl_connect('pick_event', self.onpick)
        self.fig.canvas.mpl_connect('resize_event', self.resize)
        # trace plot:
        self.axt = self.fig.add_axes([0.1, 0.7, 0.87, 0.25])
        self.axt.set_ylabel('Amplitude [{:s}]'.format(self.unit))
        ht = self.axt.text(0.98, 0.05, '(ctrl+) page and arrow up, down, home, end: scroll', ha='right',
                           transform=self.axt.transAxes)
        self.helptext.append(ht)
        ht = self.axt.text(0.98, 0.15, '+, -, X, x: zoom in/out', ha='right', transform=self.axt.transAxes)
        self.helptext.append(ht)
        ht = self.axt.text(0.98, 0.25, 'y,Y,v,V: zoom amplitudes', ha='right', transform=self.axt.transAxes)
        self.helptext.append(ht)
        ht = self.axt.text(0.98, 0.35, 'p,P: play audio (display,all)', ha='right', transform=self.axt.transAxes)
        self.helptext.append(ht)
        ht = self.axt.text(0.98, 0.45, 'ctrl-f: full screen', ha='right', transform=self.axt.transAxes)
        self.helptext.append(ht)
        ht = self.axt.text(0.98, 0.55, 'w: plot waveform into png file', ha='right', transform=self.axt.transAxes)
        self.helptext.append(ht)
        ht = self.axt.text(0.98, 0.65, 's: save figure', ha='right', transform=self.axt.transAxes)
        self.helptext.append(ht)
        ht = self.axt.text(0.98, 0.75, 'q: quit', ha='right', transform=self.axt.transAxes)
        self.helptext.append(ht)
        ht = self.axt.text(0.98, 0.85, 'h: toggle this help', ha='right', transform=self.axt.transAxes)
        self.helptext.append(ht)
        self.axt.set_xticklabels([])
        # spectrogram:
        self.axs = self.fig.add_axes([0.1, 0.45, 0.87, 0.25])
        self.axs.set_xlabel('Time [seconds]')
        self.axs.set_ylabel('Frequency [Hz]')
        # power spectrum:
        self.axp = self.fig.add_axes([0.1, 0.1, 0.87, 0.25])
        ht = self.axp.text(0.98, 0.9, 'r, R: frequency resolution', ha='right', transform=self.axp.transAxes)
        self.helptext.append(ht)
        ht = self.axp.text(0.98, 0.8, 'f, F: zoom', ha='right', transform=self.axp.transAxes)
        self.helptext.append(ht)
        ht = self.axp.text(0.98, 0.7, '(ctrl+) left, right: move', ha='right', transform=self.axp.transAxes)
        self.helptext.append(ht)
        ht = self.axp.text(0.98, 0.6, 'l: toggle legend', ha='right', transform=self.axp.transAxes)
        self.helptext.append(ht)
        ht = self.axp.text(0.98, 0.5, 'd: toggle decibel', ha='right', transform=self.axp.transAxes)
        self.helptext.append(ht)
        ht = self.axp.text(0.98, 0.4, 'm: toggle mains filter', ha='right', transform=self.axp.transAxes)
        self.helptext.append(ht)
        ht = self.axp.text(0.98, 0.3, 'left mouse: show peak properties', ha='right', transform=self.axp.transAxes)
        self.helptext.append(ht)
        ht = self.axp.text(0.98, 0.2, 'shift/ctrl + left/right mouse: goto previous/next harmonic', ha='right',
                           transform=self.axp.transAxes)
        self.helptext.append(ht)
        # plot:
        for ht in self.helptext:
            ht.set_visible(self.help)
        self.update_plots(False)
        plt.show()

    def __del(self):
        self.audio.close()

    def generate_color_range(self):
        # color and marker range:
        self.colorrange = []
        self.markerrange = []
        mr2 = []
        # first color range:
        cc0 = plt.cm.gist_rainbow(np.linspace(0.0, 1.0, 8.0))
        # shuffle it:
        for k in range((len(cc0) + 1) // 2):
            self.colorrange.extend(cc0[k::(len(cc0) + 1) // 2])
        self.markerrange.extend(len(cc0) * 'o')
        mr2.extend(len(cc0) * 'v')
        # second darker color range:
        cc1 = plt.cm.gist_rainbow(np.linspace(0.33 / 7.0, 1.0, 7.0))
        cc1 = mc.hsv_to_rgb(mc.rgb_to_hsv(np.array([cc1])) * np.array([1.0, 0.9, 0.7, 0.0]))[0]
        cc1[:, 3] = 1.0
        # shuffle it:
        for k in range((len(cc1) + 1) // 2):
            self.colorrange.extend(cc1[k::(len(cc1) + 1) // 2])
        self.markerrange.extend(len(cc1) * '^')
        mr2.extend(len(cc1) * '*')
        # third lighter color range:
        cc2 = plt.cm.gist_rainbow(np.linspace(0.67 / 6.0, 1.0, 6.0))
        cc2 = mc.hsv_to_rgb(mc.rgb_to_hsv(np.array([cc2])) * np.array([1.0, 0.5, 1.0, 0.0]))[0]
        cc2[:, 3] = 1.0
        # shuffle it:
        for k in range((len(cc2) + 1) // 2):
            self.colorrange.extend(cc2[k::(len(cc2) + 1) // 2])
        self.markerrange.extend(len(cc2) * 'D')
        mr2.extend(len(cc2) * 'x')
        self.markerrange.extend(mr2)

    def remove_peak_annotation(self):
        for fm in self.peak_specmarker:
            fm.remove()
        self.peak_specmarker = []
        for fa in self.peak_annotation:
            fa.remove()
        self.peak_annotation = []

    def annotate_peak(self, peak, harmonics=-1, inx=-1):
        # marker:
        if inx >= 0:
            m, = self.axs.plot([self.toffset + 0.01 * self.twindow], [peak[0]], linestyle='None',
                               color=self.colorrange[inx % len(self.colorrange)],
                               marker=self.markerrange[inx], ms=10.0, mec=None, mew=0.0, zorder=2)
        else:
            m, = self.axs.plot([self.toffset + 0.01 * self.twindow], [peak[0]], linestyle='None',
                               color='k', marker='o', ms=10.0, mec=None, mew=0.0, zorder=2)
        self.peak_specmarker.append(m)
        # annotation:
        fwidth = self.fmax - self.fmin
        pl = []
        if self.cfg['labelFrequency'][0]:
            pl.append(r'$f=${:.1f} Hz'.format(peak[0]))
        if self.cfg['labelHarmonic'][0] and harmonics >= 0:
            pl.append(r'$h=${:d}'.format(harmonics))
        if self.cfg['labelPower'][0]:
            pl.append(r'$p=${:g}'.format(peak[1]))
        if self.cfg['labelWidth'][0]:
            pl.append(r'$\Delta f=${:.2f} Hz'.format(peak[3]))
        if self.cfg['labelDoubleUse'][0]:
            pl.append(r'dc={:.0f}'.format(peak[4]))
        self.peak_annotation.append(self.axp.annotate('\n'.join(pl), xy=(peak[0], peak[1]),
                                                      xytext=(peak[0] + 0.03 * fwidth, peak[1]),
                                                      bbox=dict(boxstyle='round', facecolor='white'),
                                                      arrowprops=dict(arrowstyle='-')))

    def annotate_fish(self, fish, inx=-1):
        self.remove_peak_annotation()
        for harmonic, freq in enumerate(fish[:, 0]):
            peak = self.allpeaks[np.abs(self.allpeaks[:, 0] - freq) < 0.8 * self.deltaf, :]
            if len(peak) > 0:
                self.annotate_peak(peak[0, :], harmonic, inx)
        self.fig.canvas.draw()

    def update_plots(self, draw=True):
        self.remove_peak_annotation()
        # trace:
        self.axt.set_xlim(self.toffset, self.toffset + self.twindow)
        t0 = int(np.round(self.toffset * self.samplerate))
        t1 = int(np.round((self.toffset + self.twindow) * self.samplerate))
        if self.trace_artist == None:
            self.trace_artist, = self.axt.plot(self.time[t0:t1], self.data[t0:t1])
        else:
            self.trace_artist.set_data(self.time[t0:t1], self.data[t0:t1])
        self.axt.set_ylim(self.ymin, self.ymax)

        # compute power spectrum:
        nfft = int(np.round(2 ** (np.floor(np.log(self.samplerate / self.fresolution) / np.log(2.0)) + 1.0)))
        if nfft < 16:
            nfft = 16
        nfft, noverlap = nfft_noverlap(self.fresolution, self.samplerate, 0.5, 16)
        t00 = t0
        t11 = t1
        w = t11 - t00
        minw = nfft * (self.cfg['minPSDAverages'][0] + 1) // 2
        if t11 - t00 < minw:
            w = minw
            t11 = t00 + w
        if t11 >= len(self.data):
            t11 = len(self.data)
            t00 = t11 - w
        if t00 < 0:
            t00 = 0
            t11 = w
        power, freqs = ml.psd(self.data[t00:t11], NFFT=nfft, noverlap=noverlap, Fs=self.samplerate, detrend=ml.detrend_mean)
        self.deltaf = freqs[1] - freqs[0]
        # detect fish:
        h_kwargs = psd_peak_detection_args(self.cfg)
        h_kwargs.update(harmonic_groups_args(self.cfg))
        self.fishlist, fzero_harmonics, self.mains, self.allpeaks, peaks, lowth, highth, center = harmonic_groups(freqs, power, verbose=self.verbose, **h_kwargs)
        highth = center + highth - 0.5 * lowth
        lowth = center + 0.5 * lowth

        # spectrogram:
        t2 = t1 + nfft
        specpower, freqs, bins = ml.specgram(self.data[t0:t2], NFFT=nfft, Fs=self.samplerate, noverlap=nfft // 2,
                                             detrend=ml.detrend_mean)
        z = 10. * np.log10(specpower)
        z = np.flipud(z)
        extent = self.toffset, self.toffset + np.amax(bins), freqs[0], freqs[-1]
        self.axs.set_xlim(self.toffset, self.toffset + self.twindow)
        if self.spectrogram_artist == None:
            self.fmax = np.round((freqs[-1] / 4.0) / 100.0) * 100.0
            min = highth
            min = np.percentile(z, 70.0)
            max = np.percentile(z, 99.9) + 30.0
            # cm = plt.get_cmap( 'hot_r' )
            cm = plt.get_cmap('jet')
            self.spectrogram_artist = self.axs.imshow(z, aspect='auto',
                                                      extent=extent, vmin=min, vmax=max,
                                                      cmap=cm, zorder=1)
        else:
            self.spectrogram_artist.set_data(z)
            self.spectrogram_artist.set_extent(extent)
        self.axs.set_ylim(self.fmin, self.fmax)

        # power spectrum:
        self.axp.set_xlim(self.fmin, self.fmax)
        if self.deltaf >= 1000.0:
            dfs = '%.3gkHz' % 0.001 * self.deltaf
        else:
            dfs = '%.3gHz' % self.deltaf
        tw = float(w) / self.samplerate
        if tw < 1.0:
            tws = '%.3gms' % (1000.0 * tw)
        else:
            tws = '%.3gs' % (tw)
        a = 2 * w // nfft - 1  # number of ffts
        m = ''
        if self.cfg['mainsFreq'][0] > 0.0:
            m = ', mains=%.0fHz' % self.cfg['mainsFreq'][0]
        if self.power_frequency_label == None:
            self.power_frequency_label = self.axp.set_xlabel(
                r'Frequency [Hz] (nfft={:d}, $\Delta f$={:s}: T={:s}/{:d}{:s})'.format(nfft, dfs, tws, a, m))
        else:
            self.power_frequency_label.set_text(
                r'Frequency [Hz] (nfft={:d}, $\Delta f$={:s}: T={:s}/{:d}{:s})'.format(nfft, dfs, tws, a, m))
        self.axp.set_xlim(self.fmin, self.fmax)
        if self.power_label == None:
            self.power_label = self.axp.set_ylabel('Power')
        if self.decibel:
            if len(self.allpeaks) > 0:
                self.allpeaks[:, 1] = 10.0 * np.log10(self.allpeaks[:, 1])
            power = 10.0 * np.log10(power)
            pmin = np.min(power[freqs < self.fmax])
            pmin = np.floor(pmin / 10.0) * 10.0
            pmax = np.max(power[freqs < self.fmax])
            pmax = np.ceil(pmax / 10.0) * 10.0
            doty = pmax - 5.0
            self.power_label.set_text('Power [dB]')
            self.axp.set_ylim(pmin, pmax)
        else:
            pmax = np.max(power[freqs < self.fmax])
            doty = pmax
            pmax *= 1.1
            self.power_label.set_text('Power')
            self.axp.set_ylim(0.0, pmax)
        if self.all_peaks_artis == None:
            self.all_peaks_artis, = self.axp.plot(self.allpeaks[:, 0],
                                                  np.zeros(len(self.allpeaks[:, 0])) + doty,
                                                  'o', color='#ffffff')
            self.good_peaks_artist, = self.axp.plot(peaks, np.zeros(len(peaks)) + doty,
                                                    'o', color='#888888')
        else:
            self.all_peaks_artis.set_data(self.allpeaks[:, 0],
                                          np.zeros(len(self.allpeaks[:, 0])) + doty)
            self.good_peaks_artist.set_data(peaks, np.zeros(len(peaks)) + doty)
        labels = []
        fsizes = [np.sqrt(np.sum(self.fishlist[k][:, 1])) for k in range(len(self.fishlist))]
        fmaxsize = np.max(fsizes) if len(fsizes) > 0 else 1.0
        self.axp.set_color_cycle(self.colorrange)
        for k in range(len(self.peak_artists)):
            self.peak_artists[k].remove()
        self.peak_artists = []
        for k in range(len(self.fishlist)):
            if k >= len(self.markerrange):
                break
            fpeaks = self.fishlist[k][:, 0]
            fpeakinx = [int(np.round(fp / self.deltaf)) for fp in fpeaks if fp < freqs[-1]]
            fsize = 7.0 + 10.0 * (fsizes[k] / fmaxsize) ** 0.5
            fishpoints, = self.axp.plot(fpeaks[:len(fpeakinx)], power[fpeakinx], linestyle='None',
                                        marker=self.markerrange[k], ms=fsize, mec=None, mew=0.0, zorder=1)
            self.peak_artists.append(fishpoints)
            if self.deltaf < 0.1:
                labels.append('%4.2f Hz' % fpeaks[0])
            elif self.deltaf < 1.0:
                labels.append('%4.1f Hz' % fpeaks[0])
            else:
                labels.append('%4.0f Hz' % fpeaks[0])
        if len(self.mains) > 0:
            fpeaks = self.mains[:, 0]
            fpeakinx = [np.round(fp / self.deltaf) for fp in fpeaks if fp < freqs[-1]]
            fishpoints, = self.axp.plot(fpeaks[:len(fpeakinx)], power[fpeakinx], linestyle='None',
                                        marker='.', color='k', ms=10, mec=None, mew=0.0, zorder=2)
            self.peak_artists.append(fishpoints)
            labels.append('%3.0f Hz mains' % self.cfg['mainsFreq'][0])
        ncol = len(labels) // 8 + 1
        self.legendhandle = self.axs.legend(self.peak_artists[:len(labels)], labels, loc='upper right', ncol=ncol)
        self.legenddict = dict()
        for legpoints, (finx, fish) in zip(self.legendhandle.get_lines(), enumerate(self.fishlist)):
            legpoints.set_picker(8)
            self.legenddict[legpoints] = [finx, fish]
        self.legendhandle.set_visible(self.legend)
        if self.power_artist == None:
            self.power_artist, = self.axp.plot(freqs, power, 'b', zorder=3)
        else:
            self.power_artist.set_data(freqs, power)
        if draw:
            self.fig.canvas.draw()

    def keypress(self, event):
        # print('pressed', event.key)
        if event.key in '+=X':
            if self.twindow * self.samplerate > 20:
                self.twindow *= 0.5
                self.update_plots()
        elif event.key in '-x':
            if self.twindow < len(self.data) / self.samplerate:
                self.twindow *= 2.0
                self.update_plots()
        elif event.key == 'pagedown':
            if self.toffset + 0.5 * self.twindow < len(self.data) / self.samplerate:
                self.toffset += 0.5 * self.twindow
                self.update_plots()
        elif event.key == 'pageup':
            if self.toffset > 0:
                self.toffset -= 0.5 * self.twindow
                if self.toffset < 0.0:
                    self.toffset = 0.0
                self.update_plots()
        elif event.key == 'a':
            if self.min_clip == 0.0 or self.max_clip == 0.0:
                self.min_clip, self.max_clip = clip_amplitudes(
                    self.data, **clip_args(self.cfg, self.samplerate))
            try:
                idx0, idx1, clipped = best_window_indices(
                    self.data, self.samplerate, min_clip=self.min_clip,
                    max_clip=self.max_clip, **best_window_args(self.cfg))
                if idx1 > 0:
                    self.toffset = idx0 / self.samplerate
                    self.twindow = (idx1 - idx0) / self.samplerate
                    self.update_plots()
            except UserWarning as e:
                if self.verbose > 0:
                    print(str(e))
        elif event.key == 'ctrl+pagedown':
            if self.toffset + 5.0 * self.twindow < len(self.data) / self.samplerate:
                self.toffset += 5.0 * self.twindow
                self.update_plots()
        elif event.key == 'ctrl+pageup':
            if self.toffset > 0:
                self.toffset -= 5.0 * self.twindow
                if self.toffset < 0.0:
                    self.toffset = 0.0
                self.update_plots()
        elif event.key == 'down':
            if self.toffset + self.twindow < len(self.data) / self.samplerate:
                self.toffset += 0.05 * self.twindow
                self.update_plots()
        elif event.key == 'up':
            if self.toffset > 0.0:
                self.toffset -= 0.05 * self.twindow
                if self.toffset < 0.0:
                    self.toffset = 0.0
                self.update_plots()
        elif event.key == 'home':
            if self.toffset > 0.0:
                self.toffset = 0.0
                self.update_plots()
        elif event.key == 'end':
            toffs = np.floor(len(self.data) / self.samplerate / self.twindow) * self.twindow
            if self.toffset < toffs:
                self.toffset = toffs
                self.update_plots()
        elif event.key == 'y':
            h = self.ymax - self.ymin
            c = 0.5 * (self.ymax + self.ymin)
            self.ymin = c - h
            self.ymax = c + h
            self.axt.set_ylim(self.ymin, self.ymax)
            self.fig.canvas.draw()
        elif event.key == 'Y':
            h = 0.25 * (self.ymax - self.ymin)
            c = 0.5 * (self.ymax + self.ymin)
            self.ymin = c - h
            self.ymax = c + h
            self.axt.set_ylim(self.ymin, self.ymax)
            self.fig.canvas.draw()
        elif event.key == 'v':
            t0 = int(np.round(self.toffset * self.samplerate))
            t1 = int(np.round((self.toffset + self.twindow) * self.samplerate))
            min = np.min(self.data[t0:t1])
            max = np.max(self.data[t0:t1])
            h = 0.5 * (max - min)
            c = 0.5 * (max + min)
            self.ymin = c - h
            self.ymax = c + h
            self.axt.set_ylim(self.ymin, self.ymax)
            self.fig.canvas.draw()
        elif event.key == 'V':
            self.ymin = -1.0
            self.ymax = +1.0
            self.axt.set_ylim(self.ymin, self.ymax)
            self.fig.canvas.draw()
        elif event.key == 'left':
            if self.fmin > 0.0:
                fwidth = self.fmax - self.fmin
                self.fmin -= 0.5 * fwidth
                self.fmax -= 0.5 * fwidth
                if self.fmin < 0.0:
                    self.fmin = 0.0
                    self.fmax = fwidth
                self.axs.set_ylim(self.fmin, self.fmax)
                self.axp.set_xlim(self.fmin, self.fmax)
                self.fig.canvas.draw()
        elif event.key == 'right':
            if self.fmax < 0.5 * self.samplerate:
                fwidth = self.fmax - self.fmin
                self.fmin += 0.5 * fwidth
                self.fmax += 0.5 * fwidth
                self.axs.set_ylim(self.fmin, self.fmax)
                self.axp.set_xlim(self.fmin, self.fmax)
                self.fig.canvas.draw()
        elif event.key == 'ctrl+left':
            if self.fmin > 0.0:
                fwidth = self.fmax - self.fmin
                self.fmin = 0.0
                self.fmax = fwidth
                self.axs.set_ylim(self.fmin, self.fmax)
                self.axp.set_xlim(self.fmin, self.fmax)
                self.fig.canvas.draw()
        elif event.key == 'ctrl+right':
            if self.fmax < 0.5 * self.samplerate:
                fwidth = self.fmax - self.fmin
                fm = 0.5 * self.samplerate
                self.fmax = np.ceil(fm / fwidth) * fwidth
                self.fmin = self.fmax - fwidth
                if self.fmin < 0.0:
                    self.fmin = 0.0
                    self.fmax = fwidth
                self.axs.set_ylim(self.fmin, self.fmax)
                self.axp.set_xlim(self.fmin, self.fmax)
                self.fig.canvas.draw()
        elif event.key in 'f':
            if self.fmax < 0.5 * self.samplerate or self.fmin > 0.0:
                fwidth = self.fmax - self.fmin
                if self.fmax < 0.5 * self.samplerate:
                    self.fmax = self.fmin + 2.0 * fwidth
                elif self.fmin > 0.0:
                    self.fmin = self.fmax - 2.0 * fwidth
                    if self.fmin < 0.0:
                        self.fmin = 0.0
                        self.fmax = 2.0 * fwidth
                self.axs.set_ylim(self.fmin, self.fmax)
                self.axp.set_xlim(self.fmin, self.fmax)
                self.fig.canvas.draw()
        elif event.key in 'F':
            if self.fmax - self.fmin > 1.0:
                fwidth = self.fmax - self.fmin
                self.fmax = self.fmin + 0.5 * fwidth
                self.axs.set_ylim(self.fmin, self.fmax)
                self.axp.set_xlim(self.fmin, self.fmax)
                self.fig.canvas.draw()
        elif event.key in 'r':
            if self.fresolution < 1000.0:
                self.fresolution *= 2.0
                self.update_plots()
        elif event.key in 'R':
            if 1.0 / self.fresolution < self.time[-1]:
                self.fresolution *= 0.5
                self.update_plots()
        elif event.key in 'd':
            self.decibel = not self.decibel
            self.update_plots()
        elif event.key in 'm':
            if self.cfg['mainsFreq'][0] == 0.0:
                self.cfg['mainsFreq'][0] = self.mains_freq
            else:
                self.cfg['mainsFreq'][0] = 0.0
            self.update_plots()
        elif event.key in 't':
            self.cfg['peakFactor'][0] -= 0.1
            if self.cfg['peakFactor'][0] < -5.0:
                self.cfg['peakFactor'][0] = -5.0
            print('peakFactor =', self.cfg['peakFactor'][0])
            self.update_plots()
        elif event.key in 'T':
            self.cfg['peakFactor'][0] += 0.1
            if self.cfg['peakFactor'][0] > 5.0:
                self.cfg['peakFactor'][0] = 5.0
            print('peakFactor =', self.cfg['peakFactor'][0])
            self.update_plots()
        elif event.key == 'escape':
            self.remove_peak_annotation()
            self.fig.canvas.draw()
        elif event.key in 'h':
            self.help = not self.help
            for ht in self.helptext:
                ht.set_visible(self.help)
            self.fig.canvas.draw()
        elif event.key in 'l':
            self.legend = not self.legend
            self.legendhandle.set_visible(self.legend)
            self.fig.canvas.draw()
        elif event.key in 'w':
            self.plot_waveform()
        elif event.key in 'p':
            self.play_segment()
        elif event.key in 'P':
            self.play_all()
        elif event.key in '1' :
            self.play_tone('c3')
        elif event.key in '2' :
            self.play_tone('a3')
        elif event.key in '3' :
            self.play_tone('e4')
        elif event.key in '4' :
            self.play_tone('a4')
        elif event.key in '5' :
            self.play_tone('c5')
        elif event.key in '6' :
            self.play_tone('e5')
        elif event.key in '7' :
            self.play_tone('g5')
        elif event.key in '8' :
            self.play_tone('a5')
        elif event.key in '9' :
            self.play_tone('c6')

    def buttonpress( self, event ) :
        # print('mouse pressed', event.button, event.key, event.step)
        if event.inaxes == self.axp:
            if event.key == 'shift' or event.key == 'control':
                # show next or previous harmonic:
                if event.key == 'shift':
                    if event.button == 1:
                        ftarget = event.xdata / 2.0
                    elif event.button == 3:
                        ftarget = event.xdata * 2.0
                else:
                    if event.button == 1:
                        ftarget = event.xdata / 1.5
                    elif event.button == 3:
                        ftarget = event.xdata * 1.5
                foffs = event.xdata - self.fmin
                fwidth = self.fmax - self.fmin
                self.fmin = ftarget - foffs
                self.fmax = self.fmin + fwidth
                self.axs.set_ylim(self.fmin, self.fmax)
                self.axp.set_xlim(self.fmin, self.fmax)
                self.fig.canvas.draw()
            else:
                # put label on peak
                self.remove_peak_annotation()
                # find closest peak:
                fwidth = self.fmax - self.fmin
                peakdist = np.abs(self.allpeaks[:, 0] - event.xdata)
                inx = np.argmin(peakdist)
                if peakdist[inx] < 0.005 * fwidth:
                    peak = self.allpeaks[inx, :]
                    # find fish:
                    foundfish = False
                    for finx, fish in enumerate(self.fishlist):
                        if np.min(np.abs(fish[:, 0] - peak[0])) < 0.8 * self.deltaf:
                            self.annotate_fish(fish, finx)
                            foundfish = True
                            break
                    if not foundfish:
                        self.annotate_peak(peak)
                        self.fig.canvas.draw()
                else:
                    self.fig.canvas.draw()

    def onpick(self, event):
        # print('pick')
        legendpoint = event.artist
        finx, fish = self.legenddict[legendpoint]
        self.annotate_fish(fish, finx)

    def resize(self, event):
        # print('resized', event.width, event.height)
        leftpixel = 80.0
        rightpixel = 20.0
        xaxispixel = 50.0
        toppixel = 20.0
        timeaxis = 0.42
        left = leftpixel / event.width
        width = 1.0 - left - rightpixel / event.width
        xaxis = xaxispixel / event.height
        top = toppixel / event.height
        height = (1.0 - timeaxis - top) / 2.0
        if left < 0.5 and width < 1.0 and xaxis < 0.3 and top < 0.2:
            self.axt.set_position([left, timeaxis + height, width, height])
            self.axs.set_position([left, timeaxis, width, height])
            self.axp.set_position([left, xaxis, width, timeaxis - 2.0 * xaxis])

    def plot_waveform(self):
        fig = plt.figure()
        ax = fig.add_subplot(1, 1, 1)
        name = self.filename.split('.')[0]
        if self.channel > 0:
            ax.set_title('{filename} channel={channel:d}'.format(
                filename=self.filename, channel=self.channel))
            figfile = '{name}-{channel:d}-{time:.4g}s-waveform.png'.format(
                name=name, channel=self.channel, time=self.toffset)
        else:
            ax.set_title(self.filename)
            figfile = '{name}-{time:.4g}s-waveform.png'.format(
                name=name, time=self.toffset)
        t0 = int(np.round(self.toffset * self.samplerate))
        t1 = int(np.round((self.toffset + self.twindow) * self.samplerate))
        if self.twindow < 1.0:
            ax.set_xlabel('Time [ms]')
            ax.set_xlim(1000.0 * self.toffset,
                        1000.0 * (self.toffset + self.twindow))
            ax.plot(1000.0 * self.time[t0:t1], self.data[t0:t1])
        else:
            ax.set_xlabel('Time [s]')
            ax.set_xlim(self.toffset, self.toffset + self.twindow)
            ax.plot(self.time[t0:t1], self.data[t0:t1])
        ax.set_ylabel('Amplitude [{:s}]'.format(self.unit))
        fig.tight_layout()
        fig.savefig(figfile)
        fig.clear()
        plt.close(fig)
        print('saved waveform figure to', figfile)

    def play_segment(self):
        t0 = int(np.round(self.toffset * self.samplerate))
        t1 = int(np.round((self.toffset + self.twindow) * self.samplerate))
        playdata = 1.0 * self.data[t0:t1]
        fade(playdata, self.samplerate, 0.1)
        self.audio.play(playdata, self.samplerate, blocking=False)

    def play_all(self):
        self.audio.play(self.data[:], self.samplerate, blocking=False)
        
    def play_tone( self, frequency ) :
        self.audio.beep(1.0, frequency)
コード例 #8
0
ファイル: audianJ.py プロジェクト: graslandschaft/audioJ3
 def __init__(self, main):
     self.main = main
     self.audio = PlayAudio()
     self.create_actions()