Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,7 @@ doc/sg_execution_times.rst
doc/.jupyterlite.doit.db
doc/jupyterlite_contents/
doc/_contents/
emsdk/
doc/_output/
emsdk/
packages/
pyodide/
53 changes: 47 additions & 6 deletions doc/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
import importlib.metadata
from datetime import datetime

from sphinx_gallery.notebook import add_code_cell

# General information about the project.
project = "fastcan"
copyright = f"2024 - {datetime.now().year}, fastcan developers (MIT License)"
Expand Down Expand Up @@ -44,7 +46,7 @@
# For PlantUML diagrams
"sphinxcontrib.plantuml",
# For interactive examples via JupyterLite
'jupyterlite_sphinx',
"jupyterlite_sphinx",
]

# List of patterns, relative to source directory, that match files and
Expand Down Expand Up @@ -77,11 +79,6 @@
"sklearn": ("https://scikit-learn.org/stable", None),
}

sphinx_gallery_conf = {
"examples_dirs": ["../examples"],
"gallery_dirs": ["auto_examples"],
}

# -----------------------------------------------------------------------------
# Interactive documentation examples via JupyterLite
# -----------------------------------------------------------------------------
Expand All @@ -92,3 +89,47 @@
"If you encounter any issues, please report them on the"
" [fastcan issue tracker](https://github.com/scikit-learn-contrib/fastcan/issues)."
)


def notebook_modification_function(notebook_content, notebook_filename):
notebook_content_str = str(notebook_content)
dummy_notebook_content = {"cells": []}
code_lines = []

if "fetch_" in notebook_content_str:
code_lines.extend(
[
"import pyodide_http",
"pyodide_http.patch_all()",
]
)
# always import matplotlib and pandas to avoid Pyodide limitation with
# imports inside functions
code_lines.extend(
[
"import matplotlib",
"import pandas",
]
)

if code_lines:
code_lines = ["# JupyterLite-specific code"] + code_lines
code = "\n".join(code_lines)
add_code_cell(dummy_notebook_content, code)

notebook_content["cells"] = (
dummy_notebook_content["cells"] + notebook_content["cells"]
)


# -----------------------------------------------------------------------------
suppress_warnings = [
# Ignore new warning in Sphinx 7.3.0 while pickling environment:
# WARNING: cannot cache unpickable configuration value: 'sphinx_gallery_conf'
"config.cache",
]
sphinx_gallery_conf = {
"examples_dirs": ["../examples"],
"gallery_dirs": ["auto_examples"],
"jupyterlite": {"notebook_modification_function": notebook_modification_function},
}
5 changes: 4 additions & 1 deletion doc/environment.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,7 @@ channels:
dependencies:
- xeus-python
- matplotlib
- fastcan
- pandas
- fastcan
- pip:
- pyodide-http
3 changes: 0 additions & 3 deletions examples/plot_forecasting.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,6 @@

.. currentmodule:: fastcan.narx

.. note::
This example can NOT be run with JupyterLite so far.

In this examples, we will demonstrate how to use :func:`make_narx` to build (nonlinear)
AutoRegressive (AR) models for time-series forecasting.
The time series used isthe monthly average atmospheric CO2 concentrations
Expand Down
1 change: 1 addition & 0 deletions fastcan/narx/tests/test_narx.py
Original file line number Diff line number Diff line change
Expand Up @@ -647,6 +647,7 @@ def test_auto_reg_error():
with pytest.raises(ValueError, match=r"X should be an array-like of shape.*"):
model.predict(len(y), y_init=y[: model.max_delay_])


def test_predict_ndim():
"""Test the ndim of predict output"""
X = np.random.rand(10, 2)
Expand Down
3,961 changes: 1,910 additions & 2,051 deletions pixi.lock

Large diffs are not rendered by default.

21 changes: 13 additions & 8 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[project]
name = "fastcan"
version = "0.4.1"
description = "A fast canonical-correlation-based feature selection method"
description = "A fast canonical-correlation-based greedy search algorithm"
authors = [
{ name = "Matthew Sikai Zhang", email = "[email protected]" },
]
Expand Down Expand Up @@ -59,7 +59,7 @@ channels = ["conda-forge"]
platforms = ["win-64", "linux-64", "osx-64", "osx-arm64", "linux-aarch64"]

[tool.pixi.dependencies]
python = ">=3.12.0,<3.13"
python = ">=3.10"
scikit-learn = ">=1.7.0,!=1.7.1"

[tool.pixi.pypi-dependencies]
Expand All @@ -81,6 +81,7 @@ plantuml = "*"
[tool.pixi.feature.wasm.dependencies]
pip = "*"
pyodide-build = "*"
prettier = "*"

[tool.pixi.feature.asv.dependencies]
asv = "*"
Expand Down Expand Up @@ -156,19 +157,23 @@ spell = "codespell"

[tool.pixi.feature.docs.tasks]
doc = { cmd = "{{ SPHINXBUILD }} -M {{ CMD }} {{ SOURCEDIR }} {{ BUILDDIR }} {{ SPHINXOPTS }} --fail-on-warning", cwd = "doc", args = [{ arg = "SPHINXBUILD", default = "sphinx-build" }, { arg = "CMD", default = "html" }, { arg = "SOURCEDIR", default = "." }, { arg = "BUILDDIR", default = "_build" }, { arg = "SPHINXOPTS", default = "" }] }
doc-clean = { cmd = "rm -rf {{ BUILDDIR }} generated auto_examples jupyterlite_contents .jupyterlite.doit.db _contents", cwd = "doc", args = [{ arg = "BUILDDIR", default = "_build" }] }
doc-clean = { cmd = "rm -rf {{ BUILDDIR }} generated auto_examples jupyterlite_contents .jupyterlite.doit.db _contents _output .cache", cwd = "doc", args = [{ arg = "BUILDDIR", default = "_build" }] }
doc-deploy = { cmd = "python -m http.server" , cwd = "doc/_build/html" }

[tool.pixi.feature.nogil.tasks]
nogil-h = "python -Xgil=0 -m timeit -n 5 -s 'import numpy as np; from fastcan import FastCan; X = np.random.rand(3000, 100); y = np.random.rand(3000, 20)' 's = FastCan(100, verbose=0).fit(X, y)'"
nogil-eta = "python -Xgil=0 -m timeit -n 5 -s 'import numpy as np; from fastcan import FastCan; X = np.random.rand(3000, 100); y = np.random.rand(3000, 20)' 's = FastCan(100, eta=True, verbose=0).fit(X, y)'"

[tool.pixi.feature.wasm.tasks]
wasm-clone-emsdk = "bash -c '[ -d emsdk ] || git clone https://github.com/emscripten-core/emsdk.git emsdk'"
wasm-compatible = "pyodide xbuildenv search -a"
wasm-toolchain = { cmd = "LATEST_COMPATIBLE=$(pyodide xbuildenv search -a | grep '│ Yes' | head -n 1 | awk -F '│' '{print $2}' | xargs) && pyodide xbuildenv install $LATEST_COMPATIBLE" }
wasm-setup-emsdk = { cmd = "PYODIDE_EMSCRIPTEN_VERSION=$(pyodide config get emscripten_version) && ./emsdk install $PYODIDE_EMSCRIPTEN_VERSION && ./emsdk activate $PYODIDE_EMSCRIPTEN_VERSION", cwd = "emsdk", depends-on = ["wasm-clone-emsdk", "wasm-toolchain"] }
wasm-build = { cmd = "bash -c 'source emsdk/emsdk_env.sh && pyodide build'", depends-on = ["wasm-setup-emsdk"] }
emsdk-clone = "bash -c '[ -d emsdk ] || git clone https://github.com/emscripten-core/emsdk.git emsdk'"
pyodide-compatible = "pyodide xbuildenv search -a"
pyodide-toolchain = { cmd = "LATEST_COMPATIBLE=$(pyodide xbuildenv search -a | grep '│ Yes' | head -n 1 | awk -F '│' '{print $2}' | xargs) && pyodide xbuildenv install $LATEST_COMPATIBLE" }
emsdk-setup = { cmd = "PYODIDE_EMSCRIPTEN_VERSION=$(pyodide config get emscripten_version) && ./emsdk install $PYODIDE_EMSCRIPTEN_VERSION && ./emsdk activate $PYODIDE_EMSCRIPTEN_VERSION", cwd = "emsdk", depends-on = ["emsdk-clone", "pyodide-toolchain"] }
pyodide-build = { cmd = "bash -c 'source emsdk/emsdk_env.sh && pyodide build'", depends-on = ["emsdk-setup"] }
pyodide-create-recipe = "rm -rf packages && pyodide skeleton pypi fastcan"
pyodide-build-recipe = { cmd = "rm -rf dist && bash -c 'source emsdk/emsdk_env.sh && pyodide build-recipes fastcan --install'", depends-on = ["emsdk-setup"] }
pyodide-download = '''bash -c "[ -d pyodide ] || (LATEST_TAG=$(curl -s https://api.github.com/repos/pyodide/pyodide/releases/latest | grep \"tag_name\" | cut -d \" -f4) && curl -L https://github.com/pyodide/pyodide/releases/download/${LATEST_TAG}/pyodide-${LATEST_TAG}.tar.bz2 | tar -xjf -)"'''
pyodide-test-recipe = { cmd = "mv ../dist/* . && python -m http.server --directory .", cwd = "pyodide", depends-on = ["pyodide-download", "pyodide-build-recipe"] }

[tool.pixi.environments]
dev = ["docs", "test", "build", "jupyter", "asv"]
Expand Down
6 changes: 3 additions & 3 deletions rtd-environment.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@ dependencies:
- micromamba
- pip
- furo
- matplotlib
- pandas
- sphinx-gallery
- sphinx-design
- sphinxcontrib-plantuml
- jupyterlite-sphinx
- plantuml
- matplotlib
- pandas
- pip:
- .
- jupyterlite-xeus >=2.1.2
- jupyterlite-xeus
2 changes: 1 addition & 1 deletion tests/test_fastcan.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ def test_select_kbest_classif():
ssc = correlation_filter.scores_.sum()
# Test whether the ssc from the fastcan is consistent
# with the mcc from the linear regression
assert_almost_equal(actual=ssc, desired=gtruth_ssc)
assert abs(ssc - gtruth_ssc) < 1e-5

support = correlation_filter.get_support()
gtruth = np.zeros(n_features)
Expand Down