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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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,,