def test_bound(): assert helpers.bound(-1, [0, 1]) == 0 and helpers.bound(2, [0, 1]) == 1
def pulse_finder_species_set(spec, species_df, window_len="from_df", plot=False): """ perform windowed pulse finding (ribbit) on one file for each species in a set Args: spec: opensoundscape.Spectrogram object species_df: a dataframe describing species by their pulsed calls. columns: species | pulse_rate_low (Hz)| pulse_rate_high (Hz) | low_f (Hz)| high_f (Hz)| reject_low (Hz)| reject_high (Hz) | window_length (sec) (optional) | reject_low2 (opt) | reject_high2 | window_len: length of analysis window, in seconds. Or 'from_df' (default): read from dataframe. or 'dynamic': adjust window size based on pulse_rate Returns: the same dataframe with a "score" (max score) column and "time_of_score" column """ species_df = species_df.copy() species_df = species_df.set_index(species_df.columns[0], drop=True) species_df["score"] = [[] for i in range(len(species_df))] species_df["t"] = [[] for i in range(len(species_df))] species_df["max_score"] = [np.nan for i in range(len(species_df))] for i, row in species_df.iterrows(): # we can't analyze pulse rates of 0 or NaN if isNan(row.pulse_rate_low) or row.pulse_rate_low == 0: # cannot analyze continue pulse_rate_range = [row.pulse_rate_low, row.pulse_rate_high] if window_len == "from_df": window_len = row.window_length elif window_len == "dynamic": # dynamically choose the window length based on the species pulse-rate # try to capture ~4-10 pulses min_len = 0.5 # sec max_len = 10 # sec target_n_pulses = 5 window_len = bound( target_n_pulses / pulse_rate_range[0], [min_len, max_len] ) # otherwise, use the numerical value provided for window length signal_band = [row.low_f, row.high_f] # changed from low_f, high_f noise_bands = None if not isNan(row.reject_low): noise_bands = [[row.reject_low, row.reject_high]] if "reject_low2" in species_df.columns and not isNan(row.reject_low2): noise_bands.append([row.reject_low2, row.reject_high2]) # score this species for each window using ribbit if plot: print(f"{row.name}") pulse_scores, window_start_times = ribbit( spec, signal_band, pulse_rate_range, window_len, noise_bands, plot ) # add the scores to the species df species_df.at[i, "score"] = pulse_scores species_df.at[i, "t"] = window_start_times species_df.at[i, "max_score"] = ( max(pulse_scores) if len(pulse_scores) > 0 else np.nan ) species_df.at[i, "time_of_max_score"] = ( window_start_times[np.argmax(pulse_scores)] if len(pulse_scores) > 0 else np.nan ) return species_df