pywavelet 0.0.1b0__py3-none-any.whl → 0.1.0__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. pywavelet/__init__.py +1 -1
  2. pywavelet/_version.py +2 -2
  3. pywavelet/logger.py +6 -7
  4. pywavelet/transforms/__init__.py +10 -10
  5. pywavelet/transforms/forward/__init__.py +4 -0
  6. pywavelet/transforms/forward/from_freq.py +80 -0
  7. pywavelet/transforms/forward/from_time.py +66 -0
  8. pywavelet/transforms/forward/main.py +128 -0
  9. pywavelet/transforms/forward/wavelet_bins.py +58 -0
  10. pywavelet/transforms/inverse/__init__.py +3 -0
  11. pywavelet/transforms/inverse/main.py +96 -0
  12. pywavelet/transforms/{from_wavelets/inverse_wavelet_freq_funcs.py → inverse/to_freq.py} +43 -32
  13. pywavelet/transforms/{from_wavelets/inverse_wavelet_time_funcs.py → inverse/to_time.py} +49 -21
  14. pywavelet/transforms/phi_computer.py +152 -0
  15. pywavelet/transforms/types/__init__.py +4 -0
  16. pywavelet/transforms/types/common.py +53 -0
  17. pywavelet/transforms/types/frequencyseries.py +237 -0
  18. pywavelet/transforms/types/plotting.py +341 -0
  19. pywavelet/transforms/types/timeseries.py +280 -0
  20. pywavelet/transforms/types/wavelet.py +374 -0
  21. pywavelet/transforms/types/wavelet_mask.py +34 -0
  22. pywavelet/utils.py +76 -0
  23. pywavelet-0.1.0.dist-info/METADATA +35 -0
  24. pywavelet-0.1.0.dist-info/RECORD +26 -0
  25. {pywavelet-0.0.1b0.dist-info → pywavelet-0.1.0.dist-info}/WHEEL +1 -1
  26. pywavelet/fft_funcs.py +0 -16
  27. pywavelet/likelihood/__init__.py +0 -0
  28. pywavelet/likelihood/likelihood_base.py +0 -9
  29. pywavelet/likelihood/whittle.py +0 -24
  30. pywavelet/transforms/common.py +0 -77
  31. pywavelet/transforms/from_wavelets/__init__.py +0 -25
  32. pywavelet/transforms/to_wavelets/__init__.py +0 -52
  33. pywavelet/transforms/to_wavelets/transform_freq_funcs.py +0 -84
  34. pywavelet/transforms/to_wavelets/transform_time_funcs.py +0 -63
  35. pywavelet/utils/__init__.py +0 -0
  36. pywavelet/utils/fisher_matrix.py +0 -6
  37. pywavelet/utils/snr.py +0 -37
  38. pywavelet/waveform_generator/__init__.py +0 -0
  39. pywavelet/waveform_generator/build_lookup_table.py +0 -0
  40. pywavelet/waveform_generator/generators/__init__.py +0 -2
  41. pywavelet/waveform_generator/generators/functional_waveform_generator.py +0 -33
  42. pywavelet/waveform_generator/generators/lookuptable_waveform_generator.py +0 -15
  43. pywavelet/waveform_generator/generators/rom_waveform_generator.py +0 -0
  44. pywavelet/waveform_generator/waveform_generator.py +0 -14
  45. pywavelet-0.0.1b0.dist-info/METADATA +0 -35
  46. pywavelet-0.0.1b0.dist-info/RECORD +0 -29
  47. {pywavelet-0.0.1b0.dist-info → pywavelet-0.1.0.dist-info}/top_level.txt +0 -0
@@ -1,25 +0,0 @@
1
- from pywavelet import fft_funcs as fft
2
- from pywavelet.transforms.common import phi_vec, phitilde_vec_norm
3
-
4
- from .inverse_wavelet_freq_funcs import inverse_wavelet_freq_helper_fast
5
- from .inverse_wavelet_time_funcs import inverse_wavelet_time_helper_fast
6
-
7
-
8
- def from_wavelet_to_time(wave_in, Nf, Nt, nx=4.0, mult=32):
9
- """fast inverse wavelet transform to time domain"""
10
- mult = min(mult, Nt // 2) # make sure K isn't bigger than ND
11
- phi = phi_vec(Nf, nx=nx, mult=mult) / 2
12
-
13
- return inverse_wavelet_time_helper_fast(wave_in, phi, Nf, Nt, mult)
14
-
15
-
16
- def from_wavelet_to_freq_to_time(wave_in, Nf, Nt, nx=4.0):
17
- """inverse wavlet transform to time domain via fourier transform of frequency domain"""
18
- res_f = from_wavelet_to_freq(wave_in, Nf, Nt, nx)
19
- return fft.irfft(res_f)
20
-
21
-
22
- def from_wavelet_to_freq(wave_in, Nf, Nt, nx=4.0):
23
- """inverse wavelet transform to freq domain signal"""
24
- phif = phitilde_vec_norm(Nf, Nt, nx)
25
- return inverse_wavelet_freq_helper_fast(wave_in, phif, Nf, Nt)
@@ -1,52 +0,0 @@
1
- import numpy as np
2
-
3
- from ... import fft_funcs as fft
4
- from ...logger import logger
5
- from ..common import phi_vec, phitilde_vec_norm
6
- from .transform_freq_funcs import transform_wavelet_freq_helper
7
- from .transform_time_funcs import transform_wavelet_time_helper
8
-
9
-
10
- def from_time_to_wavelet(data, Nf, Nt, nx=4.0, mult=32):
11
- """From time domain data to wavelet domain
12
-
13
- Warning: there can be significant leakage if mult is too small and the
14
- transform is only approximately exact if mult=Nt/2
15
-
16
- Parameters
17
- ----------
18
- data : array_like
19
- Time domain data
20
- Nf : int
21
- Number of frequency bins
22
- Nt : int
23
- Number of time bins
24
- nx : float, optional
25
- Number of standard deviations for the gaussian wavelet, by default 4.
26
- mult : int, optional
27
- Number of time bins to use for the wavelet transform, by default 32
28
- """
29
-
30
- if mult > Nt / 2:
31
- logger.warning(
32
- f"mult={mult} is too large for Nt={Nt}. This may lead to bogus results."
33
- )
34
-
35
- mult = min(mult, Nt // 2) # make sure K isn't bigger than ND
36
- phi = phi_vec(Nf, nx, mult)
37
- wave = transform_wavelet_time_helper(data, Nf, Nt, phi, mult)
38
-
39
- return wave
40
-
41
-
42
- def from_time_to_freq_to_wavelet(data, Nf, Nt, nx=4.0):
43
- """transform time domain data into wavelet domain via fft and then frequency transform"""
44
- data_fft = fft.rfft(data)
45
-
46
- return from_freq_to_wavelet(data_fft, Nf, Nt, nx)
47
-
48
-
49
- def from_freq_to_wavelet(data, Nf, Nt, nx=4.0):
50
- """do the wavelet transform using the fast wavelet domain transform"""
51
- phif = 2 / Nf * phitilde_vec_norm(Nf, Nt, nx)
52
- return transform_wavelet_freq_helper(data, Nf, Nt, phif)
@@ -1,84 +0,0 @@
1
- """helper functions for transform_freq"""
2
- import numpy as np
3
- from numba import njit
4
-
5
- from pywavelet import fft_funcs as fft
6
-
7
-
8
- @njit()
9
- def tukey(data, alpha, N):
10
- """apply tukey window function to data"""
11
- imin = np.int64(alpha * (N - 1) / 2)
12
- imax = np.int64((N - 1) * (1 - alpha / 2))
13
- Nwin = N - imax
14
-
15
- for i in range(0, N):
16
- f_mult = 1.0
17
- if i < imin:
18
- f_mult = 0.5 * (1.0 + np.cos(np.pi * (i / imin - 1.0)))
19
- if i > imax:
20
- f_mult = 0.5 * (1.0 + np.cos(np.pi / Nwin * (i - imax)))
21
- data[i] *= f_mult
22
-
23
-
24
- def transform_wavelet_freq_helper(data, Nf, Nt, phif):
25
- """helper to do the wavelet transform using the fast wavelet domain transform"""
26
- wave = np.zeros((Nt, Nf)) # wavelet wavepacket transform of the signal
27
-
28
- DX = np.zeros(Nt, dtype=np.complex128)
29
- for m in range(0, Nf + 1):
30
- DX_assign_loop(m, Nt, Nf, DX, data, phif)
31
- DX_trans = fft.ifft(DX, Nt)
32
- DX_unpack_loop(m, Nt, Nf, DX_trans, wave)
33
- return wave
34
-
35
-
36
- @njit()
37
- def DX_assign_loop(m, Nt, Nf, DX, data, phif):
38
- """helper for assigning DX in the main loop"""
39
- i_base = Nt // 2
40
- jj_base = m * Nt // 2
41
-
42
- if m == 0 or m == Nf:
43
- # NOTE this term appears to be needed to recover correct constant (at least for m=0), but was previously missing
44
- DX[Nt // 2] = phif[0] * data[m * Nt // 2] / 2.0
45
- DX[Nt // 2] = phif[0] * data[m * Nt // 2] / 2.0
46
- else:
47
- DX[Nt // 2] = phif[0] * data[m * Nt // 2]
48
- DX[Nt // 2] = phif[0] * data[m * Nt // 2]
49
-
50
- for jj in range(jj_base + 1 - Nt // 2, jj_base + Nt // 2):
51
- j = np.abs(jj - jj_base)
52
- i = i_base - jj_base + jj
53
- if m == Nf and jj > jj_base:
54
- DX[i] = 0.0
55
- elif m == 0 and jj < jj_base:
56
- DX[i] = 0.0
57
- elif j == 0:
58
- continue
59
- else:
60
- DX[i] = phif[j] * data[jj]
61
-
62
-
63
- @njit()
64
- def DX_unpack_loop(m, Nt, Nf, DX_trans, wave):
65
- """helper for unpacking fftd DX in main loop"""
66
- if m == 0:
67
- # half of lowest and highest frequency bin pixels are redundant, so store them in even and odd components of m=0 respectively
68
- for n in range(0, Nt, 2):
69
- wave[n, 0] = np.real(DX_trans[n] * np.sqrt(2))
70
- elif m == Nf:
71
- for n in range(0, Nt, 2):
72
- wave[n + 1, 0] = np.real(DX_trans[n] * np.sqrt(2))
73
- else:
74
- for n in range(0, Nt):
75
- if m % 2:
76
- if (n + m) % 2:
77
- wave[n, m] = -np.imag(DX_trans[n])
78
- else:
79
- wave[n, m] = np.real(DX_trans[n])
80
- else:
81
- if (n + m) % 2:
82
- wave[n, m] = np.imag(DX_trans[n])
83
- else:
84
- wave[n, m] = np.real(DX_trans[n])
@@ -1,63 +0,0 @@
1
- """helper functions for transform_time.py"""
2
- import numpy as np
3
- from numba import njit
4
-
5
- from ... import fft_funcs as fft
6
-
7
-
8
- def transform_wavelet_time_helper(
9
- data, Nf: int, Nt: int, phi, mult: int
10
- ) -> np.ndarray:
11
- """helper function to do the wavelet transform in the time domain"""
12
- # the time domain data stream
13
- ND = Nf * Nt
14
-
15
- K = mult * 2 * Nf
16
-
17
- assert len(data) == ND, f"len(data)={len(data)} != Nf*Nt={ND}"
18
-
19
- # windowed data packets
20
- wdata = np.zeros(K)
21
- wave = np.zeros((Nt, Nf)) # wavelet wavepacket transform of the signal
22
- data_pad = np.concatenate((data, data[:K]))
23
-
24
- for i in range(0, Nt):
25
- assign_wdata(i, K, ND, Nf, wdata, data_pad, phi)
26
- wdata_trans = fft.rfft(wdata, K)
27
- pack_wave(i, mult, Nf, wdata_trans, wave)
28
-
29
- return wave
30
-
31
-
32
- @njit()
33
- def assign_wdata(
34
- i: int,
35
- K: int,
36
- ND: int,
37
- Nf: int,
38
- wdata: np.ndarray,
39
- data_pad: np.ndarray,
40
- phi: np.ndarray,
41
- ):
42
- """Assign wdata to be FFT'd in a loop with K extra values on the right to loop."""
43
- jj = (i * Nf - K // 2) % ND # Periodically wrap the data
44
- for j in range(K):
45
- wdata[j] = data_pad[jj] * phi[j] # Apply the window
46
- jj = (jj + 1) % ND # Periodically wrap the data
47
-
48
-
49
- @njit()
50
- def pack_wave(
51
- i: int, mult: int, Nf: int, wdata_trans: np.ndarray, wave: np.ndarray
52
- ):
53
- """pack fftd wdata into wave array"""
54
- if i % 2 == 0 and i < wave.shape[0] - 1:
55
- # m=0 value at even Nt and
56
- wave[i, 0] = np.real(wdata_trans[0]) / np.sqrt(2)
57
- wave[i + 1, 0] = np.real(wdata_trans[Nf * mult]) / np.sqrt(2)
58
-
59
- for j in range(1, Nf):
60
- if (i + j) % 2:
61
- wave[i, j] = -np.imag(wdata_trans[j * mult])
62
- else:
63
- wave[i, j] = np.real(wdata_trans[j * mult])
File without changes
@@ -1,6 +0,0 @@
1
- """ Fisher information matrix in the wavelet domain:
2
-
3
- F[ij] = Sum_{i,j} h_hat[ti, fi][i] h_hat[ti, fi][j] / PSD[ti, fi]
4
-
5
-
6
- """
pywavelet/utils/snr.py DELETED
@@ -1,37 +0,0 @@
1
- """Wavelet domain SNR
2
-
3
- SNR(h) = Sum_{ti,fi} [ h_hat[ti,fi] d[ti,fi] / PSD[ti,fi] ],
4
-
5
- where h_hat[ti,fi] is the unit normalized wavelet transform of the model:
6
- h_hat[ti,fi] = h[ti,fi] / sqrt(<h[ti,fi] | h[ti,fi] >)
7
-
8
- NOTE: to maximize over masses and spins we require some additional steps....
9
-
10
-
11
- """
12
-
13
- import numpy as np
14
-
15
-
16
- def compute_snr(h: np.ndarray, d: np.ndarray, PSD: np.ndarray) -> float:
17
- """Compute the SNR of a model h[ti,fi] given data d[ti,fi] and PSD[ti,fi].
18
-
19
- SNR(h) = Sum_{ti,fi} [ h_hat[ti,fi] d[ti,fi] / PSD[ti,fi]
20
-
21
- Parameters
22
- ----------
23
- h : np.ndarray
24
- The model in the wavelet domain (binned in [ti,fi]).
25
- d : np.ndarray
26
- The data in the wavelet domain (binned in [ti,fi]).
27
- PSD : np.ndarray
28
- The PSD in the wavelet domain (binned in [ti,fi]).
29
-
30
- Returns
31
- -------
32
- float
33
- The SNR of the model h given data d and PSD.
34
-
35
- """
36
- h_hat = h / np.sqrt(np.tensordot(h.T, h))
37
- return np.tensordot(h_hat.T, d / PSD)
File without changes
File without changes
@@ -1,2 +0,0 @@
1
- from .functional_waveform_generator import FunctionalWaveformGenerator
2
- from .lookuptable_waveform_generator import LookupTableWaveformGenerator
@@ -1,33 +0,0 @@
1
- import numpy as np
2
-
3
- from ...transforms import from_time_to_wavelet
4
- from ..waveform_generator import WaveformGenerator
5
-
6
-
7
- class FunctionalWaveformGenerator(WaveformGenerator):
8
- def __init__(self, func, Nf=1024, Nt=1024, mult=32):
9
- super().__init__("Functional")
10
- self.func = func
11
- self.Nf = Nf
12
- self.Nt = Nt
13
- self.mult = mult
14
-
15
- def __call__(self, **params) -> np.ndarray:
16
- """
17
- Generate a waveform from a functional form.
18
-
19
- Parameters
20
- ----------
21
- params: dict
22
- A dictionary of parameters to pass to the functional form.
23
-
24
- Returns
25
- -------
26
- wavelet_signal: np.ndarray
27
- The waveform in the wavelet domain matrix of (Nt, Nf).
28
- """
29
- ht = self.func(**params)
30
- wavelet_signal = from_time_to_wavelet(
31
- ht, Nf=self.Nf, Nt=self.Nt, mult=self.mult
32
- )
33
- return wavelet_signal
@@ -1,15 +0,0 @@
1
- from ...transforms import from_time_to_wavelet
2
- from ..waveform_generator import WaveformGenerator
3
-
4
-
5
- class LookupTableWaveformGenerator(WaveformGenerator):
6
- def __init__(self, name, func, Nf=1024, Nt=1024):
7
- super().__init__(name)
8
- self.func = func
9
- self.Nf = Nf
10
- self.Nt = Nt
11
-
12
- def __call__(self, **params):
13
- time_signal = self.func(**params)
14
- wavelet_signal = from_time_to_wavelet(time_signal, Nf=1024, Nt=1024)
15
- return wavelet_signal
@@ -1,14 +0,0 @@
1
- from abc import ABC, abstractmethod
2
-
3
-
4
- class WaveformGenerator(ABC):
5
- def __init__(self, name):
6
- self.name = name
7
-
8
- @abstractmethod
9
- def __call__(self, **params):
10
- """Call the waveform generator (using the lookup table) with the given parameters."""
11
- pass
12
-
13
- def __repr__(self):
14
- return f"{self.__class__.__name__}(name={self.name})"
@@ -1,35 +0,0 @@
1
- Metadata-Version: 2.1
2
- Name: pywavelet
3
- Version: 0.0.1b0
4
- Summary: WDM wavelet transform your timeseries!
5
- Author-email: Pywavelet Team <pywavelet@gmail.com>
6
- Project-URL: Homepage, https://github.com/pypa/pywavelet
7
- Project-URL: Bug Reports, https://github.com/pypa/pywavelet/issues
8
- Project-URL: Funding, https://donate.pypi.org
9
- Project-URL: Say Thanks!, http://saythanks.io/to/example
10
- Project-URL: Source, https://github.com/pypa/pywavelet/
11
- Classifier: Development Status :: 3 - Alpha
12
- Classifier: Intended Audience :: Science/Research
13
- Classifier: License :: OSI Approved :: MIT License
14
- Classifier: Operating System :: OS Independent
15
- Classifier: Programming Language :: Python :: 3.8
16
- Requires-Python: >=3.8
17
- Description-Content-Type: text/markdown
18
- Requires-Dist: numpy
19
- Requires-Dist: numba
20
- Requires-Dist: matplotlib
21
- Requires-Dist: tqdm
22
- Requires-Dist: loguru
23
- Requires-Dist: bilby
24
- Provides-Extra: dev
25
- Requires-Dist: pytest >=6.0 ; extra == 'dev'
26
- Requires-Dist: pytest-cov >=4.1.0 ; extra == 'dev'
27
- Requires-Dist: pre-commit ; extra == 'dev'
28
- Requires-Dist: flake8 >=5.0.4 ; extra == 'dev'
29
- Requires-Dist: black >=22.12.0 ; extra == 'dev'
30
- Requires-Dist: isort ; extra == 'dev'
31
- Requires-Dist: mypy ; extra == 'dev'
32
- Requires-Dist: pycbc ; extra == 'dev'
33
- Requires-Dist: bilby ; extra == 'dev'
34
- Requires-Dist: jupyter-book ; extra == 'dev'
35
-
@@ -1,29 +0,0 @@
1
- pywavelet/__init__.py,sha256=k153Uh9uMwWTbdIUTBwDQ8okniciXJrIMXbVrQUA05A,53
2
- pywavelet/_version.py,sha256=8kGCB5GtL1bKeIoFN7UDyb7dIVhe1uN9mad-aDiInQs,413
3
- pywavelet/fft_funcs.py,sha256=5Vwugv4iGnHAy2gQwiHRsKby0Ml7HEidrCh5raKs0LE,488
4
- pywavelet/logger.py,sha256=1kOyFvC86npJZUF2sajymxnSF2CrBjWiqsKP858_1xs,315
5
- pywavelet/likelihood/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
- pywavelet/likelihood/likelihood_base.py,sha256=8IA7CV6SuVmTRiYfGmujLQoaUNqpWn_c9EDpMT3sVHQ,159
7
- pywavelet/likelihood/whittle.py,sha256=cEMA1CxiNv3p-InTLJoKXJIesqoZgcTitlOMZFeqceY,685
8
- pywavelet/transforms/__init__.py,sha256=xOvUrH1d0zWzZlxr713_ONwXGJ0JUt1qkUGjfQgG8nc,232
9
- pywavelet/transforms/common.py,sha256=EXJZEwADzhMKFYgSpCYlup3zHbM75_35jc0cIqTPrEw,2034
10
- pywavelet/transforms/from_wavelets/__init__.py,sha256=crkC_i_Rr_lnuK26D9_4j0VIc5fCB0RrZN7qboCIVSE,1008
11
- pywavelet/transforms/from_wavelets/inverse_wavelet_freq_funcs.py,sha256=oMWe7YM6o98NBEgoJuolkwzSotDp-8flg5KLqVeUNLo,2454
12
- pywavelet/transforms/from_wavelets/inverse_wavelet_time_funcs.py,sha256=yrKTcETVzX3BAGovtSSTrMR8BL-bePCeugAf3mpqdYA,4493
13
- pywavelet/transforms/to_wavelets/__init__.py,sha256=pmGgx6zOMKmZBRcpznqoBKkiw6cgLp91X0k7Q8eemVQ,1669
14
- pywavelet/transforms/to_wavelets/transform_freq_funcs.py,sha256=PsFV6wJedJmbZIZ40-47igPxzkxEp0o5aSgQl0pMosA,2759
15
- pywavelet/transforms/to_wavelets/transform_time_funcs.py,sha256=Ijb_od_daKJ3TO2GkfABGnHNhVVkUZfo2RaDIRGQmzw,1775
16
- pywavelet/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
17
- pywavelet/utils/fisher_matrix.py,sha256=QYYlr1K-NR_MWVAfRm1gNVq5iun49ZQ0fNns-PkLEnY,127
18
- pywavelet/utils/snr.py,sha256=qgKu0BgW1MKA5UkI352r_kHFdoOQoLVdmacoc9Ewaoo,990
19
- pywavelet/waveform_generator/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
20
- pywavelet/waveform_generator/build_lookup_table.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
21
- pywavelet/waveform_generator/waveform_generator.py,sha256=IDicy9-IM6u4z60EbAU7tTDDdNk2yty6PU_simFsyJc,372
22
- pywavelet/waveform_generator/generators/__init__.py,sha256=sUuWkQMsJ-cydLioiKUkIG1S0OhJsFTMwIdOJwDF0yo,144
23
- pywavelet/waveform_generator/generators/functional_waveform_generator.py,sha256=1Yte9aWEvZENh8u7XrlAFq5ghJVbSgjAxJgjUhy2nM8,928
24
- pywavelet/waveform_generator/generators/lookuptable_waveform_generator.py,sha256=HC1bJuDa33clb52xu1MM7DFnHwb0qdv0uJM-r0uTxgk,491
25
- pywavelet/waveform_generator/generators/rom_waveform_generator.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
26
- pywavelet-0.0.1b0.dist-info/METADATA,sha256=akrtZZGTKNkBolvoJp1JWxJQmb1tE-yHQla32Fubp2A,1324
27
- pywavelet-0.0.1b0.dist-info/WHEEL,sha256=yQN5g4mg4AybRjkgi-9yy4iQEFibGQmlz78Pik5Or-A,92
28
- pywavelet-0.0.1b0.dist-info/top_level.txt,sha256=g0Ezt0Rg0X-nrd-a0pAXKVRkuWNsF2M9Ynsjb9b2UYQ,10
29
- pywavelet-0.0.1b0.dist-info/RECORD,,