File: pgauss.py

package info (click to toggle)
python-ltfatpy 1.1.2-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 41,412 kB
  • sloc: ansic: 8,546; python: 6,470; makefile: 15
file content (205 lines) | stat: -rw-r--r-- 7,183 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
# -*- coding: utf-8 -*-
# ######### COPYRIGHT #########
# Credits
# #######
#
# Copyright(c) 2015-2025
# ----------------------
#
# * `LabEx Archimède <http://labex-archimede.univ-amu.fr/>`_
# * `Laboratoire d'Informatique Fondamentale <http://www.lif.univ-mrs.fr/>`_
#   (now `Laboratoire d'Informatique et Systèmes <http://www.lis-lab.fr/>`_)
# * `Institut de Mathématiques de Marseille <http://www.i2m.univ-amu.fr/>`_
# * `Université d'Aix-Marseille <http://www.univ-amu.fr/>`_
#
# This software is a port from LTFAT 2.1.0 :
# Copyright (C) 2005-2025 Peter L. Soendergaard <peter@sonderport.dk>.
#
# Contributors
# ------------
#
# * Denis Arrivault <contact.dev_AT_lis-lab.fr>
# * Florent Jaillet <contact.dev_AT_lis-lab.fr>
#
# Description
# -----------
#
# ltfatpy is a partial Python port of the
# `Large Time/Frequency Analysis Toolbox <http://ltfat.sourceforge.net/>`_,
# a MATLAB®/Octave toolbox for working with time-frequency analysis and
# synthesis.
#
# Version
# -------
#
# * ltfatpy version = 1.1.2
# * LTFAT version = 2.1.0
#
# Licence
# -------
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
# ######### COPYRIGHT #########


"""This module contains sampled, periodized Gaussian window function

Ported from ltfat_2.1.0/fourier/pgauss.m

.. moduleauthor:: Denis Arrivault
"""

from __future__ import print_function, division

from ltfatpy.comp import comp_pgauss as pg
from ltfatpy.sigproc.normalize import normalize


def pgauss(L, tfr=1.0, fs=0.0, width=0.0, bw=0.0, c_f=0.0, centering='wp',
           delay=0.0, norm='2', **kwargs):
    """Sampled, periodized Gaussian

    - Usage:
        | ``(g, tfr) =  pgauss(L)``
        | ``(g, tfr) =  pgauss(L, tfr, fs, width, bw, c_f, centering, delay,
            norm)``

    - Input parameters:

    :param int L: Length of the output vector.
    :param float tfr: determines the ratio between the effective support
        of **g** and the effective support of the DFT of **g**. If
        :math:`tfr>1` then **g** has a wider support than the DFT of **g**.
        Default is 1.
    :param float fs: Use a sampling rate of **fs** Hz as unit for specifying
        the width, bandwidth, centre frequency and delay of the Gaussian.
        Default is :math:`fs=0` which indicates to measure everything in
        samples.
    :param float width: Set the width of the Gaussian such that it has an
        effective support of **width** samples. This means that
        approx. 96% of the energy or 79% of the area under the graph is
        contained within **width** samples. This corresponds to a -6 db
        cutoff. This is equivalent to calling ``pgauss(L,tfr = s^2/L)``.
        Default is zero, unset.
    :param float bw: As for the **width** argument, but specifies the width
        in the frequency domain. The bandwidth is measured in normalized
        frequencies, unless the **fs** value is given. Default is zero, unset.
    :param float c_f: Set the centre frequency of the Gaussian to **cf**.
        Default is zero.
    :param str centering: "wp" means output is whole point even. This is the
        default. Setting it to **hp** means output is half point even which
        is the case for the most Matlab filters routines.
    :param float delay: Delay the output by **delay**. Default is zero.
    :param str norm: normalization to apply (default is L2)


    - Normalization types :

                 +-------+---------+
                 | Name  | Norms   |
                 +=======+=========+
                 | '1'   | L1-norm |
                 +-------+---------+
                 | '2'   | L2-norm |
                 +-------+---------+

    - Output parameters:

    :returns: ``(g, tfr)``
    :rtype: tuple
    :var numpy array g: window array of length **L**
    :var int tfr: ratio between the effective support of **g** and the
        effective support of the DFT of **g**.

    ``pgauss(L,tfr)`` samples of a periodized Gaussian. The function returns
    a numpy array **g** containing a regular sampling of the periodization of
    the function :math:`\\exp(-\\pi*(x^2/tfr))`.

    The :math:`l^2` norm of the returned Gaussian is equal to 1.

    The function is whole-point even. This implies that
    ``fft(pgauss(L, tfr))`` is real for any **L** and **tfr**. The DFT of
    **g** is equal to ``pgauss(L, 1/tfr)``.

    If this function is used to generate a window for a Gabor frame, then
    the window giving the smallest frame bound ratio is generated by
    ``pgauss(L, a*M/L)``.

    - Examples:

    >>> import numpy as np
    >>> import matplotlib.pyplot as plt
    >>> from ltfatpy import sgram
    >>> # This example creates a Gaussian function, and demonstrates that it is
    >>> # its own Discrete Fourier Transform:
    >>> g = pgauss(128)[0]
    >>> # Test of DFT invariance: Should be close to zero.
    >>> np.linalg.norm(g - np.fft.fft(g)/np.sqrt(128)) <= 1e-10
    True
    >>> # The next plot shows the Gaussian in the time domain:
    >>> _ = plt.plot(np.fft.fftshift(g))
    >>> plt.show()
    >>> # The next plot shows the Gaussian in the time-frequency plane:
    >>> _ = sgram(g, nf=True, tc=True, normalization='lin')
    >>> plt.show()

    .. image:: images/pgauss_1.png
       :width: 700px
       :alt: Gaussian in the time domain
       :align: center
    .. image:: images/pgauss_2.png
       :width: 700px
       :alt: Gaussian in the time-frequency plane
       :align: center

    .. note:: **g** is real if **c_f** = 0 and complex if not.

    .. seealso:: :func:`~ltfatpy.gabor.dgtlength.dgtlength`,
        :func:`~ltfatpy.fourier.psech.psech`,
        :func:`~ltfatpy.sigproc.firwin.firwin`, :func:`pbspline`,
        :func:`~ltfatpy.sigproc.normalize.normalize`
    """
    cent = 0
    if centering == 'hp':
        cent = 0.5
    elif centering != 'wp':
        raise ValueError("centering should be 'wp' or 'hp'")
    if (type(L) is not int or L <= 0):
        raise TypeError("L should be non null integer")
    if(type(tfr) is int):
        tfr = float(tfr)
    if (type(tfr) is not float):
        raise TypeError("tfr should be float")

    if fs == 0:
        if width != 0:
            tfr = width**2 / L
        if bw != 0:
            tfr = L / (bw * L/2)**2
    else:
        if width != 0:
            tfr = (width * fs)**2 / L
        if bw != 0:
            tfr = L / (bw / fs * L)**2
        delay = delay*fs
        c_f = c_f/fs*L

    g = pg.comp_pgauss(L, tfr, cent-delay, c_f)
    g = normalize(g, norm)[0]
    return(g, tfr)

if __name__ == '__main__':  # pragma: no cover
    import doctest
    doctest.testmod()