From 616c9e719f99d9ed1a1a80c9b74b76d71ca2fcf4 Mon Sep 17 00:00:00 2001 From: Samuel Farrens Date: Wed, 31 Mar 2021 18:39:35 +0200 Subject: [PATCH] ModOpt v1.5 release (#108) * added workflows * test update to deploy test results from fork * fix typo * test commands copied from yaml * removed test deployment * Pyralid style update (#104) * first iteration of pyralid style update * updated progress on pyralid style refactor * further updates * latest update * all tests passing locally * all doctests passing locally * removed autodoc files * updated refactoring * test pull_request_target and add main branch * added logo and fixed link to api docs * added develop branch to CI * updated workflow * test PR review * reverted to standard PR directive * updated readme * test deploy test results from fork * attempt to fix fomatting * removed test deployment * added #97 GPU compatibility in consistent style * additional clean up * more clean up * fixed mistake * Update modopt/interface/errors.py Co-authored-by: Zaccharie Ramzi * Update modopt/tests/test_opt.py Co-authored-by: Zaccharie Ramzi * Update modopt/tests/test_opt.py Co-authored-by: Zaccharie Ramzi * Update modopt/tests/test_opt.py Co-authored-by: Zaccharie Ramzi * Update modopt/tests/test_opt.py Co-authored-by: Zaccharie Ramzi * Update modopt/tests/test_opt.py Co-authored-by: Zaccharie Ramzi * Update modopt/tests/test_math.py Co-authored-by: Zaccharie Ramzi * Update modopt/tests/test_math.py Co-authored-by: Zaccharie Ramzi * removed doc requirements from basic test suite * removed contents as they are now automatically generated on GitHub * fix GPU bug in PowerMethod * Update modopt/tests/test_opt.py Co-authored-by: Zaccharie Ramzi * Update modopt/tests/test_opt.py Co-authored-by: Zaccharie Ramzi * Update modopt/tests/test_opt.py Co-authored-by: Zaccharie Ramzi * Update modopt/tests/test_opt.py Co-authored-by: Zaccharie Ramzi * Update modopt/tests/test_opt.py Co-authored-by: Zaccharie Ramzi * Update modopt/tests/test_opt.py Co-authored-by: Zaccharie Ramzi * Update modopt/tests/test_opt.py Co-authored-by: Zaccharie Ramzi * Update modopt/tests/test_opt.py Co-authored-by: Zaccharie Ramzi * Update modopt/tests/test_opt.py Co-authored-by: Zaccharie Ramzi * Update modopt/tests/test_opt.py Co-authored-by: Zaccharie Ramzi * Update modopt/tests/test_opt.py Co-authored-by: Zaccharie Ramzi * Update modopt/tests/test_opt.py Co-authored-by: Zaccharie Ramzi * Update modopt/tests/test_opt.py Co-authored-by: Zaccharie Ramzi * Update modopt/tests/test_opt.py Co-authored-by: Zaccharie Ramzi * Update modopt/tests/test_opt.py Co-authored-by: Zaccharie Ramzi * renamed dummy functions in test_opt.py Co-authored-by: Zaccharie Ramzi * Release cleanup (#109) * cleaned up readme * cleaned up api docs Co-authored-by: Zaccharie Ramzi --- .github/workflows/cd-build.yml | 87 ++ .github/workflows/ci-build.yml | 126 +++ .gitignore | 149 ++- .pylintrc | 2 + .pyup.yml | 11 + .travis.yml | 43 - MANIFEST.in | 2 + README.md | 79 ++ README.rst | 152 ---- develop.txt | 8 + docs/_templates/module.rst_t | 8 + docs/_templates/package.rst_t | 54 ++ docs/_templates/toc.rst_t | 8 + docs/requirements.txt | 7 + docs/source/about.rst | 48 + docs/source/citing.rst | 7 + docs/source/conf.py | 416 +++------ docs/source/contributing.rst | 9 + docs/source/cosmostat_logo.jpg | Bin 0 -> 169466 bytes docs/source/dependencies.rst | 98 ++ docs/source/examples.rst | 6 - docs/source/index.rst | 142 +-- docs/source/installation.rst | 50 ++ docs/source/modopt.base.np_adjust.rst | 7 - docs/source/modopt.base.observable.rst | 7 - docs/source/modopt.base.rst | 22 - docs/source/modopt.base.transform.rst | 7 - docs/source/modopt.base.types.rst | 7 - docs/source/modopt.base.wrappers.rst | 7 - docs/source/modopt.info.rst | 7 - docs/source/modopt.interface.errors.rst | 7 - docs/source/modopt.interface.log.rst | 7 - docs/source/modopt.interface.rst | 19 - docs/source/modopt.math.convolve.rst | 7 - docs/source/modopt.math.matrix.rst | 7 - docs/source/modopt.math.metrics.rst | 7 - docs/source/modopt.math.rst | 21 - docs/source/modopt.math.stats.rst | 7 - docs/source/modopt.opt.algorithms.rst | 7 - docs/source/modopt.opt.cost.rst | 7 - docs/source/modopt.opt.gradient.rst | 7 - docs/source/modopt.opt.linear.rst | 7 - docs/source/modopt.opt.proximity.rst | 7 - docs/source/modopt.opt.reweight.rst | 7 - docs/source/modopt.opt.rst | 23 - docs/source/modopt.plot.cost_plot.rst | 7 - docs/source/modopt.plot.rst | 18 - docs/source/modopt.rst | 31 - docs/source/modopt.signal.filter.rst | 7 - docs/source/modopt.signal.noise.rst | 7 - docs/source/modopt.signal.positivity.rst | 7 - docs/source/modopt.signal.rst | 23 - docs/source/modopt.signal.svd.rst | 7 - docs/source/modopt.signal.validation.rst | 7 - docs/source/modopt.signal.wavelet.rst | 7 - docs/source/modopt_logo.png | Bin 0 -> 622687 bytes docs/source/modules.rst | 7 - docs/source/my_ref.bib | 17 + docs/source/neurospin_logo.png | Bin 0 -> 62657 bytes docs/source/notebooks.rst | 8 + docs/source/quickstart.rst | 12 + docs/source/toc.rst | 35 + docs/source/z_ref.rst | 5 + modopt/__init__.py | 23 +- modopt/base/__init__.py | 2 +- modopt/base/backend.py | 187 ++++ modopt/base/np_adjust.py | 94 +- modopt/base/observable.py | 121 +-- modopt/base/transform.py | 130 +-- modopt/base/types.py | 135 ++- modopt/base/wrappers.py | 25 +- modopt/info.py | 25 - modopt/interface/__init__.py | 4 +- modopt/interface/errors.py | 74 +- modopt/interface/log.py | 20 +- modopt/math/__init__.py | 4 +- modopt/math/convolve.py | 86 +- modopt/math/matrix.py | 163 ++-- modopt/math/metrics.py | 71 +- modopt/math/stats.py | 110 ++- modopt/opt/__init__.py | 4 +- modopt/opt/algorithms.py | 736 +++++++++------ modopt/opt/cost.py | 100 ++- modopt/opt/gradient.py | 158 ++-- modopt/opt/linear.py | 117 +-- modopt/opt/proximity.py | 660 ++++++++------ modopt/opt/reweight.py | 58 +- modopt/plot/__init__.py | 4 +- modopt/plot/cost_plot.py | 22 +- modopt/signal/__init__.py | 4 +- modopt/signal/filter.py | 57 +- modopt/signal/noise.py | 93 +- modopt/signal/positivity.py | 94 +- modopt/signal/svd.py | 167 ++-- modopt/signal/validation.py | 34 +- modopt/signal/wavelet.py | 186 ++-- modopt/tests/test_base.py | 295 +++--- modopt/tests/test_math.py | 570 +++++++----- modopt/tests/test_opt.py | 1049 ++++++++++++++-------- modopt/tests/test_signal.py | 457 ++++++---- notebooks/.gitkeep | 0 requirements.txt | 7 +- setup.cfg | 80 +- setup.py | 75 +- 104 files changed, 4868 insertions(+), 3361 deletions(-) create mode 100644 .github/workflows/cd-build.yml create mode 100644 .github/workflows/ci-build.yml create mode 100644 .pylintrc create mode 100644 .pyup.yml delete mode 100644 .travis.yml create mode 100644 README.md delete mode 100644 README.rst create mode 100644 develop.txt create mode 100644 docs/_templates/module.rst_t create mode 100644 docs/_templates/package.rst_t create mode 100644 docs/_templates/toc.rst_t create mode 100644 docs/requirements.txt create mode 100644 docs/source/about.rst create mode 100644 docs/source/citing.rst create mode 100644 docs/source/contributing.rst create mode 100644 docs/source/cosmostat_logo.jpg create mode 100644 docs/source/dependencies.rst delete mode 100644 docs/source/examples.rst create mode 100644 docs/source/installation.rst delete mode 100644 docs/source/modopt.base.np_adjust.rst delete mode 100644 docs/source/modopt.base.observable.rst delete mode 100644 docs/source/modopt.base.rst delete mode 100644 docs/source/modopt.base.transform.rst delete mode 100644 docs/source/modopt.base.types.rst delete mode 100644 docs/source/modopt.base.wrappers.rst delete mode 100644 docs/source/modopt.info.rst delete mode 100644 docs/source/modopt.interface.errors.rst delete mode 100644 docs/source/modopt.interface.log.rst delete mode 100644 docs/source/modopt.interface.rst delete mode 100644 docs/source/modopt.math.convolve.rst delete mode 100644 docs/source/modopt.math.matrix.rst delete mode 100644 docs/source/modopt.math.metrics.rst delete mode 100644 docs/source/modopt.math.rst delete mode 100644 docs/source/modopt.math.stats.rst delete mode 100644 docs/source/modopt.opt.algorithms.rst delete mode 100644 docs/source/modopt.opt.cost.rst delete mode 100644 docs/source/modopt.opt.gradient.rst delete mode 100644 docs/source/modopt.opt.linear.rst delete mode 100644 docs/source/modopt.opt.proximity.rst delete mode 100644 docs/source/modopt.opt.reweight.rst delete mode 100644 docs/source/modopt.opt.rst delete mode 100644 docs/source/modopt.plot.cost_plot.rst delete mode 100644 docs/source/modopt.plot.rst delete mode 100644 docs/source/modopt.rst delete mode 100644 docs/source/modopt.signal.filter.rst delete mode 100644 docs/source/modopt.signal.noise.rst delete mode 100644 docs/source/modopt.signal.positivity.rst delete mode 100644 docs/source/modopt.signal.rst delete mode 100644 docs/source/modopt.signal.svd.rst delete mode 100644 docs/source/modopt.signal.validation.rst delete mode 100644 docs/source/modopt.signal.wavelet.rst create mode 100644 docs/source/modopt_logo.png delete mode 100644 docs/source/modules.rst create mode 100644 docs/source/my_ref.bib create mode 100644 docs/source/neurospin_logo.png create mode 100644 docs/source/notebooks.rst create mode 100644 docs/source/quickstart.rst create mode 100644 docs/source/toc.rst create mode 100644 docs/source/z_ref.rst create mode 100644 modopt/base/backend.py mode change 100755 => 100644 modopt/base/observable.py delete mode 100644 modopt/info.py create mode 100644 notebooks/.gitkeep diff --git a/.github/workflows/cd-build.yml b/.github/workflows/cd-build.yml new file mode 100644 index 00000000..1e49f8bc --- /dev/null +++ b/.github/workflows/cd-build.yml @@ -0,0 +1,87 @@ +name: CD + +on: + push: + branches: + - master + - main + +jobs: + + coverage: + name: Deploy Coverage Results + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Set up Conda with Python 3.8 + uses: conda-incubator/setup-miniconda@v2 + with: + auto-update-conda: true + python-version: 3.8 + auto-activate-base: false + + - name: Install dependencies + shell: bash -l {0} + run: | + python -m pip install --upgrade pip + python -m pip install -r develop.txt + python -m pip install twine + python -m pip install . + + - name: Run Tests + shell: bash -l {0} + run: | + python setup.py test + + - name: Check distribution + shell: bash -l {0} + run: | + python setup.py sdist + twine check dist/* + + - name: Upload coverage to Codecov + uses: codecov/codecov-action@v1 + with: + token: ${{ secrets.CODECOV_TOKEN }} + file: coverage.xml + flags: unittests + + api: + name: Deploy API Documentation + needs: coverage + runs-on: ubuntu-latest + if: success() + + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Set up Conda with Python 3.8 + uses: conda-incubator/setup-miniconda@v2 + with: + auto-update-conda: true + python-version: 3.8 + auto-activate-base: false + + - name: Install dependencies + shell: bash -l {0} + run: | + conda install -c conda-forge pandoc + python -m pip install --upgrade pip + python -m pip install -r docs/requirements.txt + python -m pip install . + + - name: Build API documentation + shell: bash -l {0} + run: | + sphinx-apidoc -t docs/_templates -feTMo docs/source modopt + sphinx-build -E docs/source docs/_build + + - name: Deploy API documentation + uses: peaceiris/actions-gh-pages@v3.5.9 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + publish_dir: docs/_build diff --git a/.github/workflows/ci-build.yml b/.github/workflows/ci-build.yml new file mode 100644 index 00000000..2ed4960d --- /dev/null +++ b/.github/workflows/ci-build.yml @@ -0,0 +1,126 @@ +name: CI + +on: + pull_request: + branches: + - develop + - master + - main + +jobs: + test-full: + name: Full Test Suite + runs-on: ${{ matrix.os }} + + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, macos-latest] + python-version: [3.8] + + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Report WPS Errors + uses: wemake-services/wemake-python-styleguide@0.14.1 + continue-on-error: true + with: + reporter: 'github-pr-review' + path: './modopt' + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Set up Conda with Python ${{ matrix.python-version }} + uses: conda-incubator/setup-miniconda@v2 + with: + auto-update-conda: true + python-version: ${{ matrix.python-version }} + auto-activate-base: false + + - name: Check Conda + shell: bash -l {0} + run: | + conda info + conda list + python --version + + - name: Install Dependencies + shell: bash -l {0} + run: | + python --version + python -m pip install --upgrade pip + python -m pip install -r develop.txt + python -m pip install -r docs/requirements.txt + python -m pip install astropy scikit-image scikit-learn + python -m pip install twine + python -m pip install . + + - name: Run Tests + shell: bash -l {0} + run: | + export PATH=/usr/share/miniconda/bin:$PATH + python setup.py test + + - name: Save Test Results + if: always() + uses: actions/upload-artifact@v2 + with: + name: unit-test-results-${{ matrix.os }}-${{ matrix.python-version }} + path: pytest.xml + + - name: Check Distribution + shell: bash -l {0} + run: | + python setup.py sdist + twine check dist/* + + - name: Check API Documentation build + shell: bash -l {0} + run: | + conda install -c conda-forge pandoc + sphinx-apidoc -t docs/_templates -feTMo docs/source modopt + sphinx-build -b doctest -E docs/source docs/_build + + - name: Upload Coverage to Codecov + uses: codecov/codecov-action@v1 + with: + token: ${{ secrets.CODECOV_TOKEN }} + file: coverage.xml + flags: unittests + + test-basic: + name: Basic Test Suite + runs-on: ${{ matrix.os }} + + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, macos-latest] + python-version: [3.6, 3.7, 3.9] + + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Set up Conda with Python ${{ matrix.python-version }} + uses: conda-incubator/setup-miniconda@v2 + with: + auto-update-conda: true + python-version: ${{ matrix.python-version }} + auto-activate-base: false + + - name: Install Dependencies + shell: bash -l {0} + run: | + python --version + python -m pip install --upgrade pip + python -m pip install -r develop.txt + python -m pip install astropy scikit-image scikit-learn + python -m pip install . + + - name: Run Tests + shell: bash -l {0} + run: | + export PATH=/usr/share/miniconda/bin:$PATH + python setup.py test diff --git a/.gitignore b/.gitignore index f76522d1..06dff8db 100644 --- a/.gitignore +++ b/.gitignore @@ -1,21 +1,142 @@ -# Ignore Python compilation -*.pyc +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class -# Ignore scripts -*.sh +# C extensions +*.so -# Ignore cache -*.cache/ +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec -# Ignore coverage tests +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ .coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ .pytest_cache/ +cover/ +pytest.xml -# Ignore installation -.eggs/ -modopt.egg-info/ -dist/ -build/ +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ +docs/source/fortuna.* +docs/source/scripts.* +docs/source/*.nblink + +# PyBuilder +.pybuilder/ +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +# For a library or package, you might want to ignore these files since the code is +# intended to run in multiple environments; otherwise, check them in: +# .python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# pytype static type analyzer +.pytype/ -# Ignore pypi config -.pypirc +# Cython debug symbols +cython_debug/ diff --git a/.pylintrc b/.pylintrc new file mode 100644 index 00000000..3ac9aef9 --- /dev/null +++ b/.pylintrc @@ -0,0 +1,2 @@ +[MASTER] +ignore-patterns=**/docs/**/*.py diff --git a/.pyup.yml b/.pyup.yml new file mode 100644 index 00000000..d844b78b --- /dev/null +++ b/.pyup.yml @@ -0,0 +1,11 @@ +# autogenerated pyup.io config file +# see https://pyup.io/docs/configuration/ for all available options + +schedule: '' +update: all +label_prs: update +assignees: sfarrens +requirements: + - requirements.txt + - develop.txt + - docs/requirements.txt diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index b5b770d7..00000000 --- a/.travis.yml +++ /dev/null @@ -1,43 +0,0 @@ -language: python -dist: focal -sudo: required - -# GitHub branch -branches: - only: - - master - -# build jobs -jobs: - include: - - python: 3.6 - - python: 3.7 - - python: 3.8 - after_success: - - coveralls - - stage: deploy - install: - - pip install numpy scipy progressbar2 - - pip install sphinx sphinx-rtd-theme sphinxcontrib-bibtex numpydoc==0.9.2 travis-sphinx - script: - - sphinx-apidoc -feo docs/source modopt - - travis-sphinx -v -o docs/build build -n -s docs/source - after_success: - - travis-sphinx -o docs/build deploy - -# update pre-installed packages -before_install: - - pip list --outdated --format=freeze | grep -v '^\-e' | cut -d = -f 1 | xargs -n1 pip install -U - -# install dependencies -install: - - pip install scikit-learn - - pip install astropy scikit-image - -# run unit tests -script: - - python setup.py test - -# notification settings -notification: - email: false diff --git a/MANIFEST.in b/MANIFEST.in index 916c2c9b..9a2f374e 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,3 +1,5 @@ include requirements.txt +include develop.txt +include docs/requirements.txt include README.rst include LICENSE.txt diff --git a/README.md b/README.md new file mode 100644 index 00000000..aa72d976 --- /dev/null +++ b/README.md @@ -0,0 +1,79 @@ +# ModOpt + + + +| Usage | Development | Release | +| ----- | ----------- | ------- | +| [![docs](https://img.shields.io/badge/docs-Sphinx-blue)](https://cea-cosmic.github.io/ModOpt/) | [![build](https://github.com/CEA-COSMIC/modopt/workflows/CI/badge.svg)](https://github.com/CEA-COSMIC/modopt/actions?query=workflow%3ACI) | [![release](https://img.shields.io/github/v/release/CEA-COSMIC/modopt)](https://github.com/CEA-COSMIC/modopt/releases/latest) | +| [![license](https://img.shields.io/github/license/CEA-COSMIC/modopt)](https://github.com/CEA-COSMIC/modopt/blob/master/LICENCE.txt) | [![deploy](https://github.com/CEA-COSMIC/modopt/workflows/CD/badge.svg)](https://github.com/CEA-COSMIC/modopt/actions?query=workflow%3ACD) | [![pypi](https://img.shields.io/pypi/v/modopt)](https://pypi.org/project/modopt/) | +| [![wemake-python-styleguide](https://img.shields.io/badge/style-wemake-000000.svg)](https://github.com/wemake-services/wemake-python-styleguide) | [![codecov](https://codecov.io/gh/CEA-COSMIC/modopt/branch/master/graph/badge.svg?token=XHJIQXV7AX)](https://codecov.io/gh/CEA-COSMIC/modopt) | [![python](https://img.shields.io/pypi/pyversions/modopt)](https://www.python.org/downloads/source/) | +| [![contribute](https://img.shields.io/badge/contribute-read-lightgrey)](https://github.com/CEA-COSMIC/modopt/blob/master/CONTRIBUTING.md) | [![CodeFactor](https://www.codefactor.io/repository/github/CEA-COSMIC/modopt/badge)](https://www.codefactor.io/repository/github/CEA-COSMIC/modopt) | | +| [![coc](https://img.shields.io/badge/conduct-read-lightgrey)](https://github.com/CEA-COSMIC/modopt/blob/master/CODE_OF_CONDUCT.md) | [![Updates](https://pyup.io/repos/github/CEA-COSMIC/modopt/shield.svg)](https://pyup.io/repos/github/CEA-COSMIC/ModOpt/) | | + +ModOpt is a series of **Modular Optimisation** tools for solving inverse problems. + +See [documentation](https://CEA-COSMIC.github.io/ModOpt/) for more details. + +## Installation + +To install using `pip` run the following command: + +```bash + $ pip install modopt +``` + +To clone the ModOpt repository from GitHub run the following command: + +```bash + $ git clone https://github.com/CEA-COSMIC/ModOpt.git +``` + +## Dependencies + +All packages required by ModOpt should be installed automatically. Optional packages, however, will need to be installed manually. + +### Required Packages + +In order to run the code in this repository the following packages must be +installed: + +* [Python](https://www.python.org/) [> 3.6] +* [importlib_metadata](https://importlib-metadata.readthedocs.io/en/latest/) [==3.7.0] +* [Numpy](http://www.numpy.org/) [==1.19.5] +* [Scipy](http://www.scipy.org/) [==1.5.4] +* [Progressbar 2](https://progressbar-2.readthedocs.io/) [==3.53.1] + +### Optional Packages + +The following packages can optionally be installed to add extra functionality: + +* [Astropy](http://www.astropy.org/) +* [Matplotlib](http://matplotlib.org/) +* [Scikit-Image](https://scikit-image.org/) +* [Scikit-Learn](https://scikit-learn.org/) +* [Termcolor](https://pypi.python.org/pypi/termcolor) + +For (partial) GPU compliance the following packages can also be installed. +Note that none of these are required for running on a CPU. + +* [CuPy](https://cupy.dev/) +* [Torch](https://pytorch.org/) + +## Citation + +If you use ModOpt in a scientific publication, we would appreciate citations to the following paper: + +[PySAP: Python Sparse Data Analysis Package for multidisciplinary image processing](https://www.sciencedirect.com/science/article/pii/S2213133720300561), S. Farrens et al., Astronomy and Computing 32, 2020 + +The BibTeX citation is the following: +``` +@Article{farrens2020pysap, + title={{PySAP: Python Sparse Data Analysis Package for multidisciplinary image processing}}, + author={Farrens, S and Grigis, A and El Gueddari, L and Ramzi, Z and Chaithya, GR and Starck, S and Sarthou, B and Cherkaoui, H and Ciuciu, P and Starck, J-L}, + journal={Astronomy and Computing}, + volume={32}, + pages={100402}, + year={2020}, + publisher={Elsevier} +} +``` diff --git a/README.rst b/README.rst deleted file mode 100644 index 9690f9d4..00000000 --- a/README.rst +++ /dev/null @@ -1,152 +0,0 @@ -ModOpt -====== - -|travis| |coveralls| |license| |python36| |python37| |python38| |pypi| - -.. |travis| image:: https://travis-ci.org/CEA-COSMIC/ModOpt.svg?branch=master - :target: https://travis-ci.org/CEA-COSMIC/ModOpt - -.. |coveralls| image:: https://coveralls.io/repos/github/CEA-COSMIC/ModOpt/badge.svg - :target: https://coveralls.io/github/CEA-COSMIC/ModOpt - -.. |license| image:: https://img.shields.io/github/license/mashape/apistatus.svg - :target: https://github.com/CEA-COSMIC/ModOpt/blob/master/LICENCE.txt - -.. |python36| image:: https://img.shields.io/badge/python-3.6-green.svg - :target: https://www.python.org/ - -.. |python37| image:: https://img.shields.io/badge/python-3.7-green.svg - :target: https://www.python.org/ - -.. |python38| image:: https://img.shields.io/badge/python-3.8-green.svg - :target: https://www.python.org/ - -.. |pypi| image:: https://badge.fury.io/py/modopt.svg - :target: https://badge.fury.io/py/modopt - - -:Author: Samuel Farrens `(samuel.farrens@cea.fr) `_ - -:Version: 1.4.4 - -:Release Date: 16/06/2020 - -:Documentation: |link-to-docs| - -:Repository: |link-to-repo| - -.. |link-to-docs| raw:: html - - https://cea-cosmic.github.io/ModOpt/ - -.. |link-to-repo| raw:: html - - https://github.com/CEA-COSMIC/ModOpt - -ModOpt is a series of Modular Optimisation tools for solving inverse problems. - -Contents -======== - -1. `Dependencies`_ -2. `Installation`_ - -Dependencies -============ - -Required Packages ------------------ - -In order to run the code in this repository the following packages must be -installed: - -* |link-to-python| [Last tested with v3.8.2] - -* |link-to-numpy| [Tested with v1.18.3] - -* |link-to-scipy| [Tested with v1.4.1] - -* |link-to-progressbar| [Tested with v3.51.1] - -.. |link-to-python| raw:: html - - Python - -.. |link-to-numpy| raw:: html - - Numpy - -.. |link-to-scipy| raw:: html - - Scipy - -.. |link-to-progressbar| raw:: html - - Progressbar 2 - -Optional Packages ------------------ - -The following packages can optionally be installed to add extra functionality: - -* |link-to-astropy| [Last tested with v4.0.1] - -* |link-to-matplotlib| [Last tested with v3.2.1] - -* |link-to-skimage| [Requires >=v0.16.2] - -* |link-to-sklearn| [Requires >=v0.22.2] - -* |link-to-termcolor| [Last tested with v1.1.0] - -.. |link-to-astropy| raw:: html - - Astropy - -.. |link-to-matplotlib| raw:: html - - Matplotlib - -.. |link-to-skimage| raw:: html - - Scikit-Image - -.. |link-to-sklearn| raw:: html - - Scikit-Learn - -.. |link-to-termcolor| raw:: html - - Termcolor - -Installation -============ - -To install using `pip` run the following command: - -.. code-block:: bash - - $ pip install modopt - -To install using `easy_install` run the following command: - -.. code-block:: bash - - $ easy_install modopt - -To clone the ModOpt repository from GitHub run the following command: - -.. code-block:: bash - - $ git clone https://github.com/cea-cosmic/ModOpt diff --git a/develop.txt b/develop.txt new file mode 100644 index 00000000..b88396e7 --- /dev/null +++ b/develop.txt @@ -0,0 +1,8 @@ +coverage==5.5 +nose==1.3.7 +pytest==6.2.2 +pytest-cov==2.11.1 +pytest-pep8==1.0.6 +pytest-emoji==0.2.0 +pytest-flake8==1.0.7 +wemake-python-styleguide==0.15.2 diff --git a/docs/_templates/module.rst_t b/docs/_templates/module.rst_t new file mode 100644 index 00000000..73ad73fc --- /dev/null +++ b/docs/_templates/module.rst_t @@ -0,0 +1,8 @@ +{%- if show_headings %} +{{- basename | e | heading(2) }} + +{% endif -%} +.. automodule:: {{ qualname }} +{%- for option in automodule_options %} + :{{ option }}: +{%- endfor %} diff --git a/docs/_templates/package.rst_t b/docs/_templates/package.rst_t new file mode 100644 index 00000000..344f9d16 --- /dev/null +++ b/docs/_templates/package.rst_t @@ -0,0 +1,54 @@ +{%- macro automodule(modname, options) -%} +.. automodule:: {{ modname }} +{%- for option in options %} + :{{ option }}: +{%- endfor %} +{%- endmacro %} + +{%- macro toctree(docnames) -%} +.. toctree:: + :maxdepth: {{ maxdepth }} +{% for docname in docnames %} + {{ docname }} +{%- endfor %} +{%- endmacro %} + +{%- if is_namespace %} +{{- [pkgname, "namespace"] | join(" ") | e | heading }} +{% else %} +{{- pkgname | e | heading }} + +{% endif %} + +{%- if modulefirst and not is_namespace %} +{{ automodule(pkgname, automodule_options) }} +{% endif %} + +{%- if subpackages %} +Subpackages +----------- + +{{ toctree(subpackages) }} +{% endif %} + +{%- if submodules %} +Submodules +---------- +{% if separatemodules %} +{{ toctree(submodules) }} +{% else %} +{%- for submodule in submodules %} +{% if show_headings %} +{{- submodule | e | heading(2) }} +{% endif %} +{{ automodule(submodule, automodule_options) }} +{% endfor %} +{%- endif %} +{%- endif %} + +{%- if not modulefirst and not is_namespace %} +Module contents +--------------- + +{{ automodule(pkgname, automodule_options) }} +{% endif %} diff --git a/docs/_templates/toc.rst_t b/docs/_templates/toc.rst_t new file mode 100644 index 00000000..f0877eeb --- /dev/null +++ b/docs/_templates/toc.rst_t @@ -0,0 +1,8 @@ +{{ header | heading }} + +.. toctree:: + :maxdepth: {{ maxdepth }} +{% for docname in docnames %} + {{ docname }} +{%- endfor %} + diff --git a/docs/requirements.txt b/docs/requirements.txt new file mode 100644 index 00000000..e1c873a2 --- /dev/null +++ b/docs/requirements.txt @@ -0,0 +1,7 @@ +jupyter==1.0.0 +nbsphinx==0.8.2 +nbsphinx-link==1.3.0 +numpydoc==1.1.0 +sphinx==3.5.2 +sphinxcontrib-bibtex==2.2.0 +sphinxawesome-theme==1.19.2 diff --git a/docs/source/about.rst b/docs/source/about.rst new file mode 100644 index 00000000..0d412b5d --- /dev/null +++ b/docs/source/about.rst @@ -0,0 +1,48 @@ +About +===== + +ModOpt was developed as part of |link-to-cosmic|, a multi-disciplinary collaboration +between |link-to-neurospin|, experts in biomedical imaging, and |link-to-cosmostat|, +experts in astrophysical image processing. The package was +designed to provide the backend optimisation algorithms for +|link-to-pysap| :cite:`farrens:2020`, but also serves as a stand-alone library +of inverse problem solving tools. While PySAP aims to provide +application-specific tools for solving complex imaging problems, ModOpt can in +principle be applied to any linear inverse problem. + +Contributors +------------ + +You can find a |link-to-contributors|. + +.. |link-to-cosmic| raw:: html + + COSMIC + +.. |link-to-neurospin| raw:: html + + NeuroSpin + +.. |link-to-cosmostat| raw:: html + + CosmoStat + +.. |link-to-pysap| raw:: html + + PySAP + +.. |link-to-contributors| raw:: html + + list of ModOpt contributors here + + +.. image:: cosmostat_logo.jpg + :width: 300 + :alt: CosmoStat Logo + +.. image:: neurospin_logo.png + :width: 300 + :alt: NeuroSpin Logo diff --git a/docs/source/citing.rst b/docs/source/citing.rst new file mode 100644 index 00000000..19471a51 --- /dev/null +++ b/docs/source/citing.rst @@ -0,0 +1,7 @@ +Citing this Package +=================== + +We kindly request that any academic work making use of this package to cite :cite:`farrens:2020`. + +.. bibliography:: my_ref.bib + :style: alpha diff --git a/docs/source/conf.py b/docs/source/conf.py index cca36eb4..95aaba20 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -1,19 +1,10 @@ # -*- coding: utf-8 -*- -# -# ModOpt documentation build configuration file, created by -# sphinx-quickstart on Mon Oct 24 16:46:22 2016. -# -# This file is execfile()d with the current directory set to its -# containing dir. -# -# Note that not all possible configuration values are present in this -# autogenerated file. -# -# All configuration values have a default; values that are commented out -# serve to show the default. +# Python Template sphinx config +# Import relevant modules import sys import os +from importlib_metadata import metadata # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the @@ -22,8 +13,17 @@ # -- General configuration ------------------------------------------------ +# General information about the project. +project = 'modopt' + +mdata = metadata(project) +author = mdata['Author'] +version = mdata['Version'] +copyright = '2020, {}'.format(author) +gh_user = 'sfarrens' + # If your documentation needs a minimal Sphinx version, state it here. -# needs_sphinx = '1.0' +needs_sphinx = '3.3' # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom @@ -31,128 +31,79 @@ extensions = [ 'sphinx.ext.autodoc', 'sphinx.ext.autosummary', - 'sphinxcontrib.bibtex', + 'sphinx.ext.coverage', 'sphinx.ext.doctest', + 'sphinx.ext.ifconfig', 'sphinx.ext.intersphinx', - 'sphinx.ext.todo', - 'sphinx.ext.coverage', 'sphinx.ext.mathjax', - 'sphinx.ext.ifconfig', - 'sphinx.ext.viewcode', 'sphinx.ext.napoleon', - 'numpydoc' + 'sphinx.ext.todo', + 'sphinx.ext.viewcode', + 'sphinxawesome_theme', + 'sphinxcontrib.bibtex', + 'nbsphinx', + 'nbsphinx_link', + 'numpydoc', ] -# Include init in class documentation. -autoclass_content = 'both' +# Include module names for objects +add_module_names = False -# Order docstrings as in the source -autodoc_member_order = 'bysource' +# Set class documentation standard. +autoclass_content = 'class' -# Include private class methods -autodoc_default_flags = ['members', 'private-members'] +# Audodoc options +autodoc_default_options = { + 'member-order': 'bysource', + 'private-members': True, + 'show-inheritance': True +} + +# Generate summaries +autosummary_generate = True # Suppress class members in toctree. numpydoc_show_class_members = False -# Add any paths that contain templates here, relative to this directory. -templates_path = ['_templates'] - # The suffix(es) of source filenames. # You can specify multiple suffix as a list of string: -# source_suffix = ['.rst', '.md'] -source_suffix = '.rst' - -# The encoding of source files. -# source_encoding = 'utf-8-sig' +source_suffix = ['.rst', '.md'] # The master toctree document. master_doc = 'index' -# General information about the project. -project = u'modopt' -copyright = u'2017, Samuel Farrens' -author = u'Samuel Farrens' - -# The version info for the project you're documenting, acts as replacement for -# |version| and |release|, also used in various other places throughout the -# built documents. -# -# The short X.Y version. -version = u'1.0' -# The full version, including alpha/beta/rc tags. -release = u'1.0' - -# The language for content autogenerated by Sphinx. Refer to documentation -# for a list of supported languages. -# -# This is also used if you do content translation via gettext catalogs. -# Usually you set "language" from the command line for these cases. -language = None - -# There are two options for replacing |today|: either, you set today to some -# non-false value, then it is used: -# today = '' -# Else, today_fmt is used as the format for a strftime call. -# today_fmt = '%B %d, %Y' - -# List of patterns, relative to source directory, that match files and -# directories to ignore when looking for source files. -exclude_patterns = [] - -# The reST default role (used for this markup: `text`) to use for all -# documents. -# default_role = None - -# If true, '()' will be appended to :func: etc. cross-reference text. -# add_function_parentheses = True - -# If true, the current module name will be prepended to all description -# unit titles (such as .. function::). -# add_module_names = True - # If true, sectionauthor and moduleauthor directives will be shown in the # output. They are ignored by default. show_authors = True # The name of the Pygments (syntax highlighting) style to use. -pygments_style = 'sphinx' - -# A list of ignored prefixes for module index sorting. -# modindex_common_prefix = [] - -# If true, keep warnings as "system message" paragraphs in the built documents. -# keep_warnings = False +pygments_style = 'default' # If true, `todo` and `todoList` produce output, else they produce nothing. todo_include_todos = True - # -- Options for HTML output ---------------------------------------------- # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. -html_theme = 'sphinx_rtd_theme' -# html_theme = 'bizstyle' +html_theme = 'sphinxawesome_theme' +# html_theme = 'sphinx_book_theme' # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the # documentation. -# html_theme_options = {} html_theme_options = { - 'collapse_navigation': False, - 'display_version': True, - 'navigation_depth': 3, - 'titles_only': True, - 'includehidden': False, + "nav_include_hidden": True, + "show_nav": True, + "show_breadcrumbs": False, + "breadcrumbs_separator": "/" } +html_collapsible_definitions = True -# Add any paths that contain custom themes here, relative to this directory. -# html_theme_path = [] # The name for this set of Sphinx documents. If None, it defaults to # " v documentation". -# html_title = None +html_title = '{0} v{1}'.format(project, version) # A shorter title for the navigation bar. Default is the same as html_title. # html_short_title = None @@ -166,236 +117,111 @@ # pixels large. # html_favicon = None -# Add any paths that contain custom static files (such as style sheets) here, -# 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_static_path = [] - -# Add any extra paths that contain custom files (such as robots.txt or -# .htaccess) here, relative to this directory. These files are copied -# directly to the root of the documentation. -# html_extra_path = [] - # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, # using the given strftime format. -# html_last_updated_fmt = '%b %d, %Y' +html_last_updated_fmt = '%d %b, %Y' # If true, SmartyPants will be used to convert quotes and dashes to # typographically correct entities. -# html_use_smartypants = True - -# Custom sidebar templates, maps document names to template names. -# html_sidebars = {} -html_sidebars = {'**': ['globaltoc.html', 'relations.html', - 'sourcelink.html', 'searchbox.html'], } - - -# Additional templates that should be rendered to pages, maps page names to -# template names. -# html_additional_pages = {} - -# If false, no module index is generated. -# html_domain_indices = True - -# If false, no index is generated. -# html_use_index = True - -# If true, the index is split into individual pages for each letter. -# html_split_index = False - -# If true, links to the reST sources are added to the pages. -# html_show_sourcelink = True +html_use_smartypants = True # If true, "Created using Sphinx" is shown in the HTML footer. Default is True. -# html_show_sphinx = True +html_show_sphinx = True # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. -# html_show_copyright = True - -# If true, an OpenSearch description file will be output, and all pages will -# contain a tag referring to it. The value of this option must be the -# base URL from which the finished HTML is served. -# html_use_opensearch = '' - -# This is the file name suffix for HTML files (e.g. ".xhtml"). -# html_file_suffix = None - -# Language to be used for generating the HTML full-text search index. -# Sphinx supports the following languages: -# 'da', 'de', 'en', 'es', 'fi', 'fr', 'hu', 'it', 'ja' -# 'nl', 'no', 'pt', 'ro', 'ru', 'sv', 'tr' -# html_search_language = 'en' +html_show_copyright = True -# A dictionary with options for the search language support, empty by default. -# Now only 'ja' uses this config value -# html_search_options = {'type': 'default'} +# -- Options for nbshpinx output ------------------------------------------ -# The name of a javascript file (relative to the configuration directory) that -# implements a search results scorer. If empty, the default will be used. -# html_search_scorer = 'scorer.js' -# Output file base name for HTML help builder. -htmlhelp_basename = 'sftoolsdoc' +# Custom fucntion to find notebooks, create .nblink files and update the +# notebooks.rst file +def add_notebooks(nb_path='../../notebooks'): -# -- Options for LaTeX output --------------------------------------------- + print('Looking for notebooks') + nb_ext = '.ipynb' + nb_rst_file_name = 'notebooks.rst' + nb_link_format = '{{\n "path": "{0}/{1}"\n}}' -latex_elements = { - # The paper size ('letterpaper' or 'a4paper'). - # 'papersize': 'letterpaper', + nbs = sorted([nb for nb in os.listdir(nb_path) if nb.endswith(nb_ext)]) - # The font size ('10pt', '11pt' or '12pt'). - # 'pointsize': '10pt', + for list_pos, nb in enumerate(nbs): - # Additional stuff for the LaTeX preamble. - # 'preamble': '', + nb_name = nb.rstrip(nb_ext) - # Latex figure (float) alignment - # 'figure_align': 'htbp', -} - -# 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, 'modopt.tex', u'modopt Documentation', - u'Samuel Farrens', 'manual'), -] - -# The name of an image file (relative to this directory) to place at the top of -# the title page. -# latex_logo = None - -# For "manual" documents, if this is true, then toplevel headings are parts, -# not chapters. -# latex_use_parts = False - -# If true, show page references after internal links. -# latex_show_pagerefs = False - -# If true, show URL addresses after external links. -# latex_show_urls = False - -# Documents to append as an appendix to all manuals. -# latex_appendices = [] - -# If false, no module index is generated. -# latex_domain_indices = True - - -# -- 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, 'modopt', u'modopt Documentation', - [author], 1) -] - -# If true, show URL addresses after external links. -# man_show_urls = False - - -# -- 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, 'modopt', u'modopt Documentation', - author, 'modopt', 'One line description of project.', - 'Miscellaneous'), -] - -# Documents to append as an appendix to all manuals. -# texinfo_appendices = [] - -# If false, no module index is generated. -# texinfo_domain_indices = True - -# How to display URL addresses: 'footnote', 'no', or 'inline'. -# texinfo_show_urls = 'footnote' - -# If true, do not generate a @detailmenu in the "Top" node's menu. -# texinfo_no_detailmenu = False - - -# -- Options for Epub output ---------------------------------------------- - -# Bibliographic Dublin Core info. -epub_title = project -epub_author = author -epub_publisher = author -epub_copyright = copyright - -# The basename for the epub file. It defaults to the project name. -# epub_basename = project + nb_link_file_name = nb_name + '.nblink' + print('Writing {0}'.format(nb_link_file_name)) + with open(nb_link_file_name, 'w') as nb_link_file: + nb_link_file.write(nb_link_format.format(nb_path, nb)) -# The HTML theme for the epub output. Since the default themes are not -# optimized for small screen space, using the same theme for HTML and epub -# output is usually not wise. This defaults to 'epub', a theme designed to save -# visual space. -# epub_theme = 'epub' + print('Looking for {0} in {1}'.format(nb_name, nb_rst_file_name)) + with open(nb_rst_file_name, 'r') as nb_rst_file: + check_name = nb_name not in nb_rst_file.read() -# The language of the text. It defaults to the language option -# or 'en' if the language is not set. -# epub_language = '' + if check_name: + print('Adding {0} to {1}'.format(nb_name, nb_rst_file_name)) + with open(nb_rst_file_name, 'a') as nb_rst_file: + if list_pos == 0: + nb_rst_file.write('\n') + nb_rst_file.write(' {0}\n'.format(nb_name)) -# The scheme of the identifier. Typical schemes are ISBN or URL. -# epub_scheme = '' + return nbs -# The unique identifier of the text. This can be a ISBN number -# or the project homepage. -# epub_identifier = '' -# A unique identification for the text. -# epub_uid = '' +# Add notebooks +add_notebooks() -# A tuple containing the cover image and cover page html template filenames. -# epub_cover = () +binder = 'https://mybinder.org/v2/gh' +binder_badge = 'https://mybinder.org/badge_logo.svg' +github = 'https://github.com/' +github_badge = 'https://badgen.net/badge/icon/github?icon=github&label' -# A sequence of (type, uri, title) tuples for the guide element of content.opf. -# epub_guide = () +# Remove promts and add binder badge +nb_header_pt1 = r''' +{% if env.metadata[env.docname]['nbsphinx-link-target'] %} +{% set docpath = env.metadata[env.docname]['nbsphinx-link-target'] %} +{% else %} +{% set docpath = env.doc2path(env.docname, base='docs/source/') %} +{% endif %} -# HTML files that should be inserted before the pages created by sphinx. -# The format is a list of tuples containing the path and title. -# epub_pre_files = [] +.. raw:: html -# HTML files that should be inserted after the pages created by sphinx. -# The format is a list of tuples containing the path and title. -# epub_post_files = [] + -# A list of files that should not be packed into the epub file. -epub_exclude_files = ['search.html'] +''' +nb_header_pt2 = ( + r'''

''' + r'''''' + + r'''Binder badge
''' + r'''

''' +) -# The depth of the table of contents in toc.ncx. -# epub_tocdepth = 3 +nbsphinx_prolog = nb_header_pt1 + nb_header_pt2 -# Allow duplicate toc entries. -# epub_tocdup = True +# -- Intersphinx Mapping ---------------------------------------------- -# Choose between 'default' and 'includehidden'. -# epub_tocscope = 'default' - -# Fix unsupported image types using the Pillow. -# epub_fix_images = False - -# Scale large images. -# epub_max_image_width = 0 - -# How to display URL addresses: 'footnote', 'no', or 'inline'. -# epub_show_urls = 'inline' - -# If false, no index is generated. -# epub_use_index = True - - -# Example configuration for intersphinx: refer to the Python standard library. -# intersphinx_mapping = {'https://docs.python.org/': None} +# Refer to the package libraries for type definitions intersphinx_mapping = { - 'python': ('https://docs.python.org/3/', None), - 'numpy': ('https://docs.scipy.org/doc/numpy', None), - 'scipy': ('http://docs.scipy.org/doc/scipy/reference/', None), - 'matplotlib': ('http://matplotlib.sourceforge.net/', None), - 'astropy': ('http://docs.astropy.org/en/latest/', None) + 'python': ('http://docs.python.org/3', None), + 'numpy': ('https://numpy.org/doc/stable/', None), + 'scipy': ('https://docs.scipy.org/doc/scipy/reference', None), + 'matplotlib': ('https://matplotlib.org', None), + 'astropy': ('http://docs.astropy.org/en/latest/', None), + 'cupy': ('https://docs-cupy.chainer.org/en/stable/', None), + 'torch': ('https://pytorch.org/docs/stable/', None), } + +# -- BibTeX Setting ---------------------------------------------- + +bibtex_bibfiles = ['refs.bib', 'my_ref.bib'] diff --git a/docs/source/contributing.rst b/docs/source/contributing.rst new file mode 100644 index 00000000..f983d030 --- /dev/null +++ b/docs/source/contributing.rst @@ -0,0 +1,9 @@ +Contributing +============ + +Read our `Contribution Guidelines `_ +for details on how to contribute to the development of this package. + +All contributors are kindly asked to adhere to the +`Code of Conduct `_ +at all times to ensure a safe and inclusive environment for everyone. diff --git a/docs/source/cosmostat_logo.jpg b/docs/source/cosmostat_logo.jpg new file mode 100644 index 0000000000000000000000000000000000000000..4945c4684b87ba27a90190c52fa95dbeede8cd9c GIT binary patch literal 169466 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

xVv^hpABxb;PoMC0Ekk-^_M#g7TQQP4${wbB>J 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

vh$y*V^W!*o%_N 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 literal 0 HcmV?d00001 diff --git a/docs/source/dependencies.rst b/docs/source/dependencies.rst new file mode 100644 index 00000000..782807f8 --- /dev/null +++ b/docs/source/dependencies.rst @@ -0,0 +1,98 @@ +Dependencies +============ + +.. note:: + + All packages required by ModOpt should be installed automatically. Optional + packages, however, will need to be installed manually. + +Required Packages +----------------- + +In order to use ModOpt the following packages must be installed: + +* |link-to-python| ``[> 3.6]`` +* |link-to-metadata| ``[==3.7.0]`` +* |link-to-numpy| ``[==1.19.5]`` +* |link-to-scipy| ``[==1.5.4]`` +* |link-to-progressbar| ``[==3.53.1]`` + +.. |link-to-python| raw:: html + + Python + +.. |link-to-metadata| raw:: html + + importlib_metadata + +.. |link-to-numpy| raw:: html + + Numpy + +.. |link-to-scipy| raw:: html + + Scipy + +.. |link-to-progressbar| raw:: html + + Progressbar 2 + +Optional Packages +----------------- + +The following packages can optionally be installed to add extra functionality: + +* |link-to-astropy| +* |link-to-matplotlib| +* |link-to-skimage| +* |link-to-sklearn| +* |link-to-termcolor| + +.. |link-to-astropy| raw:: html + + Astropy + +.. |link-to-matplotlib| raw:: html + + Matplotlib + +.. |link-to-skimage| raw:: html + + Scikit-Image + +.. |link-to-sklearn| raw:: html + + Scikit-Learn + +.. |link-to-termcolor| raw:: html + + Termcolor + +For GPU compliance the following packages can also be installed: + +* |link-to-cupy| +* |link-to-torch| + +.. |link-to-cupy| raw:: html + + CuPy + +.. |link-to-torch| raw:: html + + Torch + +.. note:: + + Note that none of these are required for running on a CPU. diff --git a/docs/source/examples.rst b/docs/source/examples.rst deleted file mode 100644 index ad8e915d..00000000 --- a/docs/source/examples.rst +++ /dev/null @@ -1,6 +0,0 @@ -modopt examples -=============== - -.. toctree:: - - plugin_example diff --git a/docs/source/index.rst b/docs/source/index.rst index 7ed86897..8262d43d 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -6,147 +6,19 @@ ModOpt Documentation ====================== -:Author: Samuel Farrens `(samuel.farrens@cea.fr) `_ - -:Version: 1.4.4 +.. image:: modopt_logo.png -:Release Date: 16/06/2020 - -:Documentation: |link-to-docs| +.. Include table of contents +.. include:: toc.rst +:Author: Samuel Farrens `(samuel.farrens@cea.fr) `_ +:Version: 1.5.0 +:Release Date: 31/03/2021 :Repository: |link-to-repo| -.. |link-to-docs| raw:: html - - https://cea-cosmic.github.io/ModOpt/ - .. |link-to-repo| raw:: html https://github.com/CEA-COSMIC/ModOpt -ModOpt is a series of Modular Optimisation tools for solving inverse problems. - ----- - -Contents -======== - -1. `Dependencies`_ -2. `Installation`_ -3. `Package Contents`_ - ----- - -Dependencies -============ - -Required Packages ------------------ - -In order to run the code in this repository the following packages must be -installed: - -* |link-to-python| [Last tested with v3.8.2] - -* |link-to-numpy| [Tested with v1.18.3] - -* |link-to-scipy| [Tested with v1.4.1] - -* |link-to-progressbar| [Tested with v3.51.1] - -.. |link-to-python| raw:: html - - Python - -.. |link-to-numpy| raw:: html - - Numpy - -.. |link-to-scipy| raw:: html - - Scipy - -.. |link-to-progressbar| raw:: html - - Progressbar 2 - -Optional Packages ------------------ - -The following packages can optionally be installed to add extra functionality: - -* |link-to-astropy| [Last tested with v4.0.1] - -* |link-to-matplotlib| [Last tested with v3.2.1] - -* |link-to-skimage| [Requires >=v0.16.2] - -* |link-to-sklearn| [Requires >=v0.22.2] - -* |link-to-termcolor| [Last tested with v1.1.0] - -.. |link-to-astropy| raw:: html - - Astropy - -.. |link-to-matplotlib| raw:: html - - Matplotlib - -.. |link-to-skimage| raw:: html - - Scikit-Image - -.. |link-to-sklearn| raw:: html - - Scikit-Learn - -.. |link-to-termcolor| raw:: html - - Termcolor - ----- - -Installation -============ - -To install using `pip` run the following command: - -.. code-block:: bash - - $ pip install modopt - -To install using `easy_install` run the following command: - -.. code-block:: bash - - $ easy_install modopt - -To clone the ModOpt repository from GitHub run the following command: - -.. code-block:: bash - - $ git clone https://github.com/cea-cosmic/ModOpt - ----- - -Package Contents -================ - -.. toctree:: - :numbered: - :maxdepth: 3 - - modopt - examples +ModOpt is a series of **Modular Optimisation** tools for solving inverse problems. diff --git a/docs/source/installation.rst b/docs/source/installation.rst new file mode 100644 index 00000000..688f0c18 --- /dev/null +++ b/docs/source/installation.rst @@ -0,0 +1,50 @@ +Installation +============ + +.. note:: + + ModOpt is automatically installed by |link-to-pysap|. The following steps are + intended for those that wish to use ModOpt independently of PySAP or those + aiming to contribute to the development of the package. + + .. |link-to-pysap| raw:: html + + PySAP + +Users +----- + +You can install the latest release of ModOpt from `PyPi `_ +as follows: + +.. code-block:: bash + + pip install modopt + + +Alternatively clone the repository and build the package locally as follows: + +.. code-block:: bash + + pip install . + + +Developers +---------- + +Developers are recommend to clone the repository and build the package locally +in development mode with testing and documentation packages as follows: + +.. code-block:: bash + + pip install -e ".[develop]" + +Troubleshooting +--------------- +If you encounter any difficulties installing ModOpt we recommend that you +open a |link-to-issue| and we will do our best to help you. + +.. |link-to-issue| raw:: html + + new issue diff --git a/docs/source/modopt.base.np_adjust.rst b/docs/source/modopt.base.np_adjust.rst deleted file mode 100644 index ed42e9d2..00000000 --- a/docs/source/modopt.base.np_adjust.rst +++ /dev/null @@ -1,7 +0,0 @@ -modopt.base.np\_adjust module -============================= - -.. automodule:: modopt.base.np_adjust - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/source/modopt.base.observable.rst b/docs/source/modopt.base.observable.rst deleted file mode 100644 index f41f7b87..00000000 --- a/docs/source/modopt.base.observable.rst +++ /dev/null @@ -1,7 +0,0 @@ -modopt.base.observable module -============================= - -.. automodule:: modopt.base.observable - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/source/modopt.base.rst b/docs/source/modopt.base.rst deleted file mode 100644 index fc01e712..00000000 --- a/docs/source/modopt.base.rst +++ /dev/null @@ -1,22 +0,0 @@ -modopt.base package -=================== - -Submodules ----------- - -.. toctree:: - :maxdepth: 4 - - modopt.base.np_adjust - modopt.base.observable - modopt.base.transform - modopt.base.types - modopt.base.wrappers - -Module contents ---------------- - -.. automodule:: modopt.base - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/source/modopt.base.transform.rst b/docs/source/modopt.base.transform.rst deleted file mode 100644 index a44f9056..00000000 --- a/docs/source/modopt.base.transform.rst +++ /dev/null @@ -1,7 +0,0 @@ -modopt.base.transform module -============================ - -.. automodule:: modopt.base.transform - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/source/modopt.base.types.rst b/docs/source/modopt.base.types.rst deleted file mode 100644 index 1e7bc951..00000000 --- a/docs/source/modopt.base.types.rst +++ /dev/null @@ -1,7 +0,0 @@ -modopt.base.types module -======================== - -.. automodule:: modopt.base.types - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/source/modopt.base.wrappers.rst b/docs/source/modopt.base.wrappers.rst deleted file mode 100644 index c20b47dc..00000000 --- a/docs/source/modopt.base.wrappers.rst +++ /dev/null @@ -1,7 +0,0 @@ -modopt.base.wrappers module -=========================== - -.. automodule:: modopt.base.wrappers - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/source/modopt.info.rst b/docs/source/modopt.info.rst deleted file mode 100644 index 2c2cbb77..00000000 --- a/docs/source/modopt.info.rst +++ /dev/null @@ -1,7 +0,0 @@ -modopt.info module -================== - -.. automodule:: modopt.info - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/source/modopt.interface.errors.rst b/docs/source/modopt.interface.errors.rst deleted file mode 100644 index 9fd217be..00000000 --- a/docs/source/modopt.interface.errors.rst +++ /dev/null @@ -1,7 +0,0 @@ -modopt.interface.errors module -============================== - -.. automodule:: modopt.interface.errors - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/source/modopt.interface.log.rst b/docs/source/modopt.interface.log.rst deleted file mode 100644 index 0bb6ac91..00000000 --- a/docs/source/modopt.interface.log.rst +++ /dev/null @@ -1,7 +0,0 @@ -modopt.interface.log module -=========================== - -.. automodule:: modopt.interface.log - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/source/modopt.interface.rst b/docs/source/modopt.interface.rst deleted file mode 100644 index 40217949..00000000 --- a/docs/source/modopt.interface.rst +++ /dev/null @@ -1,19 +0,0 @@ -modopt.interface package -======================== - -Submodules ----------- - -.. toctree:: - :maxdepth: 4 - - modopt.interface.errors - modopt.interface.log - -Module contents ---------------- - -.. automodule:: modopt.interface - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/source/modopt.math.convolve.rst b/docs/source/modopt.math.convolve.rst deleted file mode 100644 index 10f09fec..00000000 --- a/docs/source/modopt.math.convolve.rst +++ /dev/null @@ -1,7 +0,0 @@ -modopt.math.convolve module -=========================== - -.. automodule:: modopt.math.convolve - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/source/modopt.math.matrix.rst b/docs/source/modopt.math.matrix.rst deleted file mode 100644 index 149c3b29..00000000 --- a/docs/source/modopt.math.matrix.rst +++ /dev/null @@ -1,7 +0,0 @@ -modopt.math.matrix module -========================= - -.. automodule:: modopt.math.matrix - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/source/modopt.math.metrics.rst b/docs/source/modopt.math.metrics.rst deleted file mode 100644 index 182c3d4f..00000000 --- a/docs/source/modopt.math.metrics.rst +++ /dev/null @@ -1,7 +0,0 @@ -modopt.math.metrics module -========================== - -.. automodule:: modopt.math.metrics - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/source/modopt.math.rst b/docs/source/modopt.math.rst deleted file mode 100644 index 23e3a9fd..00000000 --- a/docs/source/modopt.math.rst +++ /dev/null @@ -1,21 +0,0 @@ -modopt.math package -=================== - -Submodules ----------- - -.. toctree:: - :maxdepth: 4 - - modopt.math.convolve - modopt.math.matrix - modopt.math.metrics - modopt.math.stats - -Module contents ---------------- - -.. automodule:: modopt.math - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/source/modopt.math.stats.rst b/docs/source/modopt.math.stats.rst deleted file mode 100644 index dfc8953e..00000000 --- a/docs/source/modopt.math.stats.rst +++ /dev/null @@ -1,7 +0,0 @@ -modopt.math.stats module -======================== - -.. automodule:: modopt.math.stats - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/source/modopt.opt.algorithms.rst b/docs/source/modopt.opt.algorithms.rst deleted file mode 100644 index c23dcf1a..00000000 --- a/docs/source/modopt.opt.algorithms.rst +++ /dev/null @@ -1,7 +0,0 @@ -modopt.opt.algorithms module -============================ - -.. automodule:: modopt.opt.algorithms - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/source/modopt.opt.cost.rst b/docs/source/modopt.opt.cost.rst deleted file mode 100644 index 7d374c71..00000000 --- a/docs/source/modopt.opt.cost.rst +++ /dev/null @@ -1,7 +0,0 @@ -modopt.opt.cost module -====================== - -.. automodule:: modopt.opt.cost - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/source/modopt.opt.gradient.rst b/docs/source/modopt.opt.gradient.rst deleted file mode 100644 index a97b8bd4..00000000 --- a/docs/source/modopt.opt.gradient.rst +++ /dev/null @@ -1,7 +0,0 @@ -modopt.opt.gradient module -========================== - -.. automodule:: modopt.opt.gradient - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/source/modopt.opt.linear.rst b/docs/source/modopt.opt.linear.rst deleted file mode 100644 index 0e667748..00000000 --- a/docs/source/modopt.opt.linear.rst +++ /dev/null @@ -1,7 +0,0 @@ -modopt.opt.linear module -======================== - -.. automodule:: modopt.opt.linear - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/source/modopt.opt.proximity.rst b/docs/source/modopt.opt.proximity.rst deleted file mode 100644 index 3abfb070..00000000 --- a/docs/source/modopt.opt.proximity.rst +++ /dev/null @@ -1,7 +0,0 @@ -modopt.opt.proximity module -=========================== - -.. automodule:: modopt.opt.proximity - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/source/modopt.opt.reweight.rst b/docs/source/modopt.opt.reweight.rst deleted file mode 100644 index 740d1d22..00000000 --- a/docs/source/modopt.opt.reweight.rst +++ /dev/null @@ -1,7 +0,0 @@ -modopt.opt.reweight module -========================== - -.. automodule:: modopt.opt.reweight - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/source/modopt.opt.rst b/docs/source/modopt.opt.rst deleted file mode 100644 index 4a56c9da..00000000 --- a/docs/source/modopt.opt.rst +++ /dev/null @@ -1,23 +0,0 @@ -modopt.opt package -================== - -Submodules ----------- - -.. toctree:: - :maxdepth: 4 - - modopt.opt.algorithms - modopt.opt.cost - modopt.opt.gradient - modopt.opt.linear - modopt.opt.proximity - modopt.opt.reweight - -Module contents ---------------- - -.. automodule:: modopt.opt - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/source/modopt.plot.cost_plot.rst b/docs/source/modopt.plot.cost_plot.rst deleted file mode 100644 index 3f31b0af..00000000 --- a/docs/source/modopt.plot.cost_plot.rst +++ /dev/null @@ -1,7 +0,0 @@ -modopt.plot.cost\_plot module -============================= - -.. automodule:: modopt.plot.cost_plot - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/source/modopt.plot.rst b/docs/source/modopt.plot.rst deleted file mode 100644 index df2019eb..00000000 --- a/docs/source/modopt.plot.rst +++ /dev/null @@ -1,18 +0,0 @@ -modopt.plot package -=================== - -Submodules ----------- - -.. toctree:: - :maxdepth: 4 - - modopt.plot.cost_plot - -Module contents ---------------- - -.. automodule:: modopt.plot - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/source/modopt.rst b/docs/source/modopt.rst deleted file mode 100644 index 5aaff862..00000000 --- a/docs/source/modopt.rst +++ /dev/null @@ -1,31 +0,0 @@ -modopt package -============== - -Subpackages ------------ - -.. toctree:: - :maxdepth: 4 - - modopt.base - modopt.interface - modopt.math - modopt.opt - modopt.plot - modopt.signal - -Submodules ----------- - -.. toctree:: - :maxdepth: 4 - - modopt.info - -Module contents ---------------- - -.. automodule:: modopt - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/source/modopt.signal.filter.rst b/docs/source/modopt.signal.filter.rst deleted file mode 100644 index 2ff6f482..00000000 --- a/docs/source/modopt.signal.filter.rst +++ /dev/null @@ -1,7 +0,0 @@ -modopt.signal.filter module -=========================== - -.. automodule:: modopt.signal.filter - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/source/modopt.signal.noise.rst b/docs/source/modopt.signal.noise.rst deleted file mode 100644 index 497c1ed6..00000000 --- a/docs/source/modopt.signal.noise.rst +++ /dev/null @@ -1,7 +0,0 @@ -modopt.signal.noise module -========================== - -.. automodule:: modopt.signal.noise - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/source/modopt.signal.positivity.rst b/docs/source/modopt.signal.positivity.rst deleted file mode 100644 index 6c460885..00000000 --- a/docs/source/modopt.signal.positivity.rst +++ /dev/null @@ -1,7 +0,0 @@ -modopt.signal.positivity module -=============================== - -.. automodule:: modopt.signal.positivity - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/source/modopt.signal.rst b/docs/source/modopt.signal.rst deleted file mode 100644 index ea48be16..00000000 --- a/docs/source/modopt.signal.rst +++ /dev/null @@ -1,23 +0,0 @@ -modopt.signal package -===================== - -Submodules ----------- - -.. toctree:: - :maxdepth: 4 - - modopt.signal.filter - modopt.signal.noise - modopt.signal.positivity - modopt.signal.svd - modopt.signal.validation - modopt.signal.wavelet - -Module contents ---------------- - -.. automodule:: modopt.signal - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/source/modopt.signal.svd.rst b/docs/source/modopt.signal.svd.rst deleted file mode 100644 index 2b8adf47..00000000 --- a/docs/source/modopt.signal.svd.rst +++ /dev/null @@ -1,7 +0,0 @@ -modopt.signal.svd module -======================== - -.. automodule:: modopt.signal.svd - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/source/modopt.signal.validation.rst b/docs/source/modopt.signal.validation.rst deleted file mode 100644 index 4b79c904..00000000 --- a/docs/source/modopt.signal.validation.rst +++ /dev/null @@ -1,7 +0,0 @@ -modopt.signal.validation module -=============================== - -.. automodule:: modopt.signal.validation - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/source/modopt.signal.wavelet.rst b/docs/source/modopt.signal.wavelet.rst deleted file mode 100644 index 423bf424..00000000 --- a/docs/source/modopt.signal.wavelet.rst +++ /dev/null @@ -1,7 +0,0 @@ -modopt.signal.wavelet module -============================ - -.. automodule:: modopt.signal.wavelet - :members: - :undoc-members: - :show-inheritance: diff --git a/docs/source/modopt_logo.png b/docs/source/modopt_logo.png new file mode 100644 index 0000000000000000000000000000000000000000..0c359e9a7a405896a6a50ffc31f4983f42912450 GIT binary patch literal 622687 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Ì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νaF8&A}8 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∓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ΠiC#*ghVD?SD^3G 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 literal 0 HcmV?d00001 diff --git a/docs/source/modules.rst b/docs/source/modules.rst deleted file mode 100644 index d9d7cac1..00000000 --- a/docs/source/modules.rst +++ /dev/null @@ -1,7 +0,0 @@ -modopt -====== - -.. toctree:: - :maxdepth: 4 - - modopt diff --git a/docs/source/my_ref.bib b/docs/source/my_ref.bib new file mode 100644 index 00000000..d7c6593a --- /dev/null +++ b/docs/source/my_ref.bib @@ -0,0 +1,17 @@ +@ARTICLE{farrens:2020, + author = {{Farrens}, S. and {Grigis}, A. and {El Gueddari}, L. and {Ramzi}, Z. and {Chaithya}, G.~R. and {Starck}, S. and {Sarthou}, B. and {Cherkaoui}, H. and {Ciuciu}, P. and {Starck}, J. -L.}, + title = "{PySAP: Python Sparse Data Analysis Package for multidisciplinary image processing}", + journal = {Astronomy and Computing}, + keywords = {Image processing, Convex optimisation, Reconstruction, Open-source software, Astrophysics - Instrumentation and Methods for Astrophysics}, + year = 2020, + month = jul, + volume = {32}, + eid = {100402}, + pages = {100402}, + doi = {10.1016/j.ascom.2020.100402}, +archivePrefix = {arXiv}, + eprint = {1910.08465}, + primaryClass = {astro-ph.IM}, + adsurl = {https://ui.adsabs.harvard.edu/abs/2020A&C....3200402F}, + adsnote = {Provided by the SAO/NASA Astrophysics Data System} +} diff --git a/docs/source/neurospin_logo.png b/docs/source/neurospin_logo.png new file mode 100644 index 0000000000000000000000000000000000000000..669deb0d8cc5db48ba0197ffcbd28c32307daa76 GIT binary patch literal 62657 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 - """ -__all__ = ['base', 'interface', 'math', 'opt', 'plot', 'signal'] +from warnings import warn + +from importlib_metadata import version + +from modopt.base import * + +try: + _version = version('modopt') +except Exception: # pragma: no cover + _version = 'Unkown' + warn( + 'Could not extract package metadata. Make sure the package is ' + + 'correctly installed.', + ) -from . import * -from .base import * -from .info import __version__, __about__ +__version__ = _version diff --git a/modopt/base/__init__.py b/modopt/base/__init__.py index 97eb692a..1c0c8b2c 100644 --- a/modopt/base/__init__.py +++ b/modopt/base/__init__.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -"""BASE ROUTINES +"""BASE ROUTINES. This module contains submodules for basic operations such as type transformations and adjustments to the default output of Numpy functions. diff --git a/modopt/base/backend.py b/modopt/base/backend.py new file mode 100644 index 00000000..1f5a7a3a --- /dev/null +++ b/modopt/base/backend.py @@ -0,0 +1,187 @@ +# -*- coding: utf-8 -*- + +"""BACKEND MODULE. + +This module contains methods for GPU Compatiblity. + +:Author: Chaithya G R + +""" + +import warnings +from importlib import util + +import numpy as np + +try: + import torch +except ImportError: # pragma: no cover + import_torch = False +else: + import_torch = True + +# Handle the compatibility with variable +gpu_compatibility = { + 'cupy': False, + 'cupy-cudnn': False, +} + +if util.find_spec('cupy') is not None: + try: + import cupy as cp + gpu_compatibility['cupy'] = True + + if util.find_spec('cupy.cuda.cudnn') is not None: + gpu_compatibility['cupy-cudnn'] = True + except ImportError: + pass + + +def get_array_module(input_data): + """Get Array Module. + + This method returns the array module, which tells if the data is residing + on GPU or CPU. + + Parameters + ---------- + input_data : numpy.ndarray or cupy.ndarray + Input data array + + Returns + ------- + module + The numpy or cupy module + + """ + if gpu_compatibility['cupy']: + return cp.get_array_module(input_data) + + return np + + +def move_to_device(input_data): + """Move data to device. + + This method moves data from CPU to GPU if we have the + compatibility to do so. It returns the same data if + it is already on GPU. + + Parameters + ---------- + input_data : numpy.ndarray or cupy.ndarray + Input data array to be moved + + Returns + ------- + cupy.ndarray + The CuPy array residing on GPU + + """ + xp = get_array_module(input_data) + + if xp == cp: + return input_data + + if gpu_compatibility['cupy']: + return cp.array(input_data) + + warnings.warn('Cupy is not installed, cannot move data to GPU') + + return input_data + + +def move_to_cpu(input_data): + """Move data to CPU. + + This method moves data from GPU to CPU.It returns the same data if it is + already on CPU. + + Parameters + ---------- + input_data : cupy.ndarray + Input data array to be moved + + Returns + ------- + numpy.ndarray + The NumPy array residing on CPU + + """ + xp = get_array_module(input_data) + + if xp == np: + return input_data + + return input_data.get() + + +def convert_to_tensor(input_data): + """Convert data to a tensor. + + This method converts input data to a torch tensor. Particularly, this + method is helpful to convert CuPy array to Tensor. + + Parameters + ---------- + input_data : cupy.ndarray + Input data array to be converted + + Returns + ------- + torch.Tensor + The tensor data + + Raises + ------ + ImportError + If Torch package not found + + """ + if not import_torch: + raise ImportError( + 'Required version of Torch package not found' + + 'see documentation for details: https://cea-cosmic.' + + 'github.io/ModOpt/#optional-packages', + ) + + xp = get_array_module(input_data) + + if xp == np: + return torch.Tensor(input_data) + + return torch.utils.dlpack.from_dlpack(input_data.toDlpack()).float() + + +def convert_to_cupy_array(input_data): + """Convert Tensor data to a CuPy Array. + + This method converts input tensor data to a cupy array. + + Parameters + ---------- + input_data : torch.Tensor + Input Tensor to be converted + + Returns + ------- + cupy.ndarray + The tensor data as a CuPy array + + Raises + ------ + ImportError + If Torch package not found + + """ + if not import_torch: + raise ImportError( + 'Required version of Torch package not found' + + 'see documentation for details: https://cea-cosmic.' + + 'github.io/ModOpt/#optional-packages', + ) + + if input_data.is_cuda: + return cp.fromDlpack(torch.utils.dlpack.to_dlpack(input_data)) + + return input_data.detach().numpy() diff --git a/modopt/base/np_adjust.py b/modopt/base/np_adjust.py index b1a4e98e..3df8b411 100644 --- a/modopt/base/np_adjust.py +++ b/modopt/base/np_adjust.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -"""NUMPY ADJUSTMENT ROUTINES +"""NUMPY ADJUSTMENT ROUTINES. This module contains methods for adjusting the default output for certain Numpy functions. @@ -12,14 +12,14 @@ import numpy as np -def rotate(data): - """Rotate +def rotate(input_data): + """Rotate. This method rotates an input numpy array by 180 degrees. Parameters ---------- - data : numpy.ndarray + input_data : numpy.ndarray Input data array (at least 2D) Returns @@ -33,6 +33,7 @@ def rotate(data): Examples -------- + >>> import numpy as np >>> from modopt.base.np_adjust import rotate >>> x = np.arange(9).reshape((3, 3)) >>> x @@ -50,18 +51,17 @@ def rotate(data): numpy.rot90 : base function """ + return np.rot90(input_data, 2) - return np.rot90(data, 2) - -def rotate_stack(data): - """Rotate stack +def rotate_stack(input_data): + """Rotate stack. This method rotates each array in a stack of arrays by 180 degrees. Parameters ---------- - data : numpy.ndarray + input_data : numpy.ndarray Input data array (at least 3D) Returns @@ -71,19 +71,22 @@ def rotate_stack(data): Examples -------- + >>> import numpy as np >>> from modopt.base.np_adjust import rotate_stack >>> x = np.arange(18).reshape((2, 3, 3)) >>> x array([[[ 0, 1, 2], [ 3, 4, 5], [ 6, 7, 8]], + [[ 9, 10, 11], [12, 13, 14], - [15, 16, 17 + [15, 16, 17]]]) >>> rotate_stack(x) array([[[ 8, 7, 6], [ 5, 4, 3], [ 2, 1, 0]], + [[17, 16, 15], [14, 13, 12], [11, 10, 9]]]) @@ -93,18 +96,17 @@ def rotate_stack(data): rotate : looped function """ - - return np.array([rotate(x) for x in data]) + return np.array([rotate(array) for array in input_data]) -def pad2d(data, padding): - """Pad array +def pad2d(input_data, padding): + """Pad array. This method pads an input numpy array with zeros in all directions. Parameters ---------- - data : numpy.ndarray + input_data : numpy.ndarray Input data array (at least 2D) padding : int or tuple Amount of padding in x and y directions, respectively @@ -114,12 +116,18 @@ def pad2d(data, padding): numpy.ndarray Padded data + Raises + ------ + ValueError + For + Notes ----- Adjustment to numpy.pad() Examples -------- + >>> import numpy as np >>> from modopt.base.np_adjust import pad2d >>> x = np.arange(9).reshape((3, 3)) >>> x @@ -136,36 +144,36 @@ def pad2d(data, padding): See Also -------- numpy.pad : base function - """ - - data = np.array(data) + input_data = np.array(input_data) if isinstance(padding, int): padding = np.array([padding]) elif isinstance(padding, (tuple, list)): padding = np.array(padding) - elif isinstance(padding, np.ndarray): - pass - else: - raise ValueError('Padding must be an integer or a tuple (or list, ' - 'np.ndarray) of itegers') + elif not isinstance(padding, np.ndarray): + raise ValueError( + 'Padding must be an integer or a tuple (or list, np.ndarray) ' + + 'of itegers', + ) if padding.size == 1: padding = np.repeat(padding, 2) - return np.pad(data, ((padding[0], padding[0]), (padding[1], padding[1])), - 'constant') + pad_x = (padding[0], padding[0]) + pad_y = (padding[1], padding[1]) + return np.pad(input_data, (pad_x, pad_y), 'constant') -def ftr(data): - """Fancy transpose right + +def ftr(input_data): + """Fancy transpose right. Apply fancy_transpose() to data with roll=1. Parameters ---------- - data : numpy.ndarray + input_data : numpy.ndarray Input data array Returns @@ -178,18 +186,17 @@ def ftr(data): fancy_transpose : base function """ - - return fancy_transpose(data) + return fancy_transpose(input_data) -def ftl(data): - """Fancy transpose left +def ftl(input_data): + """Fancy transpose left. Apply fancy_transpose() to data with roll=-1. Parameters ---------- - data : numpy.ndarray + input_data : numpy.ndarray Input data array Returns @@ -202,18 +209,17 @@ def ftl(data): fancy_transpose : base function """ + return fancy_transpose(input_data, -1) - return fancy_transpose(data, -1) - -def fancy_transpose(data, roll=1): - """Fancy transpose +def fancy_transpose(input_data, roll=1): + """Fancy transpose. This method transposes a multidimensional matrix. Parameters ---------- - data : numpy.ndarray + input_data : numpy.ndarray Input data array roll : int Roll direction and amount (default is ``1``) @@ -229,15 +235,18 @@ def fancy_transpose(data, roll=1): Examples -------- + >>> import numpy as np >>> from modopt.base.np_adjust import fancy_transpose >>> x = np.arange(27).reshape(3, 3, 3) >>> x array([[[ 0, 1, 2], [ 3, 4, 5], [ 6, 7, 8]], + [[ 9, 10, 11], [12, 13, 14], [15, 16, 17]], + [[18, 19, 20], [21, 22, 23], [24, 25, 26]]]) @@ -245,9 +254,11 @@ def fancy_transpose(data, roll=1): array([[[ 0, 3, 6], [ 9, 12, 15], [18, 21, 24]], + [[ 1, 4, 7], [10, 13, 16], [19, 22, 25]], + [[ 2, 5, 8], [11, 14, 17], [20, 23, 26]]]) @@ -255,9 +266,11 @@ def fancy_transpose(data, roll=1): array([[[ 0, 9, 18], [ 1, 10, 19], [ 2, 11, 20]], + [[ 3, 12, 21], [ 4, 13, 22], [ 5, 14, 23]], + [[ 6, 15, 24], [ 7, 16, 25], [ 8, 17, 26]]]) @@ -267,7 +280,6 @@ def fancy_transpose(data, roll=1): numpy.transpose : base function """ + axis_roll = np.roll(np.arange(input_data.ndim), roll) - axis_roll = np.roll(np.arange(data.ndim), roll) - - return np.transpose(data, axes=axis_roll) + return np.transpose(input_data, axes=axis_roll) diff --git a/modopt/base/observable.py b/modopt/base/observable.py old mode 100755 new mode 100644 index 0162dd25..581d3f7c --- a/modopt/base/observable.py +++ b/modopt/base/observable.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -"""Observable +"""Observable. This module contains observable classes @@ -9,18 +9,18 @@ """ import time + import numpy as np class SignalObject(object): - """Dummy class for signals. - """ + """Dummy class for signals.""" pass class Observable(object): - """Base class for observable classes + """Base class for observable classes. This class defines a simple interface to add or remove observers on an object. @@ -47,7 +47,7 @@ def __init__(self, signals): self._locked = False def add_observer(self, signal, observer): - """Add an observer to the object + """Add an observer to the object. Raise an exception if the signal is not allowed. @@ -55,16 +55,15 @@ def add_observer(self, signal, observer): ---------- signal : str A valid signal - observer : function + observer : callable A function that will be called when the signal is emitted """ - self._is_allowed_signal(signal) self._add_observer(signal, observer) def remove_observer(self, signal, observer): - """Remove an observer from the object + """Remove an observer from the object. Raise an eception if the signal is not allowed. @@ -72,16 +71,15 @@ def remove_observer(self, signal, observer): ---------- signal : str A valid signal - observer : function + observer : callable An obervation function to be removed """ - self._is_allowed_event(signal) self._remove_observer(signal, observer) def notify_observers(self, signal, **kwargs): - """ Notify observers of a given signal + """Notify observers of a given signal. Parameters ---------- @@ -96,7 +94,6 @@ def notify_observers(self, signal, **kwargs): ``False`` if a notification is in progress, otherwise ``True`` """ - # Check if a notification if in progress if self._locked: return False @@ -105,10 +102,11 @@ def notify_observers(self, signal, **kwargs): # Create a signal object signal_to_be_notified = SignalObject() - setattr(signal_to_be_notified, "object", self) - setattr(signal_to_be_notified, "signal", signal) - for name, value in kwargs.items(): - setattr(signal_to_be_notified, name, value) + signal_to_be_notified.object = self + signal_to_be_notified.signal = signal + + for name, key_value in kwargs.items(): + setattr(signal_to_be_notified, name, key_value) # Notify all the observers for observer in self._observers[signal]: observer(signal_to_be_notified) @@ -116,18 +114,22 @@ def notify_observers(self, signal, **kwargs): self._locked = False def _get_allowed_signals(self): - """Get allowed signals + """Get allowed signals. Events allowed for the current object. - """ + Returns + ------- + list + List of allowed signals + """ return self._allowed_signals allowed_signals = property(_get_allowed_signals) def _is_allowed_signal(self, signal): - """Check if a signal is valid + """Check if a signal is valid. Raise an exception if the signal is not allowed. @@ -136,11 +138,15 @@ def _is_allowed_signal(self, signal): signal: str A signal - """ + Raises + ------ + ValueError + For invalid signal + """ if signal not in self._allowed_signals: - raise Exception("Signal '{0}' is not allowed for '{1}'.".format( - signal, type(self))) + message = 'Signal "{0}" is not allowed for "{1}"' + raise ValueError(message.format(signal, type(self))) def _add_observer(self, signal, observer): """Associate an observer to a valid signal. @@ -149,32 +155,30 @@ def _add_observer(self, signal, observer): ---------- signal : str A valid signal - observer : function + observer : callable An obervation function """ - if observer not in self._observers[signal]: self._observers[signal].append(observer) def _remove_observer(self, signal, observer): - """Remove an observer to a valid signal + """Remove an observer to a valid signal. Parameters ---------- signal : str A valid signal - observer : function + observer : callable An obervation function to be removed """ - if observer in self._observers[signal]: self._observers[signal].remove(observer) class MetricObserver(object): - """Metric observer + """Metric observer. Wrapper of the metric to the observer object notify by the Observable class. @@ -183,31 +187,34 @@ class MetricObserver(object): ---------- name : str The name of the metric - - metric : function + metric : callable Metric function with this precise signature func(test, ref) - mapping : dict Define the mapping between the iterate variable and the metric keyword: {'x_new':'name_var_1', 'y_new':'name_var_2'}. To cancel the need of a variable, the dict value should be None: 'y_new':None. - cst_kwargs : dict Keywords arguments of constant argument for the metric computation - early_stopping : bool If True it will compute the convergence flag (default is ``False``) - wind : int Window on with the convergence criteria is compute (default is ``6``) - eps : float The level of criteria of convergence (default is ``1.0e-3``) """ - def __init__(self, name, metric, mapping, cst_kwargs, early_stopping=False, - wind=6, eps=1.0e-3): + + def __init__( + self, + name, + metric, + mapping, + cst_kwargs, + early_stopping=False, + wind=6, + eps=1.0e-3, + ): self.name = name self.metric = metric @@ -222,7 +229,9 @@ def __init__(self, name, metric, mapping, cst_kwargs, early_stopping=False, self.early_stopping = early_stopping def __call__(self, signal): - """Wrapper the call from the observer signature to the metric + """Call Method. + + Wrapper the call from the observer signature to the metric signature. Parameters @@ -231,11 +240,10 @@ def __call__(self, signal): A valid signal """ - kwargs = {} - for key, value in self.mapping.items(): - if value is not None: - kwargs[value] = getattr(signal, key) + for key, key_value in self.mapping.items(): + if key_value is not None: + kwargs[key_value] = getattr(signal, key) kwargs.update(self.cst_kwargs) self.list_iters.append(signal.idx) self.list_dates.append(time.time()) @@ -245,32 +253,41 @@ def __call__(self, signal): self.is_converge() def is_converge(self): - """Check convergence + """Check convergence. Return ``True`` if the convergence criteria is matched. """ - if len(self.list_cv_values) < self.wind: return start_idx = -self.wind mid_idx = -(self.wind // 2) old_mean = np.array(self.list_cv_values[start_idx:mid_idx]).mean() current_mean = np.array(self.list_cv_values[mid_idx:]).mean() - normalize_residual_metrics = (np.abs(old_mean - current_mean) / - np.abs(old_mean)) + normalize_residual_metrics = ( + np.abs(old_mean - current_mean) / np.abs(old_mean) + ) self.converge_flag = normalize_residual_metrics < self.eps def retrieve_metrics(self): - """Retrieve metrics + """Retrieve metrics. Return the convergence metrics saved with the corresponding iterations. + Returns + ------- + dict + Convergence metrics + """ + time_val = np.array(self.list_dates) + + if time_val.size >= 1: + time_val -= time_val[0] - time = np.array(self.list_dates) - if len(time) >= 1: - time -= time[0] - return {'time': time, 'index': self.list_iters, - 'values': self.list_cv_values} + return { + 'time': time_val, + 'index': self.list_iters, + 'values': self.list_cv_values, + } diff --git a/modopt/base/transform.py b/modopt/base/transform.py index 03d569ff..44bcfa58 100644 --- a/modopt/base/transform.py +++ b/modopt/base/transform.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -"""DATA TRANSFORM ROUTINES +"""DATA TRANSFORM ROUTINES. This module contains methods for transforming data. @@ -12,7 +12,7 @@ def cube2map(data_cube, layout): - r"""Cube to Map + """Cube to Map. This method transforms the input data from a 3D cube to a 2D map with a specified layout @@ -21,7 +21,7 @@ def cube2map(data_cube, layout): ---------- data_cube : numpy.ndarray Input data cube, 3D array of 2D images - Layout : tuple + layout : tuple 2D layout of 2D images Returns @@ -38,6 +38,7 @@ def cube2map(data_cube, layout): Examples -------- + >>> import numpy as np >>> from modopt.base.transform import cube2map >>> a = np.arange(16).reshape((4, 2, 2)) >>> cube2map(a, (2, 2)) @@ -51,20 +52,25 @@ def cube2map(data_cube, layout): map2cube : complimentary function """ - if data_cube.ndim != 3: raise ValueError('The input data must have 3 dimensions.') if data_cube.shape[0] != np.prod(layout): - raise ValueError('The desired layout must match the number of input ' - 'data layers.') + raise ValueError( + 'The desired layout must match the number of input ' + + 'data layers.', + ) + + res = ([ + np.hstack(data_cube[slice(layout[1] * elem, layout[1] * (elem + 1))]) + for elem in range(layout[0]) + ]) - return np.vstack([np.hstack(data_cube[slice(layout[1] * i, layout[1] * - (i + 1))]) for i in range(layout[0])]) + return np.vstack(res) def map2cube(data_map, layout): - r"""Map to cube + """Map to cube. This method transforms the input data from a 2D map with given layout to a 3D cube @@ -88,16 +94,20 @@ def map2cube(data_map, layout): Examples -------- + >>> import numpy as np >>> from modopt.base.transform import map2cube >>> a = np.array([[0, 1, 4, 5], [2, 3, 6, 7], [8, 9, 12, 13], - [10, 11, 14, 15]]) + ... [10, 11, 14, 15]]) >>> map2cube(a, (2, 2)) array([[[ 0, 1], [ 2, 3]], + [[ 4, 5], [ 6, 7]], + [[ 8, 9], [10, 11]], + [[12, 13], [14, 15]]]) @@ -106,20 +116,26 @@ def map2cube(data_map, layout): cube2map : complimentary function """ - if np.all(np.array(data_map.shape) % np.array(layout)): - raise ValueError('The desired layout must be a multiple of the number ' - 'pixels in the data map.') + raise ValueError( + 'The desired layout must be a multiple of the number ' + + 'pixels in the data map.', + ) d_shape = np.array(data_map.shape) // np.array(layout) - return np.array([data_map[(slice(i * d_shape[0], (i + 1) * d_shape[0]), - slice(j * d_shape[1], (j + 1) * d_shape[1]))] for i in - range(layout[0]) for j in range(layout[1])]) + return np.array([ + data_map[( + slice(i_elem * d_shape[0], (i_elem + 1) * d_shape[0]), + slice(j_elem * d_shape[1], (j_elem + 1) * d_shape[1]), + )] + for i_elem in range(layout[0]) + for j_elem in range(layout[1]) + ]) def map2matrix(data_map, layout): - r"""Map to Matrix + """Map to Matrix. This method transforms a 2D map to a 2D matrix @@ -135,16 +151,12 @@ def map2matrix(data_map, layout): numpy.ndarray 2D matrix - Raises - ------ - ValueError - For invalid layout - Examples -------- + >>> import numpy as np >>> from modopt.base.transform import map2matrix >>> a = np.array([[0, 1, 4, 5], [2, 3, 6, 7], [8, 9, 12, 13], - [10, 11, 14, 15]]) + ... [10, 11, 14, 15]]) >>> map2matrix(a, (2, 2)) array([[ 0, 4, 8, 12], [ 1, 5, 9, 13], @@ -156,31 +168,34 @@ def map2matrix(data_map, layout): matrix2map : complimentary function """ - layout = np.array(layout) - # Select n objects - n_obj = np.prod(layout) - # Get the shape of the images image_shape = (np.array(data_map.shape) // layout)[0] # Stack objects from map data_matrix = [] - for i in range(n_obj): - lower = (image_shape * (i // layout[1]), - image_shape * (i % layout[1])) - upper = (image_shape * (i // layout[1] + 1), - image_shape * (i % layout[1] + 1)) - data_matrix.append((data_map[lower[0]:upper[0], - lower[1]:upper[1]]).reshape(image_shape ** 2)) + for i_elem in range(np.prod(layout)): + lower = ( + image_shape * (i_elem // layout[1]), + image_shape * (i_elem % layout[1]), + ) + upper = ( + image_shape * (i_elem // layout[1] + 1), + image_shape * (i_elem % layout[1] + 1), + ) + data_matrix.append( + ( + data_map[lower[0]:upper[0], lower[1]:upper[1]] + ).reshape(image_shape ** 2), + ) return np.array(data_matrix).T def matrix2map(data_matrix, map_shape): - r"""Matrix to Map + """Matrix to Map. This method transforms a 2D matrix to a 2D map @@ -196,17 +211,13 @@ def matrix2map(data_matrix, map_shape): numpy.ndarray 2D map - Raises - ------ - ValueError - For invalid layout - Examples -------- + >>> import numpy as np >>> from modopt.base.transform import matrix2map >>> a = np.array([[0, 4, 8, 12], [1, 5, 9, 13], [2, 6, 10, 14], - [3, 7, 11, 15]]) - >>> matrix2map(a, (2, 2)) + ... [3, 7, 11, 15]]) + >>> matrix2map(a, (4, 4)) array([[ 0, 1, 4, 5], [ 2, 3, 6, 7], [ 8, 9, 12, 13], @@ -217,7 +228,6 @@ def matrix2map(data_matrix, map_shape): map2matrix : complimentary function """ - map_shape = np.array(map_shape) # Get the shape and layout of the images @@ -229,18 +239,22 @@ def matrix2map(data_matrix, map_shape): temp = data_matrix.reshape(image_shape, image_shape, data_matrix.shape[1]) - for i in range(data_matrix.shape[1]): - lower = (image_shape * (i // layout[1]), - image_shape * (i % layout[1])) - upper = (image_shape * (i // layout[1] + 1), - image_shape * (i % layout[1] + 1)) - data_map[lower[0]:upper[0], lower[1]:upper[1]] = temp[:, :, i] + for i_elem in range(data_matrix.shape[1]): + lower = ( + image_shape * (i_elem // layout[1]), + image_shape * (i_elem % layout[1]), + ) + upper = ( + image_shape * (i_elem // layout[1] + 1), + image_shape * (i_elem % layout[1] + 1), + ) + data_map[lower[0]:upper[0], lower[1]:upper[1]] = temp[:, :, i_elem] return data_map.astype(int) def cube2matrix(data_cube): - r"""Cube to Matrix + """Cube to Matrix. This method transforms a 3D cube to a 2D matrix @@ -256,6 +270,7 @@ def cube2matrix(data_cube): Examples -------- + >>> import numpy as np >>> from modopt.base.transform import cube2matrix >>> a = np.arange(16).reshape((4, 2, 2)) >>> cube2matrix(a) @@ -269,13 +284,13 @@ def cube2matrix(data_cube): matrix2cube : complimentary function """ - - return data_cube.reshape([data_cube.shape[0]] + - [np.prod(data_cube.shape[1:])]).T + return data_cube.reshape( + [data_cube.shape[0]] + [np.prod(data_cube.shape[1:])], + ).T def matrix2cube(data_matrix, im_shape): - r"""Matrix to Cube + """Matrix to Cube. This method transforms a 2D matrix to a 3D cube @@ -293,16 +308,20 @@ def matrix2cube(data_matrix, im_shape): Examples -------- + >>> import numpy as np >>> from modopt.base.transform import matrix2cube >>> a = np.array([[0, 4, 8, 12], [1, 5, 9, 13], [2, 6, 10, 14], - [3, 7, 11, 15]]) + ... [3, 7, 11, 15]]) >>> matrix2cube(a, (2, 2)) array([[[ 0, 1], [ 2, 3]], + [[ 4, 5], [ 6, 7]], + [[ 8, 9], [10, 11]], + [[12, 13], [14, 15]]]) @@ -311,5 +330,4 @@ def matrix2cube(data_matrix, im_shape): cube2matrix : complimentary function """ - return data_matrix.T.reshape([data_matrix.shape[1]] + list(im_shape)) diff --git a/modopt/base/types.py b/modopt/base/types.py index 5de2036b..f0eff33f 100644 --- a/modopt/base/types.py +++ b/modopt/base/types.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -"""TYPE HANDLING ROUTINES +"""TYPE HANDLING ROUTINES. This module contains methods for handing object types. @@ -9,12 +9,13 @@ """ import numpy as np + from modopt.base.wrappers import add_args_kwargs from modopt.interface.errors import warn -def check_callable(val, add_agrs=True): - r""" Check input object is callable +def check_callable(input_obj, add_agrs=True): + """Check input object is callable. This method checks if the input operator is a callable funciton and optionally adds support for arguments and keyword arguments if not already @@ -22,7 +23,7 @@ def check_callable(val, add_agrs=True): Parameters ---------- - val : function + input_obj : callable Callable function add_agrs : bool, optional Option to add support for agrs and kwargs (default is ``True``) @@ -42,23 +43,24 @@ def check_callable(val, add_agrs=True): modopt.base.wrappers.add_args_kwargs : wrapper used """ - - if not callable(val): + if not callable(input_obj): raise TypeError('The input object must be a callable function.') if add_agrs: - val = add_args_kwargs(val) + input_obj = add_args_kwargs(input_obj) - return val + return input_obj -def check_float(val): - r"""Check if input value is a float or a numpy.ndarray of floats, if not +def check_float(input_obj): + """Check Float. + + Check if input object is a float or a numpy.ndarray of floats, if not convert. Parameters ---------- - val : any + input_obj : any Input value Returns @@ -66,40 +68,49 @@ def check_float(val): float or numpy.ndarray Input value as a float + Raises + ------ + TypeError + For invalid input type + Examples -------- + >>> import numpy as np >>> from modopt.base.types import check_float >>> a = np.arange(5) >>> a array([0, 1, 2, 3, 4]) >>> check_float(a) - array([ 0., 1., 2., 3., 4.]) + array([0., 1., 2., 3., 4.]) See Also -------- check_int : related function """ - - if not isinstance(val, (int, float, list, tuple, np.ndarray)): + if not isinstance(input_obj, (int, float, list, tuple, np.ndarray)): raise TypeError('Invalid input type.') - if isinstance(val, int): - val = float(val) - elif isinstance(val, (list, tuple)): - val = np.array(val, dtype=float) - elif isinstance(val, np.ndarray) and (not np.issubdtype(val.dtype, - np.floating)): - val = val.astype(float) + if isinstance(input_obj, int): + input_obj = float(input_obj) + elif isinstance(input_obj, (list, tuple)): + input_obj = np.array(input_obj, dtype=float) + elif ( + isinstance(input_obj, np.ndarray) + and (not np.issubdtype(input_obj.dtype, np.floating)) + ): + input_obj = input_obj.astype(float) + + return input_obj - return val +def check_int(input_obj): + """Check Integer. -def check_int(val): - r"""Check if input value is an int or a np.ndarray of ints, if not convert. + Check if input value is an int or a np.ndarray of ints, if not convert. Parameters ---------- - val : any + input_obj : any Input value Returns @@ -107,13 +118,19 @@ def check_int(val): int or numpy.ndarray Input value as an integer + Raises + ------ + TypeError + For invalid input type + Examples -------- + >>> import numpy as np >>> from modopt.base.types import check_int >>> a = np.arange(5).astype(float) >>> a - array([ 0., 1., 2., 3., 4.]) - >>> check_float(a) + array([0., 1., 2., 3., 4.]) + >>> check_int(a) array([0, 1, 2, 3, 4]) See Also @@ -121,39 +138,59 @@ def check_int(val): check_float : related function """ - - if not isinstance(val, (int, float, list, tuple, np.ndarray)): + if not isinstance(input_obj, (int, float, list, tuple, np.ndarray)): raise TypeError('Invalid input type.') - if isinstance(val, float): - val = int(val) - elif isinstance(val, (list, tuple)): - val = np.array(val, dtype=int) - elif isinstance(val, np.ndarray) and (not np.issubdtype(val.dtype, - np.integer)): - val = val.astype(int) + if isinstance(input_obj, float): + input_obj = int(input_obj) + elif isinstance(input_obj, (list, tuple)): + input_obj = np.array(input_obj, dtype=int) + elif ( + isinstance(input_obj, np.ndarray) + and (not np.issubdtype(input_obj.dtype, np.integer)) + ): + input_obj = input_obj.astype(int) - return val + return input_obj -def check_npndarray(val, dtype=None, writeable=True, verbose=True): - """Check if input object is a numpy array. +def check_npndarray(input_obj, dtype=None, writeable=True, verbose=True): + """Check Numpy ND-Array. + + Check if input object is a numpy array. Parameters ---------- - val : numpy.ndarray + input_obj : numpy.ndarray Input object + dtype : type + Numpy ndarray data type + writeable : bool + Option to make array immutable + verbose : bool + Verbosity option - """ + Raises + ------ + TypeError + For invalid input type + TypeError + For invalid numpy.ndarray dtype - if not isinstance(val, np.ndarray): + """ + if not isinstance(input_obj, np.ndarray): raise TypeError('Input is not a numpy array.') - if ((not isinstance(dtype, type(None))) and - (not np.issubdtype(val.dtype, dtype))): - raise TypeError('The numpy array elements are not of type: {}' - ''.format(dtype)) - - if not writeable and verbose and val.flags.writeable: + if ( + (not isinstance(dtype, type(None))) + and (not np.issubdtype(input_obj.dtype, dtype)) + ): + raise ( + TypeError( + 'The numpy array elements are not of type: {0}'.format(dtype), + ), + ) + + if not writeable and verbose and input_obj.flags.writeable: warn('Making input data immutable.') - val.flags.writeable = writeable + input_obj.flags.writeable = writeable diff --git a/modopt/base/wrappers.py b/modopt/base/wrappers.py index 7b6a1246..c6d4dbf4 100644 --- a/modopt/base/wrappers.py +++ b/modopt/base/wrappers.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -"""WRAPPERS +"""WRAPPERS. This module contains wrappers for adding additional features to functions @@ -8,23 +8,19 @@ """ -from sys import version_info from functools import wraps -if version_info[0] < 3: # pragma: no cover - from inspect import getargspec as argspec -else: - from inspect import getfullargspec as argspec +from inspect import getfullargspec as argspec def add_args_kwargs(func): - """Add Args and Kwargs + """Add Args and Kwargs. This wrapper adds support for additional arguments and keyword arguments to any callable function. Parameters ---------- - func : function + func : callable Callable function Returns @@ -33,7 +29,6 @@ def add_args_kwargs(func): wrapper """ - @wraps(func) def wrapper(*args, **kwargs): @@ -41,16 +36,14 @@ def wrapper(*args, **kwargs): # if 'args' not in props: if isinstance(props[1], type(None)): - args = args[:len(props[0])] - if ((not isinstance(props[2], type(None))) or - (not isinstance(props[3], type(None)))): - + if ( + (not isinstance(props[2], type(None))) + or (not isinstance(props[3], type(None))) + ): return func(*args, **kwargs) - else: - - return func(*args) + return func(*args) return wrapper diff --git a/modopt/info.py b/modopt/info.py deleted file mode 100644 index 04b5668b..00000000 --- a/modopt/info.py +++ /dev/null @@ -1,25 +0,0 @@ -# -*- coding: utf-8 -*- - -"""MODOPT PACKAGE INFO - -This module provides some basic information about the ModOpt package. - -:Author: Samuel Farrens - -:Version: 1.4.4 - -""" - -# Package Version -version_info = (1, 4, 4) -__version__ = '.'.join(str(c) for c in version_info) - -__about__ = ('ModOpt \n\n ' - 'Author: Samuel Farrens \n ' - 'Year: 2017 \n ' - 'Email: samuel.farrens@cea.fr \n ' - 'Website: https://sfarrens.github.io \n\n ' - 'ModOpt is a series of Modular Optimisation too ls for solving ' - 'inverse problems. \n\n ' - 'Full documentation available here: ' - 'https://cea-cosmic.github.io/ModOpt/') diff --git a/modopt/interface/__init__.py b/modopt/interface/__init__.py index 7820386b..f9439747 100644 --- a/modopt/interface/__init__.py +++ b/modopt/interface/__init__.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -"""INTERFACE ROUTINES +"""INTERFACE ROUTINES. This module contains submodules for error handling, logging and IO interaction. @@ -9,5 +9,3 @@ """ __all__ = ['errors', 'log'] - -from . import * diff --git a/modopt/interface/errors.py b/modopt/interface/errors.py index 9f84e0a6..0fbe7e71 100644 --- a/modopt/interface/errors.py +++ b/modopt/interface/errors.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -"""ERROR HANDLING ROUTINES +"""ERROR HANDLING ROUTINES. This module contains methods for handing warnings and errors. @@ -8,9 +8,10 @@ """ -import sys import os +import sys import warnings + try: from termcolor import colored except ImportError: @@ -20,7 +21,7 @@ def warn(warn_string, log=None): - """Warning + """Warning. This method creates custom warning messages. @@ -32,14 +33,13 @@ def warn(warn_string, log=None): Logging structure instance (default is ``None``) """ - if import_fail: warn_txt = 'WARNING' else: warn_txt = colored('WARNING', 'yellow') # Print warning to stdout. - sys.stderr.write(warn_txt + ': ' + warn_string + '\n') + sys.stderr.write('{0}: {1}\n'.format(warn_txt, warn_string)) # Check if a logging structure is provided. if not isinstance(log, type(None)): @@ -47,7 +47,7 @@ def warn(warn_string, log=None): def catch_error(exception, log=None): - """Catch error + """Catch error. This method catches errors and prints them to the terminal. It also saves the errors to a log if provided. @@ -60,24 +60,23 @@ def catch_error(exception, log=None): Logging structure instance (default is ``None``) """ - if import_fail: err_txt = 'ERROR' else: err_txt = colored('ERROR', 'red') # Print exception to stdout. - stream_txt = err_txt + ': ' + str(exception) + '\n' + stream_txt = '{0}: {1}\n'.format(err_txt, exception) sys.stderr.write(stream_txt) # Check if a logging structure is provided. if not isinstance(log, type(None)): - log_txt = 'ERROR: ' + str(exception) + '\n' + log_txt = 'ERROR: {0}\n'.format(exception) log.exception(log_txt) def file_name_error(file_name): - """File name error + """File name error. This method checks if the input file name is valid. @@ -92,55 +91,66 @@ def file_name_error(file_name): If file name not specified or file not found """ - if file_name == '' or file_name[0][0] == '-': raise IOError('Input file name not specified.') elif not os.path.isfile(file_name): - raise IOError('Input file name [%s] not found!' % file_name) + raise IOError('Input file name {0} not found!'.format(file_name)) -def is_executable(exe_name): - """Check if Input is Executable +def is_exe(fpath): + """Is Executable. - This methid checks if the input executable exists. + Check if the input file path corresponds to an executable on the system. Parameters ---------- - exe_name : str - Executable name + fpath : str + File path Returns ------- bool - Result of the test + True if file path exists + + """ + return os.path.isfile(fpath) and os.access(fpath, os.X_OK) + + +def is_executable(exe_name): + """Check if Input is Executable. + + This method checks if the input executable exists. + + Parameters + ---------- + exe_name : str + Executable name Raises ------ TypeError For invalid input type + IOError + For invalid system executable """ - if not isinstance(exe_name, str): - raise TypeError('Executable name must be a string.') - def is_exe(fpath): - - return os.path.isfile(fpath) and os.access(fpath, os.X_OK) - fpath, fname = os.path.split(exe_name) - if not fpath: - - res = any([is_exe(os.path.join(path, exe_name)) for path in - os.environ["PATH"].split(os.pathsep)]) + if fpath: + res = is_exe(exe_name) else: - - res = is_exe(exe_name) + res = any( + is_exe(os.path.join(path, exe_name)) + for path in os.environ['PATH'].split(os.pathsep) + ) if not res: - raise IOError('{} does not appear to be a valid executable on this ' - 'system.'.format(exe_name)) + message = ( + '{0} does not appear to be a valid executable on this system.' + ) + raise IOError(message.format(exe_name)) diff --git a/modopt/interface/log.py b/modopt/interface/log.py index fe111466..3b2fa77a 100644 --- a/modopt/interface/log.py +++ b/modopt/interface/log.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -"""LOGGING ROUTINES +"""LOGGING ROUTINES. This module contains methods for handing logging. @@ -8,12 +8,11 @@ """ -import sys import logging def set_up_log(filename, verbose=True): - """Set up log + """Set up log. This method sets up a basic log. @@ -30,9 +29,8 @@ def set_up_log(filename, verbose=True): Logging instance """ - # Add file extension. - filename += '.log' + filename = '{0}.log'.format(filename) if verbose: print('Preparing log file:', filename) @@ -41,8 +39,10 @@ def set_up_log(filename, verbose=True): logging.captureWarnings(True) # Set output format. - formatter = logging.Formatter(fmt='%(asctime)s %(message)s', - datefmt='%d/%m/%Y %H:%M:%S') + formatter = logging.Formatter( + fmt='%(asctime)s %(message)s', + datefmt='%d/%m/%Y %H:%M:%S', + ) # Create file handler. fh = logging.FileHandler(filename=filename, mode='w') @@ -61,7 +61,7 @@ def set_up_log(filename, verbose=True): def close_log(log, verbose=True): - """Close log + """Close log. This method closes and active logging.Logger instance. @@ -73,7 +73,6 @@ def close_log(log, verbose=True): Option for verbose output (default is ``True``) """ - if verbose: print('Closing log file:', log.name) @@ -81,4 +80,5 @@ def close_log(log, verbose=True): log.info('The log file has been closed.') # Remove all handlers from log. - [log.removeHandler(handler) for handler in log.handlers] + for log_handler in log.handlers: + log.removeHandler(log_handler) diff --git a/modopt/math/__init__.py b/modopt/math/__init__.py index 4341dd48..a22c0c98 100644 --- a/modopt/math/__init__.py +++ b/modopt/math/__init__.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -"""MATHEMATICS ROUTINES +"""MATHEMATICS ROUTINES. This module contains submodules for mathematical applications. @@ -9,5 +9,3 @@ """ __all__ = ['convolve', 'matrix', 'stats', 'metrics'] - -from . import * diff --git a/modopt/math/convolve.py b/modopt/math/convolve.py index a6dbe172..7074e44a 100644 --- a/modopt/math/convolve.py +++ b/modopt/math/convolve.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -"""CONVOLUTION ROUTINES +"""CONVOLUTION ROUTINES. This module contains methods for convolution. @@ -10,8 +10,10 @@ import numpy as np import scipy.signal + from modopt.base.np_adjust import rotate_stack from modopt.interface.errors import warn + try: from astropy.convolution import convolve_fft except ImportError: # pragma: no cover @@ -28,15 +30,15 @@ warn('Using pyFFTW "monkey patch" for scipy.fftpack') -def convolve(data, kernel, method='scipy'): - r"""Convolve data with kernel +def convolve(input_data, kernel, method='scipy'): + """Convolve data with kernel. This method convolves the input data with a given kernel using FFT and is the default convolution used for all routines Parameters ---------- - data : numpy.ndarray + input_data : numpy.ndarray Input data array, normally a 2D image kernel : numpy.ndarray Input kernel array, normally a 2D kernel @@ -57,19 +59,19 @@ def convolve(data, kernel, method='scipy'): Examples -------- - >>> from modopt.math.convolve import convolve >>> import numpy as np + >>> from modopt.math.convolve import convolve >>> a = np.arange(9).reshape(3, 3) >>> b = a + 10 >>> convolve(a, b) - array([[ 86., 170., 146.], - [ 246., 444., 354.], - [ 290., 494., 374.]]) + array([[ 86., 170., 146.], + [246., 444., 354.], + [290., 494., 374.]]) >>> convolve(a, b, method='astropy') - array([[ 534., 525., 534.], - [ 453., 444., 453.], - [ 534., 525., 534.]]) + array([[534., 525., 534.], + [453., 444., 453.], + [534., 525., 534.]]) See Also -------- @@ -77,33 +79,38 @@ def convolve(data, kernel, method='scipy'): astropy.convolution.convolve_fft : astropy FFT convolution """ - - if data.ndim != kernel.ndim: + if input_data.ndim != kernel.ndim: raise ValueError('Data and kernel must have the same dimensions.') - if method not in ('astropy', 'scipy'): + if method not in {'astropy', 'scipy'}: raise ValueError('Invalid method. Options are "astropy" or "scipy".') if not import_astropy: # pragma: no cover method = 'scipy' if method == 'astropy': - return convolve_fft(data, kernel, boundary='wrap', crop=False, - nan_treatment='fill', normalize_kernel=False) + return convolve_fft( + input_data, + kernel, + boundary='wrap', + crop=False, + nan_treatment='fill', + normalize_kernel=False, + ) elif method == 'scipy': - return scipy.signal.fftconvolve(data, kernel, mode='same') + return scipy.signal.fftconvolve(input_data, kernel, mode='same') -def convolve_stack(data, kernel, rot_kernel=False, method='scipy'): - r"""Convolve stack of data with stack of kernels +def convolve_stack(input_data, kernel, rot_kernel=False, method='scipy'): + """Convolve stack of data with stack of kernels. This method convolves the input data with a given kernel using FFT and is the default convolution used for all routines Parameters ---------- - data : numpy.ndarray + input_data : numpy.ndarray Input data array, normally a 2D image kernel : numpy.ndarray Input kernel array, normally a 2D kernel @@ -119,36 +126,37 @@ def convolve_stack(data, kernel, rot_kernel=False, method='scipy'): Examples -------- - >>> from math.convolve import convolve >>> import numpy as np + >>> from modopt.math.convolve import convolve_stack >>> a = np.arange(18).reshape(2, 3, 3) >>> b = a + 10 - >>> convolve_stack(a, b) - array([[[ 534., 525., 534.], - [ 453., 444., 453.], - [ 534., 525., 534.]], + >>> convolve_stack(a, b, method='astropy') + array([[[ 534., 525., 534.], + [ 453., 444., 453.], + [ 534., 525., 534.]], - [[ 2721., 2712., 2721.], - [ 2640., 2631., 2640.], - [ 2721., 2712., 2721.]]]) - - >>> convolve_stack(a, b, rot_kernel=True) - array([[[ 474., 483., 474.], - [ 555., 564., 555.], - [ 474., 483., 474.]], + [[2721., 2712., 2721.], + [2640., 2631., 2640.], + [2721., 2712., 2721.]]]) + + >>> convolve_stack(a, b, method='astropy', rot_kernel=True) + array([[[ 474., 483., 474.], + [ 555., 564., 555.], + [ 474., 483., 474.]], - [[ 2661., 2670., 2661.], - [ 2742., 2751., 2742.], - [ 2661., 2670., 2661.]]]) + [[2661., 2670., 2661.], + [2742., 2751., 2742.], + [2661., 2670., 2661.]]]) See Also -------- convolve : The convolution function called by convolve_stack """ - if rot_kernel: kernel = rotate_stack(kernel) - return np.array([convolve(data_i, kernel_i, method=method) for data_i, - kernel_i in zip(data, kernel)]) + return np.array([ + convolve(data_i, kernel_i, method=method) + for data_i, kernel_i in zip(input_data, kernel) + ]) diff --git a/modopt/math/matrix.py b/modopt/math/matrix.py index cb60bdf5..cb54cebc 100644 --- a/modopt/math/matrix.py +++ b/modopt/math/matrix.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -"""MATRIX ROUTINES +"""MATRIX ROUTINES. This module contains methods for matrix operations. @@ -8,12 +8,20 @@ """ -import numpy as np from itertools import product +import numpy as np + +from modopt.base.backend import get_array_module + +try: + import cupy as cp +except ImportError: # pragma: no cover + pass + def gram_schmidt(matrix, return_opt='orthonormal'): - r"""Gram-Schmit + """Gram-Schmit. This method orthonormalizes the row vectors of the input matrix. @@ -29,8 +37,14 @@ def gram_schmidt(matrix, return_opt='orthonormal'): tuple or numpy.ndarray Orthogonal vectors, u, and/or orthonormal vectors, e + Raises + ------ + ValueError + For invalid return option + Examples -------- + >>> import numpy as np >>> from modopt.math.matrix import gram_schmidt >>> a = np.arange(9).reshape(3, 3) >>> gram_schmidt(a) @@ -44,43 +58,44 @@ def gram_schmidt(matrix, return_opt='orthonormal'): https://en.wikipedia.org/wiki/Gram%E2%80%93Schmidt_process """ + if return_opt not in {'orthonormal', 'orthogonal', 'both'}: + raise ValueError( + 'Invalid return_opt, options are: "orthonormal", "orthogonal" or ' + + '"both"', + ) - if return_opt not in ('orthonormal', 'orthogonal', 'both'): - raise ValueError('Invalid return_opt, options are: "orthonormal", ' - '"orthogonal" or "both"') - - u = [] - e = [] + u_vec = [] + e_vec = [] for vector in matrix: - if len(u) == 0: - u_now = vector + if u_vec: + u_now = vector - sum(project(u_i, vector) for u_i in u_vec) else: - u_now = vector - sum([project(u_i, vector) for u_i in u]) + u_now = vector - u.append(u_now) - e.append(u_now / np.linalg.norm(u_now, 2)) + u_vec.append(u_now) + e_vec.append(u_now / np.linalg.norm(u_now, 2)) - u = np.array(u) - e = np.array(e) + u_vec = np.array(u_vec) + e_vec = np.array(e_vec) if return_opt == 'orthonormal': - return e + return e_vec elif return_opt == 'orthogonal': - return u + return u_vec elif return_opt == 'both': - return u, e + return u_vec, e_vec -def nuclear_norm(data): - r"""Nuclear norm +def nuclear_norm(input_data): + r"""Nuclear norm. This method computes the nuclear (or trace) norm of the input data. Parameters ---------- - data : numpy.ndarray + input_data : numpy.ndarray Input data array Returns @@ -90,6 +105,7 @@ def nuclear_norm(data): Examples -------- + >>> import numpy as np >>> from modopt.math.matrix import nuclear_norm >>> a = np.arange(9).reshape(3, 3) >>> nuclear_norm(a) @@ -103,24 +119,23 @@ def nuclear_norm(data): \|\mathbf{A}\|_* = \sum_{i=1}^{\min\{m,n\}} \sigma_i (\mathbf{A}) """ - # Get SVD of the data. - u, s, v = np.linalg.svd(data) + _, singular_values, _ = np.linalg.svd(input_data) # Return nuclear norm. - return np.sum(s) + return np.sum(singular_values) -def project(u, v): - r"""Project vector +def project(u_vec, v_vec): + r"""Project vector. This method projects vector v onto vector u. Parameters ---------- - u : numpy.ndarray + u_vec : numpy.ndarray Input vector - v : numpy.ndarray + v_vec : numpy.ndarray Input vector Returns @@ -130,11 +145,12 @@ def project(u, v): Examples -------- + >>> import numpy as np >>> from modopt.math.matrix import project >>> a = np.arange(3) >>> b = a + 3 >>> project(a, b) - array([ 0. , 2.8, 5.6]) + array([0. , 2.8, 5.6]) Notes ----- @@ -147,12 +163,11 @@ def project(u, v): (see https://en.wikipedia.org/wiki/Gram%E2%80%93Schmidt_process) """ - - return np.inner(v, u) / np.inner(u, u) * u + return np.inner(v_vec, u_vec) / np.inner(u_vec, u_vec) * u_vec def rot_matrix(angle): - r"""Rotation matrix + r"""Rotation matrix. This method produces a 2x2 rotation matrix for the given input angle. @@ -168,6 +183,7 @@ def rot_matrix(angle): Examples -------- + >>> import numpy as np >>> from modopt.math.matrix import rot_matrix >>> rot_matrix(np.pi / 6) array([[ 0.8660254, -0.5 ], @@ -184,13 +200,17 @@ def rot_matrix(angle): \end{bmatrix} """ - - return np.around(np.array([[np.cos(angle), -np.sin(angle)], - [np.sin(angle), np.cos(angle)]], dtype='float'), 10) + return np.around( + np.array( + [[np.cos(angle), -np.sin(angle)], [np.sin(angle), np.cos(angle)]], + dtype='float', + ), + 10, + ) def rotate(matrix, angle): - r"""Rotate + """Rotate. This method rotates an input matrix about the input angle. @@ -213,6 +233,7 @@ def rotate(matrix, angle): Examples -------- + >>> import numpy as np >>> from modopt.math.matrix import rotate >>> a = np.arange(9).reshape(3, 3) >>> rotate(a, np.pi / 2) @@ -221,7 +242,6 @@ def rotate(matrix, angle): [0, 3, 6]]) """ - shape = np.array(matrix.shape) if shape[0] != shape[1]: @@ -229,8 +249,10 @@ def rotate(matrix, angle): shift = (shape - 1) // 2 - index = np.array(list(product(*np.array([np.arange(val) for val in - shape])))) - shift + index = ( + np.array(list(product(*np.array([np.arange(sval) for sval in shape])))) + - shift + ) new_index = np.array(np.dot(index, rot_matrix(angle)), dtype='int') + shift new_index[new_index >= shape[0]] -= shape[0] @@ -239,7 +261,7 @@ def rotate(matrix, angle): class PowerMethod(object): - """Power method class + """Power method class. This method performs implements power method to calculate the spectral radius of the input data @@ -260,14 +282,14 @@ class PowerMethod(object): Examples -------- + >>> import numpy as np >>> from modopt.math.matrix import PowerMethod >>> np.random.seed(1) >>> pm = PowerMethod(lambda x: x.dot(x.T), (3, 3)) - - Power Method converged after 4 iterations! - >>> pm.spec_rad - 0.90429242629600848 - >>> pm.inv_spec_rad - 1.1058369736612865 + >>> np.around(pm.spec_rad, 6) + 0.904292 + >>> np.around(pm.inv_spec_rad, 6) + 1.105837 Notes ----- @@ -275,18 +297,29 @@ class PowerMethod(object): """ - def __init__(self, operator, data_shape, data_type=float, auto_run=True, - verbose=False): + def __init__( + self, + operator, + data_shape, + data_type=float, + auto_run=True, + use_gpu=False, + verbose=False, + ): self._operator = operator self._data_shape = data_shape self._data_type = data_type self._verbose = verbose + if use_gpu: + self.xp = cp + else: + self.xp = np if auto_run: self.get_spec_rad() def _set_initial_x(self): - """Set initial value of x + """Set initial value of x. This method sets the initial value of x to an arrray of random values @@ -296,11 +329,10 @@ def _set_initial_x(self): Random values of the same shape as the input data """ - - return np.random.random(self._data_shape).astype(self._data_type) + return self.xp.random.random(self._data_shape).astype(self._data_type) def get_spec_rad(self, tolerance=1e-6, max_iter=20, extra_factor=1.0): - """Get spectral radius + """Get spectral radius. This method calculates the spectral radius @@ -315,30 +347,35 @@ def get_spec_rad(self, tolerance=1e-6, max_iter=20, extra_factor=1.0): (default is ``1.0``) """ - # Set (or reset) values of x. x_old = self._set_initial_x() # Iterate until the L2 norm of x converges. - for i in range(max_iter): + for i_elem in range(max_iter): + + xp = get_array_module(x_old) - x_old_norm = np.linalg.norm(x_old) + x_old_norm = xp.linalg.norm(x_old) x_new = self._operator(x_old) / x_old_norm - x_new_norm = np.linalg.norm(x_new) + x_new_norm = xp.linalg.norm(x_new) - if(np.abs(x_new_norm - x_old_norm) < tolerance): + if (xp.abs(x_new_norm - x_old_norm) < tolerance): + message = ( + ' - Power Method converged after {0} iterations!' + ) if self._verbose: - print(' - Power Method converged after %d iterations!' % - (i + 1)) + print(message.format(i_elem + 1)) break - elif i == max_iter - 1 and self._verbose: - print(' - Power Method did not converge after %d ' - 'iterations!' % max_iter) + elif i_elem == max_iter - 1 and self._verbose: + message = ( + ' - Power Method did not converge after {0} iterations!' + ) + print(message.format(max_iter)) - np.copyto(x_old, x_new) + xp.copyto(x_old, x_new) self.spec_rad = x_new_norm * extra_factor self.inv_spec_rad = 1.0 / self.spec_rad diff --git a/modopt/math/metrics.py b/modopt/math/metrics.py index 54e303bb..1b870e23 100644 --- a/modopt/math/metrics.py +++ b/modopt/math/metrics.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -"""METRICS +"""METRICS. This module contains classes of different metric functions for optimization. @@ -9,14 +9,11 @@ """ import numpy as np -from scipy.ndimage import uniform_filter, gaussian_filter -import sys + +from modopt.base.backend import move_to_cpu try: - if sys.version_info.minor == 5: - from skimage.measure import compare_ssim - elif sys.version_info.minor > 5: - from skimage.metrics import structural_similarity as compare_ssim + from skimage.metrics import structural_similarity as compare_ssim except ImportError: # pragma: no cover import_skimage = False else: @@ -24,15 +21,21 @@ def min_max_normalize(img): - """Centre and normalize a given array. + """Min-Max Normalize. + + Centre and normalize a given array. Parameters ---------- img : numpy.ndarray Input image - """ + Returns + ------- + numpy.ndarray + Centred and normalized array + """ min_img = img.min() max_img = img.max() @@ -40,7 +43,9 @@ def min_max_normalize(img): def _preprocess_input(test, ref, mask=None): - """Wrapper to the metric + """Proprocess Input. + + Wrapper to the metric. Parameters ---------- @@ -51,6 +56,11 @@ def _preprocess_input(test, ref, mask=None): mask : numpy.ndarray, optional The mask for the ROI (default is ``None``) + Raises + ------ + ValueError + For invalid mask value + Notes ----- Compute the metric only on magnetude. @@ -61,15 +71,16 @@ def _preprocess_input(test, ref, mask=None): The SNR """ - test = np.abs(np.copy(test)).astype('float64') ref = np.abs(np.copy(ref)).astype('float64') test = min_max_normalize(test) ref = min_max_normalize(ref) if (not isinstance(mask, np.ndarray)) and (mask is not None): - raise ValueError("mask should be None, or a numpy.ndarray," - " got '{0}' instead.".format(mask)) + message = ( + 'Mask should be None, or a numpy.ndarray, got "{0}" instead.' + ) + raise ValueError(message.format(mask)) if mask is None: return test, ref, None @@ -78,7 +89,7 @@ def _preprocess_input(test, ref, mask=None): def ssim(test, ref, mask=None): - """Structural Similarity (SSIM) + """Structural Similarity (SSIM). Calculate the SSIM between a test image and a reference image. @@ -91,6 +102,11 @@ def ssim(test, ref, mask=None): mask : numpy.ndarray, optional The mask for the ROI (default is ``None``) + Raises + ------ + ImportError + If Scikit-Image package not found + Notes ----- Compute the metric only on magnetude. @@ -101,24 +117,25 @@ def ssim(test, ref, mask=None): The SNR """ - if not import_skimage: # pragma: no cover - raise ImportError('Required version of Scikit-Image package not found' - 'see documentation for details: https://cea-cosmic.' - 'github.io/ModOpt/#optional-packages') + raise ImportError( + 'Required version of Scikit-Image package not found' + + 'see documentation for details: https://cea-cosmic.' + + 'github.io/ModOpt/#optional-packages', + ) test, ref, mask = _preprocess_input(test, ref, mask) - assim, ssim = compare_ssim(test, ref, full=True) + test = move_to_cpu(test) + assim, ssim_value = compare_ssim(test, ref, full=True) if mask is None: return assim - else: - return (mask * ssim).sum() / mask.sum() + return (mask * ssim_value).sum() / mask.sum() def snr(test, ref, mask=None): - """Signal-to-Noise Ratio (SNR) + """Signal-to-Noise Ratio (SNR). Calculate the SNR between a test image and a reference image. @@ -141,7 +158,6 @@ def snr(test, ref, mask=None): The SNR """ - test, ref, mask = _preprocess_input(test, ref, mask) if mask is not None: @@ -154,7 +170,7 @@ def snr(test, ref, mask=None): def psnr(test, ref, mask=None): - """Peak Signal-to-Noise Ratio (PSNR) + """Peak Signal-to-Noise Ratio (PSNR). Calculate the PSNR between a test image and a reference image. @@ -177,7 +193,6 @@ def psnr(test, ref, mask=None): The PSNR """ - test, ref, mask = _preprocess_input(test, ref, mask) if mask is not None: @@ -191,7 +206,7 @@ def psnr(test, ref, mask=None): def mse(test, ref, mask=None): - r"""Mean Squared Error (MSE) + r"""Mean Squared Error (MSE). Calculate the MSE between a test image and a reference image. @@ -217,7 +232,6 @@ def mse(test, ref, mask=None): The MSE """ - test, ref, mask = _preprocess_input(test, ref, mask) if mask is not None: @@ -228,7 +242,7 @@ def mse(test, ref, mask=None): def nrmse(test, ref, mask=None): - """Return NRMSE + """Return NRMSE. Parameters ---------- @@ -249,7 +263,6 @@ def nrmse(test, ref, mask=None): The NRMSE """ - test, ref, mask = _preprocess_input(test, ref, mask) if mask is not None: diff --git a/modopt/math/stats.py b/modopt/math/stats.py index 19340754..858e0ade 100644 --- a/modopt/math/stats.py +++ b/modopt/math/stats.py @@ -1,20 +1,15 @@ # -*- coding: utf-8 -*- -"""STATISTICS ROUTINES +"""STATISTICS ROUTINES. This module contains methods for basic statistics. :Author: Samuel Farrens -:References: - -.. bibliography:: refs.bib - :filter: docname in docnames - """ import numpy as np -from scipy.stats import chi2 + try: from astropy.convolution import Gaussian2DKernel except ImportError: # pragma: no cover @@ -24,7 +19,7 @@ def gaussian_kernel(data_shape, sigma, norm='max'): - r"""Gaussian kernel + """Gaussian kernel. This method produces a Gaussian kerenal of a specified size and dispersion @@ -43,29 +38,36 @@ def gaussian_kernel(data_shape, sigma, norm='max'): numpy.ndarray Kernel + Raises + ------ + ImportError + If Astropy package not found + ValueError + For invalid norm + Examples -------- >>> from modopt.math.stats import gaussian_kernel >>> gaussian_kernel((3, 3), 1) - array([[ 0.36787944, 0.60653066, 0.36787944], - [ 0.60653066, 1. , 0.60653066], - [ 0.36787944, 0.60653066, 0.36787944]]) + array([[0.36787944, 0.60653066, 0.36787944], + [0.60653066, 1. , 0.60653066], + [0.36787944, 0.60653066, 0.36787944]]) >>> gaussian_kernel((3, 3), 1, norm='sum') - array([[ 0.07511361, 0.1238414 , 0.07511361], - [ 0.1238414 , 0.20417996, 0.1238414 ], - [ 0.07511361, 0.1238414 , 0.07511361]]) + array([[0.07511361, 0.1238414 , 0.07511361], + [0.1238414 , 0.20417996, 0.1238414 ], + [0.07511361, 0.1238414 , 0.07511361]]) """ - if not import_astropy: # pragma: no cover raise ImportError('Astropy package not found.') - if norm not in ('max', 'sum', 'none'): + if norm not in {'max', 'sum', 'none'}: raise ValueError('Invalid norm, options are "max", "sum" or "none".') - kernel = np.array(Gaussian2DKernel(sigma, x_size=data_shape[1], - y_size=data_shape[0])) + kernel = np.array( + Gaussian2DKernel(sigma, x_size=data_shape[1], y_size=data_shape[0]), + ) if norm == 'max': return kernel / np.max(kernel) @@ -77,14 +79,14 @@ def gaussian_kernel(data_shape, sigma, norm='max'): return kernel -def mad(data): - r"""Median absolute deviation +def mad(input_data): + r"""Median absolute deviation. This method calculates the median absolute deviation of the input data. Parameters ---------- - data : numpy.ndarray + input_data : numpy.ndarray Input data array Returns @@ -94,6 +96,7 @@ def mad(data): Examples -------- + >>> import numpy as np >>> from modopt.math.stats import mad >>> a = np.arange(9).reshape(3, 3) >>> mad(a) @@ -112,12 +115,11 @@ def mad(data): numpy.median : median function used """ - - return np.median(np.abs(data - np.median(data))) + return np.median(np.abs(input_data - np.median(input_data))) def mse(data1, data2): - """Mean Squared Error + """Mean Squared Error. This method returns the Mean Squared Error (MSE) between two data sets. @@ -128,20 +130,25 @@ def mse(data1, data2): data2 : numpy.ndarray Second data set + Returns + ------- + float + Mean squared error + Examples -------- + >>> import numpy as np >>> from modopt.math.stats import mse >>> a = np.arange(9).reshape(3, 3) >>> mse(a, a + 2) 4.0 """ - return np.mean((data1 - data2) ** 2) def psnr(data1, data2, method='starck', max_pix=255): - r"""Peak Signal-to-Noise Ratio + r"""Peak Signal-to-Noise Ratio. This method calculates the Peak Signal-to-Noise Ratio between an two data sets @@ -162,15 +169,21 @@ def psnr(data1, data2, method='starck', max_pix=255): float PSNR value + Raises + ------ + ValueError + For invalid PSNR method + Examples -------- + >>> import numpy as np >>> from modopt.math.stats import psnr >>> a = np.arange(9).reshape(3, 3) >>> psnr(a, a + 2) 12.041199826559248 >>> psnr(a, a + 2, method='wiki') - 42.110203695399477 + 42.11020369539948 Notes ----- @@ -189,25 +202,24 @@ def psnr(data1, data2, method='starck', max_pix=255): 10\log_{10}(\mathrm{MSE})) """ - if method == 'starck': - - return (20 * np.log10((data1.shape[0] * np.abs(np.max(data1) - - np.min(data1))) / np.linalg.norm(data1 - data2))) + return ( + 20 * np.log10( + (data1.shape[0] * np.abs(np.max(data1) - np.min(data1))) + / np.linalg.norm(data1 - data2), + ) + ) elif method == 'wiki': + return (20 * np.log10(max_pix) - 10 * np.log10(mse(data1, data2))) - return (20 * np.log10(max_pix) - 10 * - np.log10(mse(data1, data2))) - - else: - - raise ValueError('Invalid PSNR method. Options are "starck" and ' - '"wiki"') + raise ValueError( + 'Invalid PSNR method. Options are "starck" and "wiki"', + ) def psnr_stack(data1, data2, metric=np.mean, method='starck'): - r"""Peak Signa-to-Noise for stack of images + """Peak Signa-to-Noise for stack of images. This method calculates the PSNRs for two stacks of 2D arrays. By default the metod returns the mean value of the PSNRs, but any other @@ -237,6 +249,7 @@ def psnr_stack(data1, data2, metric=np.mean, method='starck'): Examples -------- + >>> import numpy as np >>> from modopt.math.stats import psnr_stack >>> a = np.arange(18).reshape(2, 3, 3) >>> psnr_stack(a, a + 2) @@ -247,23 +260,24 @@ def psnr_stack(data1, data2, metric=np.mean, method='starck'): numpy.mean : default metric """ - if data1.ndim != 3 or data2.ndim != 3: raise ValueError('Input data must be a 3D np.ndarray') - return metric([psnr(i, j, method=method) for i, j in - zip(data1, data2)]) + return metric([ + psnr(i_elem, j_elem, method=method) + for i_elem, j_elem in zip(data1, data2) + ]) -def sigma_mad(data): - r"""Standard deviation from MAD +def sigma_mad(input_data): + r"""MAD Standard Deviation. This method calculates the standard deviation of the input data from the MAD. Parameters ---------- - data : numpy.ndarray + input_data : numpy.ndarray Input data array Returns @@ -273,10 +287,11 @@ def sigma_mad(data): Examples -------- + >>> import numpy as np >>> from modopt.math.stats import sigma_mad >>> a = np.arange(9).reshape(3, 3) >>> sigma_mad(a) - 2.9651999999999998 + 2.9652 Notes ----- @@ -290,5 +305,4 @@ def sigma_mad(data): \sigma = 1.4826 \mathrm{MAD}(X) """ - - return 1.4826 * mad(data) + return 1.4826 * mad(input_data) diff --git a/modopt/opt/__init__.py b/modopt/opt/__init__.py index 6f926099..2fd3d747 100644 --- a/modopt/opt/__init__.py +++ b/modopt/opt/__init__.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -"""OPTIMISATION PROBLEM MODULES +"""OPTIMISATION PROBLEM MODULES. This module contains submodules for solving optimisation problems. @@ -9,5 +9,3 @@ """ __all__ = ['cost', 'gradient', 'linear', 'algorithms', 'proximity', 'reweight'] - -from . import * diff --git a/modopt/opt/algorithms.py b/modopt/opt/algorithms.py index 333f6791..ccd8fe21 100644 --- a/modopt/opt/algorithms.py +++ b/modopt/opt/algorithms.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -r"""OPTIMISATION ALGOTITHMS +r"""OPTIMISATION ALGOTITHMS. This module contains class implementations of various optimisation algoritms. @@ -41,25 +41,27 @@ * x_prox is used in place of :math:`\tilde{x}_{n+1}`. * x_temp is used for intermediate operations. -:References: - -.. bibliography:: refs.bib - :filter: docname in docnames - """ from inspect import getmro -from progressbar import ProgressBar + import numpy as np +from progressbar import ProgressBar + +from modopt.base import backend +from modopt.base.observable import MetricObserver, Observable from modopt.interface.errors import warn from modopt.opt.cost import costObj from modopt.opt.linear import Identity -# Package import -from ..base.observable import Observable, MetricObserver + +try: + import cupy as cp +except ImportError: # pragma: no cover + pass class SetUp(Observable): - """Algorithm Set-Up + r"""Algorithm Set-Up. This class contains methods for checking the set-up of an optimisation algotithm and produces warnings if they do not comply. @@ -69,7 +71,7 @@ class SetUp(Observable): metric_call_period : int, optional Metric call period (default is ``5``) metrics : dict, optional - Metrics to be used (default is ``{}``) + Metrics to be used (default is ``\{\}``) verbose : bool, optional Option for verbose output (default is ``False``) progress : bool, optional @@ -78,50 +80,123 @@ class SetUp(Observable): Generic step size parameter to override default algorithm parameter name (`e.g.` `step_size` will override the value set for `beta_param` in `ForwardBackward`) + use_gpu : bool, optional + Option to use available GPU """ - def __init__(self, metric_call_period=5, metrics={}, verbose=False, - progress=True, step_size=None, **dummy_kwargs): + def __init__( + self, + metric_call_period=5, + metrics=None, + verbose=False, + progress=True, + step_size=None, + use_gpu=False, + **dummy_kwargs, + ): self.converge = False self.verbose = verbose self.progress = progress self.metrics = metrics self.step_size = step_size - self._op_parents = ('GradParent', 'ProximityParent', 'LinearParent', - 'costObj') + self._op_parents = ( + 'GradParent', + 'ProximityParent', + 'LinearParent', + 'costObj', + ) self.metric_call_period = metric_call_period # Declaration of observers for metrics - Observable.__init__(self, ["cv_metrics"]) + super().__init__(['cv_metrics']) + + for name, dic in self.metrics.items(): + observer = MetricObserver( + name, + dic['metric'], + dic['mapping'], + dic['cst_kwargs'], + dic['early_stopping'], + ) + self.add_observer('cv_metrics', observer) + + # Check for GPU + if use_gpu: + if backend.gpu_compatibility['cupy']: + self.xp = cp + else: + warn( + 'CuPy is not installed, cannot run on GPU!' + + 'Running optimization on CPU.', + ) + self.xp = np + use_gpu = False + else: + self.xp = np + self.use_gpu = use_gpu + + @property + def metrics(self): + """Metrics.""" + return self._metrics + + @metrics.setter + def metrics(self, metrics): - for name, dic in metrics.items(): - observer = MetricObserver(name, dic['metric'], - dic['mapping'], - dic['cst_kwargs'], - dic['early_stopping']) - self.add_observer("cv_metrics", observer) + if isinstance(metrics, type(None)): + self._metrics = {} + elif not isinstance(metrics, dict): + raise TypeError( + 'Metrics must be a dictionary, not {0}.'.format(type(metrics)), + ) def any_convergence_flag(self): - """Check convergence flag + """Check convergence flag. Return if any matrices values matched the convergence criteria. + Returns + ------- + bool + True if any convergence criteria met + """ + return any( + obs.converge_flag for obs in self._observers['cv_metrics'] + ) - return any([obs.converge_flag for obs in - self._observers['cv_metrics']]) + def copy_data(self, input_data): + """Copy Data. - def _check_input_data(self, data): - """Check input data type + Set directive for copying data. + + Parameters + ---------- + input_data : numpy.ndarray + Input data + + Returns + ------- + numpy.ndarray + Copy of input data + + """ + if self.use_gpu: + return backend.move_to_device(input_data) + + return self.xp.copy(input_data) + + def _check_input_data(self, input_data): + """Check input data type. This method checks if the input data is a numpy array Parameters ---------- - data : numpy.ndarray + input_data : numpy.ndarray Input data array Raises @@ -130,18 +205,17 @@ def _check_input_data(self, data): For invalid input type """ - - if not isinstance(data, np.ndarray): + if not isinstance(input_data, self.xp.ndarray): raise TypeError('Input data must be a numpy array.') - def _check_param(self, param): - """Check algorithm parameters + def _check_param(self, param_val): + """Check algorithm parameters. This method checks if the specified algorithm parameters are floats Parameters ---------- - param : float + param_val : float Parameter value Raises @@ -150,12 +224,11 @@ def _check_param(self, param): For invalid input type """ - - if not isinstance(param, float): + if not isinstance(param_val, float): raise TypeError('Algorithm parameter must be a float value.') def _check_param_update(self, param_update): - """Check algorithm parameter update methods + """Check algorithm parameter update methods. This method checks if the specified algorithm parameters are floats @@ -170,14 +243,18 @@ def _check_param_update(self, param_update): For invalid input type """ + param_conditions = ( + not isinstance(param_update, type(None)) + and not callable(param_update) + ) - if (not isinstance(param_update, type(None)) and - not callable(param_update)): - raise TypeError('Algorithm parameter update must be a callabale ' - 'function.') + if param_conditions: + raise TypeError( + 'Algorithm parameter update must be a callabale function.', + ) def _check_operator(self, operator): - """Check set-Up + """Check set-Up. This method checks algorithm operator against the expected parent classes @@ -188,37 +265,36 @@ def _check_operator(self, operator): Algorithm operator to check """ - if not isinstance(operator, type(None)): - tree = [obj.__name__ for obj in getmro(operator.__class__)] + tree = [op_obj.__name__ for op_obj in getmro(operator.__class__)] - if not any([parent in tree for parent in self._op_parents]): - warn('{0} does not inherit an operator ' - 'parent.'.format(str(operator.__class__))) + if not any(parent in tree for parent in self._op_parents): + message = '{0} does not inherit an operator parent.' + warn(message.format(str(operator.__class__))) def _compute_metrics(self): - """Compute metrics during iteration + """Compute metrics during iteration. This method create the args necessary for metrics computation, then call the observers to compute metrics """ - kwargs = self.get_notify_observers_kwargs() self.notify_observers('cv_metrics', **kwargs) - def _iterations(self, max_iter, bar=None): - """Iterations + def _iterations(self, max_iter, progbar=None): + """Iterate method. + + Iterate the update step of the given algorithm. Parameters ---------- max_iter : int Maximum number of iterations - bar : progressbar.ProgressBar + progbar : progressbar.ProgressBar Progress bar (default is ``None``) """ - for idx in range(max_iter): self.idx = idx self._update() @@ -228,9 +304,14 @@ def _iterations(self, max_iter, bar=None): # We do not call metrics if metrics is empty or metric call # period is None if self.metrics and self.metric_call_period is not None: - if self.idx % self.metric_call_period == 0 or \ - self.idx == (max_iter - 1) or \ - self.converge: + + metric_conditions = ( + self.idx % self.metric_call_period == 0 + or self.idx == (max_iter - 1) + or self.converge, + ) + + if metric_conditions: self._compute_metrics() if self.converge: @@ -238,11 +319,11 @@ def _iterations(self, max_iter, bar=None): print(' - Converged!') break - if not isinstance(bar, type(None)): - bar.update(idx) + if not isinstance(progbar, type(None)): + progbar.update(idx) def _run_alg(self, max_iter): - """Run algorithm + """Run algorithm. Run the update step of a given algorithm up to the maximum number of iterations. @@ -253,16 +334,18 @@ def _run_alg(self, max_iter): Maximum number of iterations """ - if self.progress: - with ProgressBar(redirect_stdout=True, max_value=max_iter) as bar: - self._iterations(max_iter, bar=bar) + with ProgressBar( + redirect_stdout=True, + max_value=max_iter, + ) as progbar: + self._iterations(max_iter, progbar=progbar) else: self._iterations(max_iter) class FISTA(object): - r"""FISTA + """FISTA. This class is inherited by optimisation classes to speed up convergence The parameters for the modified FISTA are as described in :cite:`liang2018` @@ -303,16 +386,28 @@ class FISTA(object): """ - __restarting_strategies__ = [ - 'adaptive', 'adaptive-i', 'adaptive-1', # option 1 in alg 4 - 'adaptive-ii', 'adaptive-2', # option 2 in alg 4 + _restarting_strategies = ( + 'adaptive', # option 1 in alg 4 + 'adaptive-i', + 'adaptive-1', + 'adaptive-ii', # option 2 in alg 4 + 'adaptive-2', 'greedy', # alg 5 None, # no restarting - ] - - def __init__(self, restart_strategy=None, min_beta=None, s_greedy=None, - xi_restart=None, a_cd=None, p_lazy=1, q_lazy=1, r_lazy=4, - **kwargs): + ) + + def __init__( + self, + restart_strategy=None, + min_beta=None, + s_greedy=None, + xi_restart=None, + a_cd=None, + p_lazy=1, + q_lazy=1, + r_lazy=4, + **kwargs, + ): if isinstance(a_cd, type(None)): self.mode = 'regular' @@ -326,29 +421,39 @@ def __init__(self, restart_strategy=None, min_beta=None, s_greedy=None, self._n = 0 else: - raise ValueError('a_cd must either be None (for regular mode) or ' - 'a number > 2') - - if restart_strategy in self.__class__.__restarting_strategies__: - self._check_restart_params(restart_strategy, min_beta, s_greedy, - xi_restart) + raise ValueError( + 'a_cd must either be None (for regular mode) or a number > 2', + ) + + if restart_strategy in self._restarting_strategies: + self._check_restart_params( + restart_strategy, min_beta, s_greedy, xi_restart, + ) self.restart_strategy = restart_strategy self.min_beta = min_beta self.s_greedy = s_greedy self.xi_restart = xi_restart else: - raise ValueError('Restarting strategy must be one of {}.'.format( - ', '.join( - self.__class__.__restarting_strategies__))) + message = 'Restarting strategy must be one of {0}.' + raise ValueError( + message.format( + ', '.join(self._restarting_strategies), + ), + ) self._t_now = 1.0 self._t_prev = 1.0 - self._delta_0 = None + self._delta0 = None self._safeguard = False - def _check_restart_params(self, restart_strategy, min_beta, s_greedy, - xi_restart): - r"""Check restarting parameters + def _check_restart_params( + self, + restart_strategy, + min_beta, + s_greedy, + xi_restart, + ): + """Check restarting parameters. This method checks that the restarting parameters are set and satisfy the correct assumptions. It also checks that the current mode is @@ -384,20 +489,22 @@ def _check_restart_params(self, restart_strategy, min_beta, s_greedy, correct assumptions. """ - if restart_strategy is None: return True if self.mode != 'regular': - raise ValueError('Restarting strategies can only be used with ' - 'regular mode.') + raise ValueError( + 'Restarting strategies can only be used with regular mode.', + ) - greedy_params_check = (min_beta is None or s_greedy is None or - s_greedy <= 1) + greedy_params_check = ( + min_beta is None or s_greedy is None or s_greedy <= 1 + ) if restart_strategy == 'greedy' and greedy_params_check: - raise ValueError('You need a min_beta and an s_greedy > 1 for ' - 'greedy restart.') + raise ValueError( + 'You need a min_beta and an s_greedy > 1 for greedy restart.', + ) if xi_restart is None or xi_restart >= 1: raise ValueError('You need a xi_restart < 1 for restart.') @@ -405,7 +512,7 @@ def _check_restart_params(self, restart_strategy, min_beta, s_greedy, return True def is_restart(self, z_old, x_new, x_old): - r"""Check whether the algorithm needs to restart + """Check whether the algorithm needs to restart. This method implements the checks necessary to tell whether the algorithm needs to restart depending on the restarting strategy. @@ -432,28 +539,30 @@ def is_restart(self, z_old, x_new, x_old): :cite:`liang2018` """ + xp = backend.get_array_module(x_new) + if self.restart_strategy is None: return False - criterion = np.vdot(z_old - x_new, x_new - x_old) >= 0 + criterion = xp.vdot(z_old - x_new, x_new - x_old) >= 0 if criterion: if 'adaptive' in self.restart_strategy: self.r_lazy *= self.xi_restart - if self.restart_strategy in ['adaptive-ii', 'adaptive-2']: + if self.restart_strategy in {'adaptive-ii', 'adaptive-2'}: self._t_now = 1 if self.restart_strategy == 'greedy': - cur_delta = np.linalg.norm(x_new - x_old) - if self._delta_0 is None: - self._delta_0 = self.s_greedy * cur_delta + cur_delta = xp.linalg.norm(x_new - x_old) + if self._delta0 is None: + self._delta0 = self.s_greedy * cur_delta else: - self._safeguard = cur_delta >= self._delta_0 + self._safeguard = cur_delta >= self._delta0 return criterion def update_beta(self, beta): - r"""Update beta + """Update beta. This method updates beta only in the case of safeguarding (should only be done in the greedy restarting strategy). @@ -469,7 +578,6 @@ def update_beta(self, beta): The new value for the beta parameter """ - if self._safeguard: beta *= self.xi_restart beta = max(beta, self.min_beta) @@ -477,10 +585,17 @@ def update_beta(self, beta): return beta def update_lambda(self, *args, **kwargs): - r"""Update lambda + """Update lambda. This method updates the value of lambda + Parameters + ---------- + args : interable + Positional arguments + kwargs : dict + Keyword arguments + Returns ------- float @@ -491,7 +606,6 @@ def update_lambda(self, *args, **kwargs): Implements steps 3 and 4 from algoritm 10.7 in :cite:`bauschke2009` """ - if self.restart_strategy == 'greedy': return 2 @@ -499,8 +613,8 @@ def update_lambda(self, *args, **kwargs): self._t_prev = self._t_now if self.mode == 'regular': - self._t_now = (self.p_lazy + np.sqrt(self.r_lazy * - self._t_prev ** 2 + self.q_lazy)) * 0.5 + sqrt_part = self.r_lazy * self._t_prev ** 2 + self.q_lazy + self._t_now = self.p_lazy + np.sqrt(sqrt_part) * 0.5 elif self.mode == 'CD': self._t_now = (self._n + self.a_cd - 1) / self.a_cd @@ -510,7 +624,7 @@ def update_lambda(self, *args, **kwargs): class ForwardBackward(SetUp): - r"""Forward-Backward optimisation + """Forward-Backward optimisation. This class implements standard forward-backward optimisation with an the option to use the FISTA speed-up @@ -550,23 +664,39 @@ class ForwardBackward(SetUp): """ - def __init__(self, x, grad, prox, cost='auto', beta_param=1.0, - lambda_param=1.0, beta_update=None, lambda_update='fista', - auto_iterate=True, metric_call_period=5, metrics={}, - linear=None, **kwargs): + def __init__( + self, + x, + grad, + prox, + cost='auto', + beta_param=1.0, + lambda_param=1.0, + beta_update=None, + lambda_update='fista', + auto_iterate=True, + metric_call_period=5, + metrics=None, + linear=None, + **kwargs, + ): # Set default algorithm properties - super(ForwardBackward, self).__init__( - metric_call_period=metric_call_period, - metrics=metrics, **kwargs) + super().__init__( + metric_call_period=metric_call_period, + metrics=metrics, + **kwargs, + ) # Set the initial variable values self._check_input_data(x) - self._x_old = np.copy(x) - self._z_old = np.copy(x) + self._x_old = self.copy_data(x) + self._z_old = self.copy_data(x) # Set the algorithm operators - (self._check_operator(operator) for operator in (grad, prox, cost)) + for operator in (grad, prox, cost): + self._check_operator(operator) + self._grad = grad self._prox = prox self._linear = linear @@ -577,15 +707,18 @@ def __init__(self, x, grad, prox, cost='auto', beta_param=1.0, self._cost_func = cost # Check if there is a linear op, needed for metrics in the FB algoritm - if metrics != {} and self._linear is None: - raise ValueError('When using metrics, you must pass a linear ' - 'operator') + if metrics and self._linear is None: + raise ValueError( + 'When using metrics, you must pass a linear operator', + ) if self._linear is None: self._linear = Identity() # Set the algorithm parameters - (self._check_param(param) for param in (beta_param, lambda_param)) + for param_val in (beta_param, lambda_param): + self._check_param(param_val) + self._beta = self.step_size or beta_param self._lambda = lambda_param @@ -607,13 +740,12 @@ def __init__(self, x, grad, prox, cost='auto', beta_param=1.0, self.iterate() def _update_param(self): - r"""Update parameters + """Update parameters. This method updates the values of the algorthm parameters with the methods provided """ - # Update the gamma parameter. if not isinstance(self._beta_update, type(None)): self._beta = self._beta_update(self._beta) @@ -623,7 +755,7 @@ def _update_param(self): self._lambda = self._lambda_update(self._lambda) def _update(self): - r"""Update + """Update. This method updates the current reconstruction @@ -632,7 +764,6 @@ def _update(self): Implements algorithm 10.7 (or 10.5) from :cite:`bauschke2009` """ - # Step 1 from alg.10.7. self._grad.get_grad(self._z_old) y_old = self._z_old - self._beta * self._grad.grad @@ -648,19 +779,21 @@ def _update(self): self._z_new = self._x_new # Update old values for next iteration. - np.copyto(self._x_old, self._x_new) - np.copyto(self._z_old, self._z_new) + self.xp.copyto(self._x_old, self._x_new) + self.xp.copyto(self._z_old, self._z_new) # Update parameter values for next iteration. self._update_param() # Test cost function for convergence. if self._cost_func: - self.converge = self.any_convergence_flag() or \ - self._cost_func.get_cost(self._x_new) + self.converge = ( + self.any_convergence_flag() + or self._cost_func.get_cost(self._x_new), + ) def iterate(self, max_iter=150): - r"""Iterate + """Iterate. This method calls update until either convergence criteria is met or the maximum number of iterations is reached @@ -671,7 +804,6 @@ def iterate(self, max_iter=150): Maximum number of iterations (default is ``150``) """ - self._run_alg(max_iter) # retrieve metrics results @@ -680,7 +812,7 @@ def iterate(self, max_iter=150): self.x_final = self._z_new def get_notify_observers_kwargs(self): - """Notify observers + """Notify observers. Return the mapping between the metrics call and the iterated variables. @@ -691,17 +823,19 @@ def get_notify_observers_kwargs(self): The mapping between the iterated variables """ - return {'x_new': self._linear.adj_op(self._x_new), - 'z_new': self._z_new, 'idx': self.idx} + return { + 'x_new': self._linear.adj_op(self._x_new), + 'z_new': self._z_new, + 'idx': self.idx, + } def retrieve_outputs(self): - """Retireve outputs + """Retireve outputs. Declare the outputs of the algorithms as attributes: x_final, y_final, metrics. """ - metrics = {} for obs in self._observers['cv_metrics']: metrics[obs.name] = obs.retrieve_metrics() @@ -709,7 +843,7 @@ def retrieve_outputs(self): class GenForwardBackward(SetUp): - r"""Generalized Forward-Backward Algorithm + """Generalized Forward-Backward Algorithm. This class implements algorithm 1 from :cite:`raguet2011` @@ -749,25 +883,41 @@ class GenForwardBackward(SetUp): """ - def __init__(self, x, grad, prox_list, cost='auto', gamma_param=1.0, - lambda_param=1.0, gamma_update=None, lambda_update=None, - weights=None, auto_iterate=True, metric_call_period=5, - metrics={}, linear=None, **kwargs): + def __init__( + self, + x, + grad, + prox_list, + cost='auto', + gamma_param=1.0, + lambda_param=1.0, + gamma_update=None, + lambda_update=None, + weights=None, + auto_iterate=True, + metric_call_period=5, + metrics=None, + linear=None, + **kwargs, + ): # Set default algorithm properties - super(GenForwardBackward, self).__init__( - metric_call_period=metric_call_period, - metrics=metrics, **kwargs) + super().__init__( + metric_call_period=metric_call_period, + metrics=metrics, + **kwargs, + ) # Set the initial variable values self._check_input_data(x) - self._x_old = np.copy(x) + self._x_old = self.xp.copy(x) # Set the algorithm operators - (self._check_operator(operator) for operator in [grad, cost] + - prox_list) + for operator in [grad, cost] + prox_list: + self._check_operator(operator) + self._grad = grad - self._prox_list = np.array(prox_list) + self._prox_list = self.xp.array(prox_list) self._linear = linear if cost == 'auto': @@ -776,21 +926,25 @@ def __init__(self, x, grad, prox_list, cost='auto', gamma_param=1.0, self._cost_func = cost # Check if there is a linear op, needed for metrics in the FB algoritm - if metrics != {} and self._linear is None: - raise ValueError('When using metrics, you must pass a linear ' - 'operator') + if metrics and self._linear is None: + raise ValueError( + 'When using metrics, you must pass a linear operator', + ) if self._linear is None: self._linear = Identity() # Set the algorithm parameters - (self._check_param(param) for param in (gamma_param, lambda_param)) + for param_val in (gamma_param, lambda_param): + self._check_param(param_val) + self._gamma = self.step_size or gamma_param self._lambda_param = lambda_param # Set the algorithm parameter update methods - (self._check_param_update(param_update) for param_update in - (gamma_update, lambda_update)) + for param_update in (gamma_update, lambda_update): + self._check_param_update(param_update) + self._gamma_update = gamma_update self._lambda_update = lambda_update @@ -798,14 +952,16 @@ def __init__(self, x, grad, prox_list, cost='auto', gamma_param=1.0, self._set_weights(weights) # Set initial z - self._z = np.array([self._x_old for i in range(self._prox_list.size)]) + self._z = self.xp.array([ + self._x_old for i in range(self._prox_list.size) + ]) # Automatically run the algorithm if auto_iterate: self.iterate() def _set_weights(self, weights): - """Set weights + """Set weights. This method sets weights on each of the proximty operators provided @@ -822,37 +978,42 @@ def _set_weights(self, weights): If weights do not sum to one """ - if isinstance(weights, type(None)): - weights = np.repeat(1.0 / self._prox_list.size, - self._prox_list.size) + weights = self.xp.repeat( + 1.0 / self._prox_list.size, + self._prox_list.size, + ) elif not isinstance(weights, (list, tuple, np.ndarray)): raise TypeError('Weights must be provided as a list.') - weights = np.array(weights) + weights = self.xp.array(weights) if not np.issubdtype(weights.dtype, np.floating): raise ValueError('Weights must be list of float values.') if weights.size != self._prox_list.size: - raise ValueError('The number of weights must match the number of ' - 'proximity operators.') + raise ValueError( + 'The number of weights must match the number of proximity ' + + 'operators.', + ) - if np.sum(weights) != 1.0: - raise ValueError('Proximity operator weights must sum to 1.0.' - 'Current sum of weights = ' + - str(np.sum(weights))) + expected_weight_sum = 1.0 + + if self.xp.sum(weights) != expected_weight_sum: + raise ValueError( + 'Proximity operator weights must sum to 1.0. Current sum of ' + + 'weights = {0}'.format(self.xp.sum(weights)), + ) self._weights = weights def _update_param(self): - r"""Update parameters + """Update parameters. This method updates the values of the algorthm parameters with the methods provided """ - # Update the gamma parameter. if not isinstance(self._gamma_update, type(None)): self._gamma = self._gamma_update(self._gamma) @@ -862,7 +1023,7 @@ def _update_param(self): self._lambda_param = self._lambda_update(self._lambda_param) def _update(self): - r"""Update + """Update. This method updates the current reconstruction @@ -871,24 +1032,28 @@ def _update(self): Implements algorithm 1 from :cite:`raguet2011` """ - # Calculate gradient for current iteration. self._grad.get_grad(self._x_old) # Update z values. for i in range(self._prox_list.size): - z_temp = (2 * self._x_old - self._z[i] - self._gamma * - self._grad.grad) - z_prox = self._prox_list[i].op(z_temp, extra_factor=self._gamma / - self._weights[i]) + z_temp = ( + 2 * self._x_old - self._z[i] - self._gamma * self._grad.grad + ) + z_prox = self._prox_list[i].op( + z_temp, + extra_factor=self._gamma / self._weights[i], + ) self._z[i] += self._lambda_param * (z_prox - self._x_old) # Update current reconstruction. - self._x_new = np.sum([z_i * w_i for z_i, w_i in - zip(self._z, self._weights)], axis=0) + self._x_new = self.xp.sum( + [z_i * w_i for z_i, w_i in zip(self._z, self._weights)], + axis=0, + ) # Update old values for next iteration. - np.copyto(self._x_old, self._x_new) + self.xp.copyto(self._x_old, self._x_new) # Update parameter values for next iteration. self._update_param() @@ -898,7 +1063,7 @@ def _update(self): self.converge = self._cost_func.get_cost(self._x_new) def iterate(self, max_iter=150): - r"""Iterate + """Iterate. This method calls update until either convergence criteria is met or the maximum number of iterations is reached. @@ -917,28 +1082,30 @@ def iterate(self, max_iter=150): self.x_final = self._x_new def get_notify_observers_kwargs(self): - """Notify observers + """Notify observers. Return the mapping between the metrics call and the iterated variables. - Return - ---------- + Returns + ------- dict The mapping between the iterated variables """ - return {'x_new': self._linear.adj_op(self._x_new), - 'z_new': self._z, 'idx': self.idx} + return { + 'x_new': self._linear.adj_op(self._x_new), + 'z_new': self._z, + 'idx': self.idx, + } def retrieve_outputs(self): - """Retrieve outputs + """Retrieve outputs. Declare the outputs of the algorithms as attributes: x_final, y_final, metrics. """ - metrics = {} for obs in self._observers['cv_metrics']: metrics[obs.name] = obs.retrieve_metrics() @@ -946,7 +1113,7 @@ def retrieve_outputs(self): class Condat(SetUp): - r"""Condat optimisation + """Condat optimisation. This class implements algorithm 3.1 from :cite:`condat2013` @@ -1000,24 +1167,48 @@ class Condat(SetUp): """ - def __init__(self, x, y, grad, prox, prox_dual, linear=None, cost='auto', - reweight=None, rho=0.5, sigma=1.0, tau=1.0, rho_update=None, - sigma_update=None, tau_update=None, auto_iterate=True, - max_iter=150, n_rewightings=1, metric_call_period=5, - metrics={}, **kwargs): + def __init__( + self, + x, + y, + grad, + prox, + prox_dual, + linear=None, + cost='auto', + reweight=None, + rho=0.5, + sigma=1.0, + tau=1.0, + rho_update=None, + sigma_update=None, + tau_update=None, + auto_iterate=True, + max_iter=150, + n_rewightings=1, + metric_call_period=5, + metrics=None, + **kwargs, + ): # Set default algorithm properties - super(Condat, self).__init__(metric_call_period=metric_call_period, - metrics=metrics, **kwargs) + super().__init__( + metric_call_period=metric_call_period, + metrics=metrics, + **kwargs, + ) # Set the initial variable values - (self._check_input_data(data) for data in (x, y)) - self._x_old = np.copy(x) - self._y_old = np.copy(y) + for input_data in (x, y): + self._check_input_data(input_data) + + self._x_old = self.xp.copy(x) + self._y_old = self.xp.copy(y) # Set the algorithm operators - (self._check_operator(operator) for operator in (grad, prox, prox_dual, - linear, cost)) + for operator in (grad, prox, prox_dual, linear, cost): + self._check_operator(operator) + self._grad = grad self._prox = prox self._prox_dual = prox_dual @@ -1027,20 +1218,26 @@ def __init__(self, x, y, grad, prox, prox_dual, linear=None, cost='auto', else: self._linear = linear if cost == 'auto': - self._cost_func = costObj([self._grad, self._prox, - self._prox_dual]) + self._cost_func = costObj([ + self._grad, + self._prox, + self._prox_dual, + ]) else: self._cost_func = cost # Set the algorithm parameters - (self._check_param(param) for param in (rho, sigma, tau)) + for param_val in (rho, sigma, tau): + self._check_param(param_val) + self._rho = rho self._sigma = sigma self._tau = self.step_size or tau # Set the algorithm parameter update methods - (self._check_param_update(param_update) for param_update in - (rho_update, sigma_update, tau_update)) + for param_update in (rho_update, sigma_update, tau_update): + self._check_param_update(param_update) + self._rho_update = rho_update self._sigma_update = sigma_update self._tau_update = tau_update @@ -1050,13 +1247,12 @@ def __init__(self, x, y, grad, prox, prox_dual, linear=None, cost='auto', self.iterate(max_iter=max_iter, n_rewightings=n_rewightings) def _update_param(self): - r"""Update parameters + """Update parameters. This method updates the values of the algorthm parameters with the methods provided """ - # Update relaxation parameter. if not isinstance(self._rho_update, type(None)): self._rho = self._rho_update(self._rho) @@ -1070,7 +1266,7 @@ def _update_param(self): self._tau = self._tau_update(self._tau) def _update(self): - r"""Update + """Update. This method updates the current reconstruction @@ -1084,15 +1280,24 @@ def _update(self): # Step 1 from eq.9. self._grad.get_grad(self._x_old) - x_prox = self._prox.op(self._x_old - self._tau * self._grad.grad - - self._tau * self._linear.adj_op(self._y_old)) + x_prox = self._prox.op( + self._x_old - self._tau * self._grad.grad - self._tau + * self._linear.adj_op(self._y_old), + ) # Step 2 from eq.9. - y_temp = (self._y_old + self._sigma * - self._linear.op(2 * x_prox - self._x_old)) - - y_prox = (y_temp - self._sigma * self._prox_dual.op(y_temp / - self._sigma, extra_factor=(1.0 / self._sigma))) + y_temp = ( + self._y_old + self._sigma + * self._linear.op(2 * x_prox - self._x_old) + ) + + y_prox = ( + y_temp - self._sigma + * self._prox_dual.op( + y_temp / self._sigma, + extra_factor=(1.0 / self._sigma), + ) + ) # Step 3 from eq.9. self._x_new = self._rho * x_prox + (1 - self._rho) * self._x_old @@ -1101,19 +1306,21 @@ def _update(self): del x_prox, y_prox, y_temp # Update old values for next iteration. - np.copyto(self._x_old, self._x_new) - np.copyto(self._y_old, self._y_new) + self.xp.copyto(self._x_old, self._x_new) + self.xp.copyto(self._y_old, self._y_new) # Update parameter values for next iteration. self._update_param() # Test cost function for convergence. if self._cost_func: - self.converge = self.any_convergence_flag() or\ - self._cost_func.get_cost(self._x_new, self._y_new) + self.converge = ( + self.any_convergence_flag() + or self._cost_func.get_cost(self._x_new, self._y_new) + ) def iterate(self, max_iter=150, n_rewightings=1): - r"""Iterate + """Iterate. This method calls update until either convergence criteria is met or the maximum number of iterations is reached @@ -1126,11 +1333,10 @@ def iterate(self, max_iter=150, n_rewightings=1): Number of reweightings to perform (default is ``1``) """ - self._run_alg(max_iter) if not isinstance(self._reweight, type(None)): - for k in range(n_rewightings): + for _ in range(n_rewightings): self._reweight.reweight(self._linear.op(self._x_new)) self._run_alg(max_iter) @@ -1141,7 +1347,7 @@ def iterate(self, max_iter=150, n_rewightings=1): self.y_final = self._y_new def get_notify_observers_kwargs(self): - """Notify observers + """Notify observers. Return the mapping between the metrics call and the iterated variables. @@ -1155,13 +1361,12 @@ def get_notify_observers_kwargs(self): return {'x_new': self._x_new, 'y_new': self._y_new, 'idx': self.idx} def retrieve_outputs(self): - """Retrieve outputs + """Retrieve outputs. Declare the outputs of the algorithms as attributes: x_final, y_final, metrics. """ - metrics = {} for obs in self._observers['cv_metrics']: metrics[obs.name] = obs.retrieve_metrics() @@ -1169,7 +1374,7 @@ def retrieve_outputs(self): class POGM(SetUp): - r"""Proximal Optimised Gradient Method + """Proximal Optimised Gradient Method. This class implements algorithm 3 from :cite:`kim2017` @@ -1211,23 +1416,46 @@ class POGM(SetUp): SetUp : parent class """ - def __init__(self, u, x, y, z, grad, prox, cost='auto', linear=None, - beta_param=1.0, sigma_bar=1.0, auto_iterate=True, - metric_call_period=5, metrics={}, **kwargs): + + def __init__( + self, + u, + x, + y, + z, + grad, + prox, + cost='auto', + linear=None, + beta_param=1.0, + sigma_bar=1.0, + auto_iterate=True, + metric_call_period=5, + metrics=None, + **kwargs, + ): # Set default algorithm properties - super(POGM, self).__init__(metric_call_period=metric_call_period, - metrics=metrics, linear=linear, **kwargs) + super().__init__( + metric_call_period=metric_call_period, + metrics=metrics, + linear=linear, + **kwargs, + ) # set the initial variable values - (self._check_input_data(data) for data in (u, x, y, z)) - self._u_old = np.copy(u) - self._x_old = np.copy(x) - self._y_old = np.copy(y) - self._z = np.copy(z) + for input_data in (u, x, y, z): + self._check_input_data(input_data) + + self._u_old = self.xp.copy(u) + self._x_old = self.xp.copy(x) + self._y_old = self.xp.copy(y) + self._z = self.xp.copy(z) # Set the algorithm operators - (self._check_operator(operator) for operator in (grad, prox, cost)) + for operator in (grad, prox, cost): + self._check_operator(operator) + self._grad = grad self._prox = prox self._linear = linear @@ -1235,16 +1463,22 @@ def __init__(self, u, x, y, z, grad, prox, cost='auto', linear=None, self._cost_func = costObj([self._grad, self._prox]) else: self._cost_func = cost + # If linear is None, make it Identity for call of metrics if self._linear is None: self._linear = Identity() + # Set the algorithm parameters - (self._check_param(param) for param in (beta_param, sigma_bar)) - if not (0 <= sigma_bar <= 1): + for param_val in (beta_param, sigma_bar): + self._check_param(param_val) + if sigma_bar < 0 or sigma_bar > 1: raise ValueError('The sigma bar parameter needs to be in [0, 1]') + self._beta = self.step_size or beta_param self._sigma_bar = sigma_bar - self._xi = self._sigma = self._t_old = 1.0 + self._xi = 1.0 + self._sigma = 1.0 + self._t_old = 1.0 self._grad.get_grad(self._x_old) self._g_old = self._grad.grad @@ -1253,7 +1487,7 @@ def __init__(self, u, x, y, z, grad, prox, cost='auto', linear=None, self.iterate() def _update(self): - r"""Update + """Update. This method updates the current reconstruction @@ -1267,7 +1501,7 @@ def _update(self): self._u_new = self._x_old - self._beta * self._grad.grad # Step 5 from alg. 3 - self._t_new = 0.5 * (1 + np.sqrt(1 + 4 * self._t_old**2)) + self._t_new = 0.5 * (1 + self.xp.sqrt(1 + 4 * self._t_old ** 2)) # Step 6 from alg. 3 t_shifted_ratio = (self._t_old - 1) / self._t_new @@ -1292,29 +1526,33 @@ def _update(self): self._y_new = self._x_old - self._beta * self._g_new # Step 11 from alg. 3 - restart_crit = np.vdot(- self._g_new, self._y_new - self._y_old) < 0 + restart_crit = ( + self.xp.vdot(-self._g_new, self._y_new - self._y_old) < 0 + ) if restart_crit: self._t_new = 1 self._sigma = 1 # Step 13 from alg. 3 - elif np.vdot(self._g_new, self._g_old) < 0: + elif self.xp.vdot(self._g_new, self._g_old) < 0: self._sigma *= self._sigma_bar # updating variables self._t_old = self._t_new - np.copyto(self._u_old, self._u_new) - np.copyto(self._x_old, self._x_new) - np.copyto(self._g_old, self._g_new) - np.copyto(self._y_old, self._y_new) + self.xp.copyto(self._u_old, self._u_new) + self.xp.copyto(self._x_old, self._x_new) + self.xp.copyto(self._g_old, self._g_new) + self.xp.copyto(self._y_old, self._y_new) # Test cost function for convergence. if self._cost_func: - self.converge = self.any_convergence_flag() or \ - self._cost_func.get_cost(self._x_new) + self.converge = ( + self.any_convergence_flag() + or self._cost_func.get_cost(self._x_new), + ) def iterate(self, max_iter=150): - r"""Iterate + """Iterate. This method calls update until either convergence criteria is met or the maximum number of iterations is reached. @@ -1325,7 +1563,6 @@ def iterate(self, max_iter=150): Maximum number of iterations (default is ``150``) """ - self._run_alg(max_iter) # retrieve metrics results @@ -1334,7 +1571,7 @@ def iterate(self, max_iter=150): self.x_final = self._x_new def get_notify_observers_kwargs(self): - """Notify observers + """Notify observers. Return the mapping between the metrics call and the iterated variables. @@ -1357,13 +1594,12 @@ def get_notify_observers_kwargs(self): } def retrieve_outputs(self): - """Retrieve outputs + """Retrieve outputs. Declare the outputs of the algorithms as attributes: x_final, y_final, metrics. """ - metrics = {} for obs in self._observers['cv_metrics']: metrics[obs.name] = obs.retrieve_metrics() diff --git a/modopt/opt/cost.py b/modopt/opt/cost.py index 703f7946..e5690831 100644 --- a/modopt/opt/cost.py +++ b/modopt/opt/cost.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -"""COST FUNCTIONS +"""COST FUNCTIONS. This module contains classes of different cost functions for optimization. @@ -9,13 +9,14 @@ """ import numpy as np + +from modopt.base.backend import get_array_module from modopt.base.types import check_callable from modopt.plot.cost_plot import plotCost class costObj(object): - - r"""Generic cost function object + """Generic cost function object. This class updates the cost according to the input cost functio class and tests for convergence @@ -67,20 +68,19 @@ class costObj(object): - COST: 8 False - >>> inst.get_cost(2) - - ITERATION: 4 - - COST: 8 - - - CONVERGENCE TEST - - - CHANGE IN COST: 0.0 - - True """ - def __init__(self, operators, initial_cost=1e6, tolerance=1e-4, - cost_interval=1, test_range=4, verbose=True, - plot_output=None): + def __init__( + self, + operators, + initial_cost=1e6, + tolerance=1e-4, + cost_interval=1, + test_range=4, + verbose=True, + plot_output=None, + ): self._operators = operators if not isinstance(operators, type(None)): @@ -96,22 +96,23 @@ def __init__(self, operators, initial_cost=1e6, tolerance=1e-4, self._verbose = verbose def _check_operators(self): - """Check Operators + """Check Operators. This method checks if the input operators have a `cost` method Raises ------ - ValueError + TypeError For invalid operators type ValueError For operators without `cost` method """ - if not isinstance(self._operators, (list, tuple, np.ndarray)): - raise TypeError(('Input operators must be provided as a list, ' - 'not {}').format(type(self._operators))) + message = ( + 'Input operators must be provided as a list, not {0}' + ) + raise TypeError(message.format(type(self._operators))) for op in self._operators: if not hasattr(op, 'cost'): @@ -119,7 +120,7 @@ def _check_operators(self): op.cost = check_callable(op.cost) def _check_cost(self): - """Check cost function + """Check cost function. This method tests the cost function for convergence in the specified interval of iterations using the last n (test_range) cost values @@ -130,22 +131,30 @@ def _check_cost(self): Result of the convergence test """ - # Add current cost value to the test list self._test_list.append(self.cost) + xp = get_array_module(self.cost) + # Check if enough cost values have been collected if len(self._test_list) == self._test_range: # The mean of the first half of the test list - t1 = np.mean(self._test_list[len(self._test_list) // 2:], axis=0) + t1 = xp.mean( + xp.array(self._test_list[len(self._test_list) // 2:]), + axis=0, + ) # The mean of the second half of the test list - t2 = np.mean(self._test_list[:len(self._test_list) // 2], axis=0) + t2 = xp.mean( + xp.array(self._test_list[:len(self._test_list) // 2]), + axis=0, + ) # Calculate the change across the test list - if not np.around(t1, decimals=16): - cost_diff = 0.0 + if xp.around(t1, decimals=16): + cost_diff = (xp.linalg.norm(t1 - t2) / xp.linalg.norm(t1)) else: - cost_diff = (np.linalg.norm(t1 - t2) / np.linalg.norm(t1)) + cost_diff = 0 + # Reset the test list self._test_list = [] @@ -157,14 +166,19 @@ def _check_cost(self): # Check for convergence return cost_diff <= self._tolerance - else: - - return False + return False def _calc_cost(self, *args, **kwargs): - """Calculate the cost + """Calculate the cost. - This method calculates the cost from each of the input operators + This method calculates the cost from each of the input operators. + + Parameters + ---------- + args : interable + Positional arguments + kwargs : dict + Keyword arguments Returns ------- @@ -172,13 +186,19 @@ def _calc_cost(self, *args, **kwargs): Cost """ - return np.sum([op.cost(*args, **kwargs) for op in self._operators]) def get_cost(self, *args, **kwargs): - """Get cost function + """Get cost function. - This method calculates the current cost and tests for convergence + This method calculates the current cost and tests for convergence. + + Parameters + ---------- + args : interable + Positional arguments + kwargs : dict + Keyword arguments Returns ------- @@ -186,15 +206,16 @@ def get_cost(self, *args, **kwargs): Result of the convergence test """ - # Check if the cost should be calculated - if self._cost_interval is None or \ - self._iteration % self._cost_interval: + test_conditions = ( + self._cost_interval is None + or self._iteration % self._cost_interval + ) + if test_conditions: test_result = False else: - if self._verbose: print(' - ITERATION:', self._iteration) @@ -215,10 +236,9 @@ def get_cost(self, *args, **kwargs): return test_result def plot_cost(self): # pragma: no cover - """Plot the cost function + """Plot the cost function. This method plots the cost function as function of iteration number """ - plotCost(self._cost_list, self._plot_output) diff --git a/modopt/opt/gradient.py b/modopt/opt/gradient.py index 98f07891..b949a7eb 100644 --- a/modopt/opt/gradient.py +++ b/modopt/opt/gradient.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -"""GRADIENT CLASSES +"""GRADIENT CLASSES. This module contains classses for defining algorithm gradients. Based on work by Yinghao Ge and Fred Ngole. @@ -10,18 +10,19 @@ """ import numpy as np + from modopt.base.types import check_callable, check_float, check_npndarray class GradParent(object): - r"""Gradient Parent Class + """Gradient Parent Class. This class defines the basic methods that will be inherited by specific gradient classes Parameters ---------- - data : numpy.ndarray + input_data : numpy.ndarray The observed data op : function The operator @@ -38,30 +39,39 @@ class GradParent(object): Examples -------- + >>> import numpy as np >>> from modopt.opt.gradient import GradParent >>> y = np.arange(9).reshape(3, 3).astype(float) >>> g = GradParent(y, lambda x: x ** 2, lambda x: x ** 3) >>> g.op(y) - array([[ 0., 1., 4.], - [ 9., 16., 25.], - [ 36., 49., 64.]]) + array([[ 0., 1., 4.], + [ 9., 16., 25.], + [36., 49., 64.]]) >>> g.trans_op(y) - array([[ 0., 1., 8.], - [ 27., 64., 125.], - [ 216., 343., 512.]]) + array([[ 0., 1., 8.], + [ 27., 64., 125.], + [216., 343., 512.]]) >>> g.trans_op_op(y) - array([[ 0.00000000e+00, 1.00000000e+00, 6.40000000e+01], - [ 7.29000000e+02, 4.09600000e+03, 1.56250000e+04], - [ 4.66560000e+04, 1.17649000e+05, 2.62144000e+05]]) + array([[0.00000e+00, 1.00000e+00, 6.40000e+01], + [7.29000e+02, 4.09600e+03, 1.56250e+04], + [4.66560e+04, 1.17649e+05, 2.62144e+05]]) """ - def __init__(self, data, op, trans_op, get_grad=None, cost=None, - data_type=None, verbose=True): + def __init__( + self, + input_data, + op, + trans_op, + get_grad=None, + cost=None, + data_type=None, + verbose=True, + ): self.verbose = verbose self._grad_data_type = data_type - self.obs_data = data + self.obs_data = input_data self.op = op self.trans_op = trans_op @@ -72,35 +82,26 @@ def __init__(self, data, op, trans_op, get_grad=None, cost=None, @property def obs_data(self): - """Observed Data - - Raises - ------ - TypeError - For invalid input type - - """ - + """Observed Data.""" return self._obs_data @obs_data.setter - def obs_data(self, data): + def obs_data(self, input_data): - if self._grad_data_type in (float, np.floating): - data = check_float(data) - check_npndarray(data, dtype=self._grad_data_type, writeable=False, - verbose=self.verbose) + if self._grad_data_type in {float, np.floating}: + input_data = check_float(input_data) + check_npndarray( + input_data, + dtype=self._grad_data_type, + writeable=False, + verbose=self.verbose, + ) - self._obs_data = data + self._obs_data = input_data @property def op(self): - """Operator - - This method defines the operator - - """ - + """Operator.""" return self._op @op.setter @@ -110,12 +111,7 @@ def op(self, operator): @property def trans_op(self): - """Transpose Operator - - This method defines the transpose operator - - """ - + """Transpose operator.""" return self._trans_op @trans_op.setter @@ -125,12 +121,7 @@ def trans_op(self, operator): @property def get_grad(self): - """Get Gradient - - This method defines the calculation of the gradient - - """ - + """Get gradient value.""" return self._get_grad @get_grad.setter @@ -140,30 +131,19 @@ def get_grad(self, method): @property def grad(self): - """Gradient - - The gradient value - - """ - + """Gradient value.""" return self._grad @grad.setter - def grad(self, value): + def grad(self, input_value): - if self._grad_data_type in (float, np.floating): - value = check_float(value) - self._grad = value + if self._grad_data_type in {float, np.floating}: + input_value = check_float(input_value) + self._grad = input_value @property def cost(self): - """Cost Contribution - - This method defines the proximity operator's contribution to the total - cost - - """ - + """Cost contribution.""" return self._cost @cost.setter @@ -171,15 +151,15 @@ def cost(self, method): self._cost = check_callable(method) - def trans_op_op(self, data): - r"""Transpose Operation of the Operator + def trans_op_op(self, input_data): + r"""Transpose Operation of the Operator. This method calculates the action of the transpose operator on the action of the operator on the data Parameters ---------- - data : numpy.ndarray + input_data : numpy.ndarray Input data array Returns @@ -195,26 +175,33 @@ def trans_op_op(self, data): \mathbf{H}^T(\mathbf{H}\mathbf{x}) """ - - return self.trans_op(self.op(data)) + return self.trans_op(self.op(input_data)) class GradBasic(GradParent): - r"""Basic Gradient Class + """Basic Gradient Class. This class defines the gradient calculation and costs methods for - common inverse problems + common inverse problems. + + Parameters + ---------- + args : interable + Positional arguments + kwargs : dict + Keyword arguments Examples -------- + >>> import numpy as np >>> from modopt.opt.gradient import GradBasic >>> y = np.arange(9).reshape(3, 3).astype(float) >>> g = GradBasic(y, lambda x: x ** 2, lambda x: x ** 3) >>> g.get_grad(y) >>> g.grad - array([[ 0.00000000e+00, 0.00000000e+00, 8.00000000e+00], - [ 2.16000000e+02, 1.72800000e+03, 8.00000000e+03], - [ 2.70000000e+04, 7.40880000e+04, 1.75616000e+05]]) + array([[0.00000e+00, 0.00000e+00, 8.00000e+00], + [2.16000e+02, 1.72800e+03, 8.00000e+03], + [2.70000e+04, 7.40880e+04, 1.75616e+05]]) See Also -------- @@ -224,18 +211,18 @@ class GradBasic(GradParent): def __init__(self, *args, **kwargs): - super(GradBasic, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.get_grad = self._get_grad_method self.cost = self._cost_method - def _get_grad_method(self, data): - r"""Get the gradient + def _get_grad_method(self, input_data): + r"""Get the gradient. This method calculates the gradient step from the input data Parameters ---------- - data : numpy.ndarray + input_data : numpy.ndarray Input data array Notes @@ -246,22 +233,27 @@ def _get_grad_method(self, data): \nabla F(x) = \mathbf{H}^T(\mathbf{H}\mathbf{x} - \mathbf{y}) """ - - self.grad = self.trans_op(self.op(data) - self.obs_data) + self.grad = self.trans_op(self.op(input_data) - self.obs_data) def _cost_method(self, *args, **kwargs): - """Calculate gradient component of the cost + """Calculate gradient component of the cost. This method returns the l2 norm error of the difference between the original data and the data obtained after optimisation + Parameters + ---------- + args : interable + Positional arguments + kwargs : dict + Keyword arguments + Returns ------- float Gradient cost component """ - cost_val = 0.5 * np.linalg.norm(self.obs_data - self.op(args[0])) ** 2 if 'verbose' in kwargs and kwargs['verbose']: diff --git a/modopt/opt/linear.py b/modopt/opt/linear.py index 4d0d1e3f..e21ffac9 100644 --- a/modopt/opt/linear.py +++ b/modopt/opt/linear.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -"""LINEAR OPERATORS +"""LINEAR OPERATORS. This module contains linear operator classes. @@ -8,15 +8,14 @@ """ -from builtins import range, zip import numpy as np + from modopt.base.types import check_callable, check_float -from modopt.math.matrix import rotate -from modopt.signal.wavelet import * +from modopt.signal.wavelet import filter_convolve_stack class LinearParent(object): - r"""Linear Operator Parent Class + """Linear Operator Parent Class. This class sets the structure for defining linear operator instances. @@ -45,12 +44,7 @@ def __init__(self, op, adj_op): @property def op(self): - """Linear Operator - - This method defines the linear operator - - """ - + """Linear Operator.""" return self._op @op.setter @@ -60,12 +54,7 @@ def op(self, operator): @property def adj_op(self): - """Linear Adjoint Operator - - This method defines the linear adjoint operator - - """ - + """Linear Adjoint Operator.""" return self._adj_op @adj_op.setter @@ -75,7 +64,7 @@ def adj_op(self, operator): class Identity(LinearParent): - """Identity Operator Class + """Identity Operator Class. This is a dummy class that can be used in the optimisation classes. @@ -87,12 +76,12 @@ class Identity(LinearParent): def __init__(self): - self.op = lambda x: x + self.op = lambda input_data: input_data self.adj_op = self.op class WaveletConvolve(LinearParent): - """Wavelet Convolution Class + """Wavelet Convolution Class. This class defines the wavelet transform operators via convolution with predefined filters. @@ -113,15 +102,21 @@ class WaveletConvolve(LinearParent): def __init__(self, filters, method='scipy'): self._filters = check_float(filters) - self.op = lambda x: filter_convolve_stack(x, self._filters, - method=method) - self.adj_op = lambda x: filter_convolve_stack(x, self._filters, - filter_rot=True, - method=method) + self.op = lambda input_data: filter_convolve_stack( + input_data, + self._filters, + method=method, + ) + self.adj_op = lambda input_data: filter_convolve_stack( + input_data, + self._filters, + filter_rot=True, + method=method, + ) class LinearCombo(LinearParent): - r"""Linear Combination Class + """Linear Combination Class. This class defines a combination of linear transform operators. @@ -166,7 +161,7 @@ def __init__(self, operators, weights=None): self.adj_op = self._adj_op_method def _check_type(self, input_val): - """ Check input type + """Check input type. This method checks if the input is a list, tuple or a numpy array and converts the input to a numpy array. @@ -185,12 +180,15 @@ def _check_type(self, input_val): ------ TypeError For invalid input type + ValueError + If input list is empty """ - if not isinstance(input_val, (list, tuple, np.ndarray)): - raise TypeError('Invalid input type, input must be a list, tuple ' - 'or numpy array.') + raise TypeError( + 'Invalid input type, input must be a list, tuple or numpy ' + + 'array.', + ) input_val = np.array(input_val) @@ -200,7 +198,7 @@ def _check_type(self, input_val): return input_val def _check_inputs(self, operators, weights): - """ Check inputs + """Check inputs. This method cheks that the input operators and weights are correctly formatted. @@ -225,38 +223,41 @@ def _check_inputs(self, operators, weights): If the individual weight values are not floats """ - operators = self._check_type(operators) for operator in operators: + if not hasattr(operator, 'op'): raise ValueError('Operators must contain "op" method.') + if not hasattr(operator, 'adj_op'): raise ValueError('Operators must contain "adj_op" method.') + operator.op = check_callable(operator.op) operator.cost = check_callable(operator.adj_op) if not isinstance(weights, type(None)): - weights = self._check_type(weights) if weights.size != operators.size: - raise ValueError('The number of weights must match the ' - 'number of operators.') + raise ValueError( + 'The number of weights must match the number of ' + + 'operators.', + ) if not np.issubdtype(weights.dtype, np.floating): raise TypeError('The weights must be a list of float values.') return operators, weights - def _op_method(self, data): - """Operator + def _op_method(self, input_data): + """Operator. This method returns the input data operated on by all of the operators. Parameters ---------- - data : numpy.ndarray + input_data : numpy.ndarray Input data array Returns @@ -265,16 +266,15 @@ def _op_method(self, data): Linear operation results """ - res = np.empty(len(self.operators), dtype=np.ndarray) - for i in range(len(self.operators)): - res[i] = self.operators[i].op(data) + for index, _ in enumerate(self.operators): + res[index] = self.operators[index].op(input_data) return res - def _adj_op_method(self, data): - """Adjoint operator + def _adj_op_method(self, input_data): + """Adjoint operator. This method returns the combination of the result of all of the adjoint operators. If weights are provided the comibination is the sum @@ -282,7 +282,7 @@ def _adj_op_method(self, data): Parameters ---------- - data : numpy.ndarray + input_data : numpy.ndarray Input data array Returns @@ -291,14 +291,23 @@ def _adj_op_method(self, data): Adjoint operation results """ - if isinstance(self.weights, type(None)): - - return np.mean([operator.adj_op(x) for x, operator in - zip(data, self.operators)], axis=0) - - else: - - return np.sum([weight * operator.adj_op(x) for x, operator, - weight in zip(data, self.operators, self.weights)], - axis=0) + return np.mean( + [ + operator.adj_op(elem) + for elem, operator in zip(input_data, self.operators) + ], + axis=0, + ) + + return np.sum( + [ + weight * operator.adj_op(elem) + for elem, operator, weight in zip( + input_data, + self.operators, + self.weights, + ) + ], + axis=0, + ) diff --git a/modopt/opt/proximity.py b/modopt/opt/proximity.py index f30486ca..474d7395 100644 --- a/modopt/opt/proximity.py +++ b/modopt/opt/proximity.py @@ -1,20 +1,17 @@ # -*- coding: utf-8 -*- -"""PROXIMITY OPERATORS +"""PROXIMITY OPERATORS. This module contains classes of proximity operators for optimisation :Author: Samuel Farrens -:References: - -.. bibliography:: refs.bib - :filter: docname in docnames - """ -import numpy as np import sys + +import numpy as np + try: from sklearn.isotonic import isotonic_regression except ImportError: @@ -22,17 +19,17 @@ else: import_sklearn = True +from modopt.base.transform import cube2matrix, matrix2cube from modopt.base.types import check_callable +from modopt.interface.errors import warn +from modopt.math.matrix import nuclear_norm from modopt.signal.noise import thresh -from modopt.signal.svd import svd_thresh, svd_thresh_coef from modopt.signal.positivity import positive -from modopt.math.matrix import nuclear_norm -from modopt.base.transform import cube2matrix, matrix2cube -from modopt.interface.errors import warn +from modopt.signal.svd import svd_thresh, svd_thresh_coef class ProximityParent(object): - r"""Proximity Operator Parent Class + """Proximity Operator Parent Class. This class sets the structure for defining proximity operator instances. @@ -53,12 +50,7 @@ def __init__(self, op, cost): @property def op(self): - """Linear operator - - This method defines the linear operator. - - """ - + """Linear operator.""" return self._op @op.setter @@ -68,13 +60,17 @@ def op(self, operator): @property def cost(self): - """Cost contribution + """Cost contribution. This method defines the proximity operator's contribution to the total cost. - """ + Returns + ------- + float + Cost + """ return self._cost @cost.setter @@ -84,7 +80,7 @@ def cost(self, method): class IdentityProx(ProximityParent): - """Identity Proxmity Operator + """Identity Proxmity Operator. This is a dummy class that can be used as a proximity operator. @@ -100,12 +96,12 @@ class IdentityProx(ProximityParent): def __init__(self): - self.op = lambda x: x - self.cost = lambda x: 0.0 + self.op = lambda x_val: x_val + self.cost = lambda x_val: 0 class Positivity(ProximityParent): - """Positivity Proximity Operator + """Positivity Proximity Operator. This class defines the positivity proximity operator. @@ -117,30 +113,36 @@ class Positivity(ProximityParent): def __init__(self): - self.op = lambda x: positive(x) + self.op = lambda input_data: positive(input_data) self.cost = self._cost_method def _cost_method(self, *args, **kwargs): - """Calculate positivity component of the cost + """Calculate positivity component of the cost. This method returns 0 as the posivituty does not contribute to the cost. + Parameters + ---------- + args : interable + Positional arguments + kwargs : dict + Keyword arguments + Returns ------- float ``0.0`` """ - if 'verbose' in kwargs and kwargs['verbose']: print(' - Min (X):', np.min(args[0])) - return 0.0 + return 0 class SparseThreshold(ProximityParent): - """Threshold Proximity Operator + """Threshold Proximity Operator. This class defines the threshold proximity operator. @@ -167,14 +169,14 @@ def __init__(self, linear, weights, thresh_type='soft'): self.op = self._op_method self.cost = self._cost_method - def _op_method(self, data, extra_factor=1.0): - """Operator + def _op_method(self, input_data, extra_factor=1.0): + """Operator. This method returns the input data thresholded by the weights. Parameters ---------- - data : numpy.ndarray + input_data : numpy.ndarray Input data array extra_factor : float Additional multiplication factor (default is ``1.0``) @@ -185,24 +187,29 @@ def _op_method(self, data, extra_factor=1.0): Thresholded data """ - threshold = self.weights * extra_factor - return thresh(data, threshold, self._thresh_type) + return thresh(input_data, threshold, self._thresh_type) def _cost_method(self, *args, **kwargs): - """Calculate sparsity component of the cost + """Calculate sparsity component of the cost. This method returns the l1 norm error of the weighted wavelet coefficients. + Parameters + ---------- + args : interable + Positional arguments + kwargs : dict + Keyword arguments + Returns ------- float Sparsity cost component """ - cost_val = np.sum(np.abs(self.weights * self._linear.op(args[0]))) if 'verbose' in kwargs and kwargs['verbose']: @@ -212,13 +219,13 @@ def _cost_method(self, *args, **kwargs): class LowRankMatrix(ProximityParent): - r"""Low-rank Proximity Operator + """Low-rank Proximity Operator. This class defines the low-rank proximity operator. Parameters ---------- - thresh : float + threshold : float Threshold value treshold_type : {'hard', 'soft'} Threshold type (options are 'hard' or 'soft', default is 'soft') @@ -230,20 +237,17 @@ class LowRankMatrix(ProximityParent): Examples -------- + >>> import numpy as np >>> from modopt.opt.proximity import LowRankMatrix >>> a = np.arange(9).reshape(3, 3).astype(float) >>> inst = LowRankMatrix(10.0, thresh_type='hard') >>> inst.op(a) - array([[[ 2.73843189, 3.14594066, 3.55344943], - [ 3.9609582 , 4.36846698, 4.77597575], - [ 5.18348452, 5.59099329, 5.99850206]], - - [[ 8.07085295, 9.2718846 , 10.47291625], - [ 11.67394789, 12.87497954, 14.07601119], - [ 15.27704284, 16.47807449, 17.67910614]]]) + array([[0.89642146, 1.0976143 , 1.29880715], + [3.29284291, 4.03188864, 4.77093436], + [5.68926437, 6.96616297, 8.24306156]]) >>> inst.cost(a, verbose=True) - - NUCLEAR NORM (X): 469.391329425 - 469.39132942464983 + - NUCLEAR NORM (X): 154.91933384829667 + 154.91933384829667 See Also -------- @@ -251,25 +255,30 @@ class LowRankMatrix(ProximityParent): """ - def __init__(self, thresh, thresh_type='soft', - lowr_type='standard', operator=None): + def __init__( + self, + threshold, + thresh_type='soft', + lowr_type='standard', + operator=None, + ): - self.thresh = thresh + self.thresh = threshold self.thresh_type = thresh_type self.lowr_type = lowr_type self.operator = operator self.op = self._op_method self.cost = self._cost_method - def _op_method(self, data, extra_factor=1.0): - """Operator + def _op_method(self, input_data, extra_factor=1.0): + """Operator. This method returns the input data after the singular values have been thresholded. Parameters ---------- - data : numpy.ndarray + input_data : numpy.ndarray Input data array extra_factor : float Additional multiplication factor (default is ``1.0``) @@ -280,37 +289,46 @@ def _op_method(self, data, extra_factor=1.0): SVD thresholded data """ - # Update threshold with extra factor. threshold = self.thresh * extra_factor if self.lowr_type == 'standard': - data_matrix = svd_thresh(cube2matrix(data), threshold, - thresh_type=self.thresh_type) + data_matrix = svd_thresh( + cube2matrix(input_data), + threshold, + thresh_type=self.thresh_type, + ) elif self.lowr_type == 'ngole': - data_matrix = svd_thresh_coef(cube2matrix(data), self.operator, - threshold, - thresh_type=self.thresh_type) - - new_data = matrix2cube(data_matrix, data.shape[1:]) + data_matrix = svd_thresh_coef( + cube2matrix(input_data), + self.operator, + threshold, + thresh_type=self.thresh_type, + ) # Return updated data. - return new_data + return matrix2cube(data_matrix, input_data.shape[1:]) def _cost_method(self, *args, **kwargs): - """Calculate low-rank component of the cost + """Calculate low-rank component of the cost. This method returns the nuclear norm error of the deconvolved data in matrix form. + Parameters + ---------- + args : interable + Positional arguments + kwargs : dict + Keyword arguments + Returns ------- float Low-rank cost component """ - cost_val = self.thresh * nuclear_norm(cube2matrix(args[0])) if 'verbose' in kwargs and kwargs['verbose']: @@ -320,7 +338,7 @@ def _cost_method(self, *args, **kwargs): class LinearCompositionProx(ProximityParent): - """Proximity Operator of a Linear Composition + """Proximity Operator of a Linear Composition. This class defines the proximity operator of a function given by a composition between an initial function whose proximity operator is known @@ -345,15 +363,15 @@ def __init__(self, linear_op, prox_op): self.op = self._op_method self.cost = self._cost_method - def _op_method(self, data, extra_factor=1.0): - r"""Operator + def _op_method(self, input_data, extra_factor=1.0): + """Operator. This method returns the scaled version of the proximity operator as given by Lemma 2.8 of :cite:`combettes2005`. Parameters ---------- - data : numpy.ndarray + input_data : numpy.ndarray Input data array extra_factor : float Additional multiplication factor (default is ``1.0``) @@ -364,12 +382,22 @@ def _op_method(self, data, extra_factor=1.0): Result of the scaled proximity operator """ - - return self.linear_op.adj_op(self.prox_op.op(self.linear_op.op(data), - extra_factor=extra_factor)) + return self.linear_op.adj_op( + self.prox_op.op( + self.linear_op.op(input_data), + extra_factor=extra_factor, + ), + ) def _cost_method(self, *args, **kwargs): - """Calculate the cost function associated to the composed function + """Calculate the cost function associated to the composed function. + + Parameters + ---------- + args : interable + Positional arguments + kwargs : dict + Keyword arguments Returns ------- @@ -377,12 +405,11 @@ def _cost_method(self, *args, **kwargs): The cost of the associated composed function """ - return self.prox_op.cost(self.linear_op.op(args[0]), **kwargs) class ProximityCombo(ProximityParent): - r"""Proximity Combo + """Proximity Combo. This class defines a combined proximity operator. @@ -416,7 +443,7 @@ def __init__(self, operators): self.cost = self._cost_method def _check_operators(self, operators): - """Check operators + """Check operators. This method cheks that the input operators and weights are correctly formatted. @@ -435,12 +462,19 @@ def _check_operators(self, operators): ------ TypeError For invalid input type + ValueError + For empty list + ValueError + For missing op method + ValueError + For missing cost method """ - if not isinstance(operators, (list, tuple, np.ndarray)): - raise TypeError('Invalid input type, operators must be a list, ' - 'tuple or numpy array.') + raise TypeError( + 'Invalid input type, operators must be a list, tuple or ' + + 'numpy array.', + ) operators = np.array(operators) @@ -457,15 +491,15 @@ def _check_operators(self, operators): return operators - def _op_method(self, data, extra_factor=1.0): - """Operator + def _op_method(self, input_data, extra_factor=1.0): + """Operator. This method returns the result of applying all of the proximity operators to the data. Parameters ---------- - data : numpy.ndarray + input_data : numpy.ndarray Input data array extra_factor : float Additional multiplication factor (default is ``1.0``) @@ -476,33 +510,43 @@ def _op_method(self, data, extra_factor=1.0): Result """ - res = np.empty(len(self.operators), dtype=np.ndarray) - for i in range(len(self.operators)): - res[i] = self.operators[i].op(data[i], extra_factor=extra_factor) + for index, _ in enumerate(self.operators): + res[index] = self.operators[index].op( + input_data[index], + extra_factor=extra_factor, + ) return res def _cost_method(self, *args, **kwargs): - """Calculate combined proximity operator components of the cost + """Calculate combined proximity operator components of the cost. This method returns the sum of the cost components from each of the proximity operators. + Parameters + ---------- + args : interable + Positional arguments + kwargs : dict + Keyword arguments + Returns ------- float Combinded cost components """ - - return np.sum([operator.cost(data) for operator, data in - zip(self.operators, args[0])]) + return np.sum([ + operator.cost(input_data) + for operator, input_data in zip(self.operators, args[0]) + ]) class OrderedWeightedL1Norm(ProximityParent): - r"""Ordered Weighted L1 norm proximity operator + """Ordered Weighted L1 norm proximity operator. This class defines the OWL proximity operator described in :cite:`figueiredo2014`. @@ -516,16 +560,18 @@ class OrderedWeightedL1Norm(ProximityParent): -------- >>> import numpy as np >>> from modopt.opt.proximity import OrderedWeightedL1Norm - >>> A = np.arange(5)*5 + >>> A = np.arange(5) * 5 + >>> A array([ 0, 5, 10, 15, 20]) - >>> prox_op = OrderedWeightedL1Norm(np.arange(5)) + >>> weights = np.arange(5)[::-1] + >>> prox_op = OrderedWeightedL1Norm(weights) >>> prox_op.weights array([4, 3, 2, 1, 0]) >>> prox_op.op(A) array([ 0., 4., 8., 12., 16.]) >>> prox_op.cost(A, verbose=True) - - OWL NORM (X): 150 - 150 + - OWL NORM (X): 50 + 50 See Also -------- @@ -535,28 +581,30 @@ class OrderedWeightedL1Norm(ProximityParent): def __init__(self, weights): if not import_sklearn: # pragma: no cover - raise ImportError('Required version of Scikit-Learn package not' - ' found see documentation for details: ' - 'https://cea-cosmic.github.io/ModOpt/' - '#optional-packages') + raise ImportError( + 'Required version of Scikit-Learn package not found see ' + + 'documentation for details: ' + + 'https://cea-cosmic.github.io/ModOpt/#optional-packages', + ) if np.max(np.diff(weights)) > 0: raise ValueError('Weights must be non increasing') self.weights = weights.flatten() if (self.weights < 0).any(): - raise ValueError("The weight values must be provided " - "in descending order") + raise ValueError( + 'The weight values must be provided in descending order', + ) self.op = self._op_method self.cost = self._cost_method - def _op_method(self, data, extra_factor=1.0): - """Operator + def _op_method(self, input_data, extra_factor=1.0): + """Operator. This method returns the input data after the a clustering and a thresholding. Implements (Eq 24) in :cite:`figueiredo2014`. Parameters ---------- - data : numpy.ndarray + input_data : numpy.ndarray Input data array extra_factor : float Additional multiplication factor (default is ``1.0``) @@ -567,12 +615,11 @@ def _op_method(self, data, extra_factor=1.0): Thresholded data """ - # Update threshold with extra factor. threshold = self.weights * extra_factor # Squeezing the data - data_squeezed = np.squeeze(data) + data_squeezed = np.squeeze(input_data) # Sorting (non increasing order) input vector's absolute values data_abs = np.abs(data_squeezed) @@ -581,9 +628,10 @@ def _op_method(self, data, extra_factor=1.0): # Projection onto the monotone non-negative cone using # isotonic_regression + data_abs = isotonic_regression( + data_abs - threshold, y_min=0, increasing=False, + ) - data_abs = isotonic_regression(data_abs - threshold, y_min=0, - increasing=False) # Unsorting the data data_abs_unsorted = np.empty_like(data_abs) data_abs_unsorted[data_abs_sort_idx] = data_abs @@ -595,22 +643,29 @@ def _op_method(self, data, extra_factor=1.0): # Removing NAN caused by the sign sign_data[np.isnan(sign_data)] = 0 - return np.reshape(sign_data * data_abs_unsorted, data.shape) + return np.reshape(sign_data * data_abs_unsorted, input_data.shape) def _cost_method(self, *args, **kwargs): - """Calculate OWL component of the cost + """Calculate OWL component of the cost. This method returns the ordered weighted l1 norm of the data. + Parameters + ---------- + args : interable + Positional arguments + kwargs : dict + Keyword arguments + Returns ------- float OWL cost component """ - - cost_val = np.sum(self.weights * np.sort(np.squeeze( - np.abs(args[0]))[::-1])) + cost_val = np.sum( + self.weights * np.sort(np.squeeze(np.abs(args[0]))[::-1]), + ) if 'verbose' in kwargs and kwargs['verbose']: print(' - OWL NORM (X):', cost_val) @@ -619,7 +674,7 @@ def _cost_method(self, *args, **kwargs): class Ridge(ProximityParent): - r"""L2-norm Proximity Operator (`i.e.` Shrinkage) + r"""L2-norm Proximity Operator (`i.e.` Shrinkage). This class defines the L2-norm proximity operator. @@ -651,14 +706,14 @@ def __init__(self, linear, weights, thresh_type='soft'): self.op = self._op_method self.cost = self._cost_method - def _op_method(self, data, extra_factor=1.0): - """Operator Method + def _op_method(self, input_data, extra_factor=1.0): + """Operator Method. This method returns the input data shrinked by the weights Parameters ---------- - data : numpy.ndarray + input_data : numpy.ndarray Input data array extra_factor : float Additional multiplication factor (default is ``1.0``) @@ -669,25 +724,32 @@ def _op_method(self, data, extra_factor=1.0): Thresholded data """ - threshold = self.weights * extra_factor * 2 - return self._linear.op(data) / (1 + threshold) + return self._linear.op(input_data) / (1 + threshold) def _cost_method(self, *args, **kwargs): - """Calculate Ridge component of the cost + """Calculate Ridge component of the cost. This method returns the l2 norm error of the weighted wavelet coefficients. + Parameters + ---------- + args : interable + Positional arguments + kwargs : dict + Keyword arguments + Returns ------- float Sparsity cost component """ - - cost_val = np.sum(np.abs(self.weights * self._linear.op(args[0])**2)) + cost_val = np.sum( + np.abs(self.weights * self._linear.op(args[0]) ** 2), + ) if 'verbose' in kwargs and kwargs['verbose']: print(' - L2 NORM (X):', cost_val) @@ -696,7 +758,7 @@ def _cost_method(self, *args, **kwargs): class ElasticNet(ProximityParent): - r"""Elastic Net + r"""Elastic Net. This class defines the Elastic net proximity operator, which is a linear combination between L2 and L1 norm proximity operators, @@ -731,14 +793,14 @@ def __init__(self, linear, alpha, beta): self.op = self._op_method self.cost = self._cost_method - def _op_method(self, data, extra_factor=1.0): - """Operator + def _op_method(self, input_data, extra_factor=1.0): + """Operator. This method returns the input data shrinked by the weights. Parameters ---------- - data : numpy.ndarray + input_data : numpy.ndarray Input data array extra_factor : float Additional multiplication factor @@ -749,26 +811,33 @@ def _op_method(self, data, extra_factor=1.0): Thresholded data """ - soft_threshold = self.beta * extra_factor normalization = (self.alpha * 2 * extra_factor + 1) - return thresh(data, soft_threshold, 'soft') / normalization + return thresh(input_data, soft_threshold, 'soft') / normalization def _cost_method(self, *args, **kwargs): - """Calculate Ridge component of the cost + """Calculate Ridge component of the cost. This method returns the l2 norm error of the weighted wavelet coefficients. + Parameters + ---------- + args : interable + Positional arguments + kwargs : dict + Keyword arguments + Returns ------- float Sparsity cost component """ - - cost_val = np.sum(np.abs(self.alpha * self._linear.op(args[0])**2) + - np.abs(self.beta * self._linear.op(args[0]))) + cost_val = np.sum( + np.abs(self.alpha * self._linear.op(args[0]) ** 2) + + np.abs(self.beta * self._linear.op(args[0])), + ) if 'verbose' in kwargs and kwargs['verbose']: print(' - ELASTIC NET (X):', cost_val) @@ -777,7 +846,7 @@ def _cost_method(self, *args, **kwargs): class KSupportNorm(ProximityParent): - r"""K-support Norm Proximity Operator + """K-support Norm Proximity Operator. This class defines the squarred K-support norm proximity operator described in :cite:`mcdonald2014`. @@ -804,13 +873,14 @@ class KSupportNorm(ProximityParent): -------- >>> import numpy as np >>> from modopt.opt.proximity import KSupportNorm - >>> A = np.arange(5)*5 + >>> A = np.arange(5) * 5 + >>> A array([ 0, 5, 10, 15, 20]) >>> prox_op = KSupportNorm(beta=3, k_value=1) >>> prox_op.op(A) - array([ 0., 0., 0., 0., 5.]) + array([0., 0., 0., 0., 5.]) >>> prox_op.cost(A, verbose=True) - - OWL NORM (X): 7500.0 + - K-SUPPORT NORM (X): 7500.0 7500.0 See Also @@ -827,20 +897,19 @@ def __init__(self, beta, k_value): @property def k_value(self): - """k value - - """ + """K value.""" return self._k_value @k_value.setter - def k_value(self, k): - if k < 1: - raise ValueError("The k parameter should be greater or " - "equal than 1") - self._k_value = k + def k_value(self, k_val): + if k_val < 1: + raise ValueError( + 'The k parameter should be greater or equal than 1', + ) + self._k_value = k_val def _compute_theta(self, input_data, alpha, extra_factor=1.0): - r""" Compute theta + r"""Compute theta. This method computes theta from Corollary 16: @@ -871,32 +940,33 @@ def _compute_theta(self, input_data, alpha, extra_factor=1.0): Same size as w and each component is equal to theta_i """ - alpha_input = np.dot(np.expand_dims(alpha, -1), - np.expand_dims(np.abs(input_data), -1).T) + alpha_input = np.dot( + np.expand_dims(alpha, -1), + np.expand_dims(np.abs(input_data), -1).T, + ) theta = np.zeros(alpha_input.shape) - theta = (alpha_input - self.beta * extra_factor) * \ - (((alpha_input - self.beta * extra_factor) <= 1) & - ((alpha_input - self.beta * extra_factor) >= 0)) + alpha_beta = alpha_input - self.beta * extra_factor + theta = alpha_beta * ((alpha_beta <= 1) & (alpha_beta >= 0)) theta = np.nan_to_num(theta) - theta += 1.0 * (alpha_input > (self.beta * extra_factor + 1)) + theta += (alpha_input > (self.beta * extra_factor + 1)) return theta - def _interpolate(self, alpha_0, alpha_1, sum_0, sum_1): - """ Linear interpolation of alpha + def _interpolate(self, alpha0, alpha1, sum0, sum1): + """Linear interpolation of alpha. This method estimats alpha* such that sum(theta(alpha*))=k via a linear interpolation. Parameters ----------- - alpha_0: float - A value for wich sum(theta(alpha_0)) <= k - alpha_1: float - A value for which sum(theta(alpha_1)) <= k - sum_0: float - Value of sum(theta(alpha_0)) - sum_1: - Value of sum(theta(alpha_0)) + alpha0: float + A value for wich sum(theta(alpha0)) <= k + alpha1: float + A value for which sum(theta(alpha1)) <= k + sum0: float + Value of sum(theta(alpha0)) + sum1: float + Value of sum(theta(alpha0)) Returns ------- @@ -904,19 +974,19 @@ def _interpolate(self, alpha_0, alpha_1, sum_0, sum_1): An interpolation for which sum(theta(alpha_star)) = k """ + if sum0 == self._k_value: + return alpha0 - if sum_0 == self._k_value: - return alpha_0 - elif sum_1 == self._k_value: - return alpha_1 - else: - slope = (sum_1 - sum_0) / (alpha_1 - alpha_0) - b = sum_0 - slope * alpha_0 - alpha_star = (self._k_value - b) / slope - return alpha_star + elif sum1 == self._k_value: + return alpha1 - def _binary_search(self, data, alpha, extra_factor=1.0): - """ Binary search method + slope = (sum1 - sum0) / (alpha1 - alpha0) + b_val = sum0 - slope * alpha0 + + return (self._k_value - b_val) / slope + + def _binary_search(self, input_data, alpha, extra_factor=1.0): + """Binary search method. This method finds the coordinate of alpha (i) such that sum(theta(alpha[i])) =< k and sum(theta(alpha[i+1])) >= k via binary @@ -924,7 +994,7 @@ def _binary_search(self, data, alpha, extra_factor=1.0): Parameters ---------- - data: numpy.ndarray + input_data: numpy.ndarray absolute value of the input data alpha: numpy.ndarray Array same size as the input data @@ -932,6 +1002,11 @@ def _binary_search(self, data, alpha, extra_factor=1.0): Potential extra factor comming from the optimization process (default is ``1.0``) + Raises + ------ + ValueError + For invalid output alpha value + Returns ------- tuple @@ -942,21 +1017,23 @@ def _binary_search(self, data, alpha, extra_factor=1.0): Value of sum(theta(alpha[index + 1])) """ - first_idx = 0 - data_abs = np.abs(data) + data_abs = np.abs(input_data) last_idx = alpha.shape[0] - 1 found = False prev_midpoint = 0 cnt = 0 # Avoid infinite looops + tolerance = 1e-4 # Checking particular to be sure that the solution is in the array - sum_0 = self._compute_theta(data_abs, alpha[0], extra_factor).sum() - sum_1 = self._compute_theta(data_abs, alpha[-1], extra_factor).sum() - if sum_1 <= self._k_value: + sum0 = self._compute_theta(data_abs, alpha[0], extra_factor).sum() + sum1 = self._compute_theta(data_abs, alpha[-1], extra_factor).sum() + + if sum1 <= self._k_value: midpoint = alpha.shape[0] - 2 found = True - if sum_0 >= self._k_value: + + if sum0 >= self._k_value: found = True midpoint = 0 @@ -968,55 +1045,77 @@ def _binary_search(self, data, alpha, extra_factor=1.0): if prev_midpoint == midpoint: # Particular case - sum_0 = self._compute_theta(data_abs, alpha[first_idx], - extra_factor).sum() - sum_1 = self._compute_theta(data_abs, alpha[last_idx], - extra_factor).sum() - - if (np.abs(sum_0 - self._k_value) <= 1e-4): + sum0 = self._compute_theta( + data_abs, + alpha[first_idx], + extra_factor, + ).sum() + sum1 = self._compute_theta( + data_abs, + alpha[last_idx], + extra_factor, + ).sum() + + if (np.abs(sum0 - self._k_value) <= tolerance): found = True midpoint = first_idx - if (np.abs(sum_1 - self._k_value) <= 1e-4): + if (np.abs(sum1 - self._k_value) <= tolerance): found = True midpoint = last_idx - 1 # -1 because output is index such that - # sum(theta(alpha[index])) <= k - - if (first_idx - last_idx == 2) or (first_idx - last_idx == 1): - sum_0 = self._compute_theta(data_abs, alpha[first_idx], - extra_factor).sum() - sum_1 = self._compute_theta(data_abs, alpha[last_idx], - extra_factor).sum() - if (sum_0 <= self._k_value) or (sum_1 >= self._k_value): + # `sum(theta(alpha[index])) <= k` + + if (first_idx - last_idx) in {1, 2}: + sum0 = self._compute_theta( + data_abs, + alpha[first_idx], + extra_factor, + ).sum() + sum1 = self._compute_theta( + data_abs, + alpha[last_idx], + extra_factor, + ).sum() + + if (sum0 <= self._k_value) & (sum1 >= self._k_value): found = True - sum_0 = self._compute_theta(data_abs, alpha[midpoint], - extra_factor).sum() - sum_1 = self._compute_theta(data_abs, alpha[midpoint + 1], - extra_factor).sum() - - if (sum_0 <= self._k_value) & (sum_1 >= self._k_value): + sum0 = self._compute_theta( + data_abs, + alpha[midpoint], + extra_factor, + ).sum() + sum1 = self._compute_theta( + data_abs, + alpha[midpoint + 1], + extra_factor, + ).sum() + + if sum0 <= self._k_value <= sum1: found = True - elif sum_1 < self._k_value: + elif sum1 < self._k_value: first_idx = midpoint - elif sum_0 > self._k_value: + elif sum0 > self._k_value: last_idx = midpoint prev_midpoint = midpoint if found: - return midpoint, alpha[midpoint], alpha[midpoint + 1], sum_0,\ - sum_1 - else: - raise ValueError("Cannot find the coordinate of alpha (i) such " + - "that sum(theta(alpha[i])) =< k and " + - "sum(theta(alpha[i+1])) >= k ") + return ( + midpoint, alpha[midpoint], alpha[midpoint + 1], sum0, sum1, + ) + + raise ValueError( + 'Cannot find the coordinate of alpha (i) such ' + + 'that sum(theta(alpha[i])) =< k and ' + + 'sum(theta(alpha[i+1])) >= k ', + ) def _find_alpha(self, input_data, extra_factor=1.0): - """ Find alpha value to compute theta + """Find alpha value to compute theta. This method aim at finding alpha such that sum(theta(alpha)) = k. @@ -1033,37 +1132,40 @@ def _find_alpha(self, input_data, extra_factor=1.0): An interpolation of alpha such that sum(theta(alpha)) = k """ - data_size = input_data.shape[0] # Computes the alpha^i points line 1 in Algorithm 1. alpha = np.zeros((data_size * 2)) data_abs = np.abs(input_data) - alpha[:data_size] = (self.beta * extra_factor) / \ - (data_abs + sys.float_info.epsilon) - alpha[data_size:] = (self.beta * extra_factor + 1) / \ - (data_abs + sys.float_info.epsilon) + alpha[:data_size] = ( + (self.beta * extra_factor) + / (data_abs + sys.float_info.epsilon) + ) + alpha[data_size:] = ( + (self.beta * extra_factor + 1) + / (data_abs + sys.float_info.epsilon) + ) alpha = np.sort(np.unique(alpha)) # Identify points alpha^i and alpha^{i+1} line 2. Algorithm 1 - _, alpha_0, alpha_1, sum_0, sum_1 = self._binary_search(input_data, - alpha, - extra_factor) + _, *alpha_sum = self._binary_search( + input_data, + alpha, + extra_factor, + ) # Interpolate alpha^\star such that its sum is equal to k - alpha_star = self._interpolate(alpha_0, alpha_1, sum_0, sum_1) - - return alpha_star + return self._interpolate(*alpha_sum) - def _op_method(self, data, extra_factor=1.0): - """Operator + def _op_method(self, input_data, extra_factor=1.0): + """Operator. This method returns the proximity operator of the squared k-support norm. Implements (Alg. 1) in :cite:`mcdonald2014`. Parameters ---------- - data : numpy.ndarray + input_data : numpy.ndarray Input data array extra_factor : float Additional multiplication factor (default is ``1.0``) @@ -1074,26 +1176,30 @@ def _op_method(self, data, extra_factor=1.0): Proximal map """ - data_shape = data.shape + data_shape = input_data.shape k_max = np.prod(data_shape) if self._k_value > k_max: - warn("K value of the K-support norm is greater than the input" + - " dimension, its value will be set to " + str(k_max)) + warn( + 'K value of the K-support norm is greater than the input ' + + 'dimension, its value will be set to {0}'.format(k_max), + ) self._k_value = k_max # Computes line 1., 2. and 3. in Algorithm 1 - alpha = self._find_alpha(np.abs(data.flatten()), extra_factor) + alpha = self._find_alpha(np.abs(input_data.flatten()), extra_factor) # Computes line 4. in Algorithm 1 - theta = self._compute_theta(np.abs(data.flatten()), alpha) + theta = self._compute_theta(np.abs(input_data.flatten()), alpha) # Computes line 5. in Algorithm 1. - rslt = np.nan_to_num((data.flatten() * theta) / - (theta + self.beta * extra_factor)) + rslt = np.nan_to_num( + (input_data.flatten() * theta) + / (theta + self.beta * extra_factor), + ) return rslt.reshape(data_shape) def _find_q(self, sorted_data): - """ Find q index value + """Find q index value. This method finds the value of q such that: @@ -1111,55 +1217,74 @@ def _find_q(self, sorted_data): (k - q)>= sorted_data[q+1] """ - first_idx = 0 last_idx = self._k_value - 1 found = False - q = (first_idx + last_idx) // 2 + q_val = (first_idx + last_idx) // 2 cnt = 0 # Particular case - if (sorted_data[0:].sum() / (self._k_value)) >= sorted_data[0]: + if (sorted_data.sum() / (self._k_value)) >= sorted_data[0]: found = True - q = 0 - elif (sorted_data[self._k_value - 1:].sum()) <= sorted_data[ - self._k_value - 1]: + q_val = 0 + + elif ( + (sorted_data[self._k_value - 1:].sum()) + <= sorted_data[self._k_value - 1] + ): found = True - q = self._k_value - 1 + q_val = self._k_value - 1 - while (not found and not cnt == self._k_value and - (first_idx <= last_idx) and last_idx < self._k_value): + while ( + not found and not cnt == self._k_value + and (first_idx <= last_idx < self._k_value) + ): - q = (first_idx + last_idx) // 2 + q_val = (first_idx + last_idx) // 2 cnt += 1 - l1_part = sorted_data[q:].sum() / (self._k_value - q) - if sorted_data[q] >= l1_part and l1_part >= sorted_data[q + 1]: + l1_part = sorted_data[q_val:].sum() / (self._k_value - q_val) + + if ( + sorted_data[q_val + 1] <= l1_part <= sorted_data[q_val] + ): found = True + else: - if sorted_data[q] <= l1_part: - last_idx = q - if l1_part <= sorted_data[q + 1]: - first_idx = q - return q + if sorted_data[q_val] <= l1_part: + last_idx = q_val + if l1_part <= sorted_data[q_val + 1]: + first_idx = q_val + + return q_val def _cost_method(self, *args, **kwargs): - """Calculate OWL component of the cost + """Calculate OWL component of the cost. This method returns the ordered weighted l1 norm of the data. + Parameters + ---------- + args : interable + Positional arguments + kwargs : dict + Keyword arguments + Returns ------- float OWL cost component - """ - data_abs = np.abs(args[0].flatten()) ix = np.argsort(data_abs)[::-1] data_abs = data_abs[ix] # Sorted absolute value of the data - q = self._find_q(data_abs) - cost_val = (np.sum(data_abs[:q]**2) * 0.5 + - np.sum(data_abs[q:])**2 / (self._k_value - q)) * self.beta + q_val = self._find_q(data_abs) + cost_val = ( + ( + np.sum(data_abs[:q_val]**2) * 0.5 + + np.sum(data_abs[q_val:]) ** 2 + / (self._k_value - q_val) + ) * self.beta + ) if 'verbose' in kwargs and kwargs['verbose']: print(' - K-SUPPORT NORM (X):', cost_val) @@ -1168,7 +1293,7 @@ def _cost_method(self, *args, **kwargs): class GroupLASSO(ProximityParent): - """Group LASSO norm proximity + """Group LASSO norm proximity. This class implements the proximity operator of the group-lasso regularization as defined in :cite:`yuan2006`, with groups dimension @@ -1183,7 +1308,8 @@ class GroupLASSO(ProximityParent): -------- >>> import numpy as np >>> from modopt.opt.proximity import GroupLASSO - >>> A = np.arange(15).reshape(3,5) + >>> A = np.arange(15).reshape(3, 5) + >>> A array([[ 0, 1, 2, 3, 4], [ 5, 6, 7, 8, 9], [10, 11, 12, 13, 14]]) @@ -1193,7 +1319,7 @@ class GroupLASSO(ProximityParent): [ 3.65835921, 4.56799689, 5.50381195, 6.45722157, 7.42264316], [ 7.31671843, 8.37466096, 9.4351062 , 10.49298505, 11.5463338 ]]) >>> prox_op.cost(A, verbose=True) - 211.37821733946427 + 211.37821733946427 See Also -------- @@ -1206,14 +1332,14 @@ def __init__(self, weights): self.op = self._op_method self.cost = self._cost_method - def _op_method(self, data, extra_factor=1.0): - """ Operator + def _op_method(self, input_data, extra_factor=1.0): + """Operator. This method returns the input data thresholded by the weights. Parameters ---------- - data : numpy.ndarray + input_data : numpy.ndarray Input data array extra_factor : float Additional multiplication factor (default is ``1.0``) @@ -1224,19 +1350,22 @@ def _op_method(self, data, extra_factor=1.0): With proximal of GroupLASSO regularization """ + norm2 = np.linalg.norm(input_data, axis=0) + denominator = np.maximum(norm2, np.finfo(np.float32).eps) - norm_2 = np.linalg.norm(data, axis=0) - return data * np.maximum(0, 1.0 - self.weights * extra_factor / - np.maximum(norm_2, np.finfo(np.float32).eps)) + return input_data * np.maximum( + 0, + (1.0 - self.weights * extra_factor / denominator), + ) - def _cost_method(self, data): - """Cost function + def _cost_method(self, input_data): + """Cost function. This method calculate the cost function of the proximable part. Parameters ---------- - x: numpy.ndarray + input_data : numpy.ndarray Input array of the sparse code Returns @@ -1245,5 +1374,4 @@ def _cost_method(self, data): The cost of GroupLASSO regularizer """ - - return np.sum(self.weights * np.linalg.norm(data, axis=0)) + return np.sum(self.weights * np.linalg.norm(input_data, axis=0)) diff --git a/modopt/opt/reweight.py b/modopt/opt/reweight.py index fa1ecb71..444b65d5 100644 --- a/modopt/opt/reweight.py +++ b/modopt/opt/reweight.py @@ -1,24 +1,20 @@ # -*- coding: utf-8 -*- -"""REWEIGHTING CLASSES +"""REWEIGHTING CLASSES. This module contains classes for reweighting optimisation implementations :Author: Samuel Farrens -:References: - -.. bibliography:: refs.bib - :filter: docname in docnames - """ import numpy as np + from modopt.base.types import check_float class cwbReweight(object): - r"""Candes, Wakin and Boyd reweighting class + """Candes, Wakin and Boyd reweighting class. This class implements the reweighting scheme described in :cite:`candes2007` @@ -32,39 +28,46 @@ class cwbReweight(object): Examples -------- - >>> from modopt.signal.reweight import cwbReweight + >>> import numpy as np + >>> from modopt.opt.reweight import cwbReweight >>> a = np.arange(9).reshape(3, 3).astype(float) + 1 >>> rw = cwbReweight(a) >>> rw.weights - array([[ 1., 2., 3.], - [ 4., 5., 6.], - [ 7., 8., 9.]]) + array([[1., 2., 3.], + [4., 5., 6.], + [7., 8., 9.]]) >>> rw.reweight(a) >>> rw.weights - array([[ 0.5, 1. , 1.5], - [ 2. , 2.5, 3. ], - [ 3.5, 4. , 4.5]]) + array([[0.5, 1. , 1.5], + [2. , 2.5, 3. ], + [3.5, 4. , 4.5]]) """ - def __init__(self, weights, thresh_factor=1.0): + def __init__(self, weights, thresh_factor=1.0, verbose=False): self.weights = check_float(weights) self.original_weights = np.copy(self.weights) self.thresh_factor = check_float(thresh_factor) self._rw_num = 1 + self.verbose = verbose - def reweight(self, data): - r"""Reweight + def reweight(self, input_data): + r"""Reweight. This method implements the reweighting from section 4 in :cite:`candes2007` Parameters ---------- - data : numpy.ndarray + input_data : numpy.ndarray Input data + Raises + ------ + ValueError + For invalid input shape + Notes ----- Reweighting implemented as: @@ -74,15 +77,20 @@ def reweight(self, data): w = w \left( \frac{1}{1 + \frac{|x^w|}{n \sigma}} \right) """ + if self.verbose: + print(' - Reweighting: {0}'.format(self._rw_num)) - print(' - Reweighting: {}'.format(self._rw_num)) self._rw_num += 1 - data = check_float(data) + input_data = check_float(input_data) + + if input_data.shape != self.weights.shape: + raise ValueError( + 'Input data must have the same shape as the initial weights.', + ) - if data.shape != self.weights.shape: - raise ValueError('Input data must have the same shape as the ' - 'initial weights.') + thresh_weights = self.thresh_factor * self.original_weights - self.weights *= (1.0 / (1.0 + np.abs(data) / (self.thresh_factor * - self.original_weights))) + self.weights *= np.array( + 1.0 / (1.0 + np.abs(input_data) / (thresh_weights)), + ) diff --git a/modopt/plot/__init__.py b/modopt/plot/__init__.py index 2bb2c486..28d60be6 100644 --- a/modopt/plot/__init__.py +++ b/modopt/plot/__init__.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -"""PLOTTING ROUTINES +"""PLOTTING ROUTINES. This module contains submodules for plotting applications. @@ -9,5 +9,3 @@ """ __all__ = ['cost_plot'] - -from . import * diff --git a/modopt/plot/cost_plot.py b/modopt/plot/cost_plot.py index ff244ac1..aa855eaa 100644 --- a/modopt/plot/cost_plot.py +++ b/modopt/plot/cost_plot.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -"""PLOTTING ROUTINES +"""PLOTTING ROUTINES. This module contains methods for making plots. @@ -9,7 +9,7 @@ """ import numpy as np -from modopt.interface.errors import warn + try: import matplotlib.pyplot as plt except ImportError: # pragma: no cover @@ -19,7 +19,7 @@ def plotCost(cost_list, output=None): - """Plot cost function + """Plot cost function. Plot the final cost function. @@ -30,14 +30,20 @@ def plotCost(cost_list, output=None): output : str, optional Output file name (default is ``None``) - """ + Raises + ------ + ImportError + If Matplotlib package not found - if not import_fail: + """ + if import_fail: + raise ImportError('Matplotlib package not found') + else: if isinstance(output, type(None)): file_name = 'cost_function.png' else: - file_name = output + '_cost_function.png' + file_name = '{0}_cost_function.png'.format(output) plt.figure() plt.plot(np.log10(cost_list), 'r-') @@ -48,7 +54,3 @@ def plotCost(cost_list, output=None): plt.close() print(' - Saving cost function data to:', file_name) - - else: - - warn('Matplotlib not installed.') diff --git a/modopt/signal/__init__.py b/modopt/signal/__init__.py index 55e846cd..dbc6d053 100644 --- a/modopt/signal/__init__.py +++ b/modopt/signal/__init__.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -"""SIGNAL PROCESSING ROUTINES +"""SIGNAL PROCESSING ROUTINES. This module contains submodules for signal processing. @@ -9,5 +9,3 @@ """ __all__ = ['filter', 'noise', 'positivity', 'svd', 'validation', 'wavelet'] - -from . import * diff --git a/modopt/signal/filter.py b/modopt/signal/filter.py index e50f0bba..8e24768c 100644 --- a/modopt/signal/filter.py +++ b/modopt/signal/filter.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -"""FILTER ROUTINES +"""FILTER ROUTINES. This module contains methods for distance measurements in cosmology. @@ -9,17 +9,18 @@ """ import numpy as np + from modopt.base.types import check_float -def Gaussian_filter(x, sigma, norm=True): - r"""Gaussian filter +def gaussian_filter(data_point, sigma, norm=True): + """Gaussian filter. This method implements a Gaussian filter. Parameters ---------- - x : float + data_point : float Input data point sigma : float Standard deviation (filter scale) @@ -33,35 +34,33 @@ def Gaussian_filter(x, sigma, norm=True): Examples -------- - >>> from modopt.signal.filter import Gaussian_filter - >>> Gaussian_filter(1, 1) + >>> from modopt.signal.filter import gaussian_filter + >>> gaussian_filter(1, 1) 0.24197072451914337 - >>> Gaussian_filter(1, 1, False) - 0.60653065971263342 + >>> gaussian_filter(1, 1, False) + 0.6065306597126334 """ - - x = check_float(x) + data_point = check_float(data_point) sigma = check_float(sigma) - val = np.exp(-0.5 * (x / sigma) ** 2) + numerator = np.exp(-0.5 * (data_point / sigma) ** 2) if norm: - return val / (np.sqrt(2 * np.pi) * sigma) + return numerator / (np.sqrt(2 * np.pi) * sigma) - else: - return val + return numerator -def mex_hat(x, sigma): - r"""Mexican hat +def mex_hat(data_point, sigma): + """Mexican hat. This method implements a Mexican hat (or Ricker) wavelet. Parameters ---------- - x : float + data_point : float Input data point sigma : float Standard deviation (filter scale) @@ -75,29 +74,28 @@ def mex_hat(x, sigma): -------- >>> from modopt.signal.filter import mex_hat >>> mex_hat(2, 1) - -0.35213905225713371 + -0.3521390522571337 """ - - x = check_float(x) + data_point = check_float(data_point) sigma = check_float(sigma) - xs = (x / sigma) ** 2 - val = 2 * (3 * sigma) ** -0.5 * np.pi ** -0.25 + xs = (data_point / sigma) ** 2 + factor = 2 * (3 * sigma) ** -0.5 * np.pi ** -0.25 - return val * (1 - xs) * np.exp(-0.5 * xs) + return factor * (1 - xs) * np.exp(-0.5 * xs) -def mex_hat_dir(x, y, sigma): - r"""Directional Mexican hat +def mex_hat_dir(data_gauss, data_mex, sigma): + """Directional Mexican hat. This method implements a directional Mexican hat (or Ricker) wavelet. Parameters ---------- - x : float + data_gauss : float Input data point for Gaussian - y : float + data_mex : float Input data point for Mexican hat sigma : float Standard deviation (filter scale) @@ -114,8 +112,7 @@ def mex_hat_dir(x, y, sigma): 0.17606952612856686 """ - - x = check_float(x) + data_gauss = check_float(data_gauss) sigma = check_float(sigma) - return -0.5 * (x / sigma) ** 2 * mex_hat(y, sigma) + return -0.5 * (data_gauss / sigma) ** 2 * mex_hat(data_mex, sigma) diff --git a/modopt/signal/noise.py b/modopt/signal/noise.py index 85775cd2..f67cc066 100644 --- a/modopt/signal/noise.py +++ b/modopt/signal/noise.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -"""NOISE ROUTINES +"""NOISE ROUTINES. This module contains methods for adding and removing noise from data. @@ -9,17 +9,20 @@ """ from builtins import zip + import numpy as np +from modopt.base.backend import get_array_module + -def add_noise(data, sigma=1.0, noise_type='gauss'): - r"""Add noise to data +def add_noise(input_data, sigma=1.0, noise_type='gauss'): + """Add noise to data. This method adds Gaussian or Poisson noise to the input data Parameters ---------- - data : numpy.ndarray, list or tuple + input_data : numpy.ndarray, list or tuple Input data array sigma : float or list, optional Standard deviation of the noise to be added ('gauss' only, default is @@ -46,58 +49,61 @@ def add_noise(data, sigma=1.0, noise_type='gauss'): >>> from modopt.signal.noise import add_noise >>> x = np.arange(9).reshape(3, 3).astype(float) >>> x - array([[ 0., 1., 2.], - [ 3., 4., 5.], - [ 6., 7., 8.]]) + array([[0., 1., 2.], + [3., 4., 5.], + [6., 7., 8.]]) >>> np.random.seed(1) >>> add_noise(x, noise_type='poisson') - array([[ 0., 2., 2.], - [ 4., 5., 10.], - [ 11., 15., 18.]]) + array([[ 0., 2., 2.], + [ 4., 5., 10.], + [11., 15., 18.]]) >>> import numpy as np >>> from modopt.signal.noise import add_noise >>> x = np.zeros(5) >>> x - array([ 0., 0., 0., 0., 0.]) + array([0., 0., 0., 0., 0.]) >>> np.random.seed(1) >>> add_noise(x, sigma=2.0) array([ 3.24869073, -1.22351283, -1.0563435 , -2.14593724, 1.73081526]) """ + input_data = np.array(input_data) - data = np.array(data) - - if noise_type not in ('gauss', 'poisson'): - raise ValueError('Invalid noise type. Options are "gauss" or' - '"poisson"') + if noise_type not in {'gauss', 'poisson'}: + raise ValueError( + 'Invalid noise type. Options are "gauss" or "poisson"', + ) if isinstance(sigma, (list, tuple, np.ndarray)): - if len(sigma) != data.shape[0]: - raise ValueError('Number of sigma values must match first ' - 'dimension of input data') + if len(sigma) != input_data.shape[0]: + raise ValueError( + 'Number of sigma values must match first dimension of input ' + + 'data', + ) if noise_type == 'gauss': - random = np.random.randn(*data.shape) + random = np.random.randn(*input_data.shape) elif noise_type == 'poisson': - random = np.random.poisson(np.abs(data)) + random = np.random.poisson(np.abs(input_data)) if isinstance(sigma, (int, float)): - return data + sigma * random + return input_data + sigma * random - else: - return data + np.array([s * r for s, r in zip(sigma, random)]) + noise = np.array([sig * rand for sig, rand in zip(sigma, random)]) + return input_data + noise -def thresh(data, threshold, threshold_type='hard'): - r"""Threshold data + +def thresh(input_data, threshold, threshold_type='hard'): + r"""Threshold data. This method perfoms hard or soft thresholding on the input data Parameters ---------- - data : numpy.ndarray, list or tuple + input_data : numpy.ndarray, list or tuple Input data array threshold : float or numpy.ndarray Threshold level(s) @@ -114,7 +120,6 @@ def thresh(data, threshold, threshold_type='hard'): ValueError If `threshold_type` is not 'hard' or 'soft' - Notes ----- Implements one of the following two equations: @@ -151,26 +156,28 @@ def thresh(data, threshold, threshold_type='hard'): >>> np.random.seed(1) >>> x = np.random.ranf((3, 3)) >>> x - array([[ 4.17022005e-01, 7.20324493e-01, 1.14374817e-04], - [ 3.02332573e-01, 1.46755891e-01, 9.23385948e-02], - [ 1.86260211e-01, 3.45560727e-01, 3.96767474e-01]]) + array([[4.17022005e-01, 7.20324493e-01, 1.14374817e-04], + [3.02332573e-01, 1.46755891e-01, 9.23385948e-02], + [1.86260211e-01, 3.45560727e-01, 3.96767474e-01]]) >>> thresh(x, 0.2, threshold_type='soft') - array([[ 0.217022 , 0.52032449, -0. ], - [ 0.10233257, -0. , -0. ], - [-0. , 0.14556073, 0.19676747]]) + array([[0.217022 , 0.52032449, 0. ], + [0.10233257, 0. , 0. ], + [0. , 0.14556073, 0.19676747]]) """ + xp = get_array_module(input_data) - data = np.array(data) + input_data = xp.array(input_data) - if threshold_type not in ('hard', 'soft'): - raise ValueError('Invalid threshold type. Options are "hard" or' - '"soft"') + if threshold_type not in {'hard', 'soft'}: + raise ValueError( + 'Invalid threshold type. Options are "hard" or "soft"', + ) if threshold_type == 'soft': - return np.around(np.maximum((1.0 - threshold / - np.maximum(np.finfo(np.float64).eps, np.abs(data))), - 0.0) * data, decimals=15) + denominator = xp.maximum(xp.finfo(np.float64).eps, xp.abs(input_data)) + max_value = xp.maximum((1.0 - threshold / denominator), 0) + + return xp.around(max_value * input_data, decimals=15) - else: - return data * (np.abs(data) >= threshold) + return input_data * (xp.abs(input_data) >= threshold) diff --git a/modopt/signal/positivity.py b/modopt/signal/positivity.py index 961c8dfc..7b79d0ee 100644 --- a/modopt/signal/positivity.py +++ b/modopt/signal/positivity.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -"""POSITIVITY +"""POSITIVITY. This module contains a function that retains only positive coefficients in an array @@ -12,21 +12,68 @@ import numpy as np -def positive(data): - r"""Positivity operator +def pos_thresh(input_data): + """Positive Threshold. + + Keep only positive coefficients from input data. + + Parameters + ---------- + input_data : int, float, list, tuple or numpy.ndarray + Input data + + Returns + ------- + int, float, or numpy.ndarray + Positive coefficients + + """ + return input_data * (input_data > 0) + + +def pos_recursive(input_data): + """Positive Recursive. + + Run pos_thresh on input array or recursively for ragged nested arrays. + + Parameters + ---------- + input_data : numpy.ndarray + Input data + + Returns + ------- + numpy.ndarray + Positive coefficients + + """ + if input_data.dtype == 'O': + res = np.array([pos_recursive(elem) for elem in input_data]) + + else: + res = pos_thresh(input_data) + + return res + + +def positive(input_data, ragged=False): + """Positivity operator. This method preserves only the positive coefficients of the input data, all negative coefficients are set to zero Parameters ---------- - data : int, float, list, tuple or numpy.ndarray + input_data : int, float, or numpy.ndarray Input data + ragged : bool, optional + Specify if the input_data is a ragged nested array + (defaul is ``False``) Returns ------- int or float, or numpy.ndarray - Array with only positive coefficients + Positive coefficients Raises ------ @@ -35,6 +82,7 @@ def positive(data): Examples -------- + >>> import numpy as np >>> from modopt.signal.positivity import positive >>> a = np.arange(9).reshape(3, 3) - 5 >>> a @@ -47,33 +95,19 @@ def positive(data): [1, 2, 3]]) """ + if not isinstance(input_data, (int, float, list, tuple, np.ndarray)): + raise TypeError( + 'Invalid data type, input must be `int`, `float`, `list`, ' + + '`tuple` or `np.ndarray`.', + ) - if not isinstance(data, (int, float, list, tuple, np.ndarray)): - raise TypeError('Invalid data type, input must be `int`, `float`, ' - '`list`, `tuple` or `np.ndarray`.') - - def pos_thresh(data): - - return data * (data > 0) - - def pos_recursive(data): - - data = np.array(data) - - if not data.dtype == 'O': - - result = list(pos_thresh(data)) - - else: - - result = [pos_recursive(x) for x in data] - - return result - - if isinstance(data, (int, float)): + if isinstance(input_data, (int, float)): + return pos_thresh(input_data) - return pos_thresh(data) + if ragged: + input_data = np.array(input_data, dtype='object') else: + input_data = np.array(input_data) - return np.array(pos_recursive(data)) + return pos_recursive(input_data) diff --git a/modopt/signal/svd.py b/modopt/signal/svd.py index bc171b93..de3fa453 100644 --- a/modopt/signal/svd.py +++ b/modopt/signal/svd.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -"""SVD ROUTINES +"""SVD ROUTINES. This module contains methods for thresholding singular values. @@ -10,20 +10,21 @@ import numpy as np from scipy.linalg import svd + +from modopt.base.transform import matrix2cube +from modopt.interface.errors import warn from modopt.math.convolve import convolve from modopt.signal.noise import thresh -from modopt.base.transform import cube2matrix, matrix2cube -from modopt.interface.errors import warn -def find_n_pc(u, factor=0.5): - """Find number of principal components +def find_n_pc(u_vec, factor=0.5): + """Find number of principal components. This method finds the minimum number of principal components required. Parameters ---------- - u : numpy.ndarray + u_vec : numpy.ndarray Left singular vector of the original data factor : float, optional Factor for testing the auto correlation (default is ``0.5``) @@ -33,41 +34,58 @@ def find_n_pc(u, factor=0.5): int Number of principal components + Raises + ------ + ValueError + Invalid left singular vector + Examples -------- + >>> import numpy as np >>> from scipy.linalg import svd >>> from modopt.signal.svd import find_n_pc >>> x = np.arange(18).reshape(9, 2).astype(float) >>> find_n_pc(svd(x)[0]) - array([3]) + 1 """ - - if np.sqrt(u.shape[0]) % 1: - raise ValueError('Invalid left singular value. The size of the first ' - 'dimenion of u must be perfect square.') + if np.sqrt(u_vec.shape[0]) % 1: + raise ValueError( + 'Invalid left singular vector. The size of the first ' + + 'dimenion of ``u_vec`` must be perfect square.', + ) # Get the shape of the array - array_shape = np.repeat(np.int(np.sqrt(u.shape[0])), 2) + array_shape = np.repeat(np.int(np.sqrt(u_vec.shape[0])), 2) # Find the auto correlation of the left singular vector. - u_auto = [convolve(a.reshape(array_shape), - np.rot90(a.reshape(array_shape), 2)) for a in u.T] + u_auto = [ + convolve( + elem.reshape(array_shape), + np.rot90(elem.reshape(array_shape), 2), + ) + for elem in u_vec.T + ] # Return the required number of principal components. - return np.sum([(a[tuple(zip(array_shape // 2))] ** 2 <= factor * - np.sum(a ** 2)) for a in u_auto]) + return np.sum([ + ( + u_val[tuple(zip(array_shape // 2))] ** 2 <= factor + * np.sum(u_val ** 2), + ) + for u_val in u_auto + ]) -def calculate_svd(data): - """Calculate Singular Value Decomposition +def calculate_svd(input_data): + """Calculate Singular Value Decomposition. This method calculates the Singular Value Decomposition (SVD) of the input data using SciPy. Parameters ---------- - data : numpy.ndarray + input_data : numpy.ndarray Input data array, 2D matrix Returns @@ -81,29 +99,32 @@ def calculate_svd(data): For invalid data type """ - - if (not isinstance(data, np.ndarray)) or (data.ndim != 2): + if (not isinstance(input_data, np.ndarray)) or (input_data.ndim != 2): raise TypeError('Input data must be a 2D np.ndarray.') - return svd(data, check_finite=False, lapack_driver='gesvd', - full_matrices=False) + return svd( + input_data, + check_finite=False, + lapack_driver='gesvd', + full_matrices=False, + ) -def svd_thresh(data, threshold=None, n_pc=None, thresh_type='hard'): - r"""Threshold the singular values +def svd_thresh(input_data, threshold=None, n_pc=None, thresh_type='hard'): + """Threshold the singular values. This method thresholds the input data using singular value decomposition. Parameters ---------- - data : numpy.ndarray + input_data : numpy.ndarray Input data array, 2D matrix threshold : float or numpy.ndarray, optional Threshold value(s) (default is ``None``) n_pc : int or str, optional Number of principal components, specify an integer value or 'all' (default is ``None``) - threshold_type : {'hard', 'soft'}, optional + thresh_type : {'hard', 'soft'}, optional Type of thresholding (default is 'hard') Returns @@ -118,72 +139,81 @@ def svd_thresh(data, threshold=None, n_pc=None, thresh_type='hard'): Examples -------- + >>> import numpy as np >>> from modopt.signal.svd import svd_thresh >>> x = np.arange(18).reshape(9, 2).astype(float) >>> svd_thresh(x, n_pc=1) - array([[ 0.49815487, 0.54291537], - [ 2.40863386, 2.62505584], - [ 4.31911286, 4.70719631], - [ 6.22959185, 6.78933678], - [ 8.14007085, 8.87147725], - [ 10.05054985, 10.95361772], - [ 11.96102884, 13.03575819], - [ 13.87150784, 15.11789866], - [ 15.78198684, 17.20003913]]) + array([[ 0.49815487, 0.54291537], + [ 2.40863386, 2.62505584], + [ 4.31911286, 4.70719631], + [ 6.22959185, 6.78933678], + [ 8.14007085, 8.87147725], + [10.05054985, 10.95361772], + [11.96102884, 13.03575819], + [13.87150784, 15.11789866], + [15.78198684, 17.20003913]]) """ - - if ((not isinstance(n_pc, (int, str, type(None)))) or - (isinstance(n_pc, int) and n_pc <= 0) or - (isinstance(n_pc, str) and n_pc != 'all')): - raise ValueError('Invalid value for "n_pc", specify a positive ' - 'integer value or "all"') + less_than_zero = isinstance(n_pc, int) and n_pc <= 0 + str_not_all = isinstance(n_pc, str) and n_pc != 'all' + + if ( + (not isinstance(n_pc, (int, str, type(None)))) + or less_than_zero + or str_not_all + ): + raise ValueError( + 'Invalid value for "n_pc", specify a positive integer value or ' + + '"all"', + ) # Get SVD of input data. - u, s, v = calculate_svd(data) + u_vec, s_values, v_vec = calculate_svd(input_data) # Find the threshold if not provided. if isinstance(threshold, type(None)): - # Find the required number of principal components if not specified. if isinstance(n_pc, type(None)): - n_pc = find_n_pc(u, factor=0.1) + n_pc = find_n_pc(u_vec, factor=0.1) + print('xxxx', n_pc, u_vec) # If the number of PCs is too large use all of the singular values. - if ((isinstance(n_pc, int) and n_pc >= s.size) or - (isinstance(n_pc, str) and n_pc == 'all')): - n_pc = s.size + if ( + (isinstance(n_pc, int) and n_pc >= s_values.size) + or (isinstance(n_pc, str) and n_pc == 'all') + ): + n_pc = s_values.size warn('Using all singular values.') - threshold = s[n_pc - 1] + threshold = s_values[n_pc - 1] # Threshold the singular values. - s_new = thresh(s, threshold, thresh_type) + s_new = thresh(s_values, threshold, thresh_type) - if np.all(s_new == s): + if np.all(s_new == s_values): warn('No change to singular values.') # Diagonalize the svd s_new = np.diag(s_new) # Return the thresholded data. - return np.dot(u, np.dot(s_new, v)) + return np.dot(u_vec, np.dot(s_new, v_vec)) -def svd_thresh_coef(data, operator, threshold, thresh_type='hard'): - """Threshold the singular values coefficients +def svd_thresh_coef(input_data, operator, threshold, thresh_type='hard'): + """Threshold the singular values coefficients. This method thresholds the input data using singular value decomposition Parameters ---------- - data : numpy.ndarray + input_data : numpy.ndarray Input data array, 2D matrix operator : class Operator class instance threshold : float or numpy.ndarray Threshold value(s) - threshold_type : {'hard', 'soft'} + thresh_type : {'hard', 'soft'} Type of noise to be added (default is 'hard') Returns @@ -193,33 +223,34 @@ def svd_thresh_coef(data, operator, threshold, thresh_type='hard'): Raises ------ - ValueError - For invalid string entry for n_pc + TypeError + If operator not callable """ - if not callable(operator): raise TypeError('Operator must be a callable function.') # Get SVD of data matrix - u, s, v = calculate_svd(data) + u_vec, s_values, v_vec = calculate_svd(input_data) # Diagnalise s - s = np.diag(s) + s_values = np.diag(s_values) # Compute coefficients - a = np.dot(s, v) + a_matrix = np.dot(s_values, v_vec) # Get the shape of the array - array_shape = np.repeat(np.int(np.sqrt(u.shape[0])), 2) + array_shape = np.repeat(np.int(np.sqrt(u_vec.shape[0])), 2) # Compute threshold matrix. - ti = np.array([np.linalg.norm(x) for x in - operator(matrix2cube(u, array_shape))]) - threshold *= np.repeat(ti, a.shape[1]).reshape(a.shape) + ti = np.array([ + np.linalg.norm(elem) + for elem in operator(matrix2cube(u_vec, array_shape)) + ]) + threshold *= np.repeat(ti, a_matrix.shape[1]).reshape(a_matrix.shape) # Threshold coefficients. - a_new = thresh(a, threshold, thresh_type) + a_new = thresh(a_matrix, threshold, thresh_type) # Return the thresholded image. - return np.dot(u, a_new) + return np.dot(u_vec, a_new) diff --git a/modopt/signal/validation.py b/modopt/signal/validation.py index f54483b8..f39a2eb3 100644 --- a/modopt/signal/validation.py +++ b/modopt/signal/validation.py @@ -1,4 +1,4 @@ -"""VALIDATION ROUTINES +"""VALIDATION ROUTINES. This module contains methods for testing signal and operator properties. @@ -9,9 +9,15 @@ import numpy as np -def transpose_test(operator, operator_t, x_shape, x_args=None, y_shape=None, - y_args=None): - r"""Transpose test +def transpose_test( + operator, + operator_t, + x_shape, + x_args=None, + y_shape=None, + y_args=None, +): + """Transpose test. This method tests two operators to see if they are the transpose of each other. @@ -31,16 +37,22 @@ def transpose_test(operator, operator_t, x_shape, x_args=None, y_shape=None, y_args : tuple, optional Arguments to be passed to transpose operator (default is ``None``) + Raises + ------ + TypeError + If input operators not callable + Examples -------- + >>> import numpy as np >>> from modopt.signal.validation import transpose_test - >>> np.random.seed(2) + >>> np.random.seed(1) + >>> a = np.random.ranf((3, 3)) >>> transpose_test(lambda x, y: x.dot(y), lambda x, y: x.dot(y.T), - (3, 3), x_args=x) + ... a.shape, x_args=a) - | - | = 0.0 """ - if not callable(operator) or not callable(operator_t): raise TypeError('The input operators must be callable functions.') @@ -51,14 +63,14 @@ def transpose_test(operator, operator_t, x_shape, x_args=None, y_shape=None, y_args = x_args # Generate random arrays. - x = np.random.ranf(x_shape) - y = np.random.ranf(y_shape) + x_val = np.random.ranf(x_shape) + y_val = np.random.ranf(y_shape) # Calculate - mx_y = np.sum(np.multiply(operator(x, x_args), y)) + mx_y = np.sum(np.multiply(operator(x_val, x_args), y_val)) # Calculate - x_mty = np.sum(np.multiply(x, operator_t(y, y_args))) + x_mty = np.sum(np.multiply(x_val, operator_t(y_val, y_args))) # Test the difference between the two. print(' - | - | =', np.abs(mx_y - x_mty)) diff --git a/modopt/signal/wavelet.py b/modopt/signal/wavelet.py index 8327a275..0e509cbd 100644 --- a/modopt/signal/wavelet.py +++ b/modopt/signal/wavelet.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -"""WAVELET MODULE +"""WAVELET MODULE. This module contains methods for performing wavelet transformations using iSAP @@ -9,21 +9,24 @@ Notes ----- This module serves as a wrapper for the wavelet transformation code -`mr_transform`, which is part of the Sparse2D package in iSAP. This executable +`mr_transform`, which is part of the Sparse2D package. This executable should be installed and built before using these methods. Sparse2D Repository: https://github.com/CosmoStat/Sparse2D """ -import numpy as np import subprocess as sp +from datetime import datetime from os import remove from random import getrandbits -from datetime import datetime + +import numpy as np + from modopt.base.np_adjust import rotate_stack from modopt.interface.errors import is_executable from modopt.math.convolve import convolve + try: from astropy.io import fits except ImportError: # pragma: no cover @@ -33,7 +36,7 @@ def execute(command_line): - """ Execute + """Execute. This method executes a given command line. @@ -53,7 +56,6 @@ def execute(command_line): For invalid input type """ - if not isinstance(command_line, str): raise TypeError('Command line must be a string.') @@ -65,15 +67,19 @@ def execute(command_line): return stdout.decode('utf-8'), stderr.decode('utf-8') -def call_mr_transform(data, opt='', path='./', - remove_files=True): # pragma: no cover - r"""Call mr_transform +def call_mr_transform( + input_data, + opt='', + path='./', + remove_files=True, +): # pragma: no cover + """Call mr_transform. This method calls the iSAP module mr_transform Parameters ---------- - data : numpy.ndarray + input_data : numpy.ndarray Input data, 2D array opt : list or str, optional Options to be passed to mr_transform (default is '') @@ -89,14 +95,19 @@ def call_mr_transform(data, opt='', path='./', Raises ------ + ImportError + If the Astropy package is not found ValueError If the input data is not a 2D numpy array + RuntimeError + For exception encountered in call to mr_transform Examples -------- + >>> import numpy as np >>> from modopt.signal.wavelet import * >>> a = np.arange(9).reshape(3, 3).astype(float) - >>> call_mr_transform(a) + >>> call_mr_transform(a) # doctest: +SKIP array([[[-1.5 , -1.125 , -0.75 ], [-0.375 , 0. , 0.375 ], [ 0.75 , 1.125 , 1.5 ]], @@ -111,14 +122,13 @@ def call_mr_transform(data, opt='', path='./', [[ 3.6484375 , 3.73632812, 3.82421875], [ 3.91210938, 4. , 4.08789062], - [ 4.17578125, 4.26367188, 4.3515625 ]]], dtype=float32) + [ 4.17578125, 4.26367188, 4.3515625 ]]]) """ - if not import_astropy: raise ImportError('Astropy package not found.') - if (not isinstance(data, np.ndarray)) or (data.ndim != 2): + if (not isinstance(input_data, np.ndarray)) or (input_data.ndim != 2): raise ValueError('Input data must be a 2D numpy array.') executable = 'mr_transform' @@ -127,33 +137,36 @@ def call_mr_transform(data, opt='', path='./', is_executable(executable) # Create a unique string using the current date and time. - unique_string = (datetime.now().strftime('%Y.%m.%d_%H.%M.%S') + - str(getrandbits(128))) + unique_string = ( + datetime.now().strftime('%Y.%m.%d_%H.%M.%S') + + str(getrandbits(128)) + ) # Set the ouput file names. - file_name = path + 'mr_temp_' + unique_string - file_fits = file_name + '.fits' - file_mr = file_name + '.mr' + file_name = '{0}mr_temp_{1}'.format(path, unique_string) + file_fits = '{0}.fits'.format(file_name) + file_mr = '{0}.mr'.format(file_name) # Write the input data to a fits file. - fits.writeto(file_fits, data) + fits.writeto(file_fits, input_data) if isinstance(opt, str): opt = opt.split() # Prepare command and execute it command_line = ' '.join([executable] + opt + [file_fits, file_mr]) - stdout, stderr = execute(command_line) + stdout, _ = execute(command_line) # Check for errors if any(word in stdout for word in ('bad', 'Error', 'Sorry')): - remove(file_fits) - raise RuntimeError('{} raised following exception: "{}"' - ''.format(executable, stdout.rstrip('\n'))) + message = '{0} raised following exception: "{1}"' + raise RuntimeError( + message.format(executable, stdout.rstrip('\n')), + ) # Retrieve wavelet transformed data. - result = fits.getdata(file_mr).astype(data.dtype) + data_trans = fits.getdata(file_mr).astype(input_data.dtype) # Remove the temporary files. if remove_files: @@ -161,11 +174,11 @@ def call_mr_transform(data, opt='', path='./', remove(file_mr) # Return the mr_transform results. - return result + return data_trans def trim_filter(filter_array): - """Trim the filters to the minimal size + """Trim the filters to the minimal size. This method will get rid of the extra zero coefficients in the filter. @@ -183,12 +196,17 @@ def trim_filter(filter_array): non_zero_indices = np.array(np.where(filter_array != 0)) min_idx = np.min(non_zero_indices, axis=-1) max_idx = np.max(non_zero_indices, axis=-1) + return filter_array[min_idx[0]:max_idx[0] + 1, min_idx[1]:max_idx[1] + 1] -def get_mr_filters(data_shape, opt='', coarse=False, - trim=False): # pragma: no cover - """Get mr_transform filters +def get_mr_filters( + data_shape, + opt='', + coarse=False, + trim=False, +): # pragma: no cover + """Get mr_transform filters. This method obtains wavelet filters by calling mr_transform. @@ -216,7 +234,6 @@ def get_mr_filters(data_shape, opt='', coarse=False, trim_filter : The function for trimming the wavelet filters """ - # Adjust the shape of the input data. data_shape = np.array(data_shape) data_shape += data_shape % 2 - 1 @@ -229,23 +246,23 @@ def get_mr_filters(data_shape, opt='', coarse=False, mr_filters = call_mr_transform(fake_data.astype(float), opt=opt) if trim: - mr_filters = np.array([trim_filter(f) for f in mr_filters]) + mr_filters = np.array([trim_filter(filt) for filt in mr_filters]) # Return filters if coarse: return mr_filters - else: - return mr_filters[:-1] + return mr_filters[:-1] -def filter_convolve(data, filters, filter_rot=False, method='scipy'): - r"""Filter convolve + +def filter_convolve(input_data, filters, filter_rot=False, method='scipy'): + """Filter convolve. This method convolves the input image with the wavelet filters. Parameters ---------- - data : numpy.ndarray + input_data : numpy.ndarray Input data, 2D array filters : numpy.ndarray Wavelet filters, 3D array @@ -261,49 +278,60 @@ def filter_convolve(data, filters, filter_rot=False, method='scipy'): Examples -------- + >>> import numpy as np >>> from modopt.signal.wavelet import filter_convolve >>> x = np.arange(9).reshape(3, 3).astype(float) >>> y = np.arange(36).reshape(4, 3, 3).astype(float) - >>> filter_convolve(x, y) - array([[[ 174., 165., 174.], - [ 93., 84., 93.], - [ 174., 165., 174.]], + >>> filter_convolve(x, y, method='astropy') + array([[[ 174., 165., 174.], + [ 93., 84., 93.], + [ 174., 165., 174.]], - [[ 498., 489., 498.], - [ 417., 408., 417.], - [ 498., 489., 498.]], + [[ 498., 489., 498.], + [ 417., 408., 417.], + [ 498., 489., 498.]], - [[ 822., 813., 822.], - [ 741., 732., 741.], - [ 822., 813., 822.]], + [[ 822., 813., 822.], + [ 741., 732., 741.], + [ 822., 813., 822.]], - [[ 1146., 1137., 1146.], - [ 1065., 1056., 1065.], - [ 1146., 1137., 1146.]]]) + [[1146., 1137., 1146.], + [1065., 1056., 1065.], + [1146., 1137., 1146.]]]) - >>> filter_convolve(y, y, filter_rot=True) - array([[ 14550., 14586., 14550.], - [ 14874., 14910., 14874.], - [ 14550., 14586., 14550.]]) + >>> filter_convolve(y, y, method='astropy', filter_rot=True) + array([[14550., 14586., 14550.], + [14874., 14910., 14874.], + [14550., 14586., 14550.]]) """ - if filter_rot: - return np.sum([convolve(coef, f, method=method) for coef, f in - zip(data, rotate_stack(filters))], axis=0) - - else: - return np.array([convolve(data, f, method=method) for f in filters]) - - -def filter_convolve_stack(data, filters, filter_rot=False, method='scipy'): - r"""Filter convolve + return np.sum( + [ + convolve(coef, filt, method=method) + for coef, filt in zip(input_data, rotate_stack(filters)) + ], + axis=0, + ) + + return np.array([ + convolve(input_data, filt, method=method) for filt in filters + ]) + + +def filter_convolve_stack( + input_data, + filters, + filter_rot=False, + method='scipy', +): + """Filter convolve. This method convolves the a stack of input images with the wavelet filters Parameters ---------- - data : numpy.ndarray + input_data : numpy.ndarray Input data, 3D array filters : numpy.ndarray Wavelet filters, 3D array @@ -319,23 +347,25 @@ def filter_convolve_stack(data, filters, filter_rot=False, method='scipy'): Examples -------- + >>> import numpy as np >>> from modopt.signal.wavelet import filter_convolve_stack >>> x = np.arange(9).reshape(3, 3).astype(float) - >>> filter_convolve(x, x) - array([[[ 4., 1., 4.], - [ 13., 10., 13.], - [ 22., 19., 22.]], + >>> filter_convolve_stack(x, x, method='astropy') + array([[[ 4., 1., 4.], + [ 13., 10., 13.], + [ 22., 19., 22.]], - [[ 13., 10., 13.], - [ 49., 46., 49.], - [ 85., 82., 85.]], + [[ 13., 10., 13.], + [ 49., 46., 49.], + [ 85., 82., 85.]], - [[ 22., 19., 22.], - [ 85., 82., 85.], - [ 148., 145., 148.]]]) + [[ 22., 19., 22.], + [ 85., 82., 85.], + [148., 145., 148.]]]) """ - # Return the convolved data cube. - return np.array([filter_convolve(x, filters, filter_rot=filter_rot, - method=method) for x in data]) + return np.array([ + filter_convolve(elem, filters, filter_rot=filter_rot, method=method) + for elem in input_data + ]) diff --git a/modopt/tests/test_base.py b/modopt/tests/test_base.py index 25305062..26e1e4ea 100644 --- a/modopt/tests/test_base.py +++ b/modopt/tests/test_base.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -"""UNIT TESTS FOR BASE +"""UNIT TESTS FOR BASE. This module contains unit tests for the modopt.base module. @@ -8,189 +8,270 @@ """ +from builtins import range from unittest import TestCase + import numpy as np import numpy.testing as npt -from builtins import range -from modopt.base import * + +from modopt.base import np_adjust, transform, types class NPAdjustTestCase(TestCase): + """Test case for np_adjust module.""" def setUp(self): - + """Set test parameter values.""" self.data1 = np.arange(9).reshape((3, 3)) self.data2 = np.arange(18).reshape((2, 3, 3)) - self.data3 = np.array([[0, 0, 0, 0, 0], [0, 0, 1, 2, 0], - [0, 3, 4, 5, 0], [0, 6, 7, 8, 0], - [0, 0, 0, 0, 0]]) + self.data3 = np.array([ + [0, 0, 0, 0, 0], + [0, 0, 1, 2, 0], + [0, 3, 4, 5, 0], + [0, 6, 7, 8, 0], + [0, 0, 0, 0, 0], + ]) def tearDown(self): - + """Unset test parameter values.""" self.data1 = None self.data2 = None self.data3 = None def test_rotate(self): - - npt.assert_array_equal(np_adjust.rotate(self.data1), - np.array([[8, 7, 6], [5, 4, 3], [2, 1, 0]]), - err_msg='Incorrect rotation') + """Test rotate.""" + npt.assert_array_equal( + np_adjust.rotate(self.data1), + np.array([[8, 7, 6], [5, 4, 3], [2, 1, 0]]), + err_msg='Incorrect rotation', + ) def test_rotate_stack(self): - - npt.assert_array_equal(np_adjust.rotate_stack(self.data2), - np.array([[[8, 7, 6], [5, 4, 3], [2, 1, 0]], - [[17, 16, 15], [14, 13, 12], - [11, 10, 9]]]), - err_msg='Incorrect stack rotation') + """Test rotate_stack.""" + npt.assert_array_equal( + np_adjust.rotate_stack(self.data2), + np.array([ + [[8, 7, 6], [5, 4, 3], [2, 1, 0]], + [[17, 16, 15], [14, 13, 12], [11, 10, 9]], + ]), + err_msg='Incorrect stack rotation', + ) def test_pad2d(self): - - npt.assert_array_equal(np_adjust.pad2d(self.data1, (1, 1)), - self.data3, err_msg='Incorrect padding') - - npt.assert_array_equal(np_adjust.pad2d(self.data1, 1), - self.data3, err_msg='Incorrect padding') - - npt.assert_array_equal(np_adjust.pad2d(self.data1, np.array([1, 1])), - self.data3, err_msg='Incorrect padding') + """Test pad2d.""" + npt.assert_array_equal( + np_adjust.pad2d(self.data1, (1, 1)), + self.data3, + err_msg='Incorrect padding', + ) + + npt.assert_array_equal( + np_adjust.pad2d(self.data1, 1), + self.data3, + err_msg='Incorrect padding', + ) + + npt.assert_array_equal( + np_adjust.pad2d(self.data1, np.array([1, 1])), + self.data3, + err_msg='Incorrect padding', + ) npt.assert_raises(ValueError, np_adjust.pad2d, self.data1, '1') def test_fancy_transpose(self): - - npt.assert_array_equal(np_adjust.fancy_transpose(self.data2), - np.array([[[0, 3, 6], [9, 12, 15]], - [[1, 4, 7], [10, 13, 16]], - [[2, 5, 8], [11, 14, 17]]]), - err_msg='Incorrect fancy transpose') + """Test fancy_transpose.""" + npt.assert_array_equal( + np_adjust.fancy_transpose(self.data2), + np.array([ + [[0, 3, 6], [9, 12, 15]], + [[1, 4, 7], [10, 13, 16]], + [[2, 5, 8], [11, 14, 17]], + ]), + err_msg='Incorrect fancy transpose', + ) def test_ftr(self): - - npt.assert_array_equal(np_adjust.ftr(self.data2), - np.array([[[0, 3, 6], [9, 12, 15]], - [[1, 4, 7], [10, 13, 16]], - [[2, 5, 8], [11, 14, 17]]]), - err_msg='Incorrect fancy transpose: ftr') + """Test ftr.""" + npt.assert_array_equal( + np_adjust.ftr(self.data2), + np.array([ + [[0, 3, 6], [9, 12, 15]], + [[1, 4, 7], [10, 13, 16]], + [[2, 5, 8], [11, 14, 17]], + ]), + err_msg='Incorrect fancy transpose: ftr', + ) def test_ftl(self): - - npt.assert_array_equal(np_adjust.ftl(self.data2), - np.array([[[0, 9], [1, 10], [2, 11]], - [[3, 12], [4, 13], [5, 14]], - [[6, 15], [7, 16], [8, 17]]]), - err_msg='Incorrect fancy transpose: ftl') + """Test ftl.""" + npt.assert_array_equal( + np_adjust.ftl(self.data2), + np.array([ + [[0, 9], [1, 10], [2, 11]], + [[3, 12], [4, 13], [5, 14]], + [[6, 15], [7, 16], [8, 17]], + ]), + err_msg='Incorrect fancy transpose: ftl', + ) class TransformTestCase(TestCase): + """Test case for transform module.""" def setUp(self): - + """Set test parameter values.""" self.cube = np.arange(16).reshape((4, 2, 2)) - self.map = np.array([[0, 1, 4, 5], [2, 3, 6, 7], [8, 9, 12, 13], - [10, 11, 14, 15]]) - self.matrix = np.array([[0, 4, 8, 12], [1, 5, 9, 13], [2, 6, 10, 14], - [3, 7, 11, 15]]) + self.map = np.array( + [[0, 1, 4, 5], [2, 3, 6, 7], [8, 9, 12, 13], [10, 11, 14, 15]], + ) + self.matrix = np.array( + [[0, 4, 8, 12], [1, 5, 9, 13], [2, 6, 10, 14], [3, 7, 11, 15]], + ) self.layout = (2, 2) def tearDown(self): - + """Unset test parameter values.""" self.cube = None self.map = None self.layout = None def test_cube2map(self): - - npt.assert_array_equal(transform.cube2map(self.cube, self.layout), - self.map, - err_msg='Incorrect transformation: cube2map') - - npt.assert_raises(ValueError, transform.cube2map, self.map, - self.layout) + """Test cube2map.""" + npt.assert_array_equal( + transform.cube2map(self.cube, self.layout), + self.map, + err_msg='Incorrect transformation: cube2map', + ) + + npt.assert_raises( + ValueError, + transform.cube2map, + self.map, + self.layout, + ) npt.assert_raises(ValueError, transform.cube2map, self.cube, (3, 3)) def test_map2cube(self): - - npt.assert_array_equal(transform.map2cube(self.map, self.layout), - self.cube, - err_msg='Incorrect transformation: map2cube') + """Test map2cube.""" + npt.assert_array_equal( + transform.map2cube(self.map, self.layout), + self.cube, + err_msg='Incorrect transformation: map2cube', + ) npt.assert_raises(ValueError, transform.map2cube, self.map, (3, 3)) def test_map2matrix(self): - - npt.assert_array_equal(transform.map2matrix(self.map, self.layout), - self.matrix, - err_msg='Incorrect transformation: map2matrix') + """Test map2matrix.""" + npt.assert_array_equal( + transform.map2matrix(self.map, self.layout), + self.matrix, + err_msg='Incorrect transformation: map2matrix', + ) def test_matrix2map(self): - - npt.assert_array_equal(transform.matrix2map(self.matrix, - self.map.shape), self.map, - err_msg='Incorrect transformation: matrix2map') + """Test matrix2map.""" + npt.assert_array_equal( + transform.matrix2map(self.matrix, self.map.shape), + self.map, + err_msg='Incorrect transformation: matrix2map', + ) def test_cube2matrix(self): - - npt.assert_array_equal(transform.cube2matrix(self.cube), - self.matrix, - err_msg='Incorrect transformation: cube2matrix') + """Test cube2matrix.""" + npt.assert_array_equal( + transform.cube2matrix(self.cube), + self.matrix, + err_msg='Incorrect transformation: cube2matrix', + ) def test_matrix2cube(self): - - npt.assert_array_equal(transform.matrix2cube(self.matrix, - self.cube[0].shape), self.cube, - err_msg='Incorrect transformation: matrix2cube') + """Test matrix2cube.""" + npt.assert_array_equal( + transform.matrix2cube(self.matrix, self.cube[0].shape), + self.cube, + err_msg='Incorrect transformation: matrix2cube', + ) class TypesTestCase(TestCase): + """Test case for types module.""" def setUp(self): - + """Set test parameter values.""" self.data1 = list(range(5)) self.data2 = np.arange(5) self.data3 = np.arange(5).astype(float) def tearDown(self): - + """Unset test parameter values.""" self.data1 = None self.data2 = None self.data3 = None def test_check_float(self): - - npt.assert_array_equal(types.check_float(1.0), 1.0, - err_msg='Float check failed') - - npt.assert_array_equal(types.check_float(1), 1.0, - err_msg='Float check failed') - - npt.assert_array_equal(types.check_float(self.data1), self.data3, - err_msg='Float check failed') - - npt.assert_array_equal(types.check_float(self.data2), self.data3, - err_msg='Float check failed') + """Test check_float.""" + npt.assert_array_equal( + types.check_float(1.0), + 1.0, + err_msg='Float check failed', + ) + + npt.assert_array_equal( + types.check_float(1), + 1.0, + err_msg='Float check failed', + ) + + npt.assert_array_equal( + types.check_float(self.data1), + self.data3, + err_msg='Float check failed', + ) + + npt.assert_array_equal( + types.check_float(self.data2), + self.data3, + err_msg='Float check failed', + ) npt.assert_raises(TypeError, types.check_float, '1') def test_check_int(self): - - npt.assert_array_equal(types.check_int(1), 1, - err_msg='Float check failed') - - npt.assert_array_equal(types.check_int(1.0), 1, - err_msg='Float check failed') - - npt.assert_array_equal(types.check_int(self.data1), self.data2, - err_msg='Float check failed') - - npt.assert_array_equal(types.check_int(self.data3), self.data2, - err_msg='Int check failed') + """Test check_int.""" + npt.assert_array_equal( + types.check_int(1), + 1, + err_msg='Float check failed', + ) + + npt.assert_array_equal( + types.check_int(1.0), + 1, + err_msg='Float check failed', + ) + + npt.assert_array_equal( + types.check_int(self.data1), + self.data2, + err_msg='Float check failed', + ) + + npt.assert_array_equal( + types.check_int(self.data3), + self.data2, + err_msg='Int check failed', + ) npt.assert_raises(TypeError, types.check_int, '1') def test_check_npndarray(self): - - npt.assert_raises(TypeError, types.check_npndarray, self.data3, - dtype=np.integer) + """Test check_npndarray.""" + npt.assert_raises( + TypeError, + types.check_npndarray, + self.data3, + dtype=np.integer, + ) diff --git a/modopt/tests/test_math.py b/modopt/tests/test_math.py index 9aa76f44..99908e02 100644 --- a/modopt/tests/test_math.py +++ b/modopt/tests/test_math.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -"""UNIT TESTS FOR MATH +"""UNIT TESTS FOR MATH. This module contains unit tests for the modopt.math module. @@ -9,10 +9,12 @@ """ from unittest import TestCase, skipIf, skipUnless + import numpy as np import numpy.testing as npt -import sys -from modopt.math import * + +from modopt.math import convolve, matrix, metrics, stats + try: import astropy except ImportError: # pragma: no cover @@ -20,10 +22,7 @@ else: # pragma: no cover import_astropy = True try: - if sys.version_info.minor == 5: - from skimage.measure import compare_ssim - elif sys.version_info.minor > 5: - from skimage.metrics import structural_similarity as compare_ssim + from skimage.metrics import structural_similarity as compare_ssim except ImportError: # pragma: no cover import_skimage = False else: @@ -31,178 +30,240 @@ class ConvolveTestCase(TestCase): + """Test case for convolve module.""" def setUp(self): - + """Set test parameter values.""" self.data1 = np.arange(18).reshape(2, 3, 3) self.data2 = self.data1 + 1 def tearDown(self): - + """Unset test parameter values.""" self.data1 = None self.data2 = None @skipUnless(import_astropy, 'Astropy not installed.') # pragma: no cover def test_convolve_astropy(self): - - npt.assert_allclose(convolve.convolve(self.data1[0], self.data2[0], - method='astropy'), - np.array([[210., 201., 210.], - [129., 120., 129.], - [210., 201., 210.]]), - err_msg='Incorrect convolution: astropy') - - npt.assert_raises(ValueError, convolve.convolve, self.data1[0], - self.data2) - - npt.assert_raises(ValueError, convolve.convolve, self.data1[0], - self.data2[0], method='bla') + """Test convolve using astropy.""" + npt.assert_allclose( + convolve.convolve(self.data1[0], self.data2[0], method='astropy'), + np.array([ + [210.0, 201.0, 210.0], + [129.0, 120.0, 129.0], + [210.0, 201.0, 210.0], + ]), + err_msg='Incorrect convolution: astropy', + ) + + npt.assert_raises( + ValueError, + convolve.convolve, + self.data1[0], + self.data2, + ) + + npt.assert_raises( + ValueError, + convolve.convolve, + self.data1[0], + self.data2[0], + method='bla', + ) def test_convolve_scipy(self): - - npt.assert_allclose(convolve.convolve(self.data1[0], self.data2[0], - method='scipy'), - np.array([[14., 35., 38.], [57., 120., 111.], - [110., 197., 158.]]), - err_msg='Incorrect convolution: scipy') + """Test convolve using scipy.""" + npt.assert_allclose( + convolve.convolve(self.data1[0], self.data2[0], method='scipy'), + np.array([ + [14.0, 35.0, 38.0], + [57.0, 120.0, 111.0], + [110.0, 197.0, 158.0], + ]), + err_msg='Incorrect convolution: scipy', + ) def test_convolve_stack(self): - - npt.assert_allclose(convolve.convolve_stack(self.data1, self.data2), - np.array([[[14., 35., 38.], - [57., 120., 111.], - [110., 197., 158.]], - [[518., 845., 614.], - [975., 1578., 1137.], - [830., 1331., 950.]]]), - err_msg='Incorrect convolution: stack') + """Test convolve_stack.""" + npt.assert_allclose( + convolve.convolve_stack(self.data1, self.data2), + np.array([ + [ + [14.0, 35.0, 38.0], + [57.0, 120.0, 111.0], + [110.0, 197.0, 158.0], + ], + [ + [518.0, 845.0, 614.0], + [975.0, 1578.0, 1137.0], + [830.0, 1331.0, 950.0], + ], + ]), + err_msg='Incorrect convolution: stack', + ) def test_convolve_stack_rot(self): - - npt.assert_allclose(convolve.convolve_stack(self.data1, self.data2, - rot_kernel=True), - np.array([[[66., 115., 82.], - [153., 240., 159.], - [90., 133., 82.]], - [[714., 1087., 730.], - [1125., 1698., 1131.], - [738., 1105., 730.]]]), - err_msg='Incorrect convolution: stack rot') + """Test convolve_stack rotated.""" + npt.assert_allclose( + convolve.convolve_stack(self.data1, self.data2, rot_kernel=True), + np.array([ + [ + [66.0, 115.0, 82.0], + [153.0, 240.0, 159.0], + [90.0, 133.0, 82.0], + ], + [ + [714.0, 1087.0, 730.0], + [1125.0, 1698.0, 1131.0], + [738.0, 1105.0, 730.0], + ], + ]), + err_msg='Incorrect convolution: stack rot', + ) class MatrixTestCase(TestCase): + """Test case for matrix module.""" def setUp(self): - + """Set test parameter values.""" self.data1 = np.arange(9).reshape(3, 3) self.data2 = np.arange(3) self.data3 = np.arange(6).reshape(2, 3) np.random.seed(1) - self.pmInstance1 = matrix.PowerMethod(lambda x: x.dot(x.T), - self.data1.shape, verbose=True) + self.pmInstance1 = matrix.PowerMethod( + lambda x_val: x_val.dot(x_val.T), + self.data1.shape, + verbose=True, + ) np.random.seed(1) - self.pmInstance2 = matrix.PowerMethod(lambda x: x.dot(x.T), - self.data1.shape, auto_run=False, - verbose=True) + self.pmInstance2 = matrix.PowerMethod( + lambda x_val: x_val.dot(x_val.T), + self.data1.shape, + auto_run=False, + verbose=True, + ) self.pmInstance2.get_spec_rad(max_iter=1) + self.gram_schmidt_out = ( + np.array([ + [0, 1.0, 2.0], + [3.0, 1.2, -6e-1], + [-1.77635684e-15, 0, 0], + ]), + np.array([ + [0, 0.4472136, 0.89442719], + [0.91287093, 0.36514837, -0.18257419], + [-1.0, 0, 0], + ]), + ) def tearDown(self): - + """Unset test parameter values.""" self.data1 = None self.data2 = None + self.data3 = None + self.pmInstance1 = None + self.pmInstance2 = None + self.gram_schmidt_out = None def test_gram_schmidt_orthonormal(self): - - npt.assert_allclose(matrix.gram_schmidt(self.data1), - np.array([[0., 0.4472136, 0.89442719], - [0.91287093, 0.36514837, -0.18257419], - [-1., 0., 0.]]), - err_msg='Incorrect Gram-Schmidt: orthonormal') - - npt.assert_raises(ValueError, matrix.gram_schmidt, self.data1, - return_opt='bla') + """Test gram_schmidt with orthonormal output.""" + npt.assert_allclose( + matrix.gram_schmidt(self.data1), + self.gram_schmidt_out[1], + err_msg='Incorrect Gram-Schmidt: orthonormal', + ) + + npt.assert_raises( + ValueError, + matrix.gram_schmidt, + self.data1, + return_opt='bla', + ) def test_gram_schmidt_orthogonal(self): - - npt.assert_allclose(matrix.gram_schmidt(self.data1, - return_opt='orthogonal'), - np.array([[0.00000000e+00, 1.00000000e+00, - 2.00000000e+00], - [3.00000000e+00, 1.20000000e+00, - -6.00000000e-01], - [-1.77635684e-15, 0.00000000e+00, - 0.00000000e+00]]), - err_msg='Incorrect Gram-Schmidt: orthogonal') + """Test gram_schmidt with orthogonal output.""" + npt.assert_allclose( + matrix.gram_schmidt(self.data1, return_opt='orthogonal'), + self.gram_schmidt_out[0], + err_msg='Incorrect Gram-Schmidt: orthogonal', + ) def test_gram_schmidt_both(self): - - npt.assert_allclose(matrix.gram_schmidt(self.data1, return_opt='both'), - (np.array([[0.00000000e+00, 1.00000000e+00, - 2.00000000e+00], - [3.00000000e+00, 1.20000000e+00, - -6.00000000e-01], - [-1.77635684e-15, 0.00000000e+00, - 0.00000000e+00]]), - np.array([[0., 0.4472136, 0.89442719], - [0.91287093, 0.36514837, -0.18257419], - [-1., 0., 0.]])), - err_msg='Incorrect Gram-Schmidt: both') + """Test gram_schmidt with both outputs.""" + npt.assert_allclose( + matrix.gram_schmidt(self.data1, return_opt='both'), + self.gram_schmidt_out, + err_msg='Incorrect Gram-Schmidt: both', + ) def test_nuclear_norm(self): - - npt.assert_almost_equal(matrix.nuclear_norm(self.data1), - 15.49193338482967, - err_msg='Incorrect nuclear norm') + """Test nuclear_norm.""" + npt.assert_almost_equal( + matrix.nuclear_norm(self.data1), + 15.49193338482967, + err_msg='Incorrect nuclear norm', + ) def test_project(self): - - npt.assert_array_equal(matrix.project(self.data2, self.data2 + 3), - np.array([0., 2.8, 5.6]), - err_msg='Incorrect projection') + """Test project.""" + npt.assert_array_equal( + matrix.project(self.data2, self.data2 + 3), + np.array([0, 2.8, 5.6]), + err_msg='Incorrect projection', + ) def test_rot_matrix(self): - - npt.assert_allclose(matrix.rot_matrix(np.pi / 6), - np.array([[0.8660254, -0.5], - [0.5, 0.8660254]]), - err_msg='Incorrect rotation matrix') + """Test rot_matrix.""" + npt.assert_allclose( + matrix.rot_matrix(np.pi / 6), + np.array([[0.8660254, -0.5], [0.5, 0.8660254]]), + err_msg='Incorrect rotation matrix', + ) def test_rotate(self): - - npt.assert_array_equal(matrix.rotate(self.data1, np.pi / 2), - np.array([[2, 5, 8], [1, 4, 7], [0, 3, 6]]), - err_msg='Incorrect rotation') + """Test rotate.""" + npt.assert_array_equal( + matrix.rotate(self.data1, np.pi / 2), + np.array([[2, 5, 8], [1, 4, 7], [0, 3, 6]]), + err_msg='Incorrect rotation', + ) npt.assert_raises(ValueError, matrix.rotate, self.data3, np.pi / 2) - def test_PowerMethod_converged(self): - - npt.assert_almost_equal(self.pmInstance1.spec_rad, - 0.90429242629600837, - err_msg='Incorrect spectral radius: converged') - - npt.assert_almost_equal(self.pmInstance1.inv_spec_rad, - 1.1058369736612865, - err_msg='Incorrect inverse spectral radius: ' - 'converged') - - def test_PowerMethod_unconverged(self): - - npt.assert_almost_equal(self.pmInstance2.spec_rad, - 0.92048833577059219, - err_msg='Incorrect spectral radius: ' - 'unconverged') - - npt.assert_almost_equal(self.pmInstance2.inv_spec_rad, - 1.0863798715741946, - err_msg='Incorrect inverse spectral radius: ' - 'unconverged') + def test_powermethod_converged(self): + """Test PowerMethod converged.""" + npt.assert_almost_equal( + self.pmInstance1.spec_rad, + 0.90429242629600837, + err_msg='Incorrect spectral radius: converged', + ) + + npt.assert_almost_equal( + self.pmInstance1.inv_spec_rad, + 1.1058369736612865, + err_msg='Incorrect inverse spectral radius: converged', + ) + + def test_powermethod_unconverged(self): + """Test PowerMethod unconverged.""" + npt.assert_almost_equal( + self.pmInstance2.spec_rad, + 0.92048833577059219, + err_msg='Incorrect spectral radius: unconverged', + ) + + npt.assert_almost_equal( + self.pmInstance2.inv_spec_rad, + 1.0863798715741946, + err_msg='Incorrect inverse spectral radius: unconverged', + ) class MetricsTestCase(TestCase): + """Test case for metrics module.""" def setUp(self): - + """Set test parameter values.""" self.data1 = np.arange(49).reshape(7, 7) self.mask = np.ones(self.data1.shape) self.ssim_res = 0.8963363560519094 @@ -213,7 +274,7 @@ def setUp(self): self.nrmse_res = 0.31136678840022625 def tearDown(self): - + """Unset test parameter values.""" self.data1 = None self.mask = None self.ssim_res = None @@ -224,149 +285,212 @@ def tearDown(self): @skipIf(import_skimage, 'skimage is installed.') # pragma: no cover def test_ssim_skimage_error(self): - + """Test ssim skimage error.""" npt.assert_raises(ImportError, metrics.ssim, self.data1, self.data1) @skipUnless(import_skimage, 'skimage not installed.') # pragma: no cover def test_ssim(self): - - npt.assert_almost_equal(metrics.ssim(self.data1, self.data1 ** 2), - self.ssim_res, - err_msg='Incorrect SSIM result') - - npt.assert_almost_equal(metrics.ssim(self.data1, self.data1 ** 2, - mask=self.mask), self.ssim_mask_res, - err_msg='Incorrect SSIM result') - - npt.assert_raises(ValueError, metrics.ssim, self.data1, self.data1, - mask=1) + """Test ssim.""" + npt.assert_almost_equal( + metrics.ssim(self.data1, self.data1 ** 2), + self.ssim_res, + err_msg='Incorrect SSIM result', + ) + + npt.assert_almost_equal( + metrics.ssim(self.data1, self.data1 ** 2, mask=self.mask), + self.ssim_mask_res, + err_msg='Incorrect SSIM result', + ) + + npt.assert_raises( + ValueError, + metrics.ssim, + self.data1, + self.data1, + mask=1, + ) def test_snr(self): - - npt.assert_almost_equal(metrics.snr(self.data1, self.data1 ** 2), - self.snr_res, - err_msg='Incorrect SNR result') - - npt.assert_almost_equal(metrics.snr(self.data1, self.data1 ** 2, - mask=self.mask), self.snr_res, - err_msg='Incorrect SNR result') + """Test snr.""" + npt.assert_almost_equal( + metrics.snr(self.data1, self.data1 ** 2), + self.snr_res, + err_msg='Incorrect SNR result', + ) + + npt.assert_almost_equal( + metrics.snr(self.data1, self.data1 ** 2, mask=self.mask), + self.snr_res, + err_msg='Incorrect SNR result', + ) def test_psnr(self): - - npt.assert_almost_equal(metrics.psnr(self.data1, self.data1 ** 2), - self.psnr_res, - err_msg='Incorrect PSNR result') - - npt.assert_almost_equal(metrics.psnr(self.data1, self.data1 ** 2, - mask=self.mask), self.psnr_res, - err_msg='Incorrect PSNR result') + """Test psnr.""" + npt.assert_almost_equal( + metrics.psnr(self.data1, self.data1 ** 2), + self.psnr_res, + err_msg='Incorrect PSNR result', + ) + + npt.assert_almost_equal( + metrics.psnr(self.data1, self.data1 ** 2, mask=self.mask), + self.psnr_res, + err_msg='Incorrect PSNR result', + ) def test_mse(self): - - npt.assert_almost_equal(metrics.mse(self.data1, self.data1 ** 2), - self.mse_res, - err_msg='Incorrect MSE result') - - npt.assert_almost_equal(metrics.mse(self.data1, self.data1 ** 2, - mask=self.mask), self.mse_res, - err_msg='Incorrect MSE result') + """Test mse.""" + npt.assert_almost_equal( + metrics.mse(self.data1, self.data1 ** 2), + self.mse_res, + err_msg='Incorrect MSE result', + ) + + npt.assert_almost_equal( + metrics.mse(self.data1, self.data1 ** 2, mask=self.mask), + self.mse_res, + err_msg='Incorrect MSE result', + ) def test_nrmse(self): + """Test nrmse.""" + npt.assert_almost_equal( + metrics.nrmse(self.data1, self.data1 ** 2), + self.nrmse_res, + err_msg='Incorrect NRMSE result', + ) - npt.assert_almost_equal(metrics.nrmse(self.data1, self.data1 ** 2), - self.nrmse_res, - err_msg='Incorrect NRMSE result') - - npt.assert_almost_equal(metrics.nrmse(self.data1, self.data1 ** 2, - mask=self.mask), self.nrmse_res, - err_msg='Incorrect NRMSE result') + npt.assert_almost_equal( + metrics.nrmse(self.data1, self.data1 ** 2, mask=self.mask), + self.nrmse_res, + err_msg='Incorrect NRMSE result', + ) class StatsTestCase(TestCase): + """Test case for stats module.""" def setUp(self): - + """Set test parameter values.""" self.data1 = np.arange(9).reshape(3, 3) self.data2 = np.arange(18).reshape(2, 3, 3) def tearDown(self): - + """Unset test parameter values.""" self.data1 = None @skipIf(import_astropy, 'Astropy is installed.') # pragma: no cover def test_gaussian_kernel_astropy_error(self): - - npt.assert_raises(ImportError, stats.gaussian_kernel, - self.data1.shape, 1) + """Test gaussian_kernel astropy error.""" + npt.assert_raises( + ImportError, + stats.gaussian_kernel, + self.data1.shape, + 1, + ) @skipUnless(import_astropy, 'Astropy not installed.') # pragma: no cover def test_gaussian_kernel_max(self): - - npt.assert_allclose(stats.gaussian_kernel(self.data1.shape, 1), - np.array([[0.36787944, 0.60653066, 0.36787944], - [0.60653066, 1., 0.60653066], - [0.36787944, 0.60653066, 0.36787944]]), - err_msg='Incorrect gaussian kernel: max norm') - - npt.assert_raises(ValueError, stats.gaussian_kernel, - self.data1.shape, 1, norm='bla') + """Test gaussian_kernel with max norm.""" + npt.assert_allclose( + stats.gaussian_kernel(self.data1.shape, 1), + np.array([ + [0.36787944, 0.60653066, 0.36787944], + [0.60653066, 1.0, 0.60653066], + [0.36787944, 0.60653066, 0.36787944], + ]), + err_msg='Incorrect gaussian kernel: max norm', + ) + + npt.assert_raises( + ValueError, + stats.gaussian_kernel, + self.data1.shape, + 1, + norm='bla', + ) @skipUnless(import_astropy, 'Astropy not installed.') # pragma: no cover def test_gaussian_kernel_sum(self): - - npt.assert_allclose(stats.gaussian_kernel(self.data1.shape, 1, - norm='sum'), - np.array([[0.07511361, 0.1238414, 0.07511361], - [0.1238414, 0.20417996, 0.1238414], - [0.07511361, 0.1238414, 0.07511361]]), - err_msg='Incorrect gaussian kernel: sum norm') + """Test gaussian_kernel with sum norm.""" + npt.assert_allclose( + stats.gaussian_kernel(self.data1.shape, 1, norm='sum'), + np.array([ + [0.07511361, 0.1238414, 0.07511361], + [0.1238414, 0.20417996, 0.1238414], + [0.07511361, 0.1238414, 0.07511361], + ]), + err_msg='Incorrect gaussian kernel: sum norm', + ) @skipUnless(import_astropy, 'Astropy not installed.') # pragma: no cover def test_gaussian_kernel_none(self): - - npt.assert_allclose(stats.gaussian_kernel(self.data1.shape, 1, - norm='none'), - np.array([[0.05854983, 0.09653235, 0.05854983], - [0.09653235, 0.15915494, 0.09653235], - [0.05854983, 0.09653235, 0.05854983]]), - err_msg='Incorrect gaussian kernel: sum norm') + """Test gaussian_kernel with no norm.""" + npt.assert_allclose( + stats.gaussian_kernel(self.data1.shape, 1, norm='none'), + np.array([ + [0.05854983, 0.09653235, 0.05854983], + [0.09653235, 0.15915494, 0.09653235], + [0.05854983, 0.09653235, 0.05854983], + ]), + err_msg='Incorrect gaussian kernel: sum norm', + ) def test_mad(self): - - npt.assert_equal(stats.mad(self.data1), 2.0, - err_msg='Incorrect median absolute deviation') + """Test mad.""" + npt.assert_equal( + stats.mad(self.data1), + 2.0, + err_msg='Incorrect median absolute deviation', + ) def test_mse(self): - - npt.assert_equal(stats.mse(self.data1, self.data1 + 2), 4.0, - err_msg='Incorrect mean squared error') + """Test mse.""" + npt.assert_equal( + stats.mse(self.data1, self.data1 + 2), + 4.0, + err_msg='Incorrect mean squared error', + ) def test_psnr_starck(self): - - npt.assert_almost_equal(stats.psnr(self.data1, self.data1 + 2), - 12.041199826559248, - err_msg='Incorrect PSNR: starck') - - npt.assert_raises(ValueError, stats.psnr, self.data1, self.data1, - method='bla') + """Test psnr.""" + npt.assert_almost_equal( + stats.psnr(self.data1, self.data1 + 2), + 12.041199826559248, + err_msg='Incorrect PSNR: starck', + ) + + npt.assert_raises( + ValueError, + stats.psnr, + self.data1, + self.data1, + method='bla', + ) def test_psnr_wiki(self): - - npt.assert_almost_equal(stats.psnr(self.data1, self.data1 + 2, - method='wiki'), - 42.110203695399477, - err_msg='Incorrect PSNR: wiki') + """Test psnr wiki method.""" + npt.assert_almost_equal( + stats.psnr(self.data1, self.data1 + 2, method='wiki'), + 42.110203695399477, + err_msg='Incorrect PSNR: wiki', + ) def test_psnr_stack(self): - - npt.assert_almost_equal(stats.psnr_stack(self.data2, self.data2 + 2), - 12.041199826559248, - err_msg='Incorrect PSNR stack') + """Test psnr stack.""" + npt.assert_almost_equal( + stats.psnr_stack(self.data2, self.data2 + 2), + 12.041199826559248, + err_msg='Incorrect PSNR stack', + ) npt.assert_raises(ValueError, stats.psnr_stack, self.data1, self.data1) def test_sigma_mad(self): - - npt.assert_almost_equal(stats.sigma_mad(self.data1), - 2.9651999999999998, - err_msg='Incorrect sigma from MAD') + """Test sigma_mad.""" + npt.assert_almost_equal( + stats.sigma_mad(self.data1), + 2.9651999999999998, + err_msg='Incorrect sigma from MAD', + ) diff --git a/modopt/tests/test_opt.py b/modopt/tests/test_opt.py index c1e6c808..b6805006 100644 --- a/modopt/tests/test_opt.py +++ b/modopt/tests/test_opt.py @@ -1,18 +1,21 @@ # -*- coding: utf-8 -*- -"""UNIT TESTS FOR SIGNAL +"""UNIT TESTS FOR OPT. -This module contains unit tests for the modopt.signal module. +This module contains unit tests for the modopt.opt module. :Author: Samuel Farrens """ +from builtins import zip from unittest import TestCase, skipIf, skipUnless + import numpy as np import numpy.testing as npt -from builtins import zip -from modopt.opt import * + +from modopt.opt import algorithms, cost, gradient, linear, proximity, reweight + try: import sklearn except ImportError: # pragma: no cover @@ -21,94 +24,148 @@ import_sklearn = True -class dummy(object): +# Basic functions to be used as operators or as dummy functions +func_identity = lambda x_val: x_val +func_double = lambda x_val: x_val * 2 +func_sq = lambda x_val: x_val ** 2 +func_cube = lambda x_val: x_val ** 3 + + +class Dummy(object): + """Dummy class for tests.""" + pass class AlgorithmTestCase(TestCase): + """Test case for algorithms module.""" def setUp(self): - + """Set test parameter values.""" self.data1 = np.arange(9).reshape(3, 3).astype(float) self.data2 = self.data1 + np.random.randn(*self.data1.shape) * 1e-6 self.data3 = np.arange(9).reshape(3, 3).astype(float) + 1 - grad_inst = gradient.GradBasic(self.data1, lambda x: x, lambda x: x) + + grad_inst = gradient.GradBasic( + self.data1, + func_identity, + func_identity, + ) + prox_inst = proximity.Positivity() prox_dual_inst = proximity.IdentityProx() linear_inst = linear.Identity() reweight_inst = reweight.cwbReweight(self.data3) cost_inst = cost.costObj([grad_inst, prox_inst, prox_dual_inst]) self.setup = algorithms.SetUp() - self.fb1 = algorithms.ForwardBackward(self.data1, - grad=grad_inst, - prox=prox_inst, - beta_update=lambda x: x) - self.fb2 = algorithms.ForwardBackward(self.data1, - grad=grad_inst, - prox=prox_inst, - cost=cost_inst, - lambda_update=None) - self.fb3 = algorithms.ForwardBackward(self.data1, - grad=grad_inst, - prox=prox_inst, - beta_update=lambda x: x, - a_cd=3) - self.fb4 = algorithms.ForwardBackward(self.data1, - grad=grad_inst, - prox=prox_inst, - beta_update=lambda x: x, - r_lazy=3, - p_lazy=0.7, - q_lazy=0.7) - self.fb5 = algorithms.ForwardBackward(self.data1, - grad=grad_inst, - prox=prox_inst, - restart_strategy='adaptive', - xi_restart=0.9) - self.fb6 = algorithms.ForwardBackward(self.data1, - grad=grad_inst, - prox=prox_inst, - restart_strategy='greedy', - xi_restart=0.9, - min_beta=1.0, - s_greedy=1.1) - self.gfb1 = algorithms.GenForwardBackward(self.data1, - grad=grad_inst, - prox_list=[prox_inst, - prox_dual_inst], - gamma_update=lambda x: x, - lambda_update=lambda x: x) - self.gfb2 = algorithms.GenForwardBackward(self.data1, - grad=grad_inst, - prox_list=[prox_inst, - prox_dual_inst], - cost=cost_inst) - self.gfb3 = algorithms.GenForwardBackward(self.data1, - grad=grad_inst, - prox_list=[prox_inst, - prox_dual_inst], - cost=cost_inst, - step_size=2) - self.condat1 = algorithms.Condat(self.data1, self.data2, - grad=grad_inst, - prox=prox_inst, - prox_dual=prox_dual_inst, - sigma_update=lambda x: x, - tau_update=lambda x: x, - rho_update=lambda x: x) - self.condat2 = algorithms.Condat(self.data1, self.data2, - grad=grad_inst, - prox=prox_inst, - prox_dual=prox_dual_inst, - linear=linear_inst, - cost=cost_inst, - reweight=reweight_inst) - self.condat3 = algorithms.Condat(self.data1, self.data2, - grad=grad_inst, - prox=prox_inst, - prox_dual=prox_dual_inst, - linear=dummy(), - cost=cost_inst, auto_iterate=False) + + self.fb1 = algorithms.ForwardBackward( + self.data1, + grad=grad_inst, + prox=prox_inst, + beta_update=func_identity, + ) + + self.fb2 = algorithms.ForwardBackward( + self.data1, + grad=grad_inst, + prox=prox_inst, + cost=cost_inst, + lambda_update=None, + ) + + self.fb3 = algorithms.ForwardBackward( + self.data1, + grad=grad_inst, + prox=prox_inst, + beta_update=func_identity, + a_cd=3, + ) + + self.fb4 = algorithms.ForwardBackward( + self.data1, + grad=grad_inst, + prox=prox_inst, + beta_update=func_identity, + r_lazy=3, + p_lazy=0.7, + q_lazy=0.7, + ) + + self.fb5 = algorithms.ForwardBackward( + self.data1, + grad=grad_inst, + prox=prox_inst, + restart_strategy='adaptive', + xi_restart=0.9, + ) + + self.fb6 = algorithms.ForwardBackward( + self.data1, + grad=grad_inst, + prox=prox_inst, + restart_strategy='greedy', + xi_restart=0.9, + min_beta=1.0, + s_greedy=1.1, + ) + + self.gfb1 = algorithms.GenForwardBackward( + self.data1, + grad=grad_inst, + prox_list=[prox_inst, prox_dual_inst], + gamma_update=func_identity, + lambda_update=func_identity, + ) + + self.gfb2 = algorithms.GenForwardBackward( + self.data1, + grad=grad_inst, + prox_list=[prox_inst, prox_dual_inst], + cost=cost_inst, + ) + + self.gfb3 = algorithms.GenForwardBackward( + self.data1, + grad=grad_inst, + prox_list=[prox_inst, prox_dual_inst], + cost=cost_inst, + step_size=2, + ) + + self.condat1 = algorithms.Condat( + self.data1, + self.data2, + grad=grad_inst, + prox=prox_inst, + prox_dual=prox_dual_inst, + sigma_update=func_identity, + tau_update=func_identity, + rho_update=func_identity, + ) + + self.condat2 = algorithms.Condat( + self.data1, + self.data2, + grad=grad_inst, + prox=prox_inst, + prox_dual=prox_dual_inst, + linear=linear_inst, + cost=cost_inst, + reweight=reweight_inst, + ) + + self.condat3 = algorithms.Condat( + self.data1, + self.data2, + grad=grad_inst, + prox=prox_inst, + prox_dual=prox_dual_inst, + linear=Dummy(), + cost=cost_inst, + auto_iterate=False, + ) + self.pogm1 = algorithms.POGM( u=self.data1, x=self.data1, @@ -117,12 +174,13 @@ def setUp(self): grad=grad_inst, prox=prox_inst, ) - self.dummy = dummy() - self.dummy.cost = lambda x: x + + self.dummy = Dummy() + self.dummy.cost = func_identity self.setup._check_operator(self.dummy.cost) def tearDown(self): - + """Unset test parameter values.""" self.data1 = None self.data2 = None self.setup = None @@ -136,7 +194,7 @@ def tearDown(self): self.dummy = None def test_set_up(self): - + """Test set_up.""" npt.assert_raises(TypeError, self.setup._check_input_data, 1) npt.assert_raises(TypeError, self.setup._check_param, 1) @@ -144,61 +202,121 @@ def test_set_up(self): npt.assert_raises(TypeError, self.setup._check_param_update, 1) def test_forward_backward(self): + """Test forward_backward.""" + npt.assert_array_equal( + self.fb1.x_final, + self.data1, + err_msg='Incorrect ForwardBackward result.', + ) - npt.assert_array_equal(self.fb1.x_final, self.data1, - err_msg='Incorrect ForwardBackward result.') - - npt.assert_array_equal(self.fb2.x_final, self.data1, - err_msg='Incorrect ForwardBackward result.') + npt.assert_array_equal( + self.fb2.x_final, + self.data1, + err_msg='Incorrect ForwardBackward result.', + ) - npt.assert_array_equal(self.fb3.x_final, self.data1, - err_msg='Incorrect ForwardBackward result.') + npt.assert_array_equal( + self.fb3.x_final, + self.data1, + err_msg='Incorrect ForwardBackward result.', + ) - npt.assert_array_equal(self.fb4.x_final, self.data1, - err_msg='Incorrect ForwardBackward result.') + npt.assert_array_equal( + self.fb4.x_final, + self.data1, + err_msg='Incorrect ForwardBackward result.', + ) - npt.assert_array_equal(self.fb5.x_final, self.data1, - err_msg='Incorrect ForwardBackward result.') + npt.assert_array_equal( + self.fb5.x_final, + self.data1, + err_msg='Incorrect ForwardBackward result.', + ) - npt.assert_array_equal(self.fb6.x_final, self.data1, - err_msg='Incorrect ForwardBackward result.') + npt.assert_array_equal( + self.fb6.x_final, + self.data1, + err_msg='Incorrect ForwardBackward result.', + ) def test_gen_forward_backward(self): + """Test gen_forward_backward.""" + npt.assert_array_equal( + self.gfb1.x_final, + self.data1, + err_msg='Incorrect GenForwardBackward result.', + ) - npt.assert_array_equal(self.gfb1.x_final, self.data1, - err_msg='Incorrect GenForwardBackward result.') - - npt.assert_array_equal(self.gfb2.x_final, self.data1, - err_msg='Incorrect GenForwardBackward result.') + npt.assert_array_equal( + self.gfb2.x_final, + self.data1, + err_msg='Incorrect GenForwardBackward result.', + ) - npt.assert_array_equal(self.gfb3.x_final, self.data1, - err_msg='Incorrect GenForwardBackward result.') + npt.assert_array_equal( + self.gfb3.x_final, + self.data1, + err_msg='Incorrect GenForwardBackward result.', + ) - npt.assert_equal(self.gfb3.step_size, 2, - err_msg='Incorrect step size.') + npt.assert_equal( + self.gfb3.step_size, + 2, + err_msg='Incorrect step size.', + ) - npt.assert_raises(TypeError, algorithms.GenForwardBackward, - self.data1, self.dummy, [self.dummy], weights=1) + npt.assert_raises( + TypeError, + algorithms.GenForwardBackward, + self.data1, + self.dummy, + [self.dummy], + weights=1, + ) - npt.assert_raises(ValueError, algorithms.GenForwardBackward, - self.data1, self.dummy, [self.dummy], weights=[1]) + npt.assert_raises( + ValueError, + algorithms.GenForwardBackward, + self.data1, + self.dummy, + [self.dummy], + weights=[1], + ) - npt.assert_raises(ValueError, algorithms.GenForwardBackward, - self.data1, self.dummy, [self.dummy], - weights=[0.5, 0.5]) + npt.assert_raises( + ValueError, + algorithms.GenForwardBackward, + self.data1, + self.dummy, + [self.dummy], + weights=[0.5, 0.5], + ) - npt.assert_raises(ValueError, algorithms.GenForwardBackward, - self.data1, self.dummy, [self.dummy], weights=[0.5]) + npt.assert_raises( + ValueError, + algorithms.GenForwardBackward, + self.data1, + self.dummy, + [self.dummy], + weights=[0.5], + ) def test_condat(self): + """Test gen_condat.""" + npt.assert_almost_equal( + self.condat1.x_final, + self.data1, + err_msg='Incorrect Condat result.', + ) - npt.assert_almost_equal(self.condat1.x_final, self.data1, - err_msg='Incorrect Condat result.') - - npt.assert_almost_equal(self.condat2.x_final, self.data1, - err_msg='Incorrect Condat result.') + npt.assert_almost_equal( + self.condat2.x_final, + self.data1, + err_msg='Incorrect Condat result.', + ) def test_pogm(self): + """Test pogm.""" npt.assert_almost_equal( self.pogm1.x_final, self.data1, @@ -207,39 +325,50 @@ def test_pogm(self): class CostTestCase(TestCase): + """Test case for cost module.""" def setUp(self): - - class dummy(object): - pass - - dummy_inst1 = dummy() - dummy_inst1.cost = lambda x: x ** 2 - dummy_inst2 = dummy() - dummy_inst2.cost = lambda x: x ** 3 + """Set test parameter values.""" + dummy_inst1 = Dummy() + dummy_inst1.cost = func_sq + dummy_inst2 = Dummy() + dummy_inst2.cost = func_cube self.inst1 = cost.costObj([dummy_inst1, dummy_inst2]) - [self.inst1.get_cost(2) for i in range(2)] self.inst2 = cost.costObj([dummy_inst1, dummy_inst2], cost_interval=2) - [self.inst2.get_cost(2) for i in range(6)] # Test that by default cost of False if interval is None - self.inst_none = cost.costObj([dummy_inst1, dummy_inst2], - cost_interval=None) - [self.inst_none.get_cost(2) for i in range(6)] - self.dummy = dummy() + self.inst_none = cost.costObj( + [dummy_inst1, dummy_inst2], + cost_interval=None, + ) + for _ in range(2): + self.inst1.get_cost(2) + for _ in range(6): + self.inst2.get_cost(2) + self.inst_none.get_cost(2) + self.dummy = Dummy() def tearDown(self): - + """Unset test parameter values.""" self.inst = None def test_cost_object(self): - - npt.assert_equal(self.inst1.get_cost(2), False, - err_msg='Incorrect cost test result.') - npt.assert_equal(self.inst1.get_cost(2), True, - err_msg='Incorrect cost test result.') - npt.assert_equal(self.inst_none.get_cost(2), False, - err_msg='Incorrect cost test result.') + """Test cost_object.""" + npt.assert_equal( + self.inst1.get_cost(2), + False, + err_msg='Incorrect cost test result.', + ) + npt.assert_equal( + self.inst1.get_cost(2), + True, + err_msg='Incorrect cost test result.', + ) + npt.assert_equal( + self.inst_none.get_cost(2), + False, + err_msg='Incorrect cost test result.', + ) npt.assert_equal(self.inst1.cost, 12, err_msg='Incorrect cost value.') @@ -251,84 +380,112 @@ def test_cost_object(self): class GradientTestCase(TestCase): + """Test case for gradient module.""" def setUp(self): - + """Set test parameter values.""" self.data1 = np.arange(9).reshape(3, 3).astype(float) - self.gp = gradient.GradParent(self.data1, lambda x: x ** 2, - lambda x: x ** 3, lambda x: x, - lambda x: 1.0, data_type=np.floating) + self.gp = gradient.GradParent( + self.data1, + func_sq, + func_cube, + func_identity, + lambda input_val: 1.0, + data_type=np.floating, + ) self.gp.grad = self.gp.get_grad(self.data1) - self.gb = gradient.GradBasic(self.data1, lambda x: x ** 2, - lambda x: x ** 3) + self.gb = gradient.GradBasic( + self.data1, + func_sq, + func_cube, + ) self.gb.get_grad(self.data1) def tearDown(self): - + """Unset test parameter values.""" self.data1 = None self.gp = None self.gb = None def test_grad_parent_operators(self): + """Test GradParent.""" + npt.assert_array_equal( + self.gp.op(self.data1), + np.array([[0, 1.0, 4.0], [9.0, 16.0, 25.0], [36.0, 49.0, 64.0]]), + err_msg='Incorrect gradient operation.', + ) - npt.assert_array_equal(self.gp.op(self.data1), np.array([[0., 1., 4.], - [9., 16., 25.], [36., 49., 64.]]), - err_msg='Incorrect gradient operation.') - - npt.assert_array_equal(self.gp.trans_op(self.data1), - np.array([[0., 1., 8.], [27., 64., 125.], - [216., 343., 512.]]), - err_msg='Incorrect gradient transpose ' - 'operation.') + npt.assert_array_equal( + self.gp.trans_op(self.data1), + np.array( + [[0, 1.0, 8.0], [27.0, 64.0, 125.0], [216.0, 343.0, 512.0]], + ), + err_msg='Incorrect gradient transpose operation.', + ) - npt.assert_array_equal(self.gp.trans_op_op(self.data1), - np.array([[0.00000000e+00, 1.00000000e+00, - 6.40000000e+01], - [7.29000000e+02, 4.09600000e+03, - 1.56250000e+04], - [4.66560000e+04, 1.17649000e+05, - 2.62144000e+05]]), - err_msg='Incorrect gradient transpose ' - 'operation operation.') + npt.assert_array_equal( + self.gp.trans_op_op(self.data1), + np.array([ + [0, 1.0, 6.40000000e1], + [7.29000000e2, 4.09600000e3, 1.56250000e4], + [4.66560000e4, 1.17649000e5, 2.62144000e5], + ]), + err_msg='Incorrect gradient transpose operation operation.', + ) - npt.assert_equal(self.gp.cost(self.data1), 1.0, - err_msg='Incorrect cost.') + npt.assert_equal( + self.gp.cost(self.data1), + 1.0, + err_msg='Incorrect cost.', + ) - npt.assert_raises(TypeError, gradient.GradParent, 1, - lambda x: x ** 2, lambda x: x ** 3) + npt.assert_raises( + TypeError, + gradient.GradParent, + 1, + func_sq, + func_cube, + ) def test_grad_basic_gradient(self): - - npt.assert_array_equal(self.gb.grad, - np.array([[0.00000000e+00, 0.00000000e+00, - 8.00000000e+00], - [2.16000000e+02, 1.72800000e+03, - 8.00000000e+03], - [2.70000000e+04, 7.40880000e+04, - 1.75616000e+05]]), - err_msg='Incorrect gradient.') + """Test GradBasic.""" + npt.assert_array_equal( + self.gb.grad, + np.array([ + [0, 0, 8.0], + [2.16000000e2, 1.72800000e3, 8.0e3], + [2.70000000e4, 7.40880000e4, 1.75616000e5], + ]), + err_msg='Incorrect gradient.', + ) class LinearTestCase(TestCase): + """Test case for linear module.""" def setUp(self): - - self.parent = linear.LinearParent(lambda x: x ** 2, lambda x: x ** 3) + """Set test parameter values.""" + self.parent = linear.LinearParent( + func_sq, + func_cube, + ) self.ident = linear.Identity() filters = np.arange(8).reshape(2, 2, 2).astype(float) self.wave = linear.WaveletConvolve(filters) self.combo = linear.LinearCombo([self.parent, self.parent]) - self.combo_weight = linear.LinearCombo([self.parent, self.parent], - [1.0, 1.0]) + self.combo_weight = linear.LinearCombo( + [self.parent, self.parent], + [1.0, 1.0], + ) self.data1 = np.arange(18).reshape(2, 3, 3).astype(float) self.data2 = np.arange(4).reshape(1, 2, 2).astype(float) self.data3 = np.arange(8).reshape(1, 2, 2, 2).astype(float) - self.data4 = np.array([[[[0., 0.], [0., 4.]], [[0., 4.], [8., 28.]]]]) - self.data5 = np.array([[[28., 62.], [68., 140.]]]) - self.dummy = dummy() + self.data4 = np.array([[[[0, 0], [0, 4.0]], [[0, 4.0], [8.0, 28.0]]]]) + self.data5 = np.array([[[28.0, 62.0], [68.0, 140.0]]]) + self.dummy = Dummy() def tearDown(self): - + """Unset test parameter values.""" self.parent = None self.ident = None self.combo = None @@ -341,41 +498,62 @@ def tearDown(self): self.dummy = None def test_linear_parent(self): + """Test LinearParent.""" + npt.assert_equal( + self.parent.op(2), + 4, + err_msg='Incorrect linear parent operation.', + ) - npt.assert_equal(self.parent.op(2), 4, err_msg='Incorrect linear ' - 'parent operation.') - - npt.assert_equal(self.parent.adj_op(2), 8, err_msg='Incorrect linear ' - 'parent adjoint ' - 'operation.') + npt.assert_equal( + self.parent.adj_op(2), + 8, + err_msg='Incorrect linear parent adjoint operation.', + ) npt.assert_raises(TypeError, linear.LinearParent, 0, 0) def test_identity(self): + """Test Identity.""" + npt.assert_equal( + self.ident.op(1.0), + 1.0, + err_msg='Incorrect identity operation.', + ) - npt.assert_equal(self.ident.op(1.0), 1.0, - err_msg='Incorrect identity operation.') - - npt.assert_equal(self.ident.adj_op(1.0), 1.0, - err_msg='Incorrect identity adjoint operation.') + npt.assert_equal( + self.ident.adj_op(1.0), + 1.0, + err_msg='Incorrect identity adjoint operation.', + ) def test_wavelet_convolve(self): + """Test WaveletConvolve.""" + npt.assert_almost_equal( + self.wave.op(self.data2), + self.data4, + err_msg='Incorrect wavelet convolution operation.', + ) - npt.assert_almost_equal(self.wave.op(self.data2), self.data4, - err_msg='Incorrect wavelet convolution ' - 'operation.') - - npt.assert_almost_equal(self.wave.adj_op(self.data3), self.data5, - err_msg='Incorrect wavelet convolution ' - 'adjoint operation.') + npt.assert_almost_equal( + self.wave.adj_op(self.data3), + self.data5, + err_msg='Incorrect wavelet convolution adjoint operation.', + ) def test_linear_combo(self): + """Test LinearCombo.""" + npt.assert_equal( + self.combo.op(2), + np.array([4, 4]).astype(object), + err_msg='Incorrect combined linear operation', + ) - npt.assert_equal(self.combo.op(2), np.array([4, 4]).astype(object), - err_msg='Incorrect combined linear operation') - - npt.assert_equal(self.combo.adj_op([2, 2]), 8.0, - err_msg='Incorrect combined linear adjoint operation') + npt.assert_equal( + self.combo.adj_op([2, 2]), + 8.0, + err_msg='Incorrect combined linear adjoint operation', + ) npt.assert_raises(TypeError, linear.LinearCombo, self.parent) @@ -383,40 +561,61 @@ def test_linear_combo(self): npt.assert_raises(ValueError, linear.LinearCombo, [self.dummy]) - self.dummy.op = lambda x: x + self.dummy.op = func_identity npt.assert_raises(ValueError, linear.LinearCombo, [self.dummy]) def test_linear_combo_weight(self): + """Test LinearCombo with weight .""" + npt.assert_equal( + self.combo_weight.op(2), + np.array([4, 4]).astype(object), + err_msg='Incorrect combined linear operation', + ) - npt.assert_equal(self.combo_weight.op(2), - np.array([4, 4]).astype(object), - err_msg='Incorrect combined linear operation') - - npt.assert_equal(self.combo_weight.adj_op([2, 2]), 16.0, - err_msg='Incorrect combined linear adjoint operation') + npt.assert_equal( + self.combo_weight.adj_op([2, 2]), + 16.0, + err_msg='Incorrect combined linear adjoint operation', + ) - npt.assert_raises(ValueError, linear.LinearCombo, - [self.parent, self.parent], [1.0]) + npt.assert_raises( + ValueError, + linear.LinearCombo, + [self.parent, self.parent], + [1.0], + ) - npt.assert_raises(TypeError, linear.LinearCombo, - [self.parent, self.parent], ['1', '1']) + npt.assert_raises( + TypeError, + linear.LinearCombo, + [self.parent, self.parent], + ['1', '1'], + ) class ProximityTestCase(TestCase): + """Test case for proximity module.""" def setUp(self): - - self.parent = proximity.ProximityParent(lambda x: x ** 2, - lambda x: x * 2) + """Set test parameter values.""" + self.parent = proximity.ProximityParent( + func_sq, + func_double, + ) self.identity = proximity.IdentityProx() self.positivity = proximity.Positivity() weights = np.ones(9).reshape(3, 3).astype(float) * 3 - self.sparsethresh = proximity.SparseThreshold(linear.Identity(), - weights) + self.sparsethresh = proximity.SparseThreshold( + linear.Identity(), + weights, + ) self.lowrank = proximity.LowRankMatrix(10.0, thresh_type='hard') - self.lowrank_ngole = proximity.LowRankMatrix(10.0, lowr_type='ngole', - operator=lambda x: x * 2) + self.lowrank_ngole = proximity.LowRankMatrix( + 10.0, + lowr_type='ngole', + operator=func_double, + ) self.linear_comp = proximity.LinearCompositionProx( linear_op=linear.Identity(), prox_op=self.sparsethresh, @@ -425,59 +624,76 @@ def setUp(self): if import_sklearn: self.owl = proximity.OrderedWeightedL1Norm(weights.flatten()) self.ridge = proximity.Ridge(linear.Identity(), weights) - self.elasticnet_alpha_0 = proximity.ElasticNet(linear.Identity(), - alpha=0, - beta=weights) - self.elasticnet_beta_0 = proximity.ElasticNet(linear.Identity(), - alpha=weights, - beta=0) + self.elasticnet_alpha0 = proximity.ElasticNet( + linear.Identity(), + alpha=0, + beta=weights, + ) + self.elasticnet_beta0 = proximity.ElasticNet( + linear.Identity(), + alpha=weights, + beta=0, + ) self.one_support = proximity.KSupportNorm(beta=0.2, k_value=1) self.five_support_norm = proximity.KSupportNorm(beta=3, k_value=5) self.d_support = proximity.KSupportNorm(beta=3.0 * 2, k_value=19) - self.group_lasso = proximity.GroupLASSO(weights=np.tile(weights, - (4, 1, 1))) + self.group_lasso = proximity.GroupLASSO( + weights=np.tile(weights, (4, 1, 1)), + ) self.data1 = np.arange(9).reshape(3, 3).astype(float) - self.data2 = np.array([[-0., -0., -0.], [0., 1., 2.], [3., 4., 5.]]) + self.data2 = np.array([[-0, -0, -0], [0, 1.0, 2.0], [3.0, 4.0, 5.0]]) self.data3 = np.arange(18).reshape(2, 3, 3).astype(float) - self.data4 = np.array([[[2.73843189, 3.14594066, 3.55344943], - [3.9609582, 4.36846698, 4.77597575], - [5.18348452, 5.59099329, 5.99850206]], - [[8.07085295, 9.2718846, 10.47291625], - [11.67394789, 12.87497954, 14.07601119], - [15.27704284, 16.47807449, 17.67910614]]]) - self.data5 = np.array([[[0., 0., 0.], [0., 0., 0.], [0., 0., 0.]], - [[4.00795282, 4.60438026, 5.2008077], - [5.79723515, 6.39366259, 6.99009003], - [7.58651747, 8.18294492, 8.77937236]]]) + self.data4 = np.array([ + [ + [2.73843189, 3.14594066, 3.55344943], + [3.9609582, 4.36846698, 4.77597575], + [5.18348452, 5.59099329, 5.99850206], + ], + [ + [8.07085295, 9.2718846, 10.47291625], + [11.67394789, 12.87497954, 14.07601119], + [15.27704284, 16.47807449, 17.67910614], + ], + ]) + self.data5 = np.array([ + [[0, 0, 0], [0, 0, 0], [0, 0, 0]], + [ + [4.00795282, 4.60438026, 5.2008077], + [5.79723515, 6.39366259, 6.99009003], + [7.58651747, 8.18294492, 8.77937236], + ], + ]) self.data6 = self.data3 * -1 self.data7 = self.combo.op(self.data6) self.data8 = np.empty(2, dtype=np.ndarray) - self.data8[0] = np.array([[-0., -1., -2.], [-3., -4., -5.], - [-6., -7., -8.]]) - self.data8[1] = np.array([[-0., -0., -0.], [-0., -0., -0.], - [-0., -0., -0.]]) + self.data8[0] = np.array( + [[-0, -1.0, -2.0], [-3.0, -4.0, -5.0], [-6.0, -7.0, -8.0]], + ) + self.data8[1] = np.array( + [[-0, -0, -0], [-0, -0, -0], [-0, -0, -0]], + ) self.data9 = self.data1 * (1 + 1j) self.data10 = self.data9 / (2 * 3 + 1) - self.data11 = np.asarray([[0., 0., 0.], - [0., 1., 1.25], - [1.5, 1.75, 2.]]) + self.data11 = np.asarray( + [[0, 0, 0], [0, 1.0, 1.25], [1.5, 1.75, 2.0]], + ) self.random_data = 3 * np.random.random( - self.group_lasso.weights[0].shape) + self.group_lasso.weights[0].shape, + ) self.random_data_tile = np.tile( self.random_data, - (self.group_lasso.weights.shape[0], 1, 1) + (self.group_lasso.weights.shape[0], 1, 1), ) self.gl_result_data = 2 * self.random_data_tile - 3 - self.gl_result_data = (self.gl_result_data * - (self.gl_result_data > 0).astype('int')) / 2 - - class dummy(object): - pass + self.gl_result_data = np.array( + (self.gl_result_data * (self.gl_result_data > 0).astype('int')) + / 2, + ) - self.dummy = dummy() + self.dummy = Dummy() def tearDown(self): - + """Unset test parameter values.""" self.parent = None self.identity = None self.positivity = None @@ -498,66 +714,109 @@ def tearDown(self): self.gl_result_data = None def test_proximity_parent(self): + """Test ProximityParent.""" + npt.assert_equal( + self.parent.op(3), + 9, + err_msg='Inccoret proximity parent operation.', + ) - npt.assert_equal(self.parent.op(3), 9, - err_msg='Inccoret proximity parent operation.') - - npt.assert_equal(self.parent.cost(3), 6, - err_msg='Inccoret proximity parent cost.') + npt.assert_equal( + self.parent.cost(3), + 6, + err_msg='Incorrect proximity parent cost.', + ) def test_identity(self): + """Test IdentityProx.""" + npt.assert_equal( + self.identity.op(3), + 3, + err_msg='Incorrect proximity identity operation.', + ) - npt.assert_equal(self.identity.op(3), 3, - err_msg='Inccoret proximity identity operation.') - - npt.assert_equal(self.identity.cost(3), 0.0, - err_msg='Inccoret proximity identity cost.') + npt.assert_equal( + self.identity.cost(3), + 0, + err_msg='Incorrect proximity identity cost.', + ) def test_positivity(self): + """Test Positivity.""" + npt.assert_equal( + self.positivity.op(-3), + 0, + err_msg='Incorrect proximity positivity operation.', + ) - npt.assert_equal(self.positivity.op(-3), 0, - err_msg='Inccoret proximity positivity operation.') - - npt.assert_equal(self.positivity.cost(-3, verbose=True), 0.0, - err_msg='Inccoret proximity positivity cost.') + npt.assert_equal( + self.positivity.cost(-3, verbose=True), + 0, + err_msg='Incorrect proximity positivity cost.', + ) def test_sparse_threshold(self): + """Test SparseThreshold.""" + npt.assert_array_equal( + self.sparsethresh.op(self.data1), + self.data2, + err_msg='Incorrect sparse threshold operation.', + ) - npt.assert_array_equal(self.sparsethresh.op(self.data1), self.data2, - err_msg='Inccorect sparse threshold operation.') - - npt.assert_equal(self.sparsethresh.cost(self.data1, verbose=True), - 108.0, err_msg='Inccoret sparse threshold cost.') + npt.assert_equal( + self.sparsethresh.cost(self.data1, verbose=True), + 108.0, + err_msg='Incorrect sparse threshold cost.', + ) def test_low_rank_matrix(self): + """Test LowRankMatrix.""" + npt.assert_almost_equal( + self.lowrank.op(self.data3), + self.data4, + err_msg='Incorrect low rank operation: standard', + ) - npt.assert_almost_equal(self.lowrank.op(self.data3), self.data4, - err_msg='Inccorect low rank operation: ' - 'standard') - - npt.assert_almost_equal(self.lowrank_ngole.op(self.data3), self.data5, - err_msg='Inccorect low rank operation: ' - 'ngole') + npt.assert_almost_equal( + self.lowrank_ngole.op(self.data3), + self.data5, + err_msg='Incorrect low rank operation: ngole', + ) - npt.assert_almost_equal(self.lowrank.cost(self.data3, verbose=True), - 469.39132942464983, - err_msg='Inccoret low rank cost.') + npt.assert_almost_equal( + self.lowrank.cost(self.data3, verbose=True), + 469.39132942464983, + err_msg='Incorrect low rank cost.', + ) def test_linear_comp_prox(self): - npt.assert_array_equal(self.linear_comp.op(self.data1), self.data2, - err_msg='Inccorect sparse threshold operation.') + """Test LinearCompositionProx.""" + npt.assert_array_equal( + self.linear_comp.op(self.data1), + self.data2, + err_msg='Incorrect sparse threshold operation.', + ) - npt.assert_equal(self.linear_comp.cost(self.data1, verbose=True), - 108.0, err_msg='Inccoret sparse threshold cost.') + npt.assert_equal( + self.linear_comp.cost(self.data1, verbose=True), + 108.0, + err_msg='Incorrect sparse threshold cost.', + ) def test_proximity_combo(self): - + """Test ProximityCombo.""" for data7, data8 in zip(self.data7, self.data8): - npt.assert_array_equal(data7, data8, - err_msg='Inccorect combined operation') + npt.assert_array_equal( + data7, + data8, + err_msg='Incorrect combined operation', + ) - npt.assert_equal(self.combo.cost(self.data6), 0.0, - err_msg='Inccoret combined cost.') + npt.assert_equal( + self.combo.cost(self.data6), + 0, + err_msg='Incorrect combined cost.', + ) npt.assert_raises(TypeError, proximity.ProximityCombo, 1) @@ -565,132 +824,172 @@ def test_proximity_combo(self): npt.assert_raises(ValueError, proximity.ProximityCombo, [self.dummy]) - self.dummy.op = lambda x: x + self.dummy.op = func_identity npt.assert_raises(ValueError, proximity.ProximityCombo, [self.dummy]) @skipIf(import_sklearn, 'sklearn is installed.') # pragma: no cover def test_owl_sklearn_error(self): - + """Test OrderedWeightedL1Norm with Scikit-Learn.""" npt.assert_raises(ImportError, proximity.OrderedWeightedL1Norm, 1) @skipUnless(import_sklearn, 'sklearn not installed.') # pragma: no cover def test_sparse_owl(self): - + """Test OrderedWeightedL1Norm.""" npt.assert_array_equal( self.owl.op(self.data1.flatten()), self.data2.flatten(), - err_msg='Incorrect sparse threshold operation.') - - npt.assert_equal(self.owl.cost(self.data1.flatten(), verbose=True), - 108.0, err_msg='Incorret sparse threshold cost.') - npt.assert_raises(ValueError, proximity.OrderedWeightedL1Norm, - np.arange(10)) - - def test_ridge(self): + err_msg='Incorrect sparse threshold operation.', + ) - npt.assert_array_equal(self.ridge.op(self.data9), self.data10, - err_msg='Incorect shrinkage operation.') + npt.assert_equal( + self.owl.cost(self.data1.flatten(), verbose=True), + 108.0, + err_msg='Incorrect sparse threshold cost.', + ) - npt.assert_equal(self.ridge.cost(self.data9, verbose=True), - 408.0 * 3.0, err_msg='Incorect shrinkage cost.') + npt.assert_raises( + ValueError, + proximity.OrderedWeightedL1Norm, + np.arange(10), + ) - def test_elastic_net_alpha_0(self): + def test_ridge(self): + """Test Ridge.""" + npt.assert_array_equal( + self.ridge.op(self.data9), + self.data10, + err_msg='Incorect shrinkage operation.', + ) - npt.assert_array_equal(self.elasticnet_alpha_0.op(self.data1), - self.data2, - err_msg='Incorect sparse threshold operation' - ' ElasticNet class.') + npt.assert_equal( + self.ridge.cost(self.data9, verbose=True), + 408.0 * 3.0, + err_msg='Incorect shrinkage cost.', + ) - npt.assert_equal(self.elasticnet_alpha_0.cost(self.data1), - 108.0, err_msg='Incorect shrinkage cost in ElasticNet' - ' class.') + def test_elastic_net_alpha0(self): + """Test ElasticNet.""" + npt.assert_array_equal( + self.elasticnet_alpha0.op(self.data1), + self.data2, + err_msg='Incorect sparse threshold operation ElasticNet class.', + ) - def test_elastic_net_beta_0(self): + npt.assert_equal( + self.elasticnet_alpha0.cost(self.data1), + 108.0, + err_msg='Incorect shrinkage cost in ElasticNet class.', + ) - npt.assert_array_equal(self.elasticnet_beta_0.op(self.data9), - self.data10, - err_msg='Incorect ridge operation' - ' ElasticNet class.') + def test_elastic_net_beta0(self): + """Test ElasticNet with beta=0.""" + npt.assert_array_equal( + self.elasticnet_beta0.op(self.data9), + self.data10, + err_msg='Incorect ridge operation ElasticNet class.', + ) - npt.assert_equal(self.elasticnet_beta_0.cost(self.data9, - verbose=True), - 408.0 * 3.0, err_msg='Incorect shrinkage cost in' - ' ElasticNet class.') + npt.assert_equal( + self.elasticnet_beta0.cost(self.data9, verbose=True), + 408.0 * 3.0, + err_msg='Incorect shrinkage cost in ElasticNet class.', + ) def test_one_support_norm(self): + """Test KSupportNorm with k=1.""" + npt.assert_allclose( + self.one_support.op(self.data1.flatten()), + self.data2.flatten(), + err_msg='Incorect sparse threshold operation for 1-support norm', + rtol=1e-6, + ) - npt.assert_allclose(self.one_support.op(self.data1.flatten()), - self.data2.flatten(), - err_msg='Incorect sparse threshold operation' + - ' for 1-support norm', - rtol=1e-6) - - npt.assert_equal(self.one_support.cost(self.data1.flatten(), - verbose=True), - 259.2, err_msg='Incorect sparse threshold cost.') - - npt.assert_raises(ValueError, proximity.KSupportNorm, 0.0, 0) + npt.assert_equal( + self.one_support.cost(self.data1.flatten(), verbose=True), + 259.2, + err_msg='Incorect sparse threshold cost.', + ) - def test_three_support_norm(self): + npt.assert_raises(ValueError, proximity.KSupportNorm, 0, 0) - npt.assert_allclose(self.five_support_norm.op(self.data1.flatten()), - self.data11.flatten(), - err_msg='Incorect sparse Ksupport norm operation', - rtol=1e-6) + def test_five_support_norm(self): + """Test KSupportNorm with k=5.""" + npt.assert_allclose( + self.five_support_norm.op(self.data1.flatten()), + self.data11.flatten(), + err_msg='Incorect sparse Ksupport norm operation', + rtol=1e-6, + ) - npt.assert_equal(self.five_support_norm.cost(self.data1.flatten(), - verbose=True), - 684.0, err_msg='Inccoret 3-support norm cost.') + npt.assert_equal( + self.five_support_norm.cost(self.data1.flatten(), verbose=True), + 684.0, + err_msg='Incorrect 5-support norm cost.', + ) - npt.assert_raises(ValueError, proximity.KSupportNorm, 0.0, 0) + npt.assert_raises(ValueError, proximity.KSupportNorm, 0, 0) def test_d_support_norm(self): + """Test KSupportNorm with k=19.""" + npt.assert_allclose( + self.d_support.op(self.data9.flatten()), + self.data10.flatten(), + err_msg='Incorect shrinkage operation for d-support norm', + rtol=1e-6, + ) - npt.assert_allclose(self.d_support.op(self.data9.flatten()), - self.data10.flatten(), - err_msg='Incorect shrinkage operation' + - ' for d-support norm', - rtol=1e-6) - - npt.assert_almost_equal(self.d_support.cost(self.data9.flatten(), - verbose=True), - 408.0 * 3.0, - err_msg='Incorect shrinkage cost for' + - ' d-support norm.') + npt.assert_almost_equal( + self.d_support.cost(self.data9.flatten(), verbose=True), + 408.0 * 3.0, + err_msg='Incorrect shrinkage cost for d-support norm.', + ) - npt.assert_raises(ValueError, proximity.KSupportNorm, 0.0, 0) + npt.assert_raises(ValueError, proximity.KSupportNorm, 0, 0) def test_group_lasso(self): + """Test GroupLASSO.""" npt.assert_allclose( - self.group_lasso.op(self.random_data_tile), self.gl_result_data) - npt.assert_equal(self.group_lasso.cost(self.random_data_tile), - np.sum(6 * self.random_data_tile)) + self.group_lasso.op(self.random_data_tile), + self.gl_result_data, + ) + npt.assert_equal( + self.group_lasso.cost(self.random_data_tile), + np.sum(6 * self.random_data_tile), + ) # Check that for 0 weights operator doesnt change result self.group_lasso.weights = np.zeros_like(self.group_lasso.weights) npt.assert_equal( - self.group_lasso.op(self.random_data_tile), self.random_data_tile) + self.group_lasso.op(self.random_data_tile), + self.random_data_tile, + ) npt.assert_equal(self.group_lasso.cost(self.random_data_tile), 0) class ReweightTestCase(TestCase): + """Test case for reweight module.""" def setUp(self): - + """Set test parameter values.""" self.data1 = np.arange(9).reshape(3, 3).astype(float) + 1 - self.data2 = np.array([[0.5, 1., 1.5], [2., 2.5, 3.], [3.5, 4., 4.5]]) + self.data2 = np.array( + [[0.5, 1.0, 1.5], [2.0, 2.5, 3.0], [3.5, 4.0, 4.5]], + ) self.rw = reweight.cwbReweight(self.data1) self.rw.reweight(self.data1) def tearDown(self): - + """Unset test parameter values.""" self.data1 = None self.data2 = None self.rw = None - def test_cwbReweight(self): - - npt.assert_array_equal(self.rw.weights, self.data2, - err_msg='Incorrect CWB re-weighting.') + def test_cwbreweight(self): + """Test cwbReweight.""" + npt.assert_array_equal( + self.rw.weights, + self.data2, + err_msg='Incorrect CWB re-weighting.', + ) npt.assert_raises(ValueError, self.rw.reweight, self.data1[0]) diff --git a/modopt/tests/test_signal.py b/modopt/tests/test_signal.py index 2fa10125..7490b98c 100644 --- a/modopt/tests/test_signal.py +++ b/modopt/tests/test_signal.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -"""UNIT TESTS FOR SIGNAL +"""UNIT TESTS FOR SIGNAL. This module contains unit tests for the modopt.signal module. @@ -9,53 +9,68 @@ """ from unittest import TestCase + import numpy as np import numpy.testing as npt -from modopt.signal import * + +from modopt.signal import filter, noise, positivity, svd, validation, wavelet class FilterTestCase(TestCase): + """Test case for filter module.""" def test_guassian_filter(self): - - npt.assert_almost_equal(filter.Gaussian_filter(1, 1), - 0.24197072451914337, - err_msg='Incorrect Gaussian filter') - - npt.assert_almost_equal(filter.Gaussian_filter(1, 1, norm=False), - 0.60653065971263342, - err_msg='Incorrect Gaussian filter') + """Test guassian_filter.""" + npt.assert_almost_equal( + filter.gaussian_filter(1, 1), + 0.24197072451914337, + err_msg='Incorrect Gaussian filter', + ) + + npt.assert_almost_equal( + filter.gaussian_filter(1, 1, norm=False), + 0.60653065971263342, + err_msg='Incorrect Gaussian filter', + ) def test_mex_hat(self): - - npt.assert_almost_equal(filter.mex_hat(2, 1), - -0.35213905225713371, - err_msg='Incorrect Mexican hat filter') + """Test mex_hat.""" + npt.assert_almost_equal( + filter.mex_hat(2, 1), + -0.35213905225713371, + err_msg='Incorrect Mexican hat filter', + ) def test_mex_hat_dir(self): - - npt.assert_almost_equal(filter.mex_hat_dir(1, 2, 1), - 0.17606952612856686, - err_msg='Incorrect directional Mexican hat ' - 'filter') + """Test mex_hat_dir.""" + npt.assert_almost_equal( + filter.mex_hat_dir(1, 2, 1), + 0.17606952612856686, + err_msg='Incorrect directional Mexican hat filter', + ) class NoiseTestCase(TestCase): + """Test case for noise module.""" def setUp(self): - + """Set test parameter values.""" self.data1 = np.arange(9).reshape(3, 3).astype(float) - self.data2 = np.array([[0., 2., 2.], [4., 5., 10.], - [11., 15., 18.]]) - self.data3 = np.array([[1.62434536, 0.38824359, 1.47182825], - [1.92703138, 4.86540763, 2.6984613], - [7.74481176, 6.2387931, 8.3190391]]) - self.data4 = np.array([[0., 0., 0.], [0., 0., 5.], [6., 7., 8.]]) - self.data5 = np.array([[0., 0., 0.], [0., 0., 0.], - [1., 2., 3.]]) + self.data2 = np.array( + [[0, 2.0, 2.0], [4.0, 5.0, 10], [11.0, 15.0, 18.0]], + ) + self.data3 = np.array([ + [1.62434536, 0.38824359, 1.47182825], + [1.92703138, 4.86540763, 2.6984613], + [7.74481176, 6.2387931, 8.3190391], + ]) + self.data4 = np.array([[0, 0, 0], [0, 0, 5.0], [6.0, 7.0, 8.0]]) + self.data5 = np.array( + [[0, 0, 0], [0, 0, 0], [1.0, 2.0, 3.0]], + ) def tearDown(self): - + """Unset test parameter values.""" self.data1 = None self.data2 = None self.data3 = None @@ -63,114 +78,164 @@ def tearDown(self): self.data5 = None def test_add_noise_poisson(self): - + """Test add_noise with Poisson noise.""" np.random.seed(1) - npt.assert_array_equal(noise.add_noise(self.data1, - noise_type='poisson'), self.data2, - err_msg='Incorrect noise: Poisson') - - npt.assert_raises(ValueError, noise.add_noise, self.data1, - noise_type='bla') + npt.assert_array_equal( + noise.add_noise(self.data1, noise_type='poisson'), + self.data2, + err_msg='Incorrect noise: Poisson', + ) + + npt.assert_raises( + ValueError, + noise.add_noise, + self.data1, + noise_type='bla', + ) npt.assert_raises(ValueError, noise.add_noise, self.data1, (1, 1)) def test_add_noise_gaussian(self): - + """Test add_noise with Gaussian noise.""" np.random.seed(1) - npt.assert_almost_equal(noise.add_noise(self.data1), self.data3, - err_msg='Incorrect noise: Gaussian') + npt.assert_almost_equal( + noise.add_noise(self.data1), + self.data3, + err_msg='Incorrect noise: Gaussian', + ) np.random.seed(1) - npt.assert_almost_equal(noise.add_noise(self.data1, - sigma=(1, 1, 1)), self.data3, - err_msg='Incorrect noise: Gaussian') + npt.assert_almost_equal( + noise.add_noise(self.data1, sigma=(1, 1, 1)), + self.data3, + err_msg='Incorrect noise: Gaussian', + ) def test_thresh_hard(self): - - npt.assert_array_equal(noise.thresh(self.data1, 5), self.data4, - err_msg='Incorrect threshold: hard') - - npt.assert_raises(ValueError, noise.thresh, self.data1, 5, - threshold_type='bla') + """Test thresh with hard threshold.""" + npt.assert_array_equal( + noise.thresh(self.data1, 5), + self.data4, + err_msg='Incorrect threshold: hard', + ) + + npt.assert_raises( + ValueError, + noise.thresh, + self.data1, + 5, + threshold_type='bla', + ) def test_thresh_soft(self): - - npt.assert_array_equal(noise.thresh(self.data1, 5, - threshold_type='soft'), self.data5, - err_msg='Incorrect threshold: soft') + """Test thresh with soft threshold.""" + npt.assert_array_equal( + noise.thresh(self.data1, 5, threshold_type='soft'), + self.data5, + err_msg='Incorrect threshold: soft', + ) class PositivityTestCase(TestCase): + """Test case for positivity module.""" def setUp(self): - + """Set test parameter values.""" self.data1 = np.arange(9).reshape(3, 3) - 5 self.data2 = np.array([[0, 0, 0], [0, 0, 0], [1, 2, 3]]) - self.data3 = [np.arange(5) - 3, np.arange(4) - 2] - self.data4 = np.array([list([0, 0, 0, 0, 1]), list([0, 0, 0, 1])], - dtype=object) + self.data3 = np.array( + [np.arange(5) - 3, np.arange(4) - 2], + dtype=object, + ) + self.data4 = np.array( + [np.array([0, 0, 0, 0, 1]), np.array([0, 0, 0, 1])], + dtype=object, + ) + self.pos_dtype_obj = positivity.positive(self.data3) self.err = 'Incorrect positivity' def tearDown(self): - + """Unset test parameter values.""" self.data1 = None self.data2 = None def test_positivity(self): - + """Test positivity.""" npt.assert_equal(positivity.positive(-1), 0, err_msg=self.err) - npt.assert_equal(positivity.positive(-1.0), -0.0, err_msg=self.err) + npt.assert_equal( + positivity.positive(-1.0), + -float(0), + err_msg=self.err, + ) - npt.assert_equal(positivity.positive(self.data1), self.data2, - err_msg=self.err) + npt.assert_equal( + positivity.positive(self.data1), + self.data2, + err_msg=self.err, + ) - npt.assert_equal(positivity.positive(self.data3), self.data4, - err_msg=self.err) + for expected, output in zip(self.data4, self.pos_dtype_obj): + print(expected, output) + npt.assert_array_equal(expected, output, err_msg=self.err) npt.assert_raises(TypeError, positivity.positive, '-1') class SVDTestCase(TestCase): + """Test case for svd module.""" def setUp(self): - + """Set test parameter values.""" self.data1 = np.arange(18).reshape(9, 2).astype(float) self.data2 = np.arange(32).reshape(16, 2).astype(float) - self.data3 = (np.array([[-0.01744594, -0.61438865], - [-0.08435304, -0.50397984], - [-0.15126014, -0.39357102], - [-0.21816724, -0.28316221], - [-0.28507434, -0.17275339], - [-0.35198144, -0.06234457], - [-0.41888854, 0.04806424], - [-0.48579564, 0.15847306], - [-0.55270274, 0.26888188]]), - np.array([42.23492742, 1.10041151]), - np.array([[-0.67608034, -0.73682791], - [0.73682791, -0.67608034]])) - self.data4 = np.array([[-1.05426832e-16, 1.00000000e+00], - [2.00000000e+00, 3.00000000e+00], - [4.00000000e+00, 5.00000000e+00], - [6.00000000e+00, 7.00000000e+00], - [8.00000000e+00, 9.00000000e+00], - [1.00000000e+01, 1.10000000e+01], - [1.20000000e+01, 1.30000000e+01], - [1.40000000e+01, 1.50000000e+01], - [1.60000000e+01, 1.70000000e+01]]) - self.data5 = np.array([[0.49815487, 0.54291537], - [2.40863386, 2.62505584], - [4.31911286, 4.70719631], - [6.22959185, 6.78933678], - [8.14007085, 8.87147725], - [10.05054985, 10.95361772], - [11.96102884, 13.03575819], - [13.87150784, 15.11789866], - [15.78198684, 17.20003913]]) + self.data3 = np.array( + [ + np.array([ + [-0.01744594, -0.61438865], + [-0.08435304, -0.50397984], + [-0.15126014, -0.39357102], + [-0.21816724, -0.28316221], + [-0.28507434, -0.17275339], + [-0.35198144, -0.06234457], + [-0.41888854, 0.04806424], + [-0.48579564, 0.15847306], + [-0.55270274, 0.26888188], + ]), + np.array([42.23492742, 1.10041151]), + np.array([ + [-0.67608034, -0.73682791], + [0.73682791, -0.67608034], + ]), + ], + dtype=object, + ) + self.data4 = np.array([ + [-1.05426832e-16, 1.0], + [2.0, 3.0], + [4.0, 5.0], + [6.0, 7.0], + [8.0, 9.0], + [1.0e1, 1.1e1], + [1.2e1, 1.3e1], + [1.4e1, 1.5e1], + [1.6e1, 1.7e1], + ]) + self.data5 = np.array([ + [0.49815487, 0.54291537], + [2.40863386, 2.62505584], + [4.31911286, 4.70719631], + [6.22959185, 6.78933678], + [8.14007085, 8.87147725], + [10.05054985, 10.95361772], + [11.96102884, 13.03575819], + [13.87150784, 15.11789866], + [15.78198684, 17.20003913], + ]) self.svd = svd.calculate_svd(self.data1) def tearDown(self): - + """Unset test parameter values.""" self.data1 = None self.data2 = None self.data3 = None @@ -178,106 +243,148 @@ def tearDown(self): self.svd = None def test_find_n_pc(self): - - npt.assert_equal(svd.find_n_pc(svd.svd(self.data2)[0]), 2, - err_msg='Incorrect number of principal components.') + """Test find_n_pc.""" + npt.assert_equal( + svd.find_n_pc(svd.svd(self.data2)[0]), + 2, + err_msg='Incorrect number of principal components.', + ) npt.assert_raises(ValueError, svd.find_n_pc, np.arange(3)) def test_calculate_svd(self): - - npt.assert_almost_equal(self.svd[0], np.array(self.data3)[0], - err_msg='Incorrect SVD calculation: U') - - npt.assert_almost_equal(self.svd[1], np.array(self.data3)[1], - err_msg='Incorrect SVD calculation: S') - - npt.assert_almost_equal(self.svd[2], np.array(self.data3)[2], - err_msg='Incorrect SVD calculation: V') + """Test calculate_svd.""" + npt.assert_almost_equal( + self.svd[0], + np.array(self.data3)[0], + err_msg='Incorrect SVD calculation: U', + ) + + npt.assert_almost_equal( + self.svd[1], + np.array(self.data3)[1], + err_msg='Incorrect SVD calculation: S', + ) + + npt.assert_almost_equal( + self.svd[2], + np.array(self.data3)[2], + err_msg='Incorrect SVD calculation: V', + ) def test_svd_thresh(self): - - npt.assert_almost_equal(svd.svd_thresh(self.data1), self.data4, - err_msg='Incorrect SVD tresholding') - - npt.assert_almost_equal(svd.svd_thresh(self.data1, n_pc=1), self.data5, - err_msg='Incorrect SVD tresholding') - - npt.assert_almost_equal(svd.svd_thresh(self.data1, n_pc='all'), - self.data1, - err_msg='Incorrect SVD tresholding') + """Test svd_thresh.""" + npt.assert_almost_equal( + svd.svd_thresh(self.data1), + self.data4, + err_msg='Incorrect SVD tresholding', + ) + + npt.assert_almost_equal( + svd.svd_thresh(self.data1, n_pc=1), + self.data5, + err_msg='Incorrect SVD tresholding', + ) + + npt.assert_almost_equal( + svd.svd_thresh(self.data1, n_pc='all'), + self.data1, + err_msg='Incorrect SVD tresholding', + ) npt.assert_raises(TypeError, svd.svd_thresh, 1) npt.assert_raises(ValueError, svd.svd_thresh, self.data1, n_pc='bla') def test_svd_thresh_coef(self): - - npt.assert_almost_equal(svd.svd_thresh_coef(self.data1, - lambda x: x, 0), - self.data1, - err_msg='Incorrect SVD coefficient ' - 'tresholding') + """Test svd_thresh_coef.""" + npt.assert_almost_equal( + svd.svd_thresh_coef(self.data1, lambda x_val: x_val, 0), + self.data1, + err_msg='Incorrect SVD coefficient tresholding', + ) npt.assert_raises(TypeError, svd.svd_thresh_coef, self.data1, 0, 0) class ValidationTestCase(TestCase): + """Test case for validation module.""" def setUp(self): - + """Set test parameter values.""" self.data1 = np.arange(9).reshape(3, 3).astype(float) def tearDown(self): - + """Unset test parameter values.""" self.data1 = None def test_transpose_test(self): - + """Test transpose_test.""" np.random.seed(2) - npt.assert_equal(validation.transpose_test(lambda x, y: x.dot(y), - lambda x, y: x.dot(y.T), self.data1.shape, - x_args=self.data1), None) - - npt.assert_raises(TypeError, validation.transpose_test, 0, 0, - self.data1.shape, x_args=self.data1) + npt.assert_equal( + validation.transpose_test( + lambda x_val, y_val: x_val.dot(y_val), + lambda x_val, y_val: x_val.dot(y_val.T), + self.data1.shape, + x_args=self.data1, + ), + None, + ) + + npt.assert_raises( + TypeError, + validation.transpose_test, + 0, + 0, + self.data1.shape, + x_args=self.data1, + ) class WaveletTestCase(TestCase): + """Test case for wavelet module.""" def setUp(self): - + """Set test parameter values.""" self.data1 = np.arange(9).reshape(3, 3).astype(float) self.data2 = np.arange(36).reshape(4, 3, 3).astype(float) - self.data3 = np.array([[[6., 20., 26.], - [36., 84., 84.], - [90., 164., 134.]], - [[78., 155., 134.], - [225., 408., 327.], - [270., 461., 350.]], - [[150., 290., 242.], - [414., 732., 570.], - [450., 758., 566.]], - [[222., 425., 350.], - [603., 1056., 813.], - [630., 1055., 782.]]]) - - self.data4 = np.array([[6496., 9796., 6544.], - [9924., 14910., 9924.], - [6544., 9796., 6496.]]) - - self.data5 = np.array([[[0., 1., 4.], - [3., 10., 13.], - [6., 19., 22.]], - [[3., 10., 13.], - [24., 46., 40.], - [45., 82., 67.]], - [[6., 19., 22.], - [45., 82., 67.], - [84., 145., 112.]]]) + self.data3 = np.array([ + [ + [6.0, 20, 26.0], + [36.0, 84.0, 84.0], + [90, 164.0, 134.0], + ], + [ + [78.0, 155.0, 134.0], + [225.0, 408.0, 327.0], + [270, 461.0, 350], + ], + [ + [150, 290, 242.0], + [414.0, 732.0, 570], + [450, 758.0, 566.0], + ], + [ + [222.0, 425.0, 350], + [603.0, 1056.0, 813.0], + [630, 1055.0, 782.0], + ], + ]) + + self.data4 = np.array([ + [6496.0, 9796.0, 6544.0], + [9924.0, 14910, 9924.0], + [6544.0, 9796.0, 6496.0], + ]) + + self.data5 = np.array([ + [[0, 1.0, 4.0], [3.0, 10, 13.0], [6.0, 19.0, 22.0]], + [[3.0, 10, 13.0], [24.0, 46.0, 40], [45.0, 82.0, 67.0]], + [[6.0, 19.0, 22.0], [45.0, 82.0, 67.0], [84.0, 145.0, 112.0]], + ]) def tearDown(self): - + """Unset test parameter values.""" self.data1 = None self.data2 = None self.data3 = None @@ -285,17 +392,23 @@ def tearDown(self): self.data5 = None def test_filter_convolve(self): - - npt.assert_almost_equal(wavelet.filter_convolve(self.data1, - self.data2), self.data3, - err_msg='Inccorect filter comvolution.') - - npt.assert_almost_equal(wavelet.filter_convolve(self.data2, - self.data2, filter_rot=True), self.data4, - err_msg='Inccorect filter comvolution.') + """Test filter_convolve.""" + npt.assert_almost_equal( + wavelet.filter_convolve(self.data1, self.data2), + self.data3, + err_msg='Inccorect filter comvolution.', + ) + + npt.assert_almost_equal( + wavelet.filter_convolve(self.data2, self.data2, filter_rot=True), + self.data4, + err_msg='Inccorect filter comvolution.', + ) def test_filter_convolve_stack(self): - - npt.assert_almost_equal(wavelet.filter_convolve_stack(self.data1, - self.data1), self.data5, - err_msg='Inccorect filter stack comvolution.') + """Test filter_convolve_stack.""" + npt.assert_almost_equal( + wavelet.filter_convolve_stack(self.data1, self.data1), + self.data5, + err_msg='Inccorect filter stack comvolution.', + ) diff --git a/notebooks/.gitkeep b/notebooks/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/requirements.txt b/requirements.txt index 0292ca57..3c0e6d4f 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,4 @@ -numpy>=1.16.4 -scipy>=1.3.0 -progressbar2>=3.34.3 +importlib_metadata==3.7.0 +numpy==1.19.5 +scipy==1.5.4 +progressbar2==3.53.1 diff --git a/setup.cfg b/setup.cfg index 1af5f76a..56a40d12 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,17 +1,79 @@ [aliases] test=pytest -[build_sphinx] -all_files=1 -build-dir=docs/build - [metadata] description-file = README.rst -[pycodestyle] -ignore = E121,E126,E402,W504 -statistics = True +[darglint] +docstring_style = numpy +strictness = short + +[flake8] +ignore = + D107, #Justification: Don't need docstring for __init__ in numpydoc style + RST304, #Justification: Need to use :cite: role for citations + W503, #Justification: Have to choose one multiline operator format + WPS202, #Todo: Rethink module size, possibly split large modules + WPS337, #Todo: Consider simplifying multiline conditions. + WPS338, #Todo: Consider changing method order + WPS403, #Todo: Rethink no cover lines + WPS421, #Todo: Review need for print statements + WPS432, #Justification: Mathematical codes require "magic numbers" + WPS433, #Todo: Rethink conditional imports + WPS463, #Todo: Rename get_ methods + WPS615, #Todo: Rename get_ methods +per-file-ignores = + #Justification: Needed for keeping package version and current API + *__init__.py*: F401,F403,WPS347,WPS410,WPS412 + #Todo: Rethink conditional imports + modopt/base/backend.py: WPS229, WPS420 + #Todo: Rethink conditional imports + modopt/base/observable.py: WPS420,WPS604 + #Todo: Check string for log formatting + modopt/interface/log.py: WPS323 + #Todo: Rethink conditional imports + modopt/math/convolve.py: WPS301,WPS420 + #Todo: Rethink conditional imports + modopt/math/matrix.py: WPS420 + #Todo: Check need for del statement, + modopt/opt/algorithms.py: WPS111,WPS420 + #Todo: Consider changing costObj name + modopt/opt/cost.py: N801 + #Todo: + # - Rethink subscript slice assignment + # - Reduce complexity of KSupportNorm + # - Check bitwise operations + modopt/opt/proximity.py: WPS220,WPS231,WPS352,WPS362,WPS465,WPS506,WPS508 + #Todo: Consider changing cwbReweight name + modopt/opt/reweight.py: N801 + #Justification: Needed to import matplotlib.pyplot + modopt/plot/cost_plot.py: N802,WPS301 + #Todo: Investigate possible bug in find_n_pc function + modopt/signal/svd.py: WPS345 + #Todo: Check security of using system executable call + modopt/signal/wavelet.py: S404,S603 + #Todo: Clean up tests + modopt/tests/*.py: E731,F401,WPS301,WPS420,WPS425,WPS437,WPS604 +#WPS Settings +max-arguments = 25 +max-attributes = 40 +max-cognitive-score = 20 +max-function-expressions = 20 +max-line-complexity = 30 +max-local-variables = 10 +max-methods = 20 +max-module-expressions = 20 +max-string-usages = 20 +max-raises = 5 [tool:pytest] -addopts = --verbose --pycodestyle --cov=modopt -testpaths = modopt +testpaths = + modopt +addopts = + --verbose + --emoji + --flake8 + --cov=modopt + --cov-report=term + --cov-report=xml + --junitxml=pytest.xml diff --git a/setup.py b/setup.py index b39f4ed3..92040f6d 100644 --- a/setup.py +++ b/setup.py @@ -4,28 +4,69 @@ from setuptools import setup, find_packages import os -release_info = {} -infopath = os.path.abspath(os.path.join(os.path.dirname(__file__), - "modopt", "info.py")) -with open(infopath) as open_file: - exec(open_file.read(), release_info) +# Set the package release version +major = 1 +minor = 5 +patch = 0 +# Set the package details +name = 'modopt' +version = '.'.join(str(value) for value in (major, minor, patch)) +author = 'Samuel Farrens' +email = 'samuel.farrens@cea.fr' +gh_user = 'cea-cosmic' +url = 'https://github.com/{0}/{1}'.format(gh_user, name) +description = 'Modular Optimisation tools for soliving inverse problems.' +license = 'MIT' + +# Set the package classifiers +python_versions_supported = ['3.6', '3.7', '3.8', '3.9'] +os_platforms_supported = ['Unix', 'MacOS'] + +lc_str = 'License :: OSI Approved :: {0} License' +ln_str = 'Programming Language :: Python' +py_str = 'Programming Language :: Python :: {0}' +os_str = 'Operating System :: {0}' + +classifiers = ( + [lc_str.format(license)] + [ln_str] + + [py_str.format(ver) for ver in python_versions_supported] + + [os_str.format(ops) for ops in os_platforms_supported] +) + +# Source package description from README.md +this_directory = os.path.abspath(os.path.dirname(__file__)) +with open(os.path.join(this_directory, 'README.md'), encoding='utf-8') as f: + long_description = f.read() + +# Source package requirements from requirements.txt with open('requirements.txt') as open_file: install_requires = open_file.read() +# Source test requirements from develop.txt +with open('develop.txt') as open_file: + tests_require = open_file.read() + +# Source doc requirements from docs/requirements.txt +with open('docs/requirements.txt') as open_file: + docs_require = open_file.read() + + setup( - name='modopt', - author='sfarrens', - author_email='samuel.farrens@cea.fr', - version=release_info["__version__"], - url='https://github.com/cea-cosmic/ModOpt', - download_url='https://github.com/cea-cosmic/ModOpt', + name=name, + author=author, + author_email=email, + version=version, + license=license, + url=url, + description=description, + long_description=long_description, + long_description_content_type='text/markdown', packages=find_packages(), install_requires=install_requires, - license='MIT', - description='Modular Optimisation tools for soliving inverse problems.', - long_description=release_info["__about__"], - setup_requires=['pytest-runner', ], - tests_require=['pytest>=6.0.2', 'pytest-cov>=2.10', - 'pytest-pycodestyle>=2.2'], + python_requires='>=3.6', + setup_requires=['pytest-runner'], + tests_require=tests_require, + extras_require={'develop': tests_require + docs_require}, + classifiers=classifiers, )