From f2c0fe8c6d67e3b505d68023b6e9727c9e4a2339 Mon Sep 17 00:00:00 2001 From: Sylvain Chevallier Date: Mon, 14 Jun 2021 13:05:06 +0200 Subject: [PATCH] Adding what's new and correct doc (#200) * add cache for poetry, datasets and html docs * correct doc building error, add whatsnew, update class/function template * adding gh function from braindecode/MNE * correct cache path for docs, dont cache venv for windows test --- .github/workflows/docs.yml | 45 +++++-- .github/workflows/test.yml | 41 +++++- docs/source/README.md | 2 + docs/source/_static/placeholder.css | 0 docs/source/_templates/class.rst | 10 +- docs/source/_templates/function.rst | 6 + docs/source/conf.py | 114 ++++++++++++++++- docs/source/datasets.rst | 18 ++- docs/source/index.rst | 18 ++- docs/source/sphinxext/gh_substitutions.py | 28 ++++ docs/source/whats_new.rst | 148 ++++++++++++++++++++++ examples/plot_explore_paradigm.py | 2 +- moabb/evaluations/base.py | 4 +- moabb/pipelines/utils.py | 4 +- 14 files changed, 400 insertions(+), 40 deletions(-) create mode 100644 docs/source/_static/placeholder.css create mode 100644 docs/source/sphinxext/gh_substitutions.py create mode 100644 docs/source/whats_new.rst diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 46fd02539..00134d8f3 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -8,10 +8,9 @@ on: jobs: build_docs: - name: ${{ matrix.os }}, py-${{ matrix.python-version }} runs-on: ${{ matrix.os }} strategy: - fail-fast: false + fail-fast: true matrix: os: [ubuntu-18.04] python-version: ["3.6"] @@ -23,21 +22,34 @@ jobs: run: | mkdir ~/mne_data - - name: Cache datasets - uses: actions/cache@v2 - with: - path: ~/mne_data - key: ${{ runner.os }}-${{ hashFiles('moabb/datasets/**') }} - - name: Setup Python uses: actions/setup-python@v2 with: python-version: ${{ matrix.python-version }} + - name: Install Poetry + uses: snok/install-poetry@v1.1.6 + with: + virtualenvs-create: true + virtualenvs-in-project: true + + - name: Cache poetry, datasets and docs + id: cached-poetry-dataset-docs + uses: actions/cache@v2 + with: + key: + ${{ runner.os }}-${{ hashFiles('moabb/datasets/**', '**/poetry.lock') }}-doc + path: | + ~/mne_data + .venv + docs/build + - name: Install dependencies - run: | - pip install poetry - poetry install -E external + if: steps.cached-poetry-dataset-docs.outputs.cache-hit != 'true' + run: poetry install --no-interaction --no-root -E external + + - name: Install library + run: poetry install --no-interaction -E external - name: Build docs run: | @@ -59,6 +71,17 @@ jobs: os: [ubuntu-18.04] steps: + - name: Cache poetry, datasets and docs + id: cached-poetry-dataset-docs + uses: actions/cache@v2 + with: + key: + ${{ runner.os }}-${{ hashFiles('moabb/datasets/**', '**/poetry.lock') }}-doc + path: | + ~/mne_data + .venv + docs/build + - name: Checkout moabb.github.io uses: actions/checkout@v2 with: diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 0004ba125..02f8aecca 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -11,27 +11,54 @@ jobs: name: ${{ matrix.os }}, py-${{ matrix.python-version }} runs-on: ${{ matrix.os }} strategy: - fail-fast: false + fail-fast: true matrix: os: [ubuntu-18.04, windows-latest, macOS-latest] python-version: ["3.6", "3.7", "3.8", "3.9"] + defaults: + run: + shell: bash steps: - uses: actions/checkout@v2 + - name: Setup Python uses: actions/setup-python@v2 with: python-version: ${{ matrix.python-version }} + - uses: pre-commit/action@v2.0.0 + + - name: Install Poetry + uses: snok/install-poetry@v1.1.6 + with: + virtualenvs-create: true + virtualenvs-in-project: true + + - name: Load cached venv + if: runner.os != 'Windows' + id: cached-poetry-dependencies + uses: actions/cache@v2 + with: + path: .venv + key: + venv-${{ matrix.os }}-py${{matrix.python-version}}-${{ + hashFiles('**/poetry.lock') }} + - name: Install dependencies - shell: bash - run: | - python -m pip install --upgrade pip poetry wheel - poetry install + if: | + (runner.os != 'Windows') && + (steps.cached-poetry-dependencies.outputs.cache-hit != 'true') + run: poetry install --no-interaction --no-root + + - name: Install library + run: poetry install --no-interaction + - name: Run tests - shell: bash run: | + source $VENV poetry run python -m unittest moabb.tests + - name: Run pipelines - shell: bash run: | + source $VENV poetry run python -m moabb.run --pipelines=./moabb/tests/test_pipelines/ --verbose diff --git a/docs/source/README.md b/docs/source/README.md index 866e2b98e..8de1dd932 100644 --- a/docs/source/README.md +++ b/docs/source/README.md @@ -1,3 +1,5 @@ +.. currentmodule:: moabb + # Mother of all BCI Benchmarks ![banner](images/M.png) diff --git a/docs/source/_static/placeholder.css b/docs/source/_static/placeholder.css new file mode 100644 index 000000000..e69de29bb diff --git a/docs/source/_templates/class.rst b/docs/source/_templates/class.rst index f71c4d49e..fd96dcd91 100644 --- a/docs/source/_templates/class.rst +++ b/docs/source/_templates/class.rst @@ -4,7 +4,11 @@ .. currentmodule:: {{ module }} .. autoclass:: {{ objname }} + :special-members: __contains__,__getitem__,__iter__,__len__,__add__,__sub__,__mul__,__div__,__neg__,__hash__ + :members: - {% block methods %} - .. automethod:: __init__ - {% endblock %} +.. include:: {{fullname}}.examples + +.. raw:: html + +
diff --git a/docs/source/_templates/function.rst b/docs/source/_templates/function.rst index 4d7ea38a1..2e45d656f 100644 --- a/docs/source/_templates/function.rst +++ b/docs/source/_templates/function.rst @@ -4,3 +4,9 @@ .. currentmodule:: {{ module }} .. autofunction:: {{ objname }} + +.. include:: {{ fullname }}.examples + +.. raw:: html + +
diff --git a/docs/source/conf.py b/docs/source/conf.py index c751ba662..39d5f8ccc 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -8,7 +8,9 @@ # -- Path setup -------------------------------------------------------------- +import inspect import os +import os.path as op import sys import matplotlib @@ -18,6 +20,7 @@ # documentation root, use os.path.abspath to make it absolute, like shown here. # import sphinx_bootstrap_theme +from numpydoc import docscrape, numpydoc # noqa # Sort tutorials and examples but filename from sphinx_gallery.sorting import FileNameSortKey @@ -33,7 +36,7 @@ # -- Project information ----------------------------------------------------- project = "moabb" -copyright = "2018, Alexandre Barachant" +copyright = "2018-2021, Alexandre Barachant, Sylvain Chevallier" author = "Alexandre Barachant, Vinay Jayaram, Sylvain Chevallier" # The short X.Y version @@ -48,27 +51,115 @@ # # needs_sphinx = '1.0' +curdir = os.path.dirname(__file__) +sys.path.append(os.path.abspath(os.path.join(curdir, "sphinxext"))) + # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. extensions = [ "sphinx.ext.autodoc", + "sphinx.ext.autosummary", "sphinx.ext.doctest", - "sphinx.ext.intersphinx", "sphinx.ext.todo", "sphinx.ext.coverage", + "sphinx.ext.githubpages", + "sphinx.ext.intersphinx", "sphinx.ext.imgmath", - "sphinx.ext.viewcode", "sphinx.ext.napoleon", - "sphinx.ext.autosummary", + "sphinx.ext.linkcode", + "sphinx.ext.mathjax", + "sphinx.ext.viewcode", "sphinx_gallery.gen_gallery", + "gh_substitutions", "m2r2", + "numpydoc", ] + +def linkcode_resolve(domain, info): # noqa: C901 + """Determine the URL corresponding to a Python object. + Parameters + ---------- + domain : str + Only useful when 'py'. + info : dict + With keys "module" and "fullname". + Returns + ------- + url : str + The code URL. + Notes + ----- + This has been adapted to deal with our "verbose" decorator. + Adapted from SciPy (doc/source/conf.py). + """ + import mne + + if domain != "py": + return None + + modname = info["module"] + fullname = info["fullname"] + + submod = sys.modules.get(modname) + if submod is None: + return None + + obj = submod + for part in fullname.split("."): + try: + obj = getattr(obj, part) + except Exception: + return None + # deal with our decorators properly + while hasattr(obj, "__wrapped__"): + obj = obj.__wrapped__ + + try: + fn = inspect.getsourcefile(obj) + except Exception: + fn = None + if not fn: + try: + fn = inspect.getsourcefile(sys.modules[obj.__module__]) + except Exception: + fn = None + if not fn: + return None + fn = op.relpath(fn, start=op.dirname(mne.__file__)) + fn = "/".join(op.normpath(fn).split(os.sep)) # in case on Windows + + try: + source, lineno = inspect.getsourcelines(obj) + except Exception: + lineno = None + + if lineno: + linespec = "#L%d-L%d" % (lineno, lineno + len(source) - 1) + else: + linespec = "" + + if "dev" in moabb.__version__: + kind = "master" + else: + kind = "maint/%s" % (".".join(mne.__version__.split(".")[:2])) + return "http://github.com/NeuroTechX/moabb/blob/%s/moabb/%s%s" % ( # noqa + kind, + fn, + linespec, + ) + + napoleon_google_docstring = False napoleon_use_param = False napoleon_use_ivar = True +numpydoc_show_class_members = True +numpydoc_class_members_toctree = False +numpydoc_attributes_as_param_list = True +numpydoc_xref_param_type = True + plot_include_source = True plot_formats = [("png", 90)] plot_html_show_formats = False @@ -77,6 +168,8 @@ sphinx_gallery_conf = { "examples_dirs": ["../../examples", "../../tutorials"], "gallery_dirs": ["auto_examples", "auto_tutorials"], + "doc_module": ("moabb", "mne"), + "backreferences_dir": "generated", "filename_pattern": "(/plot_|/tutorial_)", "default_thumb_file": "../images/M.png", "within_subsection_order": FileNameSortKey, @@ -85,9 +178,9 @@ # Add any paths that contain templates here, relative to this directory. templates_path = ["_templates"] -autodoc_default_flags = ["inherited-members"] +autodoc_default_flags = {"inherited-members": None} autosummary_generate = True -numpydoc_show_class_members = True + # The suffix(es) of source filenames. # You can specify multiple suffix as a list of string: # @@ -264,7 +357,14 @@ # -- Options for intersphinx extension --------------------------------------- # Example configuration for intersphinx: refer to the Python standard library. -intersphinx_mapping = {"https://docs.python.org/": None} +intersphinx_mapping = { + "python": ("https://docs.python.org/{.major}".format(sys.version_info), None), + "numpy": ("https://docs.scipy.org/doc/numpy/", None), + "scipy": ("https://docs.scipy.org/doc/scipy/reference", None), + "matplotlib": ("https://matplotlib.org/", None), + "sklearn": ("http://scikit-learn.org/stable", None), + "mne": ("http://mne.tools/stable", None), +} # -- Options for todo extension ---------------------------------------------- diff --git a/docs/source/datasets.rst b/docs/source/datasets.rst index da351f5ab..a5a7ade38 100644 --- a/docs/source/datasets.rst +++ b/docs/source/datasets.rst @@ -73,12 +73,18 @@ Base & Utils :template: class.rst base.BaseDataset + + +.. autosummary:: + :toctree: generated/ + :template: function.rst + download.data_path - download.data_dl - download.fs_issue_request - download.fs_get_file_list - download.fs_get_file_hash - download.fs_get_file_id - download.fs_get_file_name + download.data_dl + download.fs_issue_request + download.fs_get_file_list + download.fs_get_file_hash + download.fs_get_file_id + download.fs_get_file_name utils.dataset_search utils.find_intersecting_channels diff --git a/docs/source/index.rst b/docs/source/index.rst index b7b4fa41c..c31745043 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -4,12 +4,28 @@ contain the root `toctree` directive. .. mdinclude:: README.md + +What's new +========== +.. toctree:: + :maxdepth: 2 + + whats_new + +Public API +========== + .. toctree:: :maxdepth: 2 - :caption: Contents: + :caption: Main classes of MOABB: datasets evaluations paradigms pipelines analysis + +Indices and tables +================== + +* :ref:`genindex` diff --git a/docs/source/sphinxext/gh_substitutions.py b/docs/source/sphinxext/gh_substitutions.py new file mode 100644 index 000000000..3dc9ce555 --- /dev/null +++ b/docs/source/sphinxext/gh_substitutions.py @@ -0,0 +1,28 @@ +from docutils.nodes import reference +from docutils.parsers.rst.roles import set_classes + + +# adapted from +# https://doughellmann.com/blog/2010/05/09/defining-custom-roles-in-sphinx/ + + +def gh_role(name, rawtext, text, lineno, inliner, options={}, content=[]): # noqa: B006 + """Link to a GitHub issue.""" + try: + # issue/PR mode (issues/PR-num will redirect to pull/PR-num) + int(text) + except ValueError: + # direct link mode + slug = text + else: + slug = "issues/" + text + text = "#" + text + ref = "https://github.com/NeuroTechX/moabb/" + slug + set_classes(options) + node = reference(rawtext, text, refuri=ref, **options) + return [node], [] + + +def setup(app): + app.add_role("gh", gh_role) + return diff --git a/docs/source/whats_new.rst b/docs/source/whats_new.rst new file mode 100644 index 000000000..994c741c5 --- /dev/null +++ b/docs/source/whats_new.rst @@ -0,0 +1,148 @@ +.. _whats_new: + +.. currentmodule:: moabb + +What's new +========== + +.. NOTE: there are 3 separate sections for changes, based on type: + - "Enhancements" for new features + - "Bugs" for bug fixes + - "API changes" for backward-incompatible changes +.. _current: + +Dev - 0.4.0dev +--------------- + +Enhancements +~~~~~~~~~~~~ +- Implementation for learning curves (:gh:`155` by `Jan Sosulski`_) +- Adding Neiry Demons P300 dataset (:gh:`156` by `Vladislav Goncharenko`_) +- Coloredlogs removal (:gh:`163` by `Vladislav Goncharenko`_) +- Update for README (:gh:`164` by `Vladislav Goncharenko`_ and `Sylvain Chevallier`_) +- Test all relevant python versions in Github Actions CI (:gh:`167` by `Vladislav Goncharenko`_) +- Adding motor imagery part of the Lee2019 dataset (:gh:`170` by `Ali Abdul Hussain`_) +- CI: deploy docs from CI pipeline (:gh:`124` by `Erik Bjäreholt`_, `Divyesh Narayanan`_ and `Sylvain Chevallier`_) +- Remove dependencies: WFDB and pyunpack (:gh:`180` and :gh:`188` by `Sylvain Chevallier`_) +- Add support for FigShare API (:gh:`188` by `Sylvain Chevallier`_) +- New download backend function relying on Pooch, handling FTP, HTTP and HTTPS (:gh:`188` by `Sylvain Chevallier`_) +- Complete rework of examples and tutorial (:gh:`188` by `Sylvain Chevallier`_) +- Change default storage location for results: instead of moabb source code directory it is now stored in mne_data (:gh:`188` by `Sylvain Chevallier`_) +- Major update of test (:gh:`188` by `Sylvain Chevallier`_) +- Adding troubleshooting and badges in README (:gh:`189` by `Jan Sosulski`_ and `Sylvain Chevallier`_) +- Use MNE epoch in evaluation (:gh:`192` by `Sylvain Chevallier`_) +- Allow changing of storage location (:gh:`192` by `Divyesh Narayanan`_ and `Sylvain Chevallier`_) +- Deploy docs on moabb.github.io (:gh:`196` by `Sylvain Chevallier`_) +- Broadening subject_list type (:gh:`198` by `Sylvain Chevallier`_) + + + +Bugs +~~~~ +- Restore basic logging (:gh:`177` by `Jan Sosulski`_) +- Correct wrong type of results dataframe columns (:gh:`188` by `Sylvain Chevallier`_) + +API changes +~~~~~~~~~~~ +- Drop `update_path` from moabb.download.data_path and moabb.download.data_dl + + +Current - 0.3.0 +---------------- + +Enhancements +~~~~~~~~~~~~ +- Expose sklearn error_score parameter (:gh:`70` by `Jan Sosulski`_) +- Adds a ``unit_factor`` attribute to base_paradigms (:gh:`72` by `Jan Sosulski`_) +- Allow event lists in P300 paradigm (:gh:`83` by `Jan Sosulski`_) +- Return epochs instead of np.ndarray in process_raw (:gh:`86` by `Jan Sosulski`_) +- Set path for hdf5 files (:gh:`92` by `Jan Sosulski`_) +- Update to MNE 0.21 (:gh:`101` by `Ramiro Gatti`_ and `Sylvain Chevallier`_) +- Adding a baseline correction (:gh:`115` by `Ramiro Gatti`_) +- Adding SSVEP datasets: MAMEM1, MAMEM2, MAMEM3, Nakanishi2015, Wang2016, (:gh:`118` by `Sylvain Chevallier`_, `Quentin Barthelemy`_, and `Divyesh Narayanan`_) +- Switch to GitHub Actions (:gh:`124` by `Erik Bjäreholt`_) +- Allow recording of additional scores/parameters/metrics in evaluation (:gh:`127` and :gh:`128` by `Jan Sosulski`_) +- Fix Ofner2017 and PhysionetMI annotations (:gh:`135` by `Ali Abdul Hussain`_) +- Adding Graz workshop tutorials (:gh:`130` and :gh:`137` by `Sylvain Chevallier`_ and `Lucas Custódio`_) +- Adding pre-commit configuration using isort, black and flake8 (:gh:`140` by `Vladislav Goncharenko`_) +- style: format Python code with black (:gh:`147` by `Erik Bjäreholt`_) +- Switching to Poetry dependency management (:gh:`150` by `Vladislav Goncharenko`_) +- Using Prettier to format md and yml files (:gh:`151` by `Vladislav Goncharenko`_) + + +Bugs +~~~~ +- Use stim_channels or check annotation when loading files in Paradigm (:gh:`72` by `Jan Sosulski`_) +- Correct MNE issues (:gh:`76` by `Sylvain Chevallier`_) +- Fix capitalization in channel names of cho dataset (:gh:`90` by `Jan Sosulski`_) +- Correct failling CI tests (:gh:`100` by `Sylvain Chevallier`_) +- Fix EPFL dataset flat signal sections and wrong scaling (:gh:`104` and :gh:`96` by `Jan Sosulski`_) +- Fix schirrmeister dataset for Python3.8 (:gh:`105` by `Robin Schirrmeister`_) +- Correct event detection problem and duplicate event error (:gh:`106` by `Sylvain Chevallier`_) +- Fix channel selection in paradigm (:gh:`108` by `Sylvain Chevallier`_) +- Fix upperlimb Ofner2017 error and gdf import problem (:gh:`111` and :gh:`110` by `Sylvain Chevallier`_) +- Fix event_id in events_from_annotations missed (:gh:`112` by `Ramiro Gatti`_) +- Fix h5py>=3.0 compatibility issue (:gh:`138` by `Mohammad Mostafa Farzan`_) +- Python 2 support removal (:gh:`148` by `Vladislav Goncharenko`_) +- Travis-ci config removal (:gh:`149` by `Vladislav Goncharenko`_) + +API changes +~~~~~~~~~~~ +- None + +Version 0.2.1 +------------- + +Enhancements +~~~~~~~~~~~~ +- Add Tikhonov regularized CSP in ``moabb.pipelines.csp`` from the paper (:gh:`60` by `Vinay Jayaram`_) +- update to MNE version 0.19 (:gh:`73` by `Jan Sosulski`_) +- Improve doc building in CI (:gh:`60` by `Sylvain Chevallier`_) + +Bugs +~~~~ +- Update GigaDB Cho2017 URL (`Pedro L. C. Rodrigues`_ and `Vinay Jayaram`_) +- Fix braininvaders ERP data (`Pedro L. C. Rodrigues`_) +- Replace MNE ``read_montage`` with ``make_standard_montage`` (`Jan Sosulski`_) +- Correct Flake and PEP8 error (`Sylvain Chevallier`_) + +API changes +~~~~~~~~~~~ +- None + + +Version 0.2.0 +------------- + +Enhancements +~~~~~~~~~~~~ +- MOABB corresponding to the paper version by `Vinay Jayaram`_ and `Alexandre Barachant`_ +- Creating P300 paradigm and BNCI datasets (:gh:`53` by `Pedro L. C. Rodrigues`_) +- Adding EPFL P300 dataset (:gh:`56` by `Pedro L. C. Rodrigues`_) +- Adding BrainInvaders P300 dataset (:gh:`57` by `Pedro L. C. Rodrigues`_) +- Creating SSVEP paradigm and SSVEPExo dataset (:gh:`59` by `Sylvain Chevallier`_) + +Bugs +~~~~ +- None + +API changes +~~~~~~~~~~~ +- None + + + +.. _Alexandre Barachant: https://github.com/alexandrebarachant +.. _Quentin Barthelemy: https://github.com/qbarthelemy +.. _Erik Bjäreholt: https://github.com/ErikBjare +.. _Sylvain Chevallier: https://github.com/sylvchev +.. _Lucas Custódio: https://github.com/lucascust +.. _Mohammad Mostafa Farzan: https://github.com/m2-farzan +.. _Ramiro Gatti: https://github.com/ragatti +.. _Vladislav Goncharenko: https://github.com/v-goncharenko +.. _Ali Abdul Hussain: https://github.com/AliAbdulHussain +.. _Vinay Jayaram: https://github.com/vinay-jayaram +.. _Divyesh Narayanan: https://github.com/Div12345 +.. _Pedro L. C. Rodrigues: https://github.com/plcrodrigues +.. _Robin Schirrmeister: https://github.com/robintibor +.. _Jan Sosulski: https://github.com/jsosulski diff --git a/examples/plot_explore_paradigm.py b/examples/plot_explore_paradigm.py index 96231b0c8..ab92b2c55 100644 --- a/examples/plot_explore_paradigm.py +++ b/examples/plot_explore_paradigm.py @@ -81,7 +81,7 @@ # - session is the session id. A session is a all the data recorded without # removing the EEG cap. # - run is the individual continuous recording made during a session. A Session -# may or may not contain multiple run. +# may or may not contain multiple run. # diff --git a/moabb/evaluations/base.py b/moabb/evaluations/base.py index 20666bcc7..ad1e51dc5 100644 --- a/moabb/evaluations/base.py +++ b/moabb/evaluations/base.py @@ -134,8 +134,8 @@ def process(self, pipelines): pipelines : dict of pipeline instance. A dict containing the sklearn pipeline to evaluate. - Return - ------ + Returns + ------- results: pd.DataFrame A dataframe containing the results. diff --git a/moabb/pipelines/utils.py b/moabb/pipelines/utils.py index 9c4355327..c9c09b6cc 100644 --- a/moabb/pipelines/utils.py +++ b/moabb/pipelines/utils.py @@ -15,8 +15,8 @@ def create_pipeline_from_config(config): config : Dict. Dict containing the config parameters. - Return - ------ + Returns + ------- pipeline : Pipeline sklearn Pipeline