Source code for sage.data.waveform.taper

#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""
Filename        : taper.py
Description     : Short description of the file

Created on 2026-02-08 00:45:34

__author__        = Narenraju Nagarajan
__copyright__     = Copyright 2026, ProjectName
__license__       = MIT Licence
__version__       = 0.0.1
__maintainer__    = Narenraju Nagarajan
__affiliation__   = N/A
__email__         = N/A
__status__        = ['inProgress', 'Archived', 'inUsage', 'Debugging']


GitHub Repository: NULL

Documentation: NULL

"""

# Packages
import torch


def _taper(x, width):
    """
    Smooth sigmoid-like taper function for frequency-domain windowing.

    Maps distance ``x`` from a boundary into a ``[0, 1]`` weight using the
    Planck taper formula ``1 / (1 + exp(z))``.  Returns 0 at ``x=0`` and
    approaches 1 as ``x → width-1``.

    Parameters
    ----------
    x : torch.Tensor, shape ``(B, F)``
        Distance from the boundary in frequency bins (must be ≥ 0).
    width : float or torch.Tensor
        Taper width in frequency bins.

    Returns
    -------
    torch.Tensor, shape ``(B, F)``
        Taper weights in ``[0, 1]``.
    """
    eps = 1e-12
    x = torch.clamp(x, min=eps)
    w = width - 1.0
    z = w / x + w / (x - w)
    return 1.0 / (1.0 + torch.exp(z))


[docs] def fd_low_freq_taper(f, f_min, df, width_bins): """ Smooth low-frequency roll-on taper in the frequency domain. Returns 0 below ``f_min``, smoothly rises to 1 over ``width_bins`` frequency bins, and stays 1 above that range. Parameters ---------- f : torch.Tensor Frequency array (Hz). f_min : float Frequency at which the taper starts rising. df : float Frequency bin spacing (Hz). width_bins : int Number of bins over which the taper rises from 0 to 1. Returns ------- torch.Tensor Multiplicative taper weights, same shape as ``f``. """ x = (f - f_min) / df w = width_bins - 1.0 # Apply formula only in (0, w), 0 below, 1 above return torch.where( x <= 0, torch.zeros_like(x), torch.where(x >= w, torch.ones_like(x), _taper(x, width_bins)), )
[docs] def fd_high_freq_taper(f, f_cut, df, width_bins): """ Smooth high-frequency roll-off taper in the frequency domain. Returns 1 below ``f_cut - width_bins*df``, smoothly falls to 0 over ``width_bins`` bins, and stays 0 above ``f_cut``. Parameters ---------- f : torch.Tensor Frequency array (Hz). f_cut : float Frequency at which the taper completes its roll-off. df : float Frequency bin spacing (Hz). width_bins : int Number of bins over which the taper falls from 1 to 0. Returns ------- torch.Tensor Multiplicative taper weights, same shape as ``f``. """ x = (f_cut - f) / df w = width_bins - 1.0 # Apply formula only in (0, w), 0 beyond cut, 1 before taper start return torch.where( x <= 0, torch.zeros_like(x), torch.where(x >= w, torch.ones_like(x), _taper(x, width_bins)), )
[docs] def fd_taper( f, f_min, f_cut, df, low_width=64, high_width=64, ): """ Combined low- and high-frequency band-pass taper. Multiplies a low-frequency roll-on and a high-frequency roll-off to produce a smooth band-pass window that is 0 outside ``[f_min, f_cut]`` and 1 in the interior of that band. Parameters ---------- f : torch.Tensor Frequency array (Hz), shape ``(B, F)`` or ``(F,)``. f_min : float Lower frequency edge (Hz). f_cut : float Upper frequency cutoff (Hz). df : float Frequency bin spacing (Hz). low_width : int Taper width at the low-frequency edge (default 64 bins). high_width : int Taper width at the high-frequency edge (default 64 bins). Returns ------- torch.Tensor Multiplicative taper weights, same shape as ``f``. """ w_lo = fd_low_freq_taper(f, f_min, df, low_width) w_hi = fd_high_freq_taper(f, f_cut, df, high_width) return w_lo * w_hi