added gridspec plot layout

This commit is contained in:
weygoldt 2023-01-20 17:09:48 +01:00
parent ddf7bd545a
commit 9f46b969a5
2 changed files with 96 additions and 41 deletions

View File

@ -3,6 +3,7 @@ from dataclasses import dataclass
import numpy as np import numpy as np
import matplotlib.pyplot as plt import matplotlib.pyplot as plt
import matplotlib.gridspec as gr
from scipy.signal import find_peaks from scipy.signal import find_peaks
from thunderfish.powerspectrum import spectrogram, decibel from thunderfish.powerspectrum import spectrogram, decibel
from sklearn.preprocessing import normalize from sklearn.preprocessing import normalize
@ -13,6 +14,7 @@ from modules.plotstyle import PlotStyle
from modules.logger import makeLogger from modules.logger import makeLogger
from modules.datahandling import ( from modules.datahandling import (
flatten, flatten,
norm,
purge_duplicates, purge_duplicates,
group_timestamps, group_timestamps,
instantaneous_frequency, instantaneous_frequency,
@ -42,6 +44,7 @@ class PlotBuffer:
baseline: np.ndarray baseline: np.ndarray
baseline_envelope: np.ndarray baseline_envelope: np.ndarray
baseline_peaks: np.ndarray baseline_peaks: np.ndarray
search_frequency: float
search: np.ndarray search: np.ndarray
search_envelope: np.ndarray search_envelope: np.ndarray
search_peaks: np.ndarray search_peaks: np.ndarray
@ -57,15 +60,21 @@ class PlotBuffer:
# make data for plotting # make data for plotting
# # get index of track data in this time window # get index of track data in this time window
# window_idx = np.arange(len(self.data.idx))[ window_idx = np.arange(len(self.data.idx))[
# (self.data.ident == self.track_id) & (self.data.time[self.data.idx] >= self.t0) & ( (self.data.ident == self.track_id) & (self.data.time[self.data.idx] >= self.t0) & (
# self.data.time[self.data.idx] <= (self.t0 + self.dt)) self.data.time[self.data.idx] <= (self.t0 + self.dt))
# ] ]
# get tracked frequencies and their times # get tracked frequencies and their times
# freq_temp = self.data.freq[window_idx] freq_temp = self.data.freq[window_idx]
# time_temp = self.data.times[window_idx] time_temp = self.data.time[(self.data.time >= self.t0) & (
self.data.time <= (self.t0 + self.dt))]
# remake the band we filtered in
q25, q50, q75 = np.percentile(freq_temp, [25, 50, 75])
search_upper, search_lower = q50 + self.search_frequency + self.config.minimal_bandwidth / \
2, q50 + self.search_frequency - self.config.minimal_bandwidth / 2
# get indices on raw data # get indices on raw data
start_idx = self.t0 * self.data.raw_rate start_idx = self.t0 * self.data.raw_rate
@ -75,66 +84,90 @@ class PlotBuffer:
# get raw data # get raw data
data_oi = self.data.raw[start_idx:stop_idx, self.electrode] data_oi = self.data.raw[start_idx:stop_idx, self.electrode]
fig, axs = plt.subplots( self.time = (self.time - self.t0)
7, self.frequency_time = (self.frequency_time - self.t0)
1, chirps = (np.ararray(chirps) - self.t0)
figsize=(20 / 2.54, 12 / 2.54), self.t0 = 0
constrained_layout=True,
sharex=True, fig = plt.figure(figsize=(16 / 2.54, 24 / 2.54),
sharey="row", constrained_layout=True)
)
grid = gr.GridSpec(9, 1, figure=fig, height_ratios=[
4, 0.5, 1, 1, 1, 0.5, 1, 1, 1])
ax0 = fig.add_subplot(grid[0, 0])
ax1 = fig.add_subplot(grid[2, 0], sharex=ax0)
ax2 = fig.add_subplot(grid[3, 0], sharex=ax0)
ax3 = fig.add_subplot(grid[4, 0], sharex=ax0)
ax4 = fig.add_subplot(grid[6, 0], sharex=ax0)
ax5 = fig.add_subplot(grid[7, 0], sharex=ax0)
ax6 = fig.add_subplot(grid[8, 0], sharex=ax0)
# plot spectrogram # plot spectrogram
plot_spectrogram(axs[0], data_oi, self.data.raw_rate, self.t0) plot_spectrogram(ax0, data_oi, self.data.raw_rate, self.t0)
ax0.fill_between(
np.arange(self.t0, self.t0 + self.dt, 1 / self.data.raw_rate),
q50 - self.config.minimal_bandwidth / 2,
q50 + self.config.minimal_bandwidth / 2,
color=ps.black,
lw=0,
alpha=0.2)
ax0.fill_between(
np.arange(self.t0, self.t0 + self.dt, 1 / self.data.raw_rate),
search_lower,
search_upper,
color=ps.black,
lw=0,
alpha=0.2)
for chirp in chirps: for chirp in chirps:
axs[0].scatter( ax0.scatter(
chirp, np.median(self.frequency), c=ps.black, marker="x" chirp, np.median(self.frequency), c=ps.black, marker="x"
) )
# plot waveform of filtered signal # plot waveform of filtered signal
axs[1].plot(self.time, self.baseline, c=ps.green) ax1.plot(self.time, norm(self.baseline))
# plot waveform of filtered search signal # plot waveform of filtered search signal
axs[2].plot(self.time, self.search) ax2.plot(self.time, norm(self.search))
# plot baseline instantaneous frequency # plot baseline instantaneous frequency
axs[3].plot(self.frequency_time, self.frequency) ax3.plot(self.frequency_time, self.frequency)
# plot filtered and rectified envelope # plot filtered and rectified envelope
axs[4].plot(self.time, self.baseline_envelope) ax4.plot(self.time, self.baseline_envelope)
axs[4].scatter( ax4.scatter(
(self.time)[self.baseline_peaks], (self.time)[self.baseline_peaks],
self.baseline_envelope[self.baseline_peaks], self.baseline_envelope[self.baseline_peaks],
c=ps.red, c=ps.red,
) )
# plot envelope of search signal # plot envelope of search signal
axs[5].plot(self.time, self.search_envelope) ax5.plot(self.time, self.search_envelope)
axs[5].scatter( ax5.scatter(
(self.time)[self.search_peaks], (self.time)[self.search_peaks],
self.search_envelope[self.search_peaks], self.search_envelope[self.search_peaks],
c=ps.red, c=ps.red,
) )
# plot filtered instantaneous frequency # plot filtered instantaneous frequency
axs[6].plot(self.frequency_time, self.frequency_filtered) ax6.plot(self.frequency_time, self.frequency_filtered)
axs[6].scatter( ax6.scatter(
self.frequency_time[self.frequency_peaks], self.frequency_time[self.frequency_peaks],
self.frequency_filtered[self.frequency_peaks], self.frequency_filtered[self.frequency_peaks],
c=ps.red, c=ps.red,
) )
axs[0].set_ylim( ax0.set_ylim(
np.max(self.frequency) - 200, top=np.max(self.frequency) + 200 np.max(self.frequency) - 200, top=np.max(self.frequency) + 400
) )
axs[6].set_xlabel("Time [s]") ax0.set_title("Spectrogram of raw data")
axs[0].set_title("Spectrogram") ax1.set_title("Extracted features")
axs[1].set_title("Fitered baseline") ax4.set_title("Filtered and rectified features")
axs[2].set_title("Fitered above") ax6.set_xlabel("Time [s]")
axs[3].set_title("Fitered baseline instanenous frequency")
axs[4].set_title("Filtered envelope of baseline envelope") ax0.set_xlim(0, 5)
axs[5].set_title("Search envelope")
axs[6].set_title("Filtered absolute instantaneous frequency")
if plot == "show": if plot == "show":
plt.show() plt.show()
@ -172,7 +205,7 @@ def plot_spectrogram(
spec_power, spec_freqs, spec_times = spectrogram( spec_power, spec_freqs, spec_times = spectrogram(
signal, signal,
ratetime=samplerate, ratetime=samplerate,
freq_resolution=20, freq_resolution=10,
overlap_frac=0.5, overlap_frac=0.5,
) )
@ -339,7 +372,7 @@ def find_searchband(
q1, q2 = np.percentile( q1, q2 = np.percentile(
data.freq[data.ident == check_track_id], data.freq[data.ident == check_track_id],
config.search_freq_percentiles, [25, 75]
) )
search_window_bool[ search_window_bool[
@ -432,11 +465,13 @@ def main(datapath: str, plot: str) -> None:
raw_time = np.arange(data.raw.shape[0]) / data.raw_rate raw_time = np.arange(data.raw.shape[0]) / data.raw_rate
# good chirp times for data: 2022-06-02-10_00 # good chirp times for data: 2022-06-02-10_00
window_start_seconds = (3 * 60 * 60 + 6 * 60 + 43.5) * data.raw_rate # window_start_seconds = (3 * 60 * 60 + 6 * 60 + 43.5) * data.raw_rate
window_duration_seconds = 60 * data.raw_rate # window_duration_seconds = 60 * data.raw_rate
# t0 = 0 # t0 = 0
# dt = data.raw.shape[0] # dt = data.raw.shape[0]
window_start_seconds = (23495 + ((28336-23495)/3)) * data.raw_rate
window_duration_seconds = (28336 - 23495) * data.raw_rate
# generate starting points of rolling window # generate starting points of rolling window
window_start_indices = np.arange( window_start_indices = np.arange(
@ -773,6 +808,7 @@ def main(datapath: str, plot: str) -> None:
baseline=baselineband, baseline=baselineband,
baseline_envelope=baseline_envelope, baseline_envelope=baseline_envelope,
baseline_peaks=baseline_peak_indices, baseline_peaks=baseline_peak_indices,
search_frequency=search_frequency,
search=searchband, search=searchband,
search_envelope=search_envelope, search_envelope=search_envelope,
search_peaks=search_peak_indices, search_peaks=search_peak_indices,
@ -876,5 +912,6 @@ def main(datapath: str, plot: str) -> None:
if __name__ == "__main__": if __name__ == "__main__":
# datapath = "/home/weygoldt/Data/uni/chirpdetection/GP2023_chirp_detection/data/mount_data/2020-05-13-10_00/" # datapath = "/home/weygoldt/Data/uni/chirpdetection/GP2023_chirp_detection/data/mount_data/2020-05-13-10_00/"
datapath = "../data/2022-06-02-10_00/" # datapath = "../data/2022-06-02-10_00/"
datapath = "/home/weygoldt/Data/uni/efishdata/2016-colombia/fishgrid/2016-04-09-22_25/"
main(datapath, plot="show") main(datapath, plot="show")

View File

@ -3,6 +3,24 @@ from typing import List, Any
from scipy.ndimage import gaussian_filter1d from scipy.ndimage import gaussian_filter1d
def norm(data):
"""
Normalize data to [0, 1]
Parameters
----------
data : np.ndarray
Data to normalize.
Returns
-------
np.ndarray
Normalized data.
"""
return (2*((data - np.min(data)) / (np.max(data) - np.min(data)))) - 1
def instantaneous_frequency( def instantaneous_frequency(
signal: np.ndarray, signal: np.ndarray,
samplerate: int, samplerate: int,