Skip to content

Commit

Permalink
Merge df8fae9 into da8c021
Browse files Browse the repository at this point in the history
  • Loading branch information
tillraab committed Jul 7, 2016
2 parents da8c021 + df8fae9 commit dfca7e7
Show file tree
Hide file tree
Showing 5 changed files with 194 additions and 60 deletions.
40 changes: 25 additions & 15 deletions thunderfish/consistentfishes.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,25 @@
"""
Functions to compare fishlists created by the harmonicgroups.py module in order to create a create a fishlist with only
these fishes available in all fishlists.
consistent_fishes(): Compares a list of fishlists and builds a consistent fishlist.
"""

import numpy as np
import harmonicgroups as hg


def find_consistency(fundamentals, df_th=1.):
"""
Compares several lists to find values that are, with a certain threshhold, available in every list.
Compares lists of floats to find these values consistent in every list. (with a certain threshold)
This function gets a list of lists conatining values as input. For every value in the first list this function is
looking in the other lists if there is a entry with the same value +- threshold. The vector consistancy_help
has the length of the first list of fundamentals and it's entries are all ones. When a value from the first list is
also available in another list this function adds 1 to that particular entry in the consostany_help vector. After
comparina all values from the first list with all values of the other lists the consostancy_help vector got values
between 1 and len(fundamentals). The indices where this vector is equal to len(fundamentals) are also the indices of
fishes in the first fishlist that are available in every fishlist.
Every value of the first list is compared to the values of the other lists. The consistency_help array consists in
the beginning of ones, has the same length as the first list and is used to keep the information about values that
are available in several lists. If the difference between a value of the first list and a value of another list is
below the threshold the entry of the consistency_help array is added 1 to at the index of the value in the value in
the first list. The indices of the consistency_help array that are equal to the amount of lists compared are the
indices of the values of the first list that are consistent in all lists. The consistent value array and the indices
are returned.
:param fundamentals: (2-D array) list of lists containing the fundamentals of a fishlist.
Expand All @@ -38,7 +45,7 @@ def find_consistency(fundamentals, df_th=1.):

def consistent_fishes_plot(fishlists, filtered_fishlist, ax, fs):
"""
Creates an axis for plotting to visualize what this modul did.
Creates an axis for plotting all lists and the consistent values marked with a bar.
:param filtered_fishlist: (3-D array) Contains power and frequency of these fishes that hve been detected in
several powerspectra using different resolutions.
Expand All @@ -64,10 +71,11 @@ def consistent_fishes_plot(fishlists, filtered_fishlist, ax, fs):
ax.set_xlabel('list no.', fontsize=fs)


def consistent_fishes_psd_plot(filtered_fishlist, ax):
def consistent_fishes_psd_plot(filtered_fishlist, ax, max_freq= 3000):
"""
This function can be passed to the consistent fishes plot as plot_data_func. It's purpose is to plot the four most
powerfull fundamental frequencies into a powerspectrum plot.
Creates an axis for plotting the power of the four most powerful detected fishes with its fundamental and harmonics.
The axis passed to this function should already contain the plotted power-spectrum in dB.
:param filtered_fishlist: (3-D array) Contains power and frequency of these fishes that hve been detected in
several powerspectra using different resolutions.
Expand All @@ -83,14 +91,16 @@ def consistent_fishes_psd_plot(filtered_fishlist, ax):
x = np.array([filtered_fishlist[fish][harmonic][0] for harmonic in range(len(filtered_fishlist[fish]))])
y = np.array([filtered_fishlist[fish][harmonic][1] for harmonic in range(len(filtered_fishlist[fish]))])
y[y < 1e-20] = np.nan
ax.plot(x, 10.0 * np.log10(y), 'o', markersize=8, label='%.1f' % filtered_fishlist[fish][0][0])
ax.plot(x[x < max_freq], 10.0 * np.log10(y[x < max_freq]), 'o', markersize=8, label='%.1f' % filtered_fishlist[fish][0][0])
ax.legend(loc='upper right', frameon=False, numpoints=1)


def consistent_fishes(fishlists, verbose=0, plot_data_func=None, **kwargs):
"""
This function gets several fishlists, compares them, and gives back one fishlist that only contains these fishes
that are available in every given fishlist. This is the main function that calls the other functions in the code.
Compares several fishlists to create a fishlist only containing these fishes present in all these fishlists.
Therefore several functions are used to first extract the fundamental frequencies of every fish in each fishlist,
before comparing them and building a fishlist only containing these fishes present in all fishlists.
:param fishlists: (4-D array) List of fishlists with harmonics and each frequency and power.
fishlists[fishlist][fish][harmonic][frequency, power]
Expand Down
3 changes: 2 additions & 1 deletion thunderfish/create_parallel_jobs.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import numpy as np
import glob
import sys
import os

if __name__ == '__main__':

Expand All @@ -15,7 +16,7 @@
job_name = 'parallel_jobs_for_' + folders[-2] + '_' + folders[-1] + '.txt'

rec_dir = sys.argv[1]
rec_files = glob.glob(os.path.join(rec_dir, '*')
rec_files = glob.glob(os.path.join(rec_dir, '*'))

task_list = ['python thunderfish.py ' + e for e in rec_files]
if len(task_list) > 0:
Expand Down
16 changes: 13 additions & 3 deletions thunderfish/eodanalysis.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,23 @@
"""
Detects EODs in a given dataset and computes their mean waveform.
eod_waveform(): calculates a mean EOD of a given dataset.
"""

import numpy as np
import peakdetection as pkd


def eod_waveform(data, samplerate, th_factor=0.8, percentile=0.1, start=None, stop=None):
"""Detects EODs in the given data and computes their mean waveform.
"""Detects EODs in the given data, extracts data snippets around each EOD and computes a mean waveform with standard
deviation.
:param data: (1-D array) the data to be analysed.
:param samplerate: (float) samplerate of the data in Hertz.
:param percentile: (int). percentile parameter for the peakdetection.percentile_threshold() function used to estimate thresholds for detecting EOD peaks in the data.
:param th_factor: (float). th_factor parameter for the peakdetection.percentile_threshold() function used to estimate thresholds for detecting EOD peaks in the data.
:param percentile: (int). percentile parameter for the peakdetection.percentile_threshold() function used to
estimate thresholds for detecting EOD peaks in the data.
:param th_factor: (float). th_factor parameter for the peakdetection.percentile_threshold() function used to
estimate thresholds for detecting EOD peaks in the data.
:param start: (float or None) start time of EOD snippets relative to peak.
:param stop: (float or None) stop time of EOD snippets relative to peak.
:return mean_eod (1-D array) Average of the EOD snippets.
Expand Down Expand Up @@ -64,6 +73,7 @@ def eod_waveform_plot(time, mean_eod, std_eod, ax, unit='a.u.'):
ax.set_xlabel('Time [msec]')
ax.set_ylabel('Amplitude [%s]' % unit)
ax.set_xlim(1000.0*min(time), max(1000.0*time))
ax.legend(loc='upper right', frameon=False)


if __name__ == '__main__':
Expand Down
29 changes: 11 additions & 18 deletions thunderfish/powerspectrum.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
"""
Functions to calculate a powerspectrum o n the basis of a given dataset, a given samplingrate and a given
frequencyresolution for the psd.
multi_resolution_psd(): Performs the steps to calculate a powerspectrum.
"""

import numpy as np
Expand All @@ -15,16 +18,6 @@ def next_power_of_two(n):
return int(2 ** np.floor(np.log(n) / np.log(2.0) + 1.0-1e-8))


def nfft(freq_resolution, samplerate):
"""The required number of points for an FFT to achieve a minimum frequency resolution.
:param freq_resolution: (float) the minimum required frequency resolution in Hertz.
:param samplerate: (float) the sampling rate of the data in Hert.
:return nfft: (int) the number of FFT points
"""
return next_power_of_two(samplerate / fresolution)


def nfft_noverlap(freq_resolution, samplerate, overlap_frac, min_nfft=0):
"""The required number of points for an FFT to achieve a minimum frequency resolution
and the number of overlapping data points.
Expand All @@ -48,8 +41,7 @@ def psd(data, samplerate, fresolution, detrend=mlab.detrend_none,
sides='default', scale_by_freq=None):
"""Power spectrum density of a given frequency resolution.
From the requested frequency resolution and the samplerate
nfft is computed.
From the requested frequency resolution and the samplerate nfft is computed.
:param data: (1-D array) data array you want to calculate a psd of.
:param samplerate: (float) sampling rate of the data in Hertz.
Expand All @@ -68,7 +60,7 @@ def psd(data, samplerate, fresolution, detrend=mlab.detrend_none,

def plot_decibel_psd(power, freqs, ax, max_freq=3000, fs=12, color='blue', alpha=1.):
"""
Plots a powerspectum in decibel.
Plots the powerspectum in decibel.
:param power: (1-D array) power array of a psd.
:param freqs: (1-D array) frequency array of a psd.
Expand All @@ -81,19 +73,20 @@ def plot_decibel_psd(power, freqs, ax, max_freq=3000, fs=12, color='blue', alpha
decibel_psd = power.copy()
decibel_psd[decibel_psd < 1e-20] = np.nan
decibel_psd[decibel_psd >= 1e-20] = 10.0 * np.log10(decibel_psd[decibel_psd >= 1e-20])
ax.plot(freqs, decibel_psd, color=color, alpha=alpha)
ax.plot(freqs[freqs < max_freq], decibel_psd[freqs < max_freq], color=color, alpha=alpha)
ax.set_ylabel('Power [dB]', fontsize=fs)
ax.set_xlabel('Frequency [Hz]', fontsize=fs)
ax.set_xlim([0, max_freq])


def multi_resolution_psd(data, samplerate, fresolution=0.5,
detrend=mlab.detrend_none, window=mlab.window_hanning,
overlap=0.5, pad_to=None, sides='default',
scale_by_freq=None):
"""This function is performing the steps to calculate a powerspectrum on the basis of a given dataset, a given
samplingrate and a given frequencyresolution for the psd. Therefore two other functions are called to first
calculate the nfft value and second calculate the powerspectrum.
"""Performs the steps to calculate a powerspectrum on the basis of a given dataset, a given samplingrate and a given
frequencyresolution for the psd.
Two other functions are called to first calculate the nfft value and second calculate the powerspectrum. The given
frequencyresolution can be a float or a list/array of floats.
(for further argument information see numpy.psd documentation)
:param data: (1-D array) data array you want to calculate a psd of.
Expand Down
Loading

0 comments on commit dfca7e7

Please sign in to comment.