added plots to readme
This commit is contained in:
parent
951c22876b
commit
78cbd0498b
96
README.md
96
README.md
@ -1,49 +1,28 @@
|
|||||||
<!-- Improved compatibility of back to top link: See: https://github.com/othneildrew/Best-README-Template/pull/73 -->
|
# Chirpdetector
|
||||||
<a name="readme-top"></a>
|
|
||||||
<!-- 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 transient communication signals of weakly electric fish on multielectrode recordings.
|
|
||||||
<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></li>
|
|
||||||
<li><a href="#the-approach">Getting Started</a></li>
|
|
||||||
</ol>
|
|
||||||
</details>
|
|
||||||
|
|
||||||
|
|
||||||
## About The Project
|
|
||||||
|
|
||||||
Chirps are transient communication singals of many wave-type electric fish. Because they are so fast, detecting them when the recorded signal includes multiple individuals is hard. But to understand if, and what kind of information they transmit in a natural setting, analyzing chirps in multiple freely interacting individual is nessecary. This repository documents an approach to detect these signals on electrode grid recordings with many freely behaving individuals.
|
|
||||||
|
|
||||||
The majority of the code and its tests were part of a lab rotation with the [Neuroethology](https://github.com/bendalab) at the University of Tuebingen. It also contains a [poster](poster_printed/main.pdf) and a more thorough [lab protocol](protocol/main.pdf).
|
Chirps are transient communication singals of many wave-type electric fish. Because they are so fast, detecting them when the recorded signal includes multiple individuals is hard. But to understand if, and what kind of information they transmit in a natural setting, analyzing chirps in multiple freely interacting individual is nessecary. This repository documents an approach to detect these signals on electrode grid recordings with many freely behaving individuals by extracting EOD parameters that change during a chirp and detecting anomalies on them.
|
||||||
|
|
||||||
<p align="right">(<a href="#readme-top">back to top</a>)</p>
|
The majority of the code and its tests were part of a lab rotation with the [Neuroethology](https://github.com/bendalab) at the University of Tuebingen. It also contains a [poster](poster_printed/main.pdf) and a more thorough [lab protocol](protocol/main.pdf).
|
||||||
|
|
||||||
## The Approach
|
## The Approach
|
||||||
|
|
||||||
To detect chirps, we extract some features of the raw signal using frequency traces that were computed beforehand using the [wavetracker](https://github.com/tillraab/wavetracker). For a frequency band of a single fish, we filter the signal using a bandpass filter, extract the instantaneous frequency, the envelelope and the envelope of a frequency band slightly above the fundamental frequency of the fish. We then transform those features using various filters and detect the peaks on them. Peaks on all three features are chirps. We always use the strongest electrode relative to the fish of interest. By that, we include the spatial demensions to increase our detection performance, if fish are spaced sufficiently apart. The full algorithm is thoroughly explained in the lab protocol. All parameters can be tuned using a `yaml` config file. While this approach excels in assigning detected chirps to the currect fish, the actial chirp detection is not that reliable. If peak detection thresholds are set for each feature manually, the detector can become quite reliable. But if features are normalized to generalize the detector, noise often introduces false detections, especially during amplitude breakdowns.
|
To detect chirps, we extract some features of the raw signal using frequency traces that were computed beforehand using the [wavetracker](https://github.com/tillraab/wavetracker). For a frequency band of a single fish, we filter the signal using a bandpass filter, extract the instantaneous frequency, the envelelope and the envelope of a frequency band slightly above the fundamental frequency of the fish. We then transform those features using various filters and detect the peaks on them. Peaks on all three features are chirps. In an ideal world, the result looks like this:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
We always use the strongest electrode relative to the fish of interest. By that, we include the spatial demensions to increase our detection performance, if fish are spaced sufficiently apart. The full algorithm is thoroughly explained in the lab protocol. All parameters can be tuned using a `yaml` config file. While this approach excels in assigning detected chirps to the currect fish, the actial chirp detection is not that reliable. If peak detection thresholds are set for each feature manually, the detector can become quite reliable but performance will be sensible to changes in the recording setup. But if features are normalized to generalize the detector, noise often introduces false detections, especially during amplitude breakdowns. Below is an example of a recording with false detections:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## Open questions
|
||||||
|
|
||||||
|
One of the three features we exract to detect peaks is the instantaneous frequency of the baseline EOD of a single fish. To do that, we apply a narrow bandpass filter (+- 5 Hz) around the fundamental frequency in a single 5 second window. If when the fish chirps, its real frequency should increase beyond the filter cutoff frequencies and we should see a slight increase in the instantaneous frequency. But sometimes, the frequency decreases or does not change at all.
|
||||||
|
|
||||||
|
To understand this, we simulated chirps while changing some parameters of the chirp, notably the height, width, kurtosis, contrast and EOD phase in which the chirp is produced. What we find, is that all parameters that change the integral of the chirp frequency evolution (i.e. the height, width, and kurtosis) occasionally result in negative instantaneous frequencies in the narrow filtered EOD. Specifically, if the integral increases, the instantaneous frequency increases as well, until an integer + 0.57 is reached. At this point, the frequency flips around the x axis and gradually becomes positive again. This is illustrated in the figure below for the chirp width. The integral of the zero-shifted instantaneous frequency is indicated as the title of each subplot. 1.57 would be $\pi/2$ but how this relates to the observed pattern is not clear yet. What becomes clear from the waveform below is that the point at which the EOD flips is the point where the amplitude of just the filtered signal breaks down to 0.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
To explore the other parameters, there is a jupyter notebook in the `notebooks` [here](chirp_instantaneous_freq/chirp_exploration.ipynb).
|
||||||
|
|
||||||
<!-- # Chirp detection - GP2023 -->
|
<!-- # Chirp detection - GP2023 -->
|
||||||
<!-- ## Git-Repository and commands -->
|
<!-- ## Git-Repository and commands -->
|
||||||
@ -109,38 +88,3 @@ To detect chirps, we extract some features of the raw signal using frequency tra
|
|||||||
<!-- git merge <branch> -->
|
<!-- git merge <branch> -->
|
||||||
<!-- git push origin master -->
|
<!-- git push origin master -->
|
||||||
<!-- ``` -->
|
<!-- ``` -->
|
||||||
|
|
||||||
|
|
||||||
<!-- 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
|
|
||||||
|
|
||||||
|
|
||||||
|
14906
assets/bad_.svg
Normal file
14906
assets/bad_.svg
Normal file
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 448 KiB |
14924
assets/chirpsize.svg
Normal file
14924
assets/chirpsize.svg
Normal file
File diff suppressed because it is too large
Load Diff
After Width: | Height: | Size: 371 KiB |
15704
assets/good_.svg
Normal file
15704
assets/good_.svg
Normal file
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 466 KiB |
14910
assets/width.svg
Normal file
14910
assets/width.svg
Normal file
File diff suppressed because it is too large
Load Diff
After Width: | Height: | Size: 370 KiB |
File diff suppressed because one or more lines are too long
411
chirp_instantaneous_freq/plotstyle.py
Normal file
411
chirp_instantaneous_freq/plotstyle.py
Normal file
@ -0,0 +1,411 @@
|
|||||||
|
import cmocean as cmo
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
|
import numpy as np
|
||||||
|
from cycler import cycler
|
||||||
|
from matplotlib.colors import ListedColormap
|
||||||
|
|
||||||
|
|
||||||
|
def PlotStyle() -> None:
|
||||||
|
class style:
|
||||||
|
# lightcmap = cmocean.tools.lighten(cmocean.cm.haline, 0.8)
|
||||||
|
|
||||||
|
# units
|
||||||
|
cm = 1 / 2.54
|
||||||
|
mm = 1 / 25.4
|
||||||
|
|
||||||
|
# colors
|
||||||
|
black = "#111116"
|
||||||
|
white = "#e0e4f7"
|
||||||
|
gray = "#6c6e7d"
|
||||||
|
blue = "#89b4fa"
|
||||||
|
sapphire = "#74c7ec"
|
||||||
|
sky = "#89dceb"
|
||||||
|
teal = "#94e2d5"
|
||||||
|
green = "#a6e3a1"
|
||||||
|
yellow = "#f9d67f"
|
||||||
|
orange = "#faa472"
|
||||||
|
maroon = "#eb8486"
|
||||||
|
red = "#e0e4f7"
|
||||||
|
purple = "#d89bf7"
|
||||||
|
pink = "#f59edb"
|
||||||
|
lavender = "#b4befe"
|
||||||
|
gblue1 = "#f37588"
|
||||||
|
gblue2 = "#faa472"
|
||||||
|
gblue3 = "#f9d67f"
|
||||||
|
g = "#f3626c"
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def lims(cls, track1, track2):
|
||||||
|
"""Helper function to get frequency y axis limits from two
|
||||||
|
fundamental frequency tracks.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
track1 (array): First track
|
||||||
|
track2 (array): Second track
|
||||||
|
start (int): Index for first value to be plotted
|
||||||
|
stop (int): Index for second value to be plotted
|
||||||
|
padding (int): Padding for the upper and lower limit
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
lower (float): lower limit
|
||||||
|
upper (float): upper limit
|
||||||
|
|
||||||
|
"""
|
||||||
|
allfunds_tmp = (
|
||||||
|
np.concatenate(
|
||||||
|
[
|
||||||
|
track1,
|
||||||
|
track2,
|
||||||
|
]
|
||||||
|
)
|
||||||
|
.ravel()
|
||||||
|
.tolist()
|
||||||
|
)
|
||||||
|
lower = np.min(allfunds_tmp)
|
||||||
|
upper = np.max(allfunds_tmp)
|
||||||
|
return lower, upper
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def circled_annotation(cls, text, axis, xpos, ypos, padding=0.25):
|
||||||
|
axis.text(
|
||||||
|
xpos,
|
||||||
|
ypos,
|
||||||
|
text,
|
||||||
|
ha="center",
|
||||||
|
va="center",
|
||||||
|
zorder=1000,
|
||||||
|
bbox=dict(
|
||||||
|
boxstyle=f"circle, pad={padding}",
|
||||||
|
fc="white",
|
||||||
|
ec="black",
|
||||||
|
lw=1,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def fade_cmap(cls, cmap):
|
||||||
|
my_cmap = cmap(np.arange(cmap.N))
|
||||||
|
my_cmap[:, -1] = np.linspace(0, 1, cmap.N)
|
||||||
|
my_cmap = ListedColormap(my_cmap)
|
||||||
|
|
||||||
|
return my_cmap
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def hide_ax(cls, ax):
|
||||||
|
ax.xaxis.set_visible(False)
|
||||||
|
plt.setp(ax.spines.values(), visible=False)
|
||||||
|
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)
|
||||||
|
plt.setp(bp["whiskers"], color=white)
|
||||||
|
plt.setp(bp["caps"], color=white)
|
||||||
|
plt.setp(bp["medians"], color=black)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def label_subplots(cls, labels, axes, fig):
|
||||||
|
for axis, label in zip(axes, labels):
|
||||||
|
X = axis.get_position().x0
|
||||||
|
Y = axis.get_position().y1
|
||||||
|
fig.text(X, Y, label, weight="bold")
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def letter_subplots(
|
||||||
|
cls, axes=None, letters=None, xoffset=-0.1, yoffset=1.0, **kwargs
|
||||||
|
):
|
||||||
|
"""Add letters to the corners of subplots (panels). By default each axis is
|
||||||
|
given an uppercase bold letter label placed in the upper-left corner.
|
||||||
|
Args
|
||||||
|
axes : list of pyplot ax objects. default plt.gcf().axes.
|
||||||
|
letters : list of strings to use as labels, default ["A", "B", "C", ...]
|
||||||
|
xoffset, yoffset : positions of each label relative to plot frame
|
||||||
|
(default -0.1,1.0 = upper left margin). Can also be a list of
|
||||||
|
offsets, in which case it should be the same length as the number of
|
||||||
|
axes.
|
||||||
|
Other keyword arguments will be passed to annotate() when panel letters
|
||||||
|
are added.
|
||||||
|
Returns:
|
||||||
|
list of strings for each label added to the axes
|
||||||
|
Examples:
|
||||||
|
Defaults:
|
||||||
|
>>> fig, axes = plt.subplots(1,3)
|
||||||
|
>>> letter_subplots() # boldfaced A, B, C
|
||||||
|
|
||||||
|
Common labeling schemes inferred from the first letter:
|
||||||
|
>>> fig, axes = plt.subplots(1,4)
|
||||||
|
# panels labeled (a), (b), (c), (d)
|
||||||
|
>>> letter_subplots(letters='(a)')
|
||||||
|
Fully custom lettering:
|
||||||
|
>>> fig, axes = plt.subplots(2,1)
|
||||||
|
>>> letter_subplots(axes, letters=['(a.1)', '(b.2)'], fontweight='normal')
|
||||||
|
Per-axis offsets:
|
||||||
|
>>> fig, axes = plt.subplots(1,2)
|
||||||
|
>>> letter_subplots(axes, xoffset=[-0.1, -0.15])
|
||||||
|
|
||||||
|
Matrix of axes:
|
||||||
|
>>> fig, axes = plt.subplots(2,2, sharex=True, sharey=True)
|
||||||
|
# fig.axes is a list when axes is a 2x2 matrix
|
||||||
|
>>> letter_subplots(fig.axes)
|
||||||
|
"""
|
||||||
|
|
||||||
|
# get axes:
|
||||||
|
if axes is None:
|
||||||
|
axes = plt.gcf().axes
|
||||||
|
# handle single axes:
|
||||||
|
try:
|
||||||
|
iter(axes)
|
||||||
|
except TypeError:
|
||||||
|
axes = [axes]
|
||||||
|
|
||||||
|
# set up letter defaults (and corresponding fontweight):
|
||||||
|
fontweight = "bold"
|
||||||
|
ulets = list("ABCDEFGHIJKLMNOPQRSTUVWXYZ"[: len(axes)])
|
||||||
|
llets = list("abcdefghijklmnopqrstuvwxyz"[: len(axes)])
|
||||||
|
if letters is None or letters == "A":
|
||||||
|
letters = ulets
|
||||||
|
elif letters == "(a)":
|
||||||
|
letters = ["({})".format(lett) for lett in llets]
|
||||||
|
fontweight = "normal"
|
||||||
|
elif letters == "(A)":
|
||||||
|
letters = ["({})".format(lett) for lett in ulets]
|
||||||
|
fontweight = "normal"
|
||||||
|
elif letters in ("lower", "lowercase", "a"):
|
||||||
|
letters = llets
|
||||||
|
|
||||||
|
# make sure there are x and y offsets for each ax in axes:
|
||||||
|
if isinstance(xoffset, (int, float)):
|
||||||
|
xoffset = [xoffset] * len(axes)
|
||||||
|
else:
|
||||||
|
assert len(xoffset) == len(axes)
|
||||||
|
if isinstance(yoffset, (int, float)):
|
||||||
|
yoffset = [yoffset] * len(axes)
|
||||||
|
else:
|
||||||
|
assert len(yoffset) == len(axes)
|
||||||
|
|
||||||
|
# defaults for annotate (kwargs is second so it can overwrite these defaults):
|
||||||
|
my_defaults = dict(
|
||||||
|
fontweight=fontweight,
|
||||||
|
fontsize="large",
|
||||||
|
ha="center",
|
||||||
|
va="center",
|
||||||
|
xycoords="axes fraction",
|
||||||
|
annotation_clip=False,
|
||||||
|
)
|
||||||
|
kwargs = dict(list(my_defaults.items()) + list(kwargs.items()))
|
||||||
|
|
||||||
|
list_txts = []
|
||||||
|
for ax, lbl, xoff, yoff in zip(axes, letters, xoffset, yoffset):
|
||||||
|
t = ax.annotate(lbl, xy=(xoff, yoff), **kwargs)
|
||||||
|
list_txts.append(t)
|
||||||
|
return list_txts
|
||||||
|
|
||||||
|
pass
|
||||||
|
|
||||||
|
# rcparams text setup
|
||||||
|
SMALL_SIZE = 12
|
||||||
|
MEDIUM_SIZE = 14
|
||||||
|
BIGGER_SIZE = 16
|
||||||
|
black = "#111116"
|
||||||
|
white = "#e0e4f7"
|
||||||
|
gray = "#6c6e7d"
|
||||||
|
dark_gray = "#2a2a32"
|
||||||
|
|
||||||
|
# rcparams
|
||||||
|
plt.rc("font", size=MEDIUM_SIZE) # controls default text sizes
|
||||||
|
plt.rc("axes", titlesize=MEDIUM_SIZE) # fontsize of the axes title
|
||||||
|
plt.rc("axes", labelsize=MEDIUM_SIZE) # fontsize of the x and y labels
|
||||||
|
plt.rc("xtick", labelsize=SMALL_SIZE) # fontsize of the tick labels
|
||||||
|
plt.rc("ytick", labelsize=SMALL_SIZE) # fontsize of the tick labels
|
||||||
|
plt.rc("legend", fontsize=SMALL_SIZE) # legend fontsize
|
||||||
|
plt.rc("figure", titlesize=BIGGER_SIZE) # fontsize of the figure title
|
||||||
|
|
||||||
|
plt.rcParams["image.cmap"] = "cmo.thermal"
|
||||||
|
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
|
||||||
|
plt.rcParams["legend.frameon"] = False
|
||||||
|
plt.rcParams["legend.loc"] = "best"
|
||||||
|
plt.rcParams["legend.borderpad"] = 0.4
|
||||||
|
plt.rcParams["legend.facecolor"] = black
|
||||||
|
plt.rcParams["legend.edgecolor"] = black
|
||||||
|
plt.rcParams["legend.framealpha"] = 0.7
|
||||||
|
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"
|
||||||
|
|
||||||
|
# dark mode modifications
|
||||||
|
plt.rcParams["boxplot.flierprops.color"] = white
|
||||||
|
plt.rcParams["boxplot.flierprops.markeredgecolor"] = gray
|
||||||
|
plt.rcParams["boxplot.boxprops.color"] = gray
|
||||||
|
plt.rcParams["boxplot.whiskerprops.color"] = gray
|
||||||
|
plt.rcParams["boxplot.capprops.color"] = gray
|
||||||
|
plt.rcParams["boxplot.medianprops.color"] = black
|
||||||
|
plt.rcParams["text.color"] = white
|
||||||
|
plt.rcParams["axes.facecolor"] = black # axes background color
|
||||||
|
plt.rcParams["axes.edgecolor"] = white # axes edge color
|
||||||
|
# plt.rcParams["axes.grid"] = True # display grid or not
|
||||||
|
# plt.rcParams["axes.grid.axis"] = "y" # which axis the grid is applied to
|
||||||
|
plt.rcParams["axes.labelcolor"] = white
|
||||||
|
plt.rcParams["axes.axisbelow"] = True # draw axis gridlines and ticks:
|
||||||
|
plt.rcParams["axes.spines.left"] = True # display axis spines
|
||||||
|
plt.rcParams["axes.spines.bottom"] = True
|
||||||
|
plt.rcParams["axes.spines.top"] = False
|
||||||
|
plt.rcParams["axes.spines.right"] = False
|
||||||
|
plt.rcParams["axes.prop_cycle"] = cycler(
|
||||||
|
"color",
|
||||||
|
[
|
||||||
|
"#b4befe",
|
||||||
|
"#89b4fa",
|
||||||
|
"#74c7ec",
|
||||||
|
"#89dceb",
|
||||||
|
"#94e2d5",
|
||||||
|
"#a6e3a1",
|
||||||
|
"#f9e2af",
|
||||||
|
"#fab387",
|
||||||
|
"#eba0ac",
|
||||||
|
"#f38ba8",
|
||||||
|
"#cba6f7",
|
||||||
|
"#f5c2e7",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
plt.rcParams["xtick.color"] = white # color of the ticks
|
||||||
|
plt.rcParams["ytick.color"] = white # color of the ticks
|
||||||
|
plt.rcParams["grid.color"] = white # grid color
|
||||||
|
plt.rcParams["figure.facecolor"] = black # figure face color
|
||||||
|
plt.rcParams["figure.edgecolor"] = black # figure edge color
|
||||||
|
plt.rcParams["savefig.facecolor"] = black # figure face color when saving
|
||||||
|
|
||||||
|
return style
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
s = PlotStyle()
|
||||||
|
|
||||||
|
import matplotlib.cbook as cbook
|
||||||
|
import matplotlib.cm as cm
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
|
from matplotlib.patches import PathPatch
|
||||||
|
from matplotlib.path import Path
|
||||||
|
|
||||||
|
# Fixing random state for reproducibility
|
||||||
|
np.random.seed(19680801)
|
||||||
|
|
||||||
|
delta = 0.025
|
||||||
|
x = y = np.arange(-3.0, 3.0, delta)
|
||||||
|
X, Y = np.meshgrid(x, y)
|
||||||
|
Z1 = np.exp(-(X**2) - Y**2)
|
||||||
|
Z2 = np.exp(-((X - 1) ** 2) - (Y - 1) ** 2)
|
||||||
|
Z = (Z1 - Z2) * 2
|
||||||
|
|
||||||
|
fig1, ax = plt.subplots()
|
||||||
|
im = ax.imshow(
|
||||||
|
Z,
|
||||||
|
interpolation="bilinear",
|
||||||
|
cmap=cm.RdYlGn,
|
||||||
|
origin="lower",
|
||||||
|
extent=[-3, 3, -3, 3],
|
||||||
|
vmax=abs(Z).max(),
|
||||||
|
vmin=-abs(Z).max(),
|
||||||
|
)
|
||||||
|
|
||||||
|
plt.show()
|
||||||
|
|
||||||
|
fig, axs = plt.subplots(nrows=1, ncols=2, figsize=(9, 4))
|
||||||
|
|
||||||
|
# Fixing random state for reproducibility
|
||||||
|
np.random.seed(19680801)
|
||||||
|
|
||||||
|
# generate some random test data
|
||||||
|
all_data = [np.random.normal(0, std, 100) for std in range(6, 10)]
|
||||||
|
|
||||||
|
# plot violin plot
|
||||||
|
axs[0].violinplot(all_data, showmeans=False, showmedians=True)
|
||||||
|
axs[0].set_title("Violin plot")
|
||||||
|
|
||||||
|
# plot box plot
|
||||||
|
axs[1].boxplot(all_data)
|
||||||
|
axs[1].set_title("Box plot")
|
||||||
|
|
||||||
|
# adding horizontal grid lines
|
||||||
|
for ax in axs:
|
||||||
|
ax.yaxis.grid(True)
|
||||||
|
ax.set_xticks(
|
||||||
|
[y + 1 for y in range(len(all_data))],
|
||||||
|
labels=["x1", "x2", "x3", "x4"],
|
||||||
|
)
|
||||||
|
ax.set_xlabel("Four separate samples")
|
||||||
|
ax.set_ylabel("Observed values")
|
||||||
|
|
||||||
|
plt.show()
|
||||||
|
|
||||||
|
# Fixing random state for reproducibility
|
||||||
|
np.random.seed(19680801)
|
||||||
|
|
||||||
|
# Compute pie slices
|
||||||
|
N = 20
|
||||||
|
theta = np.linspace(0.0, 2 * np.pi, N, endpoint=False)
|
||||||
|
radii = 10 * np.random.rand(N)
|
||||||
|
width = np.pi / 4 * np.random.rand(N)
|
||||||
|
colors = cmo.cm.haline(radii / 10.0)
|
||||||
|
|
||||||
|
ax = plt.subplot(projection="polar")
|
||||||
|
ax.bar(theta, radii, width=width, bottom=0.0, color=colors, alpha=0.5)
|
||||||
|
|
||||||
|
plt.show()
|
||||||
|
|
||||||
|
methods = [
|
||||||
|
None,
|
||||||
|
"none",
|
||||||
|
"nearest",
|
||||||
|
"bilinear",
|
||||||
|
"bicubic",
|
||||||
|
"spline16",
|
||||||
|
"spline36",
|
||||||
|
"hanning",
|
||||||
|
"hamming",
|
||||||
|
"hermite",
|
||||||
|
"kaiser",
|
||||||
|
"quadric",
|
||||||
|
"catrom",
|
||||||
|
"gaussian",
|
||||||
|
"bessel",
|
||||||
|
"mitchell",
|
||||||
|
"sinc",
|
||||||
|
"lanczos",
|
||||||
|
]
|
||||||
|
|
||||||
|
# Fixing random state for reproducibility
|
||||||
|
np.random.seed(19680801)
|
||||||
|
|
||||||
|
grid = np.random.rand(4, 4)
|
||||||
|
|
||||||
|
fig, axs = plt.subplots(
|
||||||
|
nrows=3,
|
||||||
|
ncols=6,
|
||||||
|
figsize=(9, 6),
|
||||||
|
subplot_kw={"xticks": [], "yticks": []},
|
||||||
|
)
|
||||||
|
|
||||||
|
for ax, interp_method in zip(axs.flat, methods):
|
||||||
|
ax.imshow(grid, interpolation=interp_method)
|
||||||
|
ax.set_title(str(interp_method))
|
||||||
|
|
||||||
|
plt.tight_layout()
|
||||||
|
plt.show()
|
@ -726,8 +726,8 @@ def chirpdetection(datapath: str, plot: str, debug: str = "false") -> 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_index = (3 * 60 * 60 + 6 * 60 + 43.5) * data.raw_rate
|
# window_start_index = (3 * 60 * 60 + 6 * 60 + 43.5) * data.raw_rate
|
||||||
window_duration_index = 60 * data.raw_rate
|
# window_duration_index = 60 * data.raw_rate
|
||||||
|
|
||||||
# t0 = 0
|
# t0 = 0
|
||||||
# dt = data.raw.shape[0]
|
# dt = data.raw.shape[0]
|
||||||
|
@ -9,3 +9,78 @@ PyYAML==6.0
|
|||||||
scipy==1.10.1
|
scipy==1.10.1
|
||||||
scp==0.14.5
|
scp==0.14.5
|
||||||
tqdm==4.65.0
|
tqdm==4.65.0
|
||||||
|
asttokens==2.2.1
|
||||||
|
astunparse==1.6.3
|
||||||
|
audioio==0.10.0
|
||||||
|
backcall==0.2.0
|
||||||
|
bcrypt==4.0.1
|
||||||
|
cffi==1.15.1
|
||||||
|
cmocean==3.0.3
|
||||||
|
comm==0.1.3
|
||||||
|
contourpy==1.0.7
|
||||||
|
cryptography==40.0.2
|
||||||
|
cycler==0.11.0
|
||||||
|
debugpy==1.6.7
|
||||||
|
decorator==5.1.1
|
||||||
|
execnb==0.1.5
|
||||||
|
executing==1.2.0
|
||||||
|
fastcore==1.5.29
|
||||||
|
fonttools==4.39.3
|
||||||
|
ghapi==1.0.3
|
||||||
|
ipykernel==6.22.0
|
||||||
|
ipython==8.12.0
|
||||||
|
jedi==0.18.2
|
||||||
|
joblib==1.2.0
|
||||||
|
jupyter_client==8.2.0
|
||||||
|
jupyter_core==5.3.0
|
||||||
|
kiwisolver==1.4.4
|
||||||
|
matplotlib==3.7.1
|
||||||
|
matplotlib-inline==0.1.6
|
||||||
|
nbdev==2.3.12
|
||||||
|
nest-asyncio==1.5.6
|
||||||
|
numpy==1.24.2
|
||||||
|
packaging==23.1
|
||||||
|
pandas==2.0.0
|
||||||
|
paramiko==3.1.0
|
||||||
|
parso==0.8.3
|
||||||
|
pexpect==4.8.0
|
||||||
|
pickleshare==0.7.5
|
||||||
|
Pillow==9.5.0
|
||||||
|
platformdirs==3.3.0
|
||||||
|
prompt-toolkit==3.0.38
|
||||||
|
psutil==5.9.5
|
||||||
|
ptyprocess==0.7.0
|
||||||
|
pure-eval==0.2.2
|
||||||
|
pycparser==2.21
|
||||||
|
Pygments==2.15.1
|
||||||
|
PyNaCl==1.5.0
|
||||||
|
pyparsing==3.0.9
|
||||||
|
PyQt5==5.15.9
|
||||||
|
PyQt5-Qt5==5.15.2
|
||||||
|
PyQt5-sip==12.12.1
|
||||||
|
PyQt6==6.5.0
|
||||||
|
PyQt6-Qt6==6.5.0
|
||||||
|
PyQt6-sip==13.5.1
|
||||||
|
PySide2==5.13.2
|
||||||
|
PySide6==6.5.0
|
||||||
|
PySide6-Addons==6.5.0
|
||||||
|
PySide6-Essentials==6.5.0
|
||||||
|
python-dateutil==2.8.2
|
||||||
|
pytz==2023.3
|
||||||
|
PyYAML==6.0
|
||||||
|
pyzmq==25.0.2
|
||||||
|
scikit-learn==1.2.2
|
||||||
|
scipy==1.10.1
|
||||||
|
scp==0.14.5
|
||||||
|
shiboken2==5.13.2
|
||||||
|
shiboken6==6.5.0
|
||||||
|
six==1.16.0
|
||||||
|
stack-data==0.6.2
|
||||||
|
threadpoolctl==3.1.0
|
||||||
|
thunderfish==1.9.10
|
||||||
|
tornado==6.3.1
|
||||||
|
tqdm==4.65.0
|
||||||
|
traitlets==5.9.0
|
||||||
|
tzdata==2023.3
|
||||||
|
watchdog==3.0.0
|
||||||
|
wcwidth==0.2.6
|
||||||
|
Loading…
Reference in New Issue
Block a user