diff --git a/aeon/classification/deep_learning/base.py b/aeon/classification/deep_learning/base.py index 61ddeb3a72..a90c72c845 100644 --- a/aeon/classification/deep_learning/base.py +++ b/aeon/classification/deep_learning/base.py @@ -49,10 +49,9 @@ class BaseDeepClassifier(BaseClassifier): The name of the file of the last model, used only if save_last_model_to_file is used - Arguments - --------- + Attributes + ---------- self.model = None - """ _tags = { diff --git a/aeon/networks/_ae_abgru.py b/aeon/networks/_ae_abgru.py index ca9f0494ad..0154c841e8 100644 --- a/aeon/networks/_ae_abgru.py +++ b/aeon/networks/_ae_abgru.py @@ -64,8 +64,8 @@ def __init__( def build_network(self, input_shape, **kwargs): """Construct a network and return its input and output layers. - Arguments - --------- + Parameters + ---------- input_shape : tuple of shape = (n_timepoints (m), n_channels (d)) The shape of the data fed into the input layer. kwargs : dict diff --git a/aeon/networks/_ae_dcnn.py b/aeon/networks/_ae_dcnn.py index ea475d0161..2e2d26f370 100644 --- a/aeon/networks/_ae_dcnn.py +++ b/aeon/networks/_ae_dcnn.py @@ -85,8 +85,8 @@ def __init__( def build_network(self, input_shape): """Construct a network and return its input and output layers. - Arguments - --------- + Parameters + ---------- input_shape : tuple of shape = (n_timepoints (m), n_channels (d)) The shape of the data fed into the input layer. diff --git a/docs/_templates/class_with_call.rst b/docs/_templates/class_with_call.rst deleted file mode 100644 index 21936b6e6c..0000000000 --- a/docs/_templates/class_with_call.rst +++ /dev/null @@ -1,7 +0,0 @@ -{{ objname }} -{{ underline }} - -.. currentmodule:: {{ module }} - -.. autoclass:: {{ objname }} - :special-members: __call__ diff --git a/docs/about.md b/docs/about.md index ada6d723f1..1af1ae5ecd 100644 --- a/docs/about.md +++ b/docs/about.md @@ -124,6 +124,14 @@ organisations: - GitHub ID - Organization - Year +* - Balgopal Moharana + - {user}`lucifer4073` + - [Google Summer of Code](https://summerofcode.withgoogle.com) + - 2025 +* - Jiarong Jin + - {user}`TinaJin0228` + - [Google Summer of Code](https://summerofcode.withgoogle.com) + - 2025 * - Divya Tiwari - {user}`itsdivya1309` - [Google Summer of Code](https://summerofcode.withgoogle.com) diff --git a/docs/changelogs/v1.2.md b/docs/changelogs/v1.2.md index 651e51f885..b4930452fd 100644 --- a/docs/changelogs/v1.2.md +++ b/docs/changelogs/v1.2.md @@ -4,17 +4,18 @@ June 2025 ## Highlights -- `aeon` v1.2.0 drops support for Python 3.9, Python 3.10-3.13 are the current supported versions. +- `aeon` v1.2.0 drops support for Python 3.9, Python 3.10-3.13 are the currently supported versions. - Framework for whole-series anomaly detection has been implemented, and the module has been refactored into `anomaly_detection.collection` and `anomaly_detection.series` submodules. -- `ProximityForect` and `ProximityTree` classifiers have been improved to support +- `ProximityForest` and `ProximityTree` classifiers have been improved to support unequal length and multivariate series. The classifiers are also significantly faster. +- A new implementation for the `TD-MVDC` classifier - The forecasting module has been enhanced with additional methods for direct and recursive forecasting, as well as new algorithms such as ETS. This module is still in early development, and we expect framework changes in future releases. - The similarity search module has been significantly reworked to fit the `aeon` style framework seen in other modules. See the module examples and documentation for more details. -- The start of a sub-package for self suprervised learning has been added in +- The start of an experimental sub-package for self supervised learning has been added in `aeon.transformations.collection.self_supervised`, starting with the `TRILITE` algorithm. ## Anomaly Detection diff --git a/docs/conf.py b/docs/conf.py index 89da0515ed..fd2d36a896 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -19,6 +19,7 @@ # -- Path setup -------------------------------------------------------------- +# local sphinx extensions sys.path.append(str(Path(__file__).parent / "_sphinxext")) # If extensions (or modules to document with autodoc) are in another directory, @@ -37,29 +38,23 @@ # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. extensions = [ + "numpydoc", + "sphinx.ext.autosummary", + "sphinx.ext.autodoc", "sphinx.ext.autosectionlabel", "sphinx.ext.intersphinx", - "sphinx.ext.linkcode", # link to GitHub source code via linkcode_resolve() + "sphinx.ext.linkcode", "sphinxext.opengraph", - "numpydoc", - "nbsphinx", # integrates example notebooks + "nbsphinx", "sphinx_design", "sphinx_issues", "sphinx_copybutton", "versionwarning.extension", "myst_parser", - # local extensions + # local extensions (_sphinxext/) "sphinx_remove_toctrees", ] -# Notebook thumbnails -nbsphinx_thumbnails = { - "examples/02_classification": "examples/img/tsc.png", -} - -# Use bootstrap CSS from theme. -panels_add_bootstrap_css = False - # Add any paths that contain templates here, relative to this directory. templates_path = ["_templates"] @@ -90,14 +85,38 @@ ".DS_Store", ] +# A boolean that decides whether module names are prepended to all object names (for +# object types where a “module” of some kind is defined), e.g. for py:function +# directives. add_module_names = False +# -- Extension configuration ------------------------------------------------- + +# -- numpydoc -- + # see http://stackoverflow.com/q/12206334/562769 +# https://github.com/numpy/numpydoc/issues/69 +# Lots of warnings numpydoc_show_class_members = True -# this is needed for some reason... -# see https://github.com/numpy/numpydoc/issues/69 + +# Whether to create a Sphinx table of contents for the lists of class methods and +# attributes. If a table of contents is made, Sphinx expects each entry to have a +# separate page. +# We remove the toctree for API for speed and do not want separate pages for this numpydoc_class_members_toctree = False +# Whether to produce plot:: directives for Examples sections that contain +# 'import matplotlib' or 'from matplotlib import'. +numpydoc_use_plots = True + +# Options for the ::plot directive: +# https://matplotlib.org/stable/api/sphinxext_plot_directive_api.html +plot_formats = ["png"] +plot_include_source = True +plot_html_show_formats = False +plot_html_show_source_link = False + +# This will produce warnings for docstring errors. numpydoc_validation_checks = { "all", "GL01", # docstring starts after opening quotes @@ -106,6 +125,11 @@ "EX01", # no examples } +# If true, '()' will be appended to :func: etc. cross-reference text. +add_function_parentheses = False + +# -- autosummary and autodoc -- + # generate autosummary even if no references autosummary_generate = True @@ -114,114 +138,82 @@ # Member-order orders the documentation in the order of how the members are defined in # the source code. autodoc_default_options = { + "class-doc-from": "class", "members": True, + "exclude-members": "get_metadata_routing, set_output", "inherited-members": True, - "member-order": "bysource", + "show-inheritance": True, } -# If true, '()' will be appended to :func: etc. cross-reference text. -add_function_parentheses = False - -# Link to GitHub repo for github_issues extension -issues_github_path = "aeon-toolkit/aeon" - -# sphinx-copybutton configuration -copybutton_exclude = ".linenos, .gp, .go" - -# sphinx-remove-toctrees (and in-built alternative) configuration -# see https://github.com/pradyunsg/furo/pull/674 -# we use an in-built alternative currently due to a bug. See sphinx_remove_toctrees.py -# extension issue https://github.com/executablebooks/sphinx-remove-toctrees/issues/9 -remove_from_toctrees = ["api_reference/auto_generated/*"] +# -- autosectionlabel -- -# MyST Parser configuration +autosectionlabel_maxdepth = 4 -# When building HTML using the sphinx.ext.mathjax (enabled by default), -# Myst-Parser injects the tex2jax_ignore (MathJax v2) and mathjax_ignore (MathJax v3) -# classes in to the top-level section of each MyST document, and adds some default -# configuration. This ensures that MathJax processes only math, identified by the -# dollarmath and amsmath extensions, or specified in math directives. We here silence -# the corresponding warning that this override happens. -suppress_warnings = ["myst.mathjax"] +# -- intersphinx -- -# "colon_fence" and "html_image" recommended by sphinx_design when using the MyST Parser -myst_enable_extensions = ["colon_fence", "html_image", "attrs_inline"] +intersphinx_mapping = { + "python": ("https://docs.python.org/3/", None), + "numpy": ("https://numpy.org/doc/stable/", None), + "scipy": ("https://docs.scipy.org/doc/scipy/", None), + "matplotlib": ("https://matplotlib.org/stable/", None), + "pandas": ("https://pandas.pydata.org/pandas-docs/stable/", None), + "joblib": ("https://joblib.readthedocs.io/en/latest/", None), + "scikit-learn": ("https://scikit-learn.org/stable/", None), +} -myst_heading_anchors = 4 +# -- nbsphinx -- +nbsphinx_execute = "never" # whether to run notebooks +nbsphinx_allow_errors = False +nbsphinx_timeout = 600 # seconds, set to -1 to disable timeout -def linkcode_resolve(domain, info): - """Return URL to source code corresponding. +# Binder launch button +current_file = "{{ env.doc2path( env.docname, base=None) }}" +binder_url = ( + f"https://mybinder.org/v2/gh/aeon-toolkit/aeon/{github_tag}?filepath={current_file}" +) - Parameters - ---------- - domain : str - info : dict +# link to original notebook +notebook_url = f"https://github.com/aeon-toolkit/aeon/tree/{github_tag}/{current_file}" - Returns - ------- - url : str - """ +# add to the bottom of each notebook page +nbsphinx_epilog = f""" +---- - def find_source(): - # try to find the file and line number, based on code from numpy: - # https://github.com/numpy/numpy/blob/main/doc/source/conf.py#L286 +Generated using nbsphinx_. The Jupyter notebook can be found here_. - import inspect - import os +|Binder|_ - # Get the top-level object from the module name - obj = sys.modules[info["module"]] +.. _here: {notebook_url} +.. _nbsphinx: https://nbsphinx.readthedocs.io/ +.. |binder| image:: https://mybinder.org/badge_logo.svg +.. _Binder: {binder_url} +""" - # Traverse dotted path (e.g., module.submodule.Class.method) - for part in info["fullname"].split("."): - obj = getattr(obj, part) +# -- sphinx_issues -- - # Unwrapping decorators (if any), so we can get the true - # source function - if inspect.isfunction(obj): - obj = inspect.unwrap(obj) +issues_github_path = "aeon-toolkit/aeon" - # Get the source filename - try: - fn = inspect.getsourcefile(obj) - except TypeError: - fn = None +# -- sphinx_copybutton -- - # If no source file is found, return None (no link) - if not fn: - return None +copybutton_exclude = ".linenos, .gp, .go" - # Make filename relative to the aeon source directory - startdir = Path(aeon.__file__).parent.parent - try: - fn = os.path.relpath(fn, start=startdir).replace(os.path.sep, "/") - except ValueError: - return None +# -- MyST parser -- - # Filter out files not in the aeon package - # (e.g., inherited from sklearn) - if not fn.startswith("aeon/"): - return None +# "colon_fence" and "html_image" recommended by sphinx_design when using the MyST Parser +myst_enable_extensions = ["colon_fence", "html_image", "attrs_inline"] - # Get line range of the object - source, lineno = inspect.getsourcelines(obj) - return fn, lineno, lineno + len(source) - 1 +myst_heading_anchors = 4 - if domain != "py" or not info["module"]: - return None - try: - result = find_source() - if not result: - return None - filename = "%s#L%d-L%d" % result - except Exception: - filename = info["module"].replace(".", "/") + ".py" - return "https://github.com/aeon-toolkit/aeon/blob/{}/{}".format( - github_tag, - filename, - ) +# -- sphinx-remove-toctrees -- +# see https://github.com/pradyunsg/furo/pull/674 +# we use an in-built alternative currently due to a bug. See sphinx_remove_toctrees.py +# extension issue https://github.com/executablebooks/sphinx-remove-toctrees/issues/9 +remove_from_toctrees = [ + "api_reference/auto_generated/*", # including all api pages significantly slows + # down the documentation build +] # -- Options for HTML output ------------------------------------------------- @@ -308,65 +300,84 @@ def find_source(): # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". html_static_path = ["_static"] -html_css_files = [ - "css/custom.css", -] +html_css_files = ["css/custom.css"] html_show_sourcelink = False -# -- Options for HTMLHelp output --------------------------------------------- +# -- Documentation functions and setup --------------------------------------- -# Output file base name for HTML help builder. -htmlhelp_basename = "aeondoc" -# -- Options for LaTeX output ------------------------------------------------ +def linkcode_resolve(domain, info): + """Return URL to source code corresponding. -latex_elements = { - # The paper size ('letterpaper' or 'a4paper'). - # 'papersize': 'letterpaper', - # The font size ('10pt', '11pt' or '12pt'). - # 'pointsize': '10pt', - # Additional stuff for the LaTeX preamble. - # 'preamble': '', - # Latex figure (float) alignment - # 'figure_align': 'htbp', -} + Parameters + ---------- + domain : str + info : dict -# Grouping the document tree into LaTeX files. List of tuples -# (source start file, target name, title, -# author, documentclass [howto, manual, or own class]). -latex_documents = [ - ( - master_doc, - "aeon.tex", - "aeon Documentation", - "aeon developers", - "manual", - ), -] + Returns + ------- + url : str + """ -# -- Options for manual page output ------------------------------------------ - -# One entry per manual page. List of tuples -# (source start file, name, description, authors, manual section). -man_pages = [(master_doc, "aeon", "aeon Documentation", [author], 1)] - -# -- Options for Texinfo output ---------------------------------------------- - -# Grouping the document tree into Texinfo files. List of tuples -# (source start file, target name, title, author, -# dir menu entry, description, category) -texinfo_documents = [ - ( - master_doc, - "aeon", - "aeon Documentation", - author, - "aeon", - "One line description of project.", - "Miscellaneous", - ), -] + def find_source(): + # try to find the file and line number, based on code from numpy: + # https://github.com/numpy/numpy/blob/main/doc/source/conf.py#L286 + + import inspect + import os + + # Get the top-level object from the module name + obj = sys.modules[info["module"]] + + # Traverse dotted path (e.g., module.submodule.Class.method) + for part in info["fullname"].split("."): + obj = getattr(obj, part) + + # Unwrapping decorators (if any), so we can get the true + # source function + if inspect.isfunction(obj): + obj = inspect.unwrap(obj) + + # Get the source filename + try: + fn = inspect.getsourcefile(obj) + except TypeError: + fn = None + + # If no source file is found, return None (no link) + if not fn: + return None + + # Make filename relative to the aeon source directory + startdir = Path(aeon.__file__).parent.parent + try: + fn = os.path.relpath(fn, start=startdir).replace(os.path.sep, "/") + except ValueError: + return None + + # Filter out files not in the aeon package + # (e.g., inherited from sklearn) + if not fn.startswith("aeon/"): + return None + + # Get line range of the object + source, lineno = inspect.getsourcelines(obj) + return fn, lineno, lineno + len(source) - 1 + + if domain != "py" or not info["module"]: + return None + try: + result = find_source() + if not result: + return None + filename = "%s#L%d-L%d" % result + except Exception: + filename = info["module"].replace(".", "/") + ".py" + return "https://github.com/aeon-toolkit/aeon/blob/{}/{}".format( + github_tag, + filename, + ) def _make_estimator_overview(app): @@ -612,52 +623,3 @@ def setup(app): """ app.connect("builder-inited", _make_estimator_overview) app.connect("html-page-context", _add_estimator_capabilities_table) - - -# -- Extension configuration ------------------------------------------------- - -# -- Options for nbsphinx extension --------------------------------------- -nbsphinx_execute = "never" # always # whether to run notebooks -nbsphinx_allow_errors = False # False -nbsphinx_timeout = 600 # seconds, set to -1 to disable timeout - -# add Binder launch buttom at the top -current_file = "{{ env.doc2path( env.docname, base=None) }}" - -# make sure Binder points to latest stable release, not main -binder_url = f"https://mybinder.org/v2/gh/aeon-toolkit/aeon/{github_tag}?filepath={current_file}" # noqa -nbsphinx_prolog = f""" -.. |binder| image:: https://mybinder.org/badge_logo.svg -.. _Binder: {binder_url} - -|Binder|_ -""" - -# add link to original notebook at the bottom -notebook_url = f"https://github.com/aeon-toolkit/aeon/tree/{github_tag}/{current_file}" -nbsphinx_epilog = f""" ----- - -Generated using nbsphinx_. The Jupyter notebook can be found here_. - -.. _here: {notebook_url} -.. _nbsphinx: https://nbsphinx.readthedocs.io/ -""" - -# -- Options for intersphinx extension --------------------------------------- - -# Example configuration for intersphinx: refer to the Python standard library. -intersphinx_mapping = { - "python": ("https://docs.python.org/3/", None), - "numpy": ("https://numpy.org/doc/stable/", None), - "scipy": ("https://docs.scipy.org/doc/scipy/", None), - "matplotlib": ("https://matplotlib.org/stable/", None), - "pandas": ("https://pandas.pydata.org/pandas-docs/stable/", None), - "joblib": ("https://joblib.readthedocs.io/en/latest/", None), - "scikit-learn": ("https://scikit-learn.org/stable/", None), - "statsmodels": ("https://www.statsmodels.org/stable/", None), -} - - -# -- Options for _todo extension ---------------------------------------------- -todo_include_todos = False diff --git a/docs/developer_guide/coding_standards.md b/docs/developer_guide/coding_standards.md index e5f38d6abd..2ee7743e03 100644 --- a/docs/developer_guide/coding_standards.md +++ b/docs/developer_guide/coding_standards.md @@ -13,7 +13,7 @@ example can be found [here](https://gist.github.com/nateGeorge/5455d2c57fb33c1ae - Documentation formatting using the [numpydoc](https://numpydoc.readthedocs.io/en/latest/format.html) style -### Code formatting and linting +## Code formatting and linting Our coding standards are enforced through our CI/CD workflows via [pre-commit](https://pre-commit.com/). We adhere to the code formatting standards using the following `pre-commit` hooks: @@ -35,7 +35,7 @@ quality The full `pre-commit` configuration can be found in [.pre-commit-config.yaml](https://github.com/aeon-toolkit/aeon/blob/main/.pre-commit-config.yaml). Additional configurations for some hooks can be found in the [pyproject.toml](https://github.com/aeon-toolkit/aeon/blob/main/pyproject.toml). -### `aeon` specific code formatting conventions +## `aeon` specific code formatting conventions - Use underscores to separate words in non-class names i.e.`n_cases` rather than `ncases`, `nCases` or similar. @@ -45,7 +45,7 @@ part of variable names such as `X_train` if referring to data sets. - Don’t use `import *` in the source code. It is considered harmful by the official Python recommendations. -### Using `pre-commit` +## Using `pre-commit` To set up pre-commit, follow these steps in a Python environment with the `aeon` `dev` dependencies installed. diff --git a/docs/papers_using_aeon.md b/docs/papers_using_aeon.md index ee2c142f22..f8ec7e9daf 100644 --- a/docs/papers_using_aeon.md +++ b/docs/papers_using_aeon.md @@ -29,7 +29,7 @@ Research, 25(289), pp.1-10. - Serramazza, D., Nguyen, T. and Ifrim, G. A short tutorial for multivariate time series explanation using tsCaptum. Software Impacts, 22. [Paper](https://doi.org/10.1016/j.simpa.2024.100723) -- + ## 2024 - Bagnall, A.,Middlehurst, M., Forestier, G., Schäfer, P., Ismail-Fawaz, A., diff --git a/pyproject.toml b/pyproject.toml index 1a04d40bd5..b5e44e6df9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -108,7 +108,7 @@ docs = [ "sphinx-version-warning", "sphinx_issues", "sphinx-copybutton", - "sphinxext-opengraph", + "sphinxext-opengraph[social_cards]", "nbsphinx", "numpydoc", "myst-parser",