merge master

This commit is contained in:
sprause 2023-01-23 09:58:48 +01:00
commit e19ddcb391
19 changed files with 3859 additions and 526 deletions

312
README.md
View File

@ -1,64 +1,248 @@
# Chirp detection - GP2023
## Git-Repository and commands
- Go to the [Bendalab Git-Server](https://whale.am28.uni-tuebingen.de/git/) (https://whale.am28.uni-tuebingen.de/git/)
- Create your own account (and tell me ;D)
* I'll invite you the repository
- Clone the repository
-
```sh
git clone https://whale.am28.uni-tuebingen.de/git/raab/GP2023_chirp_detection.git
```
## Basic git commands
- pull changes in git
```shell
git pull origin <branch>
```
- commit chances
```shell
git commit -m '<explaination>' file # commit one file
git commit -a -m '<explaination>' # commit all files
```
- push commits
```shell
git push origin <branch>
```
## Branches
Use branches to work on specific topics (e.g. 'algorithm', 'analysis', 'writing', ore even more specific ones) and merge
them into Master-Branch when it works are up to your expectations.
The "master" branch should always contain a working/correct version of your project.
- Create/change into branches
```shell
# list all branches (highlight active branch)
git banch -a
# switch into existing
git checkout <existing branch>
# switch into new branch
git checkout master
git checkout -b <new branch>
```
- Re-merging with master branch
1) get current version of master and implement it into branch
```shell
git checkout master
git pull origin master
git checkout <branch>
git rebase master
```
This resets you branch to the fork-point, executes all commits of the current master before adding the commits of you
branch. You may have to resolve potential conflicts. Afterwards commit the corrected version and push it to your branch.
2) Update master branch master
- correct way: Create
```shell
git checkout master
git merge <branch>
git push origin master
```
<!-- Improved compatibility of back to top link: See: https://github.com/othneildrew/Best-README-Template/pull/73 -->
<a name="readme-top"></a>
<!--
*** Thanks for checking out the Best-README-Template. If you have a suggestion
*** that would make this better, please fork the repo and create a pull request
*** or simply open an issue with the tag "enhancement".
*** Don't forget to give the project a star!
*** Thanks again! Now go create something AMAZING! :D
-->
<!-- PROJECT SHIELDS -->
<!--
*** I'm using markdown "reference style" links for readability.
*** Reference links are enclosed in brackets [ ] instead of parentheses ( ).
*** See the bottom of this document for the declaration of the reference variables
*** for contributors-url, forks-url, etc. This is an optional, concise syntax you may use.
*** https://www.markdownguide.org/basic-syntax/#reference-style-links
-->
<!-- [![Contributors][contributors-shield]][contributors-url] -->
<!-- [![Forks][forks-shield]][forks-url] -->
<!-- [![Stargazers][stars-shield]][stars-url] -->
<!-- [![Issues][issues-shield]][issues-url] -->
<!-- [![MIT License][license-shield]][license-url] -->
<!-- [![LinkedIn][linkedin-shield]][linkedin-url] -->
<!-- PROJECT LOGO -->
<br />
<div align="center">
<a href="https://github.com/github_username/repo_name">
<img src="assets/logo.png" alt="Logo" width="150" height="100">
</a>
<h3 align="center">chirpdetector</h3>
<p align="center">
An algorithm to detect the chirps of weakly electric fish.
<br />
<a href="https://github.com/github_username/repo_name"><strong>Explore the docs »</strong></a>
<br />
<br />
<a href="https://github.com/github_username/repo_name">View Demo</a>
·
<a href="https://github.com/github_username/repo_name/issues">Report Bug</a>
·
<a href="https://github.com/github_username/repo_name/issues">Request Feature</a>
</p>
</div>
<!-- TABLE OF CONTENTS -->
<details>
<summary>Table of Contents</summary>
<ol>
<li>
<a href="#about-the-project">About The Project</a>
<ul>
<li><a href="#built-with">Built With</a></li>
</ul>
</li>
<li>
<a href="#getting-started">Getting Started</a>
<ul>
<li><a href="#prerequisites">Prerequisites</a></li>
<li><a href="#installation">Installation</a></li>
</ul>
</li>
<li><a href="#usage">Usage</a></li>
<li><a href="#roadmap">Roadmap</a></li>
<li><a href="#contributing">Contributing</a></li>
<li><a href="#license">License</a></li>
<li><a href="#contact">Contact</a></li>
<li><a href="#acknowledgments">Acknowledgments</a></li>
</ol>
</details>
<!-- ABOUT THE PROJECT -->
## About The Project
[![Product Name Screen Shot][product-screenshot]](https://example.com)
Here's a blank template to get started: To avoid retyping too much info. Do a search and replace with your text editor for the following: `github_username`, `repo_name`, `twitter_handle`, `linkedin_username`, `email_client`, `email`, `project_title`, `project_description`
<p align="right">(<a href="#readme-top">back to top</a>)</p>
<!-- ### Built With -->
<!-- * [![Next][Next.js]][Next-url] -->
<!-- * [![React][React.js]][React-url] -->
<!-- * [![Vue][Vue.js]][Vue-url] -->
<!-- * [![Angular][Angular.io]][Angular-url] -->
<!-- * [![Svelte][Svelte.dev]][Svelte-url] -->
<!-- * [![Laravel][Laravel.com]][Laravel-url] -->
<!-- * [![Bootstrap][Bootstrap.com]][Bootstrap-url] -->
<!-- * [![JQuery][JQuery.com]][JQuery-url] -->
<p align="right">(<a href="#readme-top">back to top</a>)</p>
<!-- GETTING STARTED -->
## Getting Started
This is an example of how you may give instructions on setting up your project locally.
To get a local copy up and running follow these simple example steps.
<!-- ### Prerequisites -->
<!-- This is an example of how to list things you need to use the software and how to install them. -->
<!-- * npm -->
<!-- ```sh -->
<!-- npm install npm@latest -g -->
<!-- ``` -->
### Installation
1. Get a free API Key at [https://example.com](https://example.com)
2. Clone the repo
```sh
git clone https://github.com/github_username/repo_name.git
```
3. Install NPM packages
```sh
npm install
```
4. Enter your API in `config.js`
```js
const API_KEY = 'ENTER YOUR API';
```
<p align="right">(<a href="#readme-top">back to top</a>)</p>
<!-- USAGE EXAMPLES -->
## Usage
Use this space to show useful examples of how a project can be used. Additional screenshots, code examples and demos work well in this space. You may also link to more resources.
_For more examples, please refer to the [Documentation](https://example.com)_
<p align="right">(<a href="#readme-top">back to top</a>)</p>
<!-- ROADMAP -->
## Roadmap
- [ ] Feature 1
- [ ] Feature 2
- [ ] Feature 3
- [ ] Nested Feature
See the [open issues](https://github.com/github_username/repo_name/issues) for a full list of proposed features (and known issues).
<p align="right">(<a href="#readme-top">back to top</a>)</p>
<!-- <!-1- CONTRIBUTING -1-> -->
<!-- ## Contributing -->
<!-- Contributions are what make the open source community such an amazing place to learn, inspire, and create. Any contributions you make are **greatly appreciated**. -->
<!-- If you have a suggestion that would make this better, please fork the repo and create a pull request. You can also simply open an issue with the tag "enhancement". -->
<!-- Don't forget to give the project a star! Thanks again! -->
<!-- 1. Fork the Project -->
<!-- 2. Create your Feature Branch (`git checkout -b feature/AmazingFeature`) -->
<!-- 3. Commit your Changes (`git commit -m 'Add some AmazingFeature'`) -->
<!-- 4. Push to the Branch (`git push origin feature/AmazingFeature`) -->
<!-- 5. Open a Pull Request -->
<!-- <p align="right">(<a href="#readme-top">back to top</a>)</p> -->
<!-- <!-1- LICENSE -1-> -->
<!-- ## License -->
<!-- Distributed under the MIT License. See `LICENSE.txt` for more information. -->
<!-- <p align="right">(<a href="#readme-top">back to top</a>)</p> -->
<!-- CONTACT -->
## Contact
Your Name - [@twitter_handle](https://twitter.com/twitter_handle) - email@email_client.com
Project Link: [https://github.com/github_username/repo_name](https://github.com/github_username/repo_name)
<p align="right">(<a href="#readme-top">back to top</a>)</p>
<!-- ACKNOWLEDGMENTS -->
## Acknowledgments
* []()
* []()
* []()
<p align="right">(<a href="#readme-top">back to top</a>)</p>
<!-- MARKDOWN LINKS & IMAGES -->
<!-- https://www.markdownguide.org/basic-syntax/#reference-style-links -->
[contributors-shield]: https://img.shields.io/github/contributors/github_username/repo_name.svg?style=for-the-badge
[contributors-url]: https://github.com/github_username/repo_name/graphs/contributors
[forks-shield]: https://img.shields.io/github/forks/github_username/repo_name.svg?style=for-the-badge
[forks-url]: https://github.com/github_username/repo_name/network/members
[stars-shield]: https://img.shields.io/github/stars/github_username/repo_name.svg?style=for-the-badge
[stars-url]: https://github.com/github_username/repo_name/stargazers
[issues-shield]: https://img.shields.io/github/issues/github_username/repo_name.svg?style=for-the-badge
[issues-url]: https://github.com/github_username/repo_name/issues
[license-shield]: https://img.shields.io/github/license/github_username/repo_name.svg?style=for-the-badge
[license-url]: https://github.com/github_username/repo_name/blob/master/LICENSE.txt
[linkedin-shield]: https://img.shields.io/badge/-LinkedIn-black.svg?style=for-the-badge&logo=linkedin&colorB=555
[linkedin-url]: https://linkedin.com/in/linkedin_username
[product-screenshot]: images/screenshot.png
[Next.js]: https://img.shields.io/badge/next.js-000000?style=for-the-badge&logo=nextdotjs&logoColor=white
[Next-url]: https://nextjs.org/
[React.js]: https://img.shields.io/badge/React-20232A?style=for-the-badge&logo=react&logoColor=61DAFB
[React-url]: https://reactjs.org/
[Vue.js]: https://img.shields.io/badge/Vue.js-35495E?style=for-the-badge&logo=vuedotjs&logoColor=4FC08D
[Vue-url]: https://vuejs.org/
[Angular.io]: https://img.shields.io/badge/Angular-DD0031?style=for-the-badge&logo=angular&logoColor=white
[Angular-url]: https://angular.io/
[Svelte.dev]: https://img.shields.io/badge/Svelte-4A4A55?style=for-the-badge&logo=svelte&logoColor=FF3E00
[Svelte-url]: https://svelte.dev/
[Laravel.com]: https://img.shields.io/badge/Laravel-FF2D20?style=for-the-badge&logo=laravel&logoColor=white
[Laravel-url]: https://laravel.com
[Bootstrap.com]: https://img.shields.io/badge/Bootstrap-563D7C?style=for-the-badge&logo=bootstrap&logoColor=white
[Bootstrap-url]: https://getbootstrap.com
[JQuery.com]: https://img.shields.io/badge/jQuery-0769AD?style=for-the-badge&logo=jquery&logoColor=white
[JQuery-url]: https://jquery.com

64
README1.md Normal file
View File

@ -0,0 +1,64 @@
# Chirp detection - GP2023
## Git-Repository and commands
- Go to the [Bendalab Git-Server](https://whale.am28.uni-tuebingen.de/git/) (https://whale.am28.uni-tuebingen.de/git/)
- Create your own account (and tell me ;D)
* I'll invite you the repository
- Clone the repository
-
```sh
git clone https://whale.am28.uni-tuebingen.de/git/raab/GP2023_chirp_detection.git
```
## Basic git commands
- pull changes in git
```shell
git pull origin <branch>
```
- commit chances
```shell
git commit -m '<explaination>' file # commit one file
git commit -a -m '<explaination>' # commit all files
```
- push commits
```shell
git push origin <branch>
```
## Branches
Use branches to work on specific topics (e.g. 'algorithm', 'analysis', 'writing', ore even more specific ones) and merge
them into Master-Branch when it works are up to your expectations.
The "master" branch should always contain a working/correct version of your project.
- Create/change into branches
```shell
# list all branches (highlight active branch)
git banch -a
# switch into existing
git checkout <existing branch>
# switch into new branch
git checkout master
git checkout -b <new branch>
```
- Re-merging with master branch
1) get current version of master and implement it into branch
```shell
git checkout master
git pull origin master
git checkout <branch>
git rebase master
```
This resets you branch to the fork-point, executes all commits of the current master before adding the commits of you
branch. You may have to resolve potential conflicts. Afterwards commit the corrected version and push it to your branch.
2) Update master branch master
- correct way: Create
```shell
git checkout master
git merge <branch>
git push origin master
```

BIN
assets/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

1184
assets/logo.svg Normal file

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 84 KiB

View File

@ -1,4 +1,5 @@
import os
import os
import numpy as np
import matplotlib.pyplot as plt
@ -268,4 +269,5 @@ def main(datapath: str):
if __name__ == '__main__':
# Path to the data
datapath = '../data/mount_data/2020-05-13-10_00/'
datapath = '../data/mount_data/2020-05-13-10_00/'
main(datapath)

1095
code/chirpdetection.py Normal file → Executable file

File diff suppressed because it is too large Load Diff

View File

@ -1,48 +1,46 @@
# directory setup
dataroot: "../data/"
outputdir: "../output/"
# Duration and overlap of the analysis window in seconds
window: 5
window: 10
overlap: 1
edge: 0.25
# Number of electrodes to go over
number_electrodes: 3
minimum_electrodes: 2
# Boundary for search frequency in Hz
search_boundary: 100
# Search window bandwidth and minimal baseline bandwidth
minimal_bandwidth: 20
# Cutoff frequency for envelope estimation by lowpass filter
envelope_cutoff: 25
# Instantaneous frequency smoothing usint a gaussian kernel of this width
baseline_frequency_smoothing: 5
# Cutoff frequency for envelope highpass filter
envelope_highpass_cutoff: 3
# Baseline processing parameters
baseline_envelope_cutoff: 25
baseline_envelope_bandpass_lowf: 4
baseline_envelope_bandpass_highf: 100
baseline_envelope_envelope_cutoff: 4
# Cutoff frequency for envelope of envelope
envelope_envelope_cutoff: 5
# search envelope processing parameters
search_envelope_cutoff: 5
# Instantaneous frequency bandpass filter cutoff frequencies
instantaneous_lowf: 15
instantaneous_highf: 8000
baseline_frequency_highpass_cutoff: 0.000005
baseline_frequency_envelope_cutoff: 0.000005
# Baseline envelope peak detection parameters
baseline_prominence_percentile: 90
# Search envelope peak detection parameters
search_prominence_percentile: 90
# Instantaneous frequency peak detection parameters
instantaneous_prominence_percentile: 90
# peak detecion parameters
prominence: 0.005
# search freq parameter
search_df_lower: 25
search_df_lower: 20
search_df_upper: 100
search_res: 1
search_freq_percentiles:
- 5
- 95
search_bandwidth: 10
default_search_freq: 50
# Classify events as chirps if they are less than this time apart
chirp_window_threshold: 0.05

View File

@ -1,5 +1,78 @@
import numpy as np
from typing import List, Any
from scipy.ndimage import gaussian_filter1d
from scipy.stats import gamma, norm
def scale01(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(
signal: np.ndarray,
samplerate: int,
smoothing_window: int,
) -> tuple[np.ndarray, np.ndarray]:
"""
Compute the instantaneous frequency of a signal that is approximately
sinusoidal and symmetric around 0.
Parameters
----------
signal : np.ndarray
Signal to compute the instantaneous frequency from.
samplerate : int
Samplerate of the signal.
smoothing_window : int
Window size for the gaussian filter.
Returns
-------
tuple[np.ndarray, np.ndarray]
"""
# calculate instantaneous frequency with zero crossings
roll_signal = np.roll(signal, shift=1)
time_signal = np.arange(len(signal)) / samplerate
period_index = np.arange(len(signal))[(roll_signal < 0) & (signal >= 0)][
1:-1
]
upper_bound = np.abs(signal[period_index])
lower_bound = np.abs(signal[period_index - 1])
upper_time = np.abs(time_signal[period_index])
lower_time = np.abs(time_signal[period_index - 1])
# create ratio
lower_ratio = lower_bound / (lower_bound + upper_bound)
# appy to time delta
time_delta = upper_time - lower_time
true_zero = lower_time + lower_ratio * time_delta
# create new time array
instantaneous_frequency_time = true_zero[:-1] + 0.5 * np.diff(true_zero)
# compute frequency
instantaneous_frequency = gaussian_filter1d(
1 / np.diff(true_zero), smoothing_window
)
return instantaneous_frequency_time, instantaneous_frequency
def purge_duplicates(
@ -64,7 +137,7 @@ def purge_duplicates(
def group_timestamps(
sublists: List[List[float]], n: int, threshold: float
sublists: List[List[float]], at_least_in: int, difference_threshold: float
) -> List[float]:
"""
Groups timestamps that are less than `threshold` milliseconds apart from
@ -100,7 +173,7 @@ def group_timestamps(
# Group timestamps that are less than threshold milliseconds apart
for i in range(1, len(timestamps)):
if timestamps[i] - timestamps[i - 1] < threshold:
if timestamps[i] - timestamps[i - 1] < difference_threshold:
current_group.append(timestamps[i])
else:
groups.append(current_group)
@ -111,7 +184,7 @@ def group_timestamps(
# Retain only groups that contain at least n timestamps
final_groups = []
for group in groups:
if len(group) >= n:
if len(group) >= at_least_in:
final_groups.append(group)
# Calculate the mean of each group
@ -137,6 +210,117 @@ def flatten(list: List[List[Any]]) -> List:
return [item for sublist in list for item in sublist]
def causal_kde1d(spikes, time, width, shape=2):
"""
causalkde computes a kernel density estimate using a causal kernel (i.e. exponential or gamma distribution).
A shape of 1 turns the gamma distribution into an exponential.
Parameters
----------
spikes : array-like
spike times
time : array-like
sampling time
width : float
kernel width
shape : int, optional
shape of gamma distribution, by default 1
Returns
-------
rate : array-like
instantaneous firing rate
"""
# compute dt
dt = time[1] - time[0]
# time on which to compute kernel:
tmax = 10 * width
# kernel not wider than time
if 2 * tmax > time[-1] - time[0]:
tmax = 0.5 * (time[-1] - time[0])
# kernel time
ktime = np.arange(-tmax, tmax, dt)
# gamma kernel centered in ktime:
kernel = gamma.pdf(
x=ktime,
a=shape,
loc=0,
scale=width,
)
# indices of spikes in time array:
indices = np.asarray((spikes - time[0]) / dt, dtype=int)
# binary spike train:
brate = np.zeros(len(time))
brate[indices[(indices >= 0) & (indices < len(time))]] = 1.0
# convolution with kernel:
rate = np.convolve(brate, kernel, mode="same")
return rate
def acausal_kde1d(spikes, time, width):
"""
causalkde computes a kernel density estimate using a causal kernel (i.e. exponential or gamma distribution).
A shape of 1 turns the gamma distribution into an exponential.
Parameters
----------
spikes : array-like
spike times
time : array-like
sampling time
width : float
kernel width
shape : int, optional
shape of gamma distribution, by default 1
Returns
-------
rate : array-like
instantaneous firing rate
"""
# compute dt
dt = time[1] - time[0]
# time on which to compute kernel:
tmax = 10 * width
# kernel not wider than time
if 2 * tmax > time[-1] - time[0]:
tmax = 0.5 * (time[-1] - time[0])
# kernel time
ktime = np.arange(-tmax, tmax, dt)
# gamma kernel centered in ktime:
kernel = norm.pdf(
x=ktime,
loc=0,
scale=width,
)
# indices of spikes in time array:
indices = np.asarray((spikes - time[0]) / dt, dtype=int)
# binary spike train:
brate = np.zeros(len(time))
brate[indices[(indices >= 0) & (indices < len(time))]] = 1.0
# convolution with kernel:
rate = np.convolve(brate, kernel, mode="same")
return rate
if __name__ == "__main__":
timestamps = [

View File

@ -3,8 +3,8 @@ import numpy as np
def bandpass_filter(
data: np.ndarray,
rate: float,
signal: np.ndarray,
samplerate: float,
lowf: float,
highf: float,
) -> np.ndarray:
@ -12,7 +12,7 @@ def bandpass_filter(
Parameters
----------
data : np.ndarray
signal : np.ndarray
The data to be filtered
rate : float
The sampling rate
@ -26,21 +26,22 @@ def bandpass_filter(
np.ndarray
The filtered data
"""
sos = butter(2, (lowf, highf), "bandpass", fs=rate, output="sos")
fdata = sosfiltfilt(sos, data)
return fdata
sos = butter(2, (lowf, highf), "bandpass", fs=samplerate, output="sos")
filtered_signal = sosfiltfilt(sos, signal)
return filtered_signal
def highpass_filter(
data: np.ndarray,
rate: float,
signal: np.ndarray,
samplerate: float,
cutoff: float,
) -> np.ndarray:
"""Highpass filter a signal.
Parameters
----------
data : np.ndarray
signal : np.ndarray
The data to be filtered
rate : float
The sampling rate
@ -52,14 +53,15 @@ def highpass_filter(
np.ndarray
The filtered data
"""
sos = butter(2, cutoff, "highpass", fs=rate, output="sos")
fdata = sosfiltfilt(sos, data)
return fdata
sos = butter(2, cutoff, "highpass", fs=samplerate, output="sos")
filtered_signal = sosfiltfilt(sos, signal)
return filtered_signal
def lowpass_filter(
data: np.ndarray,
rate: float,
signal: np.ndarray,
samplerate: float,
cutoff: float
) -> np.ndarray:
"""Lowpass filter a signal.
@ -78,21 +80,25 @@ def lowpass_filter(
np.ndarray
The filtered data
"""
sos = butter(2, cutoff, "lowpass", fs=rate, output="sos")
fdata = sosfiltfilt(sos, data)
return fdata
sos = butter(2, cutoff, "lowpass", fs=samplerate, output="sos")
filtered_signal = sosfiltfilt(sos, signal)
return filtered_signal
def envelope(data: np.ndarray, rate: float, freq: float) -> np.ndarray:
def envelope(signal: np.ndarray,
samplerate: float,
cutoff_frequency: float
) -> np.ndarray:
"""Calculate the envelope of a signal using a lowpass filter.
Parameters
----------
data : np.ndarray
signal : np.ndarray
The signal to calculate the envelope of
rate : float
samplingrate : float
The sampling rate of the signal
freq : float
cutoff_frequency : float
The cutoff frequency of the lowpass filter
Returns
@ -100,6 +106,7 @@ def envelope(data: np.ndarray, rate: float, freq: float) -> np.ndarray:
np.ndarray
The envelope of the signal
"""
sos = butter(2, freq, "lowpass", fs=rate, output="sos")
envelope = np.sqrt(2) * sosfiltfilt(sos, np.abs(data))
sos = butter(2, cutoff_frequency, "lowpass", fs=samplerate, output="sos")
envelope = np.sqrt(2) * sosfiltfilt(sos, np.abs(signal))
return envelope

View File

@ -30,10 +30,14 @@ def PlotStyle() -> None:
purple = "#cba6f7"
pink = "#f5c2e7"
lavender = "#b4befe"
gblue1 = "#8cb8ff"
gblue2 = "#7cdcdc"
gblue3 = "#82e896"
@classmethod
def lims(cls, track1, track2):
"""Helper function to get frequency y axis limits from two fundamental frequency tracks.
"""Helper function to get frequency y axis limits from two
fundamental frequency tracks.
Args:
track1 (array): First track
@ -91,6 +95,16 @@ def PlotStyle() -> None:
ax.tick_params(left=False, labelleft=False)
ax.patch.set_visible(False)
@classmethod
def hide_xax(cls, ax):
ax.xaxis.set_visible(False)
ax.spines["bottom"].set_visible(False)
@classmethod
def hide_yax(cls, ax):
ax.yaxis.set_visible(False)
ax.spines["left"].set_visible(False)
@classmethod
def set_boxplot_color(cls, bp, color):
plt.setp(bp["boxes"], color=color)
@ -216,8 +230,8 @@ def PlotStyle() -> None:
plt.rc("figure", titlesize=BIGGER_SIZE) # fontsize of the figure title
plt.rcParams["image.cmap"] = 'cmo.haline'
# plt.rcParams["axes.xmargin"] = 0.1
# plt.rcParams["axes.ymargin"] = 0.15
plt.rcParams["axes.xmargin"] = 0.05
plt.rcParams["axes.ymargin"] = 0.1
plt.rcParams["axes.titlelocation"] = "left"
plt.rcParams["axes.titlesize"] = BIGGER_SIZE
# plt.rcParams["axes.titlepad"] = -10
@ -230,9 +244,9 @@ def PlotStyle() -> None:
plt.rcParams["legend.borderaxespad"] = 0.5
plt.rcParams["legend.fancybox"] = False
# specify the custom font to use
plt.rcParams["font.family"] = "sans-serif"
plt.rcParams["font.sans-serif"] = "Helvetica Now Text"
# # specify the custom font to use
# plt.rcParams["font.family"] = "sans-serif"
# plt.rcParams["font.sans-serif"] = "Helvetica Now Text"
# dark mode modifications
plt.rcParams["boxplot.flierprops.color"] = white
@ -271,7 +285,7 @@ def PlotStyle() -> None:
plt.rcParams["ytick.color"] = gray # color of the ticks
plt.rcParams["grid.color"] = dark_gray # grid color
plt.rcParams["figure.facecolor"] = black # figure face color
plt.rcParams["figure.edgecolor"] = "#555169" # figure edge color
plt.rcParams["figure.edgecolor"] = black # figure edge color
plt.rcParams["savefig.facecolor"] = black # figure face color when saving
return style

View File

@ -0,0 +1,121 @@
import numpy as np
import matplotlib.pyplot as plt
from thunderfish.powerspectrum import spectrogram, decibel
from modules.filehandling import LoadData
from modules.datahandling import instantaneous_frequency
from modules.filters import bandpass_filter
from modules.plotstyle import PlotStyle
ps = PlotStyle()
def main():
# Load data
datapath = "../data/2022-06-02-10_00/"
data = LoadData(datapath)
# good chirp times for data: 2022-06-02-10_00
window_start_seconds = 3 * 60 * 60 + 6 * 60 + 43.5 + 9 + 6.25
window_start_index = window_start_seconds * data.raw_rate
window_duration_seconds = 0.2
window_duration_index = window_duration_seconds * data.raw_rate
timescaler = 1000
raw = data.raw[window_start_index:window_start_index +
window_duration_index, 10]
fig, (ax1, ax2, ax3) = plt.subplots(
3, 1, figsize=(12 * ps.cm, 10*ps.cm), sharex=True, sharey=True)
# plot instantaneous frequency
filtered1 = bandpass_filter(
signal=raw, lowf=750, highf=1200, samplerate=data.raw_rate)
filtered2 = bandpass_filter(
signal=raw, lowf=550, highf=700, samplerate=data.raw_rate)
freqtime1, freq1 = instantaneous_frequency(
filtered1, data.raw_rate, smoothing_window=3)
freqtime2, freq2 = instantaneous_frequency(
filtered2, data.raw_rate, smoothing_window=3)
ax1.plot(freqtime1*timescaler, freq1, color=ps.gblue1,
lw=2, label=f"fish 1, {np.median(freq1):.0f} Hz")
ax1.plot(freqtime2*timescaler, freq2, color=ps.gblue3,
lw=2, label=f"fish 2, {np.median(freq2):.0f} Hz")
ax1.legend(bbox_to_anchor=(0, 1.02, 1, 0.2), loc="lower center",
mode="normal", borderaxespad=0, ncol=2)
ps.hide_xax(ax1)
# plot fine spectrogram
spec_power, spec_freqs, spec_times = spectrogram(
raw,
ratetime=data.raw_rate,
freq_resolution=150,
overlap_frac=0.2,
)
ylims = [300, 1200]
fmask = np.zeros(spec_freqs.shape, dtype=bool)
fmask[(spec_freqs > ylims[0]) & (spec_freqs < ylims[1])] = True
ax2.imshow(
decibel(spec_power[fmask, :]),
extent=[
spec_times[0]*timescaler,
spec_times[-1]*timescaler,
spec_freqs[fmask][0],
spec_freqs[fmask][-1],
],
aspect="auto",
origin="lower",
interpolation="gaussian",
alpha=1,
)
ps.hide_xax(ax2)
# plot coarse spectrogram
spec_power, spec_freqs, spec_times = spectrogram(
raw,
ratetime=data.raw_rate,
freq_resolution=10,
overlap_frac=0.3,
)
fmask = np.zeros(spec_freqs.shape, dtype=bool)
fmask[(spec_freqs > ylims[0]) & (spec_freqs < ylims[1])] = True
ax3.imshow(
decibel(spec_power[fmask, :]),
extent=[
spec_times[0]*timescaler,
spec_times[-1]*timescaler,
spec_freqs[fmask][0],
spec_freqs[fmask][-1],
],
aspect="auto",
origin="lower",
interpolation="gaussian",
alpha=1,
)
# ps.hide_xax(ax3)
ax3.set_xlabel("time [ms]")
ax2.set_ylabel("frequency [Hz]")
ax1.set_yticks(np.arange(400, 1201, 400))
ax1.spines.left.set_bounds((400, 1200))
ax2.set_yticks(np.arange(400, 1201, 400))
ax2.spines.left.set_bounds((400, 1200))
ax3.set_yticks(np.arange(400, 1201, 400))
ax3.spines.left.set_bounds((400, 1200))
plt.subplots_adjust(left=0.17, right=0.98, top=0.9,
bottom=0.14, hspace=0.35)
plt.savefig('../poster/figs/introplot.pdf')
plt.show()
if __name__ == '__main__':
main()

BIN
poster/figs/Untitled.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 116 KiB

BIN
poster/figs/algorithm.pdf Normal file

Binary file not shown.

BIN
poster/figs/introplot.pdf Normal file

Binary file not shown.

BIN
poster/figs/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

1184
poster/figs/logo.svg Normal file

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 84 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 157 KiB

Binary file not shown.

View File

@ -7,65 +7,101 @@ blockverticalspace=2mm, colspace=20mm, subcolspace=0mm]{tikzposter} %Default val
\begin{document}
\renewcommand{\baselinestretch}{1}
\title{\parbox{1900pt}{A dark template to make colorful figures pop}}
\title{\parbox{1900pt}{Pushing the limits of time-frequency uncertainty in the
detection of transient communication signals in weakly electric fish}}
\author{Sina Prause, Alexander Wendt, Patrick Weygoldt}
\institute{Supervised by Till Raab \& Jan Benda}
\institute{Supervised by Till Raab \& Jan Benda, Neurothology Group,
University of Tübingen}
\usetitlestyle[]{sampletitle}
\maketitle
\renewcommand{\baselinestretch}{1.4}
\begin{columns}
\column{0.3}
\column{0.5}
\myblock[TranspBlock]{Introduction}{
\lipsum[1][1-5]
\begin{minipage}[t]{0.55\linewidth}
The time-frequency tradeoff makes reliable signal detecion and simultaneous
sender identification of freely interacting individuals impossible.
This profoundly limits our current understanding of chirps to experiments
with single - or physically separated - individuals.
\end{minipage} \hfill
\begin{minipage}[t]{0.40\linewidth}
\vspace{-1.5cm}
\begin{tikzfigure}[]
\label{griddrawing}
\includegraphics[width=\linewidth]{example-image-a}
\label{tradeoff}
\includegraphics[width=\linewidth]{figs/introplot}
\end{tikzfigure}
\end{minipage}
}
\myblock[TranspBlock]{Methods}{
\begin{tikzfigure}[]
\label{detector}
\includegraphics[width=\linewidth]{example-image-b}
\end{tikzfigure}
\myblock[TranspBlock]{A chirp detection algorithm}{
\begin{tikzfigure}[]
\label{modulations}
\includegraphics[width=\linewidth]{figs/algorithm}
\end{tikzfigure}
}
\column{0.4}
\myblock[TranspBlock]{Results}{
\lipsum[3][1-5]
\column{0.5}
\myblock[TranspBlock]{Chirps and diadic competitions}{
\begin{minipage}[t]{0.7\linewidth}
\begin{tikzfigure}[]
\label{modulations}
\includegraphics[width=\linewidth]{example-image-c}
\includegraphics[width=\linewidth]{figs/placeholder1}
\end{tikzfigure}
}
\end{minipage} \hfill
\begin{minipage}[t]{0.25\linewidth}
\lipsum[3][1-3]
\end{minipage}
\myblock[TranspBlock]{More Stuff}{
\lipsum[3][1-9]
}
\begin{minipage}[t]{0.7\linewidth}
\begin{tikzfigure}[]
\label{modulations}
\includegraphics[width=\linewidth]{figs/placeholder1}
\end{tikzfigure}
\end{minipage} \hfill
\begin{minipage}[t]{0.25\linewidth}
\lipsum[3][1-3]
\end{minipage}
\column{0.3}
\myblock[TranspBlock]{More Results}{
\begin{minipage}[t]{0.7\linewidth}
\begin{tikzfigure}[]
\label{results}
\includegraphics[width=\linewidth]{example-image-a}
\label{modulations}
\includegraphics[width=\linewidth]{figs/placeholder1}
\end{tikzfigure}
\end{minipage} \hfill
\begin{minipage}[t]{0.25\linewidth}
\lipsum[3][1-3]
\end{minipage}
\begin{multicols}{2}
\lipsum[5][1-8]
\end{multicols}
\vspace{-1cm}
}
\myblock[TranspBlock]{Conclusion}{
\begin{itemize}
\setlength\itemsep{0.5em}
\item \lipsum[1][1]
\item \lipsum[1][1]
\item \lipsum[1][1]
\end{itemize}
\vspace{0.2cm}
}
\lipsum[3][1-9]
}
% \column{0.3}
% \myblock[TranspBlock]{More Results}{
% \begin{tikzfigure}[]
% \label{results}
% \includegraphics[width=\linewidth]{example-image-a}
% \end{tikzfigure}
% \begin{multicols}{2}
% \lipsum[5][1-8]
% \end{multicols}
% \vspace{-1cm}
% }
% \myblock[TranspBlock]{Conclusion}{
% \begin{itemize}
% \setlength\itemsep{0.5em}
% \item \lipsum[1][1]
% \item \lipsum[1][1]
% \item \lipsum[1][1]
% \end{itemize}
% \vspace{0.2cm}
% }
\end{columns}
\node[
@ -78,6 +114,6 @@ blockverticalspace=2mm, colspace=20mm, subcolspace=0mm]{tikzposter} %Default val
fill=boxes,
color=boxes,
] at (-0.51\paperwidth,-43.5) {
\textcolor{text}{\normalsize Contact: name.surname@student.uni-tuebingen.de}};
\textcolor{text}{\normalsize Contact: \{name\}.\{surname\}@student.uni-tuebingen.de}};
\end{document}