Skip to content

Commit dd723d5

Browse files
whenxuan: polish docs homepage, user guide, and theme
Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent 0f7363b commit dd723d5

8 files changed

Lines changed: 215 additions & 47 deletions

File tree

‎.github/docs-build.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,7 @@ On Read the Docs: **Admin → Environment variables** →
273273
5. **RST warnings** from markdown→RST conversion (`unindent`, unmatched `` ` ``) do not fail the build unless you pass `-W`.
274274
6. **`autosectionlabel`** uses `autosectionlabel_prefix_document = True` because many examples share headings like “1. Imports”.
275275
7. **Release notes need GitHub** — `sphinx-github-changelog` calls the Releases API at build time. Public anonymous access works until you hit the rate limit (60/hour). On Read the Docs, set environment variable `SPHINX_GITHUB_CHANGELOG_TOKEN` (or `GITHUB_TOKEN`) to a PAT. Do not commit the token.
276+
8. **Read the Docs flyout** — the floating RTD logo is hidden in `theme_overrides.css` (`readthedocs-flyout`). If it still appears, uncheck **Settings → Addons → Flyout enabled** on the project dashboard. The navbar uses `_static/logo.png`, not that widget.
276277

277278
---
278279

‎docs/source/_static/custom.css‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ html[data-theme=light] {
2222
--pst-color-border-muted: rgba(23, 23, 26, 0.2);
2323
--pst-color-blockquote-notch: #677384;
2424
--pst-color-inline-code: #912583;
25-
--pst-color-inline-code-links: #085d6c;
25+
--pst-color-inline-code-links: #1d4ed8;
2626
--pst-color-target: #f3cf95;
2727
--pst-color-table: #14181e;
2828
--pst-color-table-row-hover-bg: #e8eaed;
@@ -35,7 +35,7 @@ html[data-theme=light] {
3535
}
3636
html[data-theme=light] {
3737
--pst-color-heading: var(--pst-color-text-base);
38-
--pst-color-link: var(--pst-color-primary);
38+
--pst-color-link: #1d4ed8;
3939
--pst-color-link-hover: var(--pst-color-secondary);
4040
--pst-color-table-outer-border: var(--pst-color-border);
4141
--pst-color-table-heading-bg: #f3f4f5;

‎docs/source/_static/favicon.png‎

9.4 KB
Loading

‎docs/source/_static/theme_overrides.css‎

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,3 +52,29 @@ html[data-theme="light"] .sphx-glr-thumbcontainer:hover {
5252
.sphx-glr-thumbcontainer .figure {
5353
margin: 0;
5454
}
55+
56+
/* PyData maps card body/header to --pst-color-on-background (#9cccf8). */
57+
html[data-theme="light"] .bd-content .sd-card,
58+
html[data-theme="light"] .bd-content .sd-card .sd-card-body,
59+
html[data-theme="light"] .bd-content .sd-card .sd-card-header,
60+
html[data-theme="light"] .bd-content .sd-card .sd-card-footer {
61+
background-color: #ffffff;
62+
}
63+
64+
html[data-theme="light"] .sphx-glr-download a code,
65+
html[data-theme="light"] .sphx-glr-download code {
66+
background: transparent;
67+
padding: 0;
68+
}
69+
70+
/* Navbar project badge (circular PNG). */
71+
.navbar-brand img {
72+
max-height: 2.2rem;
73+
width: auto;
74+
}
75+
76+
/* Hide the floating Read the Docs flyout so the header uses our logo.
77+
You can also uncheck Addons → Flyout in the RTD dashboard. */
78+
readthedocs-flyout {
79+
display: none !important;
80+
}

‎docs/source/conf.py‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@
109109
source_suffix = {".rst": "restructuredtext"}
110110

111111
html_logo = "_static/logo.png"
112+
html_favicon = "_static/favicon.png"
112113

113114
language = "en"
114115

@@ -126,7 +127,10 @@
126127
html_theme_options = {
127128
"announcement": "",
128129
"logo": {
130+
"image_light": "_static/logo.png",
131+
"image_dark": "_static/logo.png",
129132
"text": "pysdkit",
133+
"alt_text": "PySDKit",
130134
"link": "https://pysdkit.readthedocs.io/",
131135
},
132136
"header_links_before_dropdown": 6,
@@ -150,7 +154,6 @@
150154
"show_version_warning_banner": False,
151155
"secondary_sidebar_items": {
152156
"**": ["page-toc", "sourcelink"],
153-
"index": [],
154157
},
155158
"show_toc_level": 4,
156159
"collapse_navigation": True,

‎docs/source/index.rst‎

Lines changed: 45 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -3,40 +3,60 @@ PYSDKIT's documentation
33

44
**Version**: |version|
55

6-
PySDKit is a Python library for **signal decomposition**: splitting a
7-
non-stationary recording into simpler modes (IMFs) that can be plotted,
8-
used as features, or fed to a downstream model.
6+
Welcome to **PySDKit**, a Python library for **signal decomposition**,
7+
developed with NumPy, SciPy, and Matplotlib. A non-stationary recording
8+
is treated as a sum of simpler modes (intrinsic mode functions). Those
9+
modes can be plotted, used as features, or fed to a downstream model,
10+
using the same ``fit_transform`` style as scikit-learn.
911

10-
Installation
11-
------------
12+
.. image:: ../../images/Logo_sd.png
13+
:align: center
14+
:width: 48%
15+
:alt: Signal decomposition: a sensor recording split into IMFs and a Fourier spectrum
1216

13-
.. code-block:: bash
17+
Quick links
18+
-----------
1419

15-
pip install pysdkit
20+
.. grid:: 1 1 2 2
21+
:gutter: 3
1622

17-
Quick start
18-
-----------
23+
.. grid-item-card:: :octicon:`rocket` Get started
24+
:link: user_guide/index
25+
:link-type: doc
26+
27+
New to PySDKit? Install the package and learn the three-step
28+
``fit_transform`` API.
29+
30+
.. grid-item-card:: :octicon:`image` Examples
31+
:link: auto_examples/index
32+
:link-type: doc
33+
34+
Browse the gallery of algorithm demos, figures, and downloadable
35+
scripts.
36+
37+
.. grid-item-card:: :octicon:`repo` API reference
38+
:link: API/modules
39+
:link-type: doc
40+
41+
Public classes and functions you can import from :mod:`pysdkit`.
42+
43+
.. grid-item-card:: :octicon:`history` Release notes
44+
:link: release_notes/index
45+
:link-type: doc
1946

20-
.. code-block:: python
47+
What changed between versions. Filled from GitHub Releases.
2148

22-
import numpy as np
23-
from pysdkit import EMD
24-
from pysdkit.plot import plot_IMFs
49+
.. grid-item-card:: :octicon:`tools` Contribute
50+
:link: development/index
51+
:link-type: doc
2552

26-
t = np.linspace(0, 1, 1000)
27-
signal = (
28-
np.sin(2 * np.pi * 5 * t)
29-
+ 0.7 * np.sin(2 * np.pi * 25 * t)
30-
+ 0.45 * np.sin(2 * np.pi * 80 * t)
31-
)
53+
Add an algorithm, tests, or a gallery example.
3254

33-
emd = EMD()
34-
IMFs = emd.fit_transform(signal, max_imfs=3)
35-
plot_IMFs(signal, IMFs, view="2d_freq", fs=1000, freq_max=150)
55+
.. grid-item-card:: :octicon:`people` About
56+
:link: about/index
57+
:link-type: doc
3658

37-
The same three-step pattern (import, instantiate, ``fit_transform``)
38-
applies to VMD, BMEMD, and the other algorithms listed in
39-
:doc:`API/modules`.
59+
Project scope, citations, and where to find the source.
4060

4161
.. toctree::
4262
:hidden:

‎docs/source/release_notes/index.rst‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,6 @@ built. To add a version, publish a GitHub Release for the matching
66
tag (Markdown body is enough); you do not need to edit this file.
77

88
.. changelog::
9-
:changelog-url: https://pysdkit.readthedocs.io/en/stable/release_notes/index.html
9+
:changelog-url: https://github.com/wwhenxuan/PySDKit/releases/
1010
:github: https://github.com/wwhenxuan/PySDKit/releases/
1111
:pypi: https://pypi.org/project/PySDKit/

‎docs/source/user_guide/index.rst‎

Lines changed: 136 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,64 @@
11
User guide
22
==========
33

4-
Three-step API
5-
--------------
4+
What PySDKit is
5+
---------------
6+
7+
**Signal decomposition** is a post-wavelet time-frequency tool: a
8+
complex **non-stationary, nonlinear** recording is assumed to be a sum
9+
of simpler sub-signals (intrinsic mode functions). Analysing those
10+
modes recovers time-frequency structure that a single Fourier transform
11+
cannot, and that a fixed wavelet dictionary often cannot either.
12+
13+
Since the Hilbert–Huang Transform (1998), a family of univariate and
14+
multivariate decompositions has grown quickly in MATLAB. Python is the
15+
usual home of machine learning, yet it still lacked a library comparable
16+
to `PyWavelets <https://pywavelets.readthedocs.io/>`_ for this class of
17+
algorithms.
18+
19+
PySDKit was started in April 2024 to close that gap: one package, a
20+
shared ``fit_transform`` API, and matching plots so decomposition can
21+
be used as **feature engineering** next to NumPy, SciPy, and neural
22+
networks. Families already in the tree include EMD, EWT, VMD / OVMD,
23+
VNCMD, ALIF, APMD, and related 2-D methods.
24+
25+
Please cite the **original paper** of each algorithm you use; class and
26+
module docstrings point to those references.
27+
28+
Install
29+
-------
30+
31+
From PyPI:
32+
33+
.. code-block:: bash
34+
35+
pip install pysdkit
36+
37+
Runtime dependencies are NumPy, SciPy, and Matplotlib.
38+
39+
From a clone (editable, for development):
40+
41+
.. code-block:: bash
42+
43+
git clone https://github.com/wwhenxuan/PySDKit.git
44+
cd PySDKit
45+
pip install -e .
46+
47+
Demo arrays ship with the package. Prefer loaders in
48+
:mod:`pysdkit.data` (for example ``test_vmd``) over local MATLAB files.
49+
``.npy`` data live under ``pysdkit/data/real_world``. The gitignored
50+
``repo/`` tree is not installed and must not be imported at runtime.
51+
52+
Unified interface
53+
-----------------
654

755
Decomposition classes share a scikit-learn-style interface:
856

957
1. Import the algorithm from :mod:`pysdkit`.
1058
2. Create an instance (optional parameters set the rank, filter length, …).
1159
3. Call ``fit_transform`` on a 1-D array, a channel stack, or an image.
60+
4. Inspect the original recording and the IMFs with
61+
:func:`~pysdkit.plot.plot_IMFs`.
1262

1363
.. code-block:: python
1464
@@ -21,8 +71,7 @@ Decomposition classes share a scikit-learn-style interface:
2171
IMFs = vmd.fit_transform(signal)
2272
plot_IMFs(signal, IMFs, view="2d_freq", fs=fs, freq_max=fs / 2)
2373
24-
Which family to pick
25-
--------------------
74+
Which family to pick:
2675

2776
.. list-table::
2877
:header-rows: 1
@@ -49,25 +98,94 @@ Which family to pick
4998

5099
A full name list is on :doc:`/API/modules`.
51100

52-
Packaged data
53-
-------------
101+
Worked examples
102+
---------------
103+
104+
The snippets below are the three README-style demos from
105+
``examples/demo.py``. Run that script for CEEMDAN and 2-D VMD as well.
106+
107+
EMD — three-tone mixture
108+
~~~~~~~~~~~~~~~~~~~~~~~~
109+
110+
A sum of cosines at 5 / 25 / 80 Hz. EMD sifts recursively by scale.
111+
112+
.. code-block:: python
113+
114+
import numpy as np
115+
from pysdkit import EMD
116+
from pysdkit.plot import plot_IMFs
117+
118+
t = np.linspace(0, 1, 1000)
119+
signal = (
120+
np.sin(2 * np.pi * 5 * t)
121+
+ 0.7 * np.sin(2 * np.pi * 25 * t)
122+
+ 0.45 * np.sin(2 * np.pi * 80 * t)
123+
)
124+
125+
emd = EMD()
126+
IMFs = emd.fit_transform(signal, max_imfs=3)
127+
plot_IMFs(signal, IMFs, view="2d_freq", fs=1000, freq_max=150)
128+
129+
.. image:: ../auto_examples/images/sphx_glr_demo_001.png
130+
:width: 95%
131+
:alt: EMD — three-tone mixture (time and frequency)
54132

55-
Demo arrays install with the package. Prefer the loaders in
56-
:mod:`pysdkit.data` over any local MATLAB dump:
133+
VMD — packaged multicomponent signal
134+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
135+
136+
Non-recursive VMD estimates several band-limited modes jointly in the
137+
Fourier domain. Data come from ``test_vmd()``.
57138

58139
.. code-block:: python
59140
60-
from pysdkit.data import load_bmemd_source02, load_bss_beam, test_vmd
141+
from pysdkit import VMD
142+
from pysdkit.data import test_vmd
143+
from pysdkit.plot import plot_IMFs
144+
145+
t, signal, fs = test_vmd()
146+
vmd = VMD(alpha=2000, K=4, tau=0.0, tol=1e-7)
147+
IMFs = vmd.fit_transform(signal)
148+
plot_IMFs(signal, IMFs, view="2d_freq", fs=fs, freq_max=fs / 2)
149+
150+
.. image:: ../auto_examples/images/sphx_glr_demo_002.png
151+
:width: 95%
152+
:alt: VMD — packaged multi-component example (time and frequency)
153+
154+
MVMD — aligned multichannel modes
155+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
156+
157+
Three channels share a 36 Hz oscillation; each also carries a distinct
158+
tone. MVMD keeps mode index :math:`k` aligned across channels.
159+
160+
.. code-block:: python
161+
162+
import numpy as np
163+
from pysdkit import MVMD
164+
from pysdkit.plot import plot_IMFs
165+
166+
t = np.arange(0, 1, 0.001)
167+
signal = np.vstack(
168+
[
169+
np.cos(2 * np.pi * 2 * t) + np.cos(2 * np.pi * 36 * t),
170+
np.cos(2 * np.pi * 24 * t) + np.cos(2 * np.pi * 36 * t),
171+
np.cos(2 * np.pi * 80 * t) + np.cos(2 * np.pi * 36 * t),
172+
]
173+
)
174+
175+
mvmd = MVMD(alpha=2000, K=4, tau=0.0, init="uniform")
176+
IMFs = mvmd.fit_transform(signal) # (K, T, C)
177+
plot_IMFs(signal, IMFs)
61178
62-
images = load_bmemd_source02()["signal"] # (2, 224, 224) in [0, 1]
63-
beam = load_bss_beam()["signal"]
179+
.. image:: ../auto_examples/images/sphx_glr_demo_003.png
180+
:width: 95%
181+
:alt: MVMD — mode-aligned multichannel decomposition
64182

65-
``.npy`` files live under ``pysdkit/data/real_world``; callers still pass
66-
a bare file name to the loader. The gitignored ``repo/`` directory is
67-
not part of the install and must not be used at runtime.
183+
Examples gallery
184+
----------------
68185

69-
Next steps
70-
----------
186+
The full executed gallery (theory, figures, Python and notebook
187+
downloads) is :doc:`/auto_examples/index`.
71188

72-
- Example gallery: :doc:`/auto_examples/index`
73-
- Public classes: :doc:`/API/modules`
189+
``examples/demo.py`` is the overview script used above. Each algorithm
190+
family has its own folder under ``examples/`` (for example
191+
``examples/emd/``, ``examples/vmd/``).

0 commit comments

Comments
 (0)