pywavelet 0.2.3__tar.gz → 0.2.5__tar.gz

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 (75) hide show
  1. {pywavelet-0.2.3 → pywavelet-0.2.5}/CHANGELOG.rst +51 -0
  2. {pywavelet-0.2.3 → pywavelet-0.2.5}/PKG-INFO +3 -3
  3. {pywavelet-0.2.3 → pywavelet-0.2.5}/README.rst +2 -2
  4. {pywavelet-0.2.3 → pywavelet-0.2.5}/docs/api.rst +0 -1
  5. {pywavelet-0.2.3 → pywavelet-0.2.5}/docs/example.ipynb +6 -5
  6. {pywavelet-0.2.3 → pywavelet-0.2.5}/src/pywavelet/_version.py +2 -2
  7. {pywavelet-0.2.3 → pywavelet-0.2.5}/src/pywavelet/transforms/jax/forward/from_time.py +18 -10
  8. {pywavelet-0.2.3 → pywavelet-0.2.5}/src/pywavelet/transforms/jax/forward/main.py +6 -10
  9. {pywavelet-0.2.3 → pywavelet-0.2.5}/src/pywavelet/transforms/jax/inverse/to_freq.py +11 -7
  10. {pywavelet-0.2.3 → pywavelet-0.2.5}/src/pywavelet/transforms/numpy/__init__.py +1 -2
  11. {pywavelet-0.2.3 → pywavelet-0.2.5}/src/pywavelet/transforms/numpy/forward/main.py +1 -1
  12. {pywavelet-0.2.3 → pywavelet-0.2.5}/src/pywavelet/transforms/numpy/inverse/main.py +2 -2
  13. {pywavelet-0.2.3 → pywavelet-0.2.5}/src/pywavelet/transforms/phi_computer.py +6 -13
  14. {pywavelet-0.2.3 → pywavelet-0.2.5}/src/pywavelet/types/common.py +4 -3
  15. {pywavelet-0.2.3 → pywavelet-0.2.5}/src/pywavelet/types/frequencyseries.py +1 -1
  16. {pywavelet-0.2.3 → pywavelet-0.2.5}/src/pywavelet/types/timeseries.py +4 -10
  17. {pywavelet-0.2.3 → pywavelet-0.2.5}/src/pywavelet/types/wavelet.py +40 -6
  18. {pywavelet-0.2.3 → pywavelet-0.2.5}/src/pywavelet/types/wavelet_bins.py +0 -1
  19. {pywavelet-0.2.3 → pywavelet-0.2.5}/src/pywavelet/utils.py +2 -0
  20. {pywavelet-0.2.3 → pywavelet-0.2.5}/src/pywavelet.egg-info/PKG-INFO +3 -3
  21. {pywavelet-0.2.3 → pywavelet-0.2.5}/tests/test_mask.py +12 -11
  22. {pywavelet-0.2.3 → pywavelet-0.2.5}/tests/test_phi.py +1 -5
  23. {pywavelet-0.2.3 → pywavelet-0.2.5}/.github/workflows/ci.yml +0 -0
  24. {pywavelet-0.2.3 → pywavelet-0.2.5}/.github/workflows/docs.yml +0 -0
  25. {pywavelet-0.2.3 → pywavelet-0.2.5}/.github/workflows/pypi.yml +0 -0
  26. {pywavelet-0.2.3 → pywavelet-0.2.5}/.gitignore +0 -0
  27. {pywavelet-0.2.3 → pywavelet-0.2.5}/.pre-commit-config.yaml +0 -0
  28. {pywavelet-0.2.3 → pywavelet-0.2.5}/CITATION.cff +0 -0
  29. {pywavelet-0.2.3 → pywavelet-0.2.5}/docs/_config.yml +0 -0
  30. {pywavelet-0.2.3 → pywavelet-0.2.5}/docs/_static/demo.gif +0 -0
  31. {pywavelet-0.2.3 → pywavelet-0.2.5}/docs/_toc.yml +0 -0
  32. {pywavelet-0.2.3 → pywavelet-0.2.5}/docs/index.rst +0 -0
  33. {pywavelet-0.2.3 → pywavelet-0.2.5}/docs/logo.png +0 -0
  34. {pywavelet-0.2.3 → pywavelet-0.2.5}/docs/roundtrip_freq.png +0 -0
  35. {pywavelet-0.2.3 → pywavelet-0.2.5}/docs/roundtrip_time.png +0 -0
  36. {pywavelet-0.2.3 → pywavelet-0.2.5}/pyproject.toml +0 -0
  37. {pywavelet-0.2.3 → pywavelet-0.2.5}/setup.cfg +0 -0
  38. {pywavelet-0.2.3 → pywavelet-0.2.5}/src/pywavelet/__init__.py +0 -0
  39. {pywavelet-0.2.3 → pywavelet-0.2.5}/src/pywavelet/backend.py +0 -0
  40. {pywavelet-0.2.3 → pywavelet-0.2.5}/src/pywavelet/logger.py +0 -0
  41. {pywavelet-0.2.3 → pywavelet-0.2.5}/src/pywavelet/transforms/__init__.py +0 -0
  42. {pywavelet-0.2.3 → pywavelet-0.2.5}/src/pywavelet/transforms/jax/__init__.py +0 -0
  43. {pywavelet-0.2.3 → pywavelet-0.2.5}/src/pywavelet/transforms/jax/forward/__init__.py +0 -0
  44. {pywavelet-0.2.3 → pywavelet-0.2.5}/src/pywavelet/transforms/jax/forward/from_freq.py +0 -0
  45. {pywavelet-0.2.3 → pywavelet-0.2.5}/src/pywavelet/transforms/jax/inverse/__init__.py +0 -0
  46. {pywavelet-0.2.3 → pywavelet-0.2.5}/src/pywavelet/transforms/jax/inverse/main.py +0 -0
  47. {pywavelet-0.2.3 → pywavelet-0.2.5}/src/pywavelet/transforms/numpy/forward/__init__.py +0 -0
  48. {pywavelet-0.2.3 → pywavelet-0.2.5}/src/pywavelet/transforms/numpy/forward/from_freq.py +0 -0
  49. {pywavelet-0.2.3 → pywavelet-0.2.5}/src/pywavelet/transforms/numpy/forward/from_time.py +0 -0
  50. {pywavelet-0.2.3 → pywavelet-0.2.5}/src/pywavelet/transforms/numpy/inverse/__init__.py +0 -0
  51. {pywavelet-0.2.3 → pywavelet-0.2.5}/src/pywavelet/transforms/numpy/inverse/to_freq.py +0 -0
  52. {pywavelet-0.2.3 → pywavelet-0.2.5}/src/pywavelet/transforms/numpy/inverse/to_time.py +0 -0
  53. {pywavelet-0.2.3 → pywavelet-0.2.5}/src/pywavelet/types/__init__.py +0 -0
  54. {pywavelet-0.2.3 → pywavelet-0.2.5}/src/pywavelet/types/plotting.py +0 -0
  55. {pywavelet-0.2.3 → pywavelet-0.2.5}/src/pywavelet.egg-info/SOURCES.txt +0 -0
  56. {pywavelet-0.2.3 → pywavelet-0.2.5}/src/pywavelet.egg-info/dependency_links.txt +0 -0
  57. {pywavelet-0.2.3 → pywavelet-0.2.5}/src/pywavelet.egg-info/requires.txt +0 -0
  58. {pywavelet-0.2.3 → pywavelet-0.2.5}/src/pywavelet.egg-info/top_level.txt +0 -0
  59. {pywavelet-0.2.3 → pywavelet-0.2.5}/tests/conftest.py +0 -0
  60. {pywavelet-0.2.3 → pywavelet-0.2.5}/tests/test_data/roundtrip_chirp_freq.npz +0 -0
  61. {pywavelet-0.2.3 → pywavelet-0.2.5}/tests/test_data/roundtrip_chirp_time.npz +0 -0
  62. {pywavelet-0.2.3 → pywavelet-0.2.5}/tests/test_data/roundtrip_pure_f0_freq.npz +0 -0
  63. {pywavelet-0.2.3 → pywavelet-0.2.5}/tests/test_data/roundtrip_sine_freq.npz +0 -0
  64. {pywavelet-0.2.3 → pywavelet-0.2.5}/tests/test_data/roundtrip_sine_time.npz +0 -0
  65. {pywavelet-0.2.3 → pywavelet-0.2.5}/tests/test_jax.py +0 -0
  66. {pywavelet-0.2.3 → pywavelet-0.2.5}/tests/test_lnl.py +0 -0
  67. {pywavelet-0.2.3 → pywavelet-0.2.5}/tests/test_psd.py +0 -0
  68. {pywavelet-0.2.3 → pywavelet-0.2.5}/tests/test_roundtrip_conversion.py +0 -0
  69. {pywavelet-0.2.3 → pywavelet-0.2.5}/tests/test_snr.py +0 -0
  70. {pywavelet-0.2.3 → pywavelet-0.2.5}/tests/test_timefreq_type.py +0 -0
  71. {pywavelet-0.2.3 → pywavelet-0.2.5}/tests/test_version.py +0 -0
  72. {pywavelet-0.2.3 → pywavelet-0.2.5}/tests/test_wavelet_plot.py +0 -0
  73. {pywavelet-0.2.3 → pywavelet-0.2.5}/tests/utils/__init__.py +0 -0
  74. {pywavelet-0.2.3 → pywavelet-0.2.5}/tests/utils/generate_data.py +0 -0
  75. {pywavelet-0.2.3 → pywavelet-0.2.5}/tests/utils/plotting.py +0 -0
@@ -5,6 +5,48 @@ CHANGELOG
5
5
  =========
6
6
 
7
7
 
8
+ .. _changelog-v0.2.5:
9
+
10
+ v0.2.5 (2025-01-28)
11
+ ===================
12
+
13
+ Bug Fixes
14
+ ---------
15
+
16
+ * fix: filter first then window (#20)
17
+
18
+ * fix: filter first then window
19
+
20
+ * [pre-commit.ci] auto fixes from pre-commit.com hooks
21
+
22
+ for more information, see https://pre-commit.ci
23
+
24
+ ---------
25
+
26
+ Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> (`3228f7b`_)
27
+
28
+ .. _3228f7b: https://github.com/pywavelet/pywavelet/commit/3228f7be0d7efb48812920e822a14e795ebac57f
29
+
30
+
31
+ .. _changelog-v0.2.4:
32
+
33
+ v0.2.4 (2025-01-24)
34
+ ===================
35
+
36
+ Chores
37
+ ------
38
+
39
+ * chore(release): 0.2.4 (`8ea5b2f`_)
40
+
41
+ Unknown
42
+ -------
43
+
44
+ * Merge branch 'main' of github.com:avivajpeyi/pywavelet into main (`d2c84d9`_)
45
+
46
+ .. _8ea5b2f: https://github.com/pywavelet/pywavelet/commit/8ea5b2fc0ffa5a1cb274273ec48e164f8bd2064a
47
+ .. _d2c84d9: https://github.com/pywavelet/pywavelet/commit/d2c84d980b1701baf99e40ba6191cbd9336cfa59
48
+
49
+
8
50
  .. _changelog-v0.2.3:
9
51
 
10
52
  v0.2.3 (2025-01-24)
@@ -13,12 +55,21 @@ v0.2.3 (2025-01-24)
13
55
  Bug Fixes
14
56
  ---------
15
57
 
58
+ * fix: add masks to filter out gaps (`26fe40a`_)
59
+
16
60
  * fix: add backend check for os.environ (`98c0818`_)
17
61
 
18
62
  * fix: add test for jax (`1940394`_)
19
63
 
64
+ Chores
65
+ ------
66
+
67
+ * chore(release): 0.2.3 (`d067461`_)
68
+
69
+ .. _26fe40a: https://github.com/pywavelet/pywavelet/commit/26fe40ace80d5f9d598e1efeba2f8ca4a6f1043b
20
70
  .. _98c0818: https://github.com/pywavelet/pywavelet/commit/98c0818078190d829a23734f932f1f93c9932167
21
71
  .. _1940394: https://github.com/pywavelet/pywavelet/commit/194039437a3a9b3ada303d101b4e2573ab7d0afd
72
+ .. _d067461: https://github.com/pywavelet/pywavelet/commit/d0674615df328774a0d80eb224b5c503fbd8f332
22
73
 
23
74
 
24
75
  .. _changelog-v0.2.2:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pywavelet
3
- Version: 0.2.3
3
+ Version: 0.2.5
4
4
  Summary: WDM wavelet transform your time/freq series!
5
5
  Author-email: Pywavelet Team <avi.vajpeyi@gmail.com>
6
6
  Project-URL: Homepage, https://pywavelet.github.io/pywavelet/
@@ -76,10 +76,10 @@ First set up a conda environment with the latest version of python.
76
76
  Test code
77
77
  ---------
78
78
 
79
- Locate directory /tests from root directory. run
79
+ Locate directory /tests from root directory. run
80
80
 
81
81
  .. code-block::
82
82
 
83
83
  $ pytest .
84
84
 
85
- Hopefully everything should run fine.
85
+ Hopefully everything should run fine.
@@ -39,10 +39,10 @@ First set up a conda environment with the latest version of python.
39
39
  Test code
40
40
  ---------
41
41
 
42
- Locate directory /tests from root directory. run
42
+ Locate directory /tests from root directory. run
43
43
 
44
44
  .. code-block::
45
45
 
46
46
  $ pytest .
47
47
 
48
- Hopefully everything should run fine.
48
+ Hopefully everything should run fine.
@@ -32,4 +32,3 @@ Types
32
32
  .. autoclass:: pywavelet.transforms.types.Wavelet
33
33
  :members:
34
34
  :undoc-members:
35
-
@@ -70,6 +70,7 @@
70
70
  " ax.ticklabel_format(axis=\"x\", style=\"sci\", scilimits=(0, 0))\n",
71
71
  " return ax\n",
72
72
  "\n",
73
+ "\n",
73
74
  "# Sizes\n",
74
75
  "dt = 1 / 512\n",
75
76
  "Nt, Nf = 2**6, 2**6\n",
@@ -88,7 +89,7 @@
88
89
  "# transform back to time domain\n",
89
90
  "h_reconstructed = from_wavelet_to_time(h_wavelet, dt=h_time.dt, mult=mult)\n",
90
91
  "\n",
91
- "# Plots \n",
92
+ "# Plots\n",
92
93
  "fig, axes = plt.subplots(1, 4, figsize=(18, 4))\n",
93
94
  "_ = h_time.plot_spectrogram(ax=axes[0])\n",
94
95
  "_ = h_wavelet.plot(ax=axes[1], absolute=True, cmap=\"Reds\")\n",
@@ -146,7 +147,7 @@
146
147
  "freq = np.fft.rfftfreq(N, dt)\n",
147
148
  "hf = np.zeros_like(freq, dtype=np.complex128)\n",
148
149
  "hf[np.argmin(np.abs(freq - f0))] = 1.0\n",
149
- " \n",
150
+ "\n",
150
151
  "\n",
151
152
  "h_freq = FrequencySeries(data=hf, freq=freq)\n",
152
153
  "h_wavelet = from_freq_to_wavelet(h_freq, Nf=Nf, Nt=Nt)\n",
@@ -154,10 +155,10 @@
154
155
  "\n",
155
156
  "\n",
156
157
  "fig, axes = plt.subplots(1, 2, figsize=(9, 4))\n",
157
- "_ = h_freq.plot(ax=axes[0], label='Original')\n",
158
+ "_ = h_freq.plot(ax=axes[0], label=\"Original\")\n",
158
159
  "_ = h_wavelet.plot(ax=axes[1], absolute=True, cmap=\"Reds\")\n",
159
- "_ = h_reconstructed.plot(ax=axes[0], ls=\":\", label='Reconstructed')\n",
160
- "axes[1].set_ylim(f0-5, f0+5)\n",
160
+ "_ = h_reconstructed.plot(ax=axes[0], ls=\":\", label=\"Reconstructed\")\n",
161
+ "axes[1].set_ylim(f0 - 5, f0 + 5)\n",
161
162
  "axes[0].legend()\n",
162
163
  "fig.savefig(\"roundtrip_freq.png\")\n",
163
164
  "plt.close()"
@@ -12,5 +12,5 @@ __version__: str
12
12
  __version_tuple__: VERSION_TUPLE
13
13
  version_tuple: VERSION_TUPLE
14
14
 
15
- __version__ = version = '0.2.3'
16
- __version_tuple__ = version_tuple = (0, 2, 3)
15
+ __version__ = version = '0.2.5'
16
+ __version_tuple__ = version_tuple = (0, 2, 5)
@@ -1,12 +1,14 @@
1
+ from functools import partial
2
+
1
3
  import jax
2
4
  import jax.numpy as jnp
3
5
  from jax import jit
4
6
  from jax.numpy.fft import rfft
5
- from functools import partial
6
7
 
7
- @partial(jit, static_argnames=('Nf', 'Nt', 'mult'))
8
+
9
+ @partial(jit, static_argnames=("Nf", "Nt", "mult"))
8
10
  def transform_wavelet_time_helper(
9
- data: jnp.ndarray, phi: jnp.ndarray, Nf: int, Nt: int, mult: int
11
+ data: jnp.ndarray, phi: jnp.ndarray, Nf: int, Nt: int, mult: int
10
12
  ) -> jnp.ndarray:
11
13
  """Helper function to do the wavelet transform in the time domain using JAX"""
12
14
  # Define constants
@@ -35,17 +37,23 @@ def transform_wavelet_time_helper(
35
37
  even_indices = jnp.nonzero(even_mask, size=even_mask.shape[0])[0]
36
38
 
37
39
  # Update wave for m=0 using even time bins
38
- wave = wave.at[even_indices, 0].set(jnp.real(wdata_trans[even_indices, 0]) / jnp.sqrt(2))
39
- wave = wave.at[even_indices + 1, 0].set(jnp.real(wdata_trans[even_indices, Nf * mult]) / jnp.sqrt(2))
40
+ wave = wave.at[even_indices, 0].set(
41
+ jnp.real(wdata_trans[even_indices, 0]) / jnp.sqrt(2)
42
+ )
43
+ wave = wave.at[even_indices + 1, 0].set(
44
+ jnp.real(wdata_trans[even_indices, Nf * mult]) / jnp.sqrt(2)
45
+ )
40
46
 
41
47
  # Handle other cases (j > 0) using vectorized operations
42
48
  j_range = jnp.arange(1, Nf)
43
- odd_condition = ((time_bins[:, None] + j_range[None, :]) % 2 == 1)
49
+ odd_condition = (time_bins[:, None] + j_range[None, :]) % 2 == 1
44
50
 
45
51
  wave = wave.at[:, 1:].set(
46
- jnp.where(odd_condition,
47
- -jnp.imag(wdata_trans[:, j_range * mult]),
48
- jnp.real(wdata_trans[:, j_range * mult]))
52
+ jnp.where(
53
+ odd_condition,
54
+ -jnp.imag(wdata_trans[:, j_range * mult]),
55
+ jnp.real(wdata_trans[:, j_range * mult]),
56
+ )
49
57
  )
50
58
 
51
- return wave.T
59
+ return wave.T
@@ -62,10 +62,10 @@ def from_time_to_wavelet(
62
62
 
63
63
  mult = min(mult, Nt // 2) # make sure K isn't bigger than ND
64
64
  phi = jnp.array(phi_vec(Nf, d=nx, q=mult))
65
- wave = transform_wavelet_time_helper(timeseries.data, Nf=Nf, Nt=Nt, phi=phi, mult=mult)
66
- return Wavelet(
67
- wave* jnp.sqrt(2), time=t_bins, freq=f_bins
65
+ wave = transform_wavelet_time_helper(
66
+ timeseries.data, Nf=Nf, Nt=Nt, phi=phi, mult=mult
68
67
  )
68
+ return Wavelet(wave * jnp.sqrt(2), time=t_bins, freq=f_bins)
69
69
 
70
70
 
71
71
  def from_freq_to_wavelet(
@@ -98,13 +98,9 @@ def from_freq_to_wavelet(
98
98
  """
99
99
  Nf, Nt = _preprocess_bins(freqseries, Nf, Nt)
100
100
  t_bins, f_bins = _get_bins(freqseries, Nf, Nt)
101
- phif = jnp.array(phitilde_vec_norm(Nf, Nt, d=nx))
102
- wave = transform_wavelet_freq_helper(
101
+ phif = jnp.array(phitilde_vec_norm(Nf, Nt, d=nx))
102
+ wave = transform_wavelet_freq_helper(
103
103
  freqseries.data, Nf=Nf, Nt=Nt, phif=phif
104
104
  )
105
105
 
106
- return Wavelet(
107
- (2 / Nf) * wave * jnp.sqrt(2),
108
- time=t_bins,
109
- freq=f_bins
110
- )
106
+ return Wavelet((2 / Nf) * wave * jnp.sqrt(2), time=t_bins, freq=f_bins)
@@ -1,14 +1,14 @@
1
+ from functools import partial
2
+
1
3
  import jax
2
4
  import jax.numpy as jnp
3
5
  from jax import jit
4
6
  from jax.numpy.fft import fft
5
7
 
6
- from functools import partial
7
-
8
8
 
9
- @partial(jit, static_argnames=('Nf', 'Nt'))
9
+ @partial(jit, static_argnames=("Nf", "Nt"))
10
10
  def inverse_wavelet_freq_helper(
11
- wave_in: jnp.ndarray, phif: jnp.ndarray, Nf: int, Nt: int
11
+ wave_in: jnp.ndarray, phif: jnp.ndarray, Nf: int, Nt: int
12
12
  ) -> jnp.ndarray:
13
13
  """JAX vectorized function for inverse_wavelet_freq"""
14
14
  wave_in = wave_in.T
@@ -20,10 +20,14 @@ def inverse_wavelet_freq_helper(
20
20
  n_range = jnp.arange(Nt)
21
21
 
22
22
  # m == 0 case
23
- prefactor2s = prefactor2s.at[0].set(2 ** (-1 / 2) * wave_in[(2 * n_range) % Nt, 0])
23
+ prefactor2s = prefactor2s.at[0].set(
24
+ 2 ** (-1 / 2) * wave_in[(2 * n_range) % Nt, 0]
25
+ )
24
26
 
25
27
  # m == Nf case
26
- prefactor2s = prefactor2s.at[Nf].set(2 ** (-1 / 2) * wave_in[(2 * n_range) % Nt + 1, 0])
28
+ prefactor2s = prefactor2s.at[Nf].set(
29
+ 2 ** (-1 / 2) * wave_in[(2 * n_range) % Nt + 1, 0]
30
+ )
27
31
 
28
32
  # Other m cases
29
33
  m_mid = m_range[1:Nf]
@@ -67,4 +71,4 @@ def inverse_wavelet_freq_helper(
67
71
  res = res.at[i1].add(fft_prefactor2s[m_grid, ind31] * phif[i_ind_grid])
68
72
  res = res.at[i2].add(fft_prefactor2s[m_grid, ind32] * phif[i_ind_grid])
69
73
 
70
- return res
74
+ return res
@@ -1,10 +1,9 @@
1
1
  from .forward import from_freq_to_wavelet, from_time_to_wavelet
2
2
  from .inverse import from_wavelet_to_freq, from_wavelet_to_time
3
3
 
4
-
5
4
  __all__ = [
6
5
  "from_wavelet_to_time",
7
6
  "from_wavelet_to_freq",
8
7
  "from_time_to_wavelet",
9
8
  "from_freq_to_wavelet",
10
- ]
9
+ ]
@@ -113,7 +113,7 @@ def from_freq_to_wavelet(
113
113
  """
114
114
  Nf, Nt = _preprocess_bins(freqseries, Nf, Nt)
115
115
  t_bins, f_bins = _get_bins(freqseries, Nf, Nt)
116
- phif = phitilde_vec_norm(Nf, Nt, d=nx)
116
+ phif = phitilde_vec_norm(Nf, Nt, d=nx)
117
117
  wave = transform_wavelet_freq_helper(freqseries.data, Nf, Nt, phif)
118
118
 
119
119
  return Wavelet((2 / Nf) * wave.T * np.sqrt(2), time=t_bins, freq=f_bins)
@@ -1,7 +1,7 @@
1
1
  import numpy as np
2
2
 
3
- from ...phi_computer import phi_vec, phitilde_vec_norm
4
3
  from ....types import FrequencySeries, TimeSeries, Wavelet
4
+ from ...phi_computer import phi_vec, phitilde_vec_norm
5
5
  from .to_freq import inverse_wavelet_freq_helper_fast
6
6
  from .to_time import inverse_wavelet_time_helper_fast
7
7
 
@@ -84,7 +84,7 @@ def from_wavelet_to_freq(
84
84
  to ensure the proper backwards transformation.
85
85
  """
86
86
 
87
- phif = phitilde_vec_norm(wave_in.Nf, wave_in.Nt, d=nx)
87
+ phif = phitilde_vec_norm(wave_in.Nf, wave_in.Nt, d=nx)
88
88
  freq_data = inverse_wavelet_freq_helper_fast(
89
89
  wave_in.data, phif, wave_in.Nf, wave_in.Nt
90
90
  )
@@ -1,10 +1,7 @@
1
- from ..backend import xp, PI, betainc, ifft
1
+ from ..backend import PI, betainc, ifft, xp
2
2
 
3
3
 
4
-
5
- def phitilde_vec(
6
- omega: xp.ndarray, Nf: int, d: float = 4.0
7
- ) -> xp.ndarray:
4
+ def phitilde_vec(omega: xp.ndarray, Nf: int, d: float = 4.0) -> xp.ndarray:
8
5
  """Compute phi_tilde(omega_i) array, nx is filter steepness, defaults to 4.
9
6
 
10
7
  Eq 11 of https://arxiv.org/pdf/2009.00043.pdf (Cornish et al. 2020)
@@ -78,7 +75,7 @@ def __nu_d(
78
75
  return betainc(d, d, x) / betainc(d, d, 1)
79
76
 
80
77
 
81
- def phitilde_vec_norm(Nf: int, Nt: int, d: float) -> xp.ndarray:
78
+ def phitilde_vec_norm(Nf: int, Nt: int, d: float) -> xp.ndarray:
82
79
  """Normalize phitilde for inverse frequency domain transform."""
83
80
 
84
81
  # Calculate the frequency values
@@ -86,7 +83,7 @@ def phitilde_vec_norm(Nf: int, Nt: int, d: float) -> xp.ndarray:
86
83
  omegas = 2 * xp.pi / ND * xp.arange(0, Nt // 2 + 1)
87
84
 
88
85
  # Calculate the unnormalized phitilde (u_phit)
89
- u_phit = phitilde_vec(omegas, Nf, d)
86
+ u_phit = phitilde_vec(omegas, Nf, d)
90
87
 
91
88
  # Normalize the phitilde
92
89
  normalising_factor = PI ** (-1 / 2) # Ollie's normalising factor
@@ -129,13 +126,9 @@ def phi_vec(Nf: int, d: float = 4.0, q: int = 16) -> xp.ndarray:
129
126
 
130
127
  DX = DX.copy()
131
128
  # postive frequencies
132
- DX[1 : half_K + 1] = phitilde_vec(
133
- dom * xp.arange(1, half_K + 1), Nf, d
134
- )
129
+ DX[1 : half_K + 1] = phitilde_vec(dom * xp.arange(1, half_K + 1), Nf, d)
135
130
  # negative frequencies
136
- DX[half_K + 1 :] = phitilde_vec(
137
- -dom * xp.arange(half_K - 1, 0, -1), Nf, d
138
- )
131
+ DX[half_K + 1 :] = phitilde_vec(-dom * xp.arange(half_K - 1, 0, -1), Nf, d)
139
132
  DX = K * ifft(DX, K)
140
133
 
141
134
  phi = xp.zeros(K)
@@ -1,6 +1,7 @@
1
- from typing import Tuple, Union, Callable
2
- from ..logger import logger
1
+ from typing import Callable, Tuple, Union
2
+
3
3
  from ..backend import xp
4
+ from ..logger import logger
4
5
 
5
6
 
6
7
  def _len_check(d):
@@ -8,7 +9,7 @@ def _len_check(d):
8
9
  logger.warning(f"Data length {len(d)} is suggested to be a power of 2")
9
10
 
10
11
 
11
- def is_documented_by(original:Callable):
12
+ def is_documented_by(original: Callable):
12
13
  def wrapper(target):
13
14
  target.__doc__ = original.__doc__
14
15
  return target
@@ -2,7 +2,7 @@ from typing import Optional, Tuple, Union
2
2
 
3
3
  import matplotlib.pyplot as plt
4
4
 
5
- from ..backend import xp, irfft
5
+ from ..backend import irfft, xp
6
6
  from .common import fmt_pow2, fmt_time, is_documented_by
7
7
  from .plotting import plot_freqseries, plot_periodogram
8
8
 
@@ -4,15 +4,9 @@ import matplotlib.pyplot as plt
4
4
  from scipy.signal import butter, sosfiltfilt
5
5
  from scipy.signal.windows import tukey
6
6
 
7
+ from ..backend import rfft, rfftfreq, xp
7
8
  from ..logger import logger
8
- from .common import (
9
- fmt_pow2,
10
- fmt_time,
11
- fmt_timerange,
12
- is_documented_by,
13
- )
14
- from ..backend import xp, rfftfreq, rfft
15
-
9
+ from .common import fmt_pow2, fmt_time, fmt_timerange, is_documented_by
16
10
  from .plotting import plot_spectrogram, plot_timeseries
17
11
 
18
12
  __all__ = ["TimeSeries"]
@@ -272,9 +266,9 @@ class TimeSeries:
272
266
  sos = butter(
273
267
  bandpass_order, Wn=fmin, btype="highpass", output="sos", fs=self.fs
274
268
  )
275
- window = tukey(self.ND, alpha=tukey_window_alpha)
276
269
  data = self.data.copy()
277
- data = sosfiltfilt(sos, data * window)
270
+ data = sosfiltfilt(sos, data)
271
+ data = data * tukey(self.ND, alpha=tukey_window_alpha)
278
272
  return TimeSeries(data, self.time)
279
273
 
280
274
  def __copy__(self):
@@ -1,6 +1,7 @@
1
1
  from typing import List, Tuple
2
2
 
3
3
  import matplotlib.pyplot as plt
4
+ import numpy as np
4
5
 
5
6
  from .common import fmt_timerange, is_documented_by, xp
6
7
  from .plotting import plot_wavelet_grid, plot_wavelet_trend
@@ -343,14 +344,18 @@ class Wavelet:
343
344
 
344
345
  def __mul__(self, other):
345
346
  """Element-wise multiplication of two Wavelet objects."""
346
- if isinstance(other, Wavelet):
347
- return Wavelet(
348
- data=self.data * other.data, time=self.time, freq=self.freq
349
- )
347
+ if isinstance(other, WaveletMask):
348
+ data = self.data.copy()
349
+ data[~other.mask] = np.nan
350
+ return Wavelet(data=data, time=self.time, freq=self.freq)
350
351
  elif isinstance(other, float):
351
352
  return Wavelet(
352
353
  data=self.data * other, time=self.time, freq=self.freq
353
354
  )
355
+ elif isinstance(other, WaveletMask):
356
+ return Wavelet(
357
+ data=self.data * other.data, time=self.time, freq=self.freq
358
+ )
354
359
 
355
360
  def __truediv__(self, other):
356
361
  """Element-wise division of two Wavelet objects."""
@@ -445,11 +450,40 @@ class WaveletMask(Wavelet):
445
450
  return rpr
446
451
 
447
452
  @classmethod
448
- def from_frange(
449
- cls, time_grid: xp.ndarray, freq_grid: xp.ndarray, frange: List[float]
453
+ def from_restrictions(
454
+ cls,
455
+ time_grid: xp.ndarray,
456
+ freq_grid: xp.ndarray,
457
+ frange: List[float],
458
+ tgaps: List[Tuple[float, float]] = [],
450
459
  ):
460
+ """
461
+ Create a WaveletMask object from restrictions on time and frequency.
462
+
463
+ Parameters
464
+ ----------
465
+ time_grid : xp.ndarray
466
+ Array of time points.
467
+ freq_grid : xp.ndarray
468
+ Array of corresponding frequency points.
469
+ frange : List[float]
470
+ Frequency range to include.
471
+ tgaps : List[Tuple[float, float]]
472
+ List of time gaps to exclude.
473
+
474
+ Returns
475
+ -------
476
+ WaveletMask
477
+ A WaveletMask object with the specified restrictions.
478
+ """
451
479
  self = cls.zeros_from_grid(time_grid, freq_grid)
452
480
  self.data[
453
481
  (freq_grid >= frange[0]) & (freq_grid <= frange[1]), :
454
482
  ] = True
483
+
484
+ for tgap in tgaps:
485
+ self.data[
486
+ :, (time_grid >= tgap[0]) & (time_grid <= tgap[1])
487
+ ] = False
488
+ self.data = self.data.astype(bool)
455
489
  return self
@@ -1,7 +1,6 @@
1
1
  from typing import Tuple, Union
2
2
 
3
3
  from ..backend import xp
4
-
5
4
  from .frequencyseries import FrequencySeries
6
5
  from .timeseries import TimeSeries
7
6
 
@@ -71,6 +71,8 @@ def compute_likelihood(
71
71
  p = psd.data
72
72
  if mask is not None:
73
73
  m = mask.mask
74
+ # convert mask to numbers -- 0 for False, 1 for True
75
+ m = m.astype(int)
74
76
  d, h, p = d * m, h * m, p * m
75
77
 
76
78
  return -0.5 * np.nansum((d - h) ** 2 / p)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pywavelet
3
- Version: 0.2.3
3
+ Version: 0.2.5
4
4
  Summary: WDM wavelet transform your time/freq series!
5
5
  Author-email: Pywavelet Team <avi.vajpeyi@gmail.com>
6
6
  Project-URL: Homepage, https://pywavelet.github.io/pywavelet/
@@ -76,10 +76,10 @@ First set up a conda environment with the latest version of python.
76
76
  Test code
77
77
  ---------
78
78
 
79
- Locate directory /tests from root directory. run
79
+ Locate directory /tests from root directory. run
80
80
 
81
81
  .. code-block::
82
82
 
83
83
  $ pytest .
84
84
 
85
- Hopefully everything should run fine.
85
+ Hopefully everything should run fine.
@@ -13,25 +13,26 @@ def test_mask(plot_dir):
13
13
  psd = Wavelet(np.ones((h.Nf, h.Nt)), h.time, h.freq)
14
14
  assert compute_likelihood(d, h, psd) == 0
15
15
 
16
- mask = WaveletMask.from_frange(h.time, h.freq, [f0 - 0.5, f0 + 0.5])
16
+ mask = WaveletMask.from_restrictions(h.time, h.freq, [f0 - 0.5, f0 + 0.5])
17
+ dmasked = d * mask
17
18
  assert np.isclose(compute_likelihood(d, h, psd, mask), 0)
19
+ assert np.isclose(compute_likelihood(dmasked, h, psd), 0)
20
+ # number of nans in dmasked.data
21
+ assert np.isnan(dmasked.data).sum() != 0
18
22
 
19
- mask1 = WaveletMask.from_frange(h.time, h.freq, [f0 + 0.5, f0 + 1.5])
23
+ mask1 = WaveletMask.from_restrictions(
24
+ h.time, h.freq, [f0 + 0.5, f0 + 1.5], tgaps=[[1.7 * 60, 3.4 * 60]]
25
+ )
26
+ dmasked1 = d * mask1
20
27
  # assert np.isclose(compute_likelihood(d, h, psd_analysis, mask1), 0) == False
21
28
 
22
29
  # plt the 3 differnet datasets
23
30
  fig, axes = plt.subplots(1, 3, figsize=(12, 4), sharex=True, sharey=True)
24
- kwgs = dict(
25
- cmap="viridis",
26
- aspect="auto",
27
- origin="lower",
28
- extent=[d.time[0], d.time[-1], d.freq[0], d.freq[-1]],
29
- )
30
- axes[0].imshow(d.data, **kwgs)
31
+ d.plot(ax=axes[0])
31
32
  axes[0].set_title("data")
32
- axes[1].imshow(d.data * mask.mask, **kwgs)
33
+ (d * mask).plot(ax=axes[1])
33
34
  axes[1].set_title("data*mask[f0-0.5, f0+0.5]")
34
- axes[2].imshow(d.data * mask1.mask, **kwgs)
35
+ (d * mask1).plot(ax=axes[2])
35
36
  axes[2].set_title("data*mask[f0+0.5, f0+1.5]")
36
37
  plt.tight_layout()
37
38
  fig.savefig(f"{plot_dir}/test_mask.png")
@@ -1,11 +1,7 @@
1
1
  import matplotlib.pyplot as plt
2
2
  import numpy as np
3
3
 
4
- from pywavelet.transforms import (
5
- phi_vec,
6
- phitilde_vec,
7
- phitilde_vec_norm,
8
- )
4
+ from pywavelet.transforms import phi_vec, phitilde_vec, phitilde_vec_norm
9
5
 
10
6
 
11
7
  def test_phi(plot_dir):
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes