diff --git a/.flake8 b/.flake8 new file mode 100644 index 0000000..8dd399a --- /dev/null +++ b/.flake8 @@ -0,0 +1,3 @@ +[flake8] +max-line-length = 88 +extend-ignore = E203 diff --git a/.github/ISSUE_TEMPLATE/bug-report.yml b/.github/ISSUE_TEMPLATE/bug-report.yml new file mode 100644 index 0000000..a315630 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug-report.yml @@ -0,0 +1,43 @@ +name: Bug Report +description: Report an issue or a bug. +title: "[BUG]: << Please use a comprehensive title... >>" +labels: [ Defect ] + +body: + - type: markdown + attributes: + value: > + Thank you for taking the time to file a bug report. Before continuing, please take some time to check the existing [issues](https://github.com/colour-science/colour-demosaicing/issues). + The issue could already be fixed in the [develop](https://github.com/colour-science/colour-demosaicing) branch. If you have an installation problem, the [installation guide](https://www.colour-science.org/installation-guide/) describes the recommended process. + + - type: textarea + attributes: + label: "Description" + description: > + Please describe the issue in a few short sentences. + validations: + required: true + + - type: textarea + attributes: + label: "Code for Reproduction" + description: > + If possible, please provide a minimum self-contained example reproducing the issue. + placeholder: | + << Your code here... >> + render: python + + - type: textarea + attributes: + label: "Exception Message" + description: > + If any, please paste the *full* exception message. + placeholder: | + << Full traceback starting from `Traceback (most recent call last):`... >> + render: shell + + - type: textarea + attributes: + label: "Environment Information" + description: If possible, please paste the output from `import colour; colour.utilities.describe_environment()`. + render: shell diff --git a/.github/ISSUE_TEMPLATE/documentation-improvement.yml b/.github/ISSUE_TEMPLATE/documentation-improvement.yml new file mode 100644 index 0000000..50bc0ba --- /dev/null +++ b/.github/ISSUE_TEMPLATE/documentation-improvement.yml @@ -0,0 +1,40 @@ +name: Documentation Improvement +description: Report a documentation improvement. +title: "[DOCUMENTATION]: << Please use a comprehensive title... >>" +labels: [ Documentation ] + +body: + - type: markdown + attributes: + value: > + Thank you for taking the time to file a documentation improvement report. Before continuing, please take some time to check the existing [issues](https://github.com/colour-science/colour-demosaicing/issues). + + - type: input + attributes: + label: Documentation Link + description: > + Please link to any documentation or examples that you are referencing. Suggested improvements should be based on the [development version of the documentation](https://colour-demosaicing.readthedocs.io/en/develop/). + placeholder: > + << https://colour-demosaicing.readthedocs.io/en/develop/... >> + validations: + required: true + + - type: textarea + attributes: + label: Description + description: > + Please describe what is missing, unclear or incorrect. + validations: + required: true + + - type: textarea + attributes: + label: Suggested Improvement + description: > + Please describe how the documentation could be improved. + + - type: textarea + attributes: + label: "Environment Information" + description: If possible, please paste the output from `import colour; colour.utilities.describe_environment()`. + render: shell diff --git a/.github/ISSUE_TEMPLATE/feature-request.yml b/.github/ISSUE_TEMPLATE/feature-request.yml new file mode 100644 index 0000000..c86bc6d --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature-request.yml @@ -0,0 +1,18 @@ +name: Feature Request +description: Suggest a new feature to implement. +title: "[FEATURE]: << Please use a comprehensive title... >>" +labels: [ Feature ] + +body: + - type: markdown + attributes: + value: > + Thank you for taking the time to file a feature request. Before continuing, please take some time to check the existing [issues](https://github.com/colour-science/colour-demosaicing/issues) and also the [draft release notes](https://gist.github.com/KelSolaar/4a6ebe9ec3d389f0934b154fec8df51d). + + - type: textarea + attributes: + label: "Description" + description: > + Please describe the new feature in a few short sentences. + validations: + required: true diff --git a/.github/ISSUE_TEMPLATE/question.yml b/.github/ISSUE_TEMPLATE/question.yml new file mode 100644 index 0000000..9d9c125 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/question.yml @@ -0,0 +1,17 @@ +name: Question +description: Ask a question. +title: "[DISCUSSION]: << Please use a comprehensive title... >>" +labels: [ Discussion ] + +body: + - type: markdown + attributes: + value: Thank you for taking the time to ask a question or discuss. Before continuing, we would be glad if you were to start this discussion in the dedicated [discussions](https://github.com/colour-science/colour-demosaicing/discussions) area. + + - type: textarea + attributes: + label: "Question" + description: > + If you are still here, please consider using the dedicated [discussions](https://github.com/colour-science/colour-demosaicing/discussions) area. + placeholder: > + << The discussions area is this way: https://github.com/colour-science/colour-demosaicing/discussions... >> diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000..f04c387 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,31 @@ + + +# Summary + + + +# Preflight + + + +**Code Style and Quality** + +- [ ] Unit tests have been implemented and passed. +- [ ] Mypy static checking has been run and passed. +- [ ] Pre-commit hooks have been run and passed. + + + + +**Documentation** + +- [ ] New features are documented along with examples if relevant. +- [ ] The documentation is [Sphinx](https://www.sphinx-doc.org/en/master/) and [numpydoc](https://numpydoc.readthedocs.io/en/latest/format.html) compliant. + + diff --git a/.github/funding.yml b/.github/funding.yml new file mode 100644 index 0000000..2614032 --- /dev/null +++ b/.github/funding.yml @@ -0,0 +1,12 @@ +# These are supported funding model platforms + +github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] +patreon: # Replace with a single Patreon username +open_collective: colour-science # Replace with a single Open Collective username +ko_fi: # Replace with a single Ko-fi username +tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel +community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry +liberapay: # Replace with a single Liberapay username +issuehunt: # Replace with a single IssueHunt username +otechie: # Replace with a single Otechie username +custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] diff --git a/.github/workflows/continuous-integration-documentation.yml b/.github/workflows/continuous-integration-documentation.yml new file mode 100644 index 0000000..bd9f051 --- /dev/null +++ b/.github/workflows/continuous-integration-documentation.yml @@ -0,0 +1,47 @@ +name: Continuous Integration - Documentation + +on: [push, pull_request] + +jobs: + continuous-integration-documentation: + name: ${{ matrix.os }} - Python ${{ matrix.python-version }} + strategy: + matrix: + os: [ubuntu-20.04] + python-version: [3.8] + fail-fast: false + runs-on: ${{ matrix.os }} + steps: + - uses: actions/checkout@v1 + - name: Environment Variables + run: | + echo "CI_PYTHON_VERSION=${{ matrix.python-version }}" >> $GITHUB_ENV + echo "CI_PACKAGE=colour" >> $GITHUB_ENV + echo "CI_SHA=${{ github.sha }}" >> $GITHUB_ENV + echo "MPLBACKEND=AGG" >> $GITHUB_ENV + echo "COLOUR_SCIENCE__DOCUMENTATION_BUILD=True" >> $GITHUB_ENV + shell: bash + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v1 + with: + python-version: ${{ matrix.python-version }} + - name: Install Dependencies + run: | + sudo apt-get update + sudo apt-get --yes install latexmk texlive-full + - name: Install Poetry + run: | + curl -L https://raw.githubusercontent.com/sdispater/poetry/master/get-poetry.py -o get-poetry.py + python get-poetry.py + echo "$HOME/.poetry/bin" >> $GITHUB_PATH + shell: bash + - name: Install Package Dependencies + run: | + poetry run python -m pip install --upgrade pip + poetry install --extras "read-the-docs" + poetry run python -c "import imageio;imageio.plugins.freeimage.download()" + shell: bash + - name: Build Documentation + run: | + poetry run invoke docs + shell: bash diff --git a/.github/workflows/continuous-integration.yml b/.github/workflows/continuous-integration-quality-unit-tests.yml similarity index 56% rename from .github/workflows/continuous-integration.yml rename to .github/workflows/continuous-integration-quality-unit-tests.yml index 88cca6b..b26cdb5 100644 --- a/.github/workflows/continuous-integration.yml +++ b/.github/workflows/continuous-integration-quality-unit-tests.yml @@ -1,14 +1,14 @@ -name: Continuous Integration +name: Continuous Integration - Quality & Unit Tests on: [push, pull_request] jobs: - continuous-integration: + continuous-integration-package: name: ${{ matrix.os }} - Python ${{ matrix.python-version }} strategy: matrix: - os: [macOS-latest, ubuntu-18.04, windows-latest] - python-version: [2.7, 3.6, 3.7, 3.8] + os: [macOS-latest, ubuntu-20.04, windows-latest] + python-version: [3.8, 3.9, '3.10'] fail-fast: false runs-on: ${{ matrix.os }} steps: @@ -35,40 +35,28 @@ jobs: - name: Install Poetry run: | curl -L https://raw.githubusercontent.com/sdispater/poetry/master/get-poetry.py -o get-poetry.py - python get-poetry.py --version 1.0.10 + python get-poetry.py --version 1.1.12 echo "$HOME/.poetry/bin" >> $GITHUB_PATH shell: bash - - name: Update pyproject.toml file (Python 2.7) - if: matrix.python-version == '2.7' - run: | - sed -i.bak 's/python = "~2.7 || ^3.6"/python = "~2.7"/g' pyproject.toml - sed -i.bak '/colour-science = "\^0\.3\.16"/ a qtconsole = "4.7.7"' pyproject.toml - shell: bash - - name: Update pyproject.toml file (Python 3.x) - if: matrix.python-version != '2.7' - run: | - sed -i.bak 's/python = "~2.7 || ^3.6"/python = "^3.6"/g' pyproject.toml - shell: bash - - name: Update pyproject.toml file (Windows, Python 2.7) - if: matrix.os == 'windows-latest' && matrix.python-version == '2.7' - run: | - sed -i.bak '/colour-science = "\^0\.3\.16"/ a pywin32 = "228"' pyproject.toml - shell: bash - name: Install Package Dependencies run: | + poetry run python -m pip install --upgrade pip poetry install poetry run python -c "import imageio;imageio.plugins.freeimage.download()" shell: bash - - name: Lint with flake8 + - name: Pre-Commit (All Files) + run: | + poetry run pre-commit run --all-files + shell: bash + - name: Test Optimised Python Execution run: | - poetry run flake8 $CI_PACKAGE --count --show-source --statistics + poetry run python -OO -c "import $CI_PACKAGE" shell: bash - - name: Test with nosetests + - name: Test with Pytest run: | - poetry run python -W ignore -m nose -q -v --with-doctest --doctest-options=+ELLIPSIS --with-coverage --cover-package=$CI_PACKAGE $CI_PACKAGE + poetry run python -W ignore -m py.test --disable-warnings --doctest-modules --ignore=$CI_PACKAGE/examples --cov=$CI_PACKAGE $CI_PACKAGE shell: bash - name: Upload Coverage to coveralls.io - if: matrix.python-version == '3.6' || matrix.python-version == '3.7' run: | if [ -z "$COVERALLS_REPO_TOKEN" ]; then echo \"COVERALLS_REPO_TOKEN\" secret is undefined!; else poetry run coveralls; fi shell: bash diff --git a/.github/workflows/continuous-integration-static-type-checking.yml b/.github/workflows/continuous-integration-static-type-checking.yml new file mode 100644 index 0000000..d7c7329 --- /dev/null +++ b/.github/workflows/continuous-integration-static-type-checking.yml @@ -0,0 +1,32 @@ +name: Continuous Integration - Static Type Checking + +on: [push, pull_request] + +jobs: + continuous-integration-package: + name: ${{ matrix.os }} - Python ${{ matrix.python-version }} + strategy: + matrix: + os: [macOS-latest] + python-version: [3.9] + fail-fast: false + runs-on: ${{ matrix.os }} + steps: + - uses: actions/checkout@v1 + - name: Environment Variables + run: | + echo "CI_PACKAGE=colour" >> $GITHUB_ENV + shell: bash + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v1 + with: + python-version: ${{ matrix.python-version }} + - name: Install Dependencies (macOS) + run: | + brew install gnu-sed graphviz + ln -s /usr/local/bin/gsed /usr/local/bin/sed + shell: bash + - name: Static Type Checking + run: | + pip install -r requirements.txt + mypy --install-types --non-interactive --show-error-codes --warn-unused-ignores --warn-redundant-casts -p $CI_PACKAGE diff --git a/.gitignore b/.gitignore index 1048eec..008a4fa 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,10 @@ *.pyc .DS_Store .coverage +.dmypy.json .idea .ipynb_checkpoints/ +.mypy_cache __pycache__ build colour_demosaicing.egg-info diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index f759724..f2cc0b9 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,11 +1,26 @@ repos: -- repo: https://gitlab.com/pycqa/flake8 - rev: 3.7.8 +- repo: https://github.com/asottile/pyupgrade + rev: v2.31.0 + hooks: + - id: pyupgrade + args: [--py38-plus] +- repo: https://github.com/ikamensh/flynt/ + rev: '0.76' + hooks: + - id: flynt +- repo: https://github.com/psf/black + rev: 22.1.0 + hooks: + - id: black + language_version: python3.8 +- repo: https://github.com/PyCQA/flake8 + rev: 4.0.1 hooks: - id: flake8 - exclude: examples|setup\.py -- repo: https://github.com/pre-commit/mirrors-yapf - rev: v0.23.0 +- repo: https://github.com/pycqa/pydocstyle + rev: 6.1.1 hooks: - - id: yapf - exclude: setup\.py + - id: pydocstyle + args: + - --convention=numpy + - --add-ignore=D104,D200,D202,D205,D301,D400 diff --git a/.readthedocs.yaml b/.readthedocs.yaml new file mode 100644 index 0000000..3f9c1e4 --- /dev/null +++ b/.readthedocs.yaml @@ -0,0 +1,20 @@ +version: 2 + +build: + os: ubuntu-20.04 + tools: + python: "3.8" + +sphinx: + configuration: docs/conf.py + +formats: + - htmlzip + - pdf + +python: + install: + - method: pip + path: . + extra_requirements: + - read-the-docs \ No newline at end of file diff --git a/.readthedocs.yml b/.readthedocs.yml deleted file mode 100644 index 6e5818f..0000000 --- a/.readthedocs.yml +++ /dev/null @@ -1,8 +0,0 @@ -build: - image: latest - -python: - version: 3.7 - pip_install: true - extra_requirements: - - read-the-docs diff --git a/.style.yapf b/.style.yapf deleted file mode 100644 index 45e56e9..0000000 --- a/.style.yapf +++ /dev/null @@ -1,180 +0,0 @@ -[style] -# Align closing bracket with visual indentation. -align_closing_bracket_with_visual_indent=True - -# Allow dictionary keys to exist on multiple lines. For example: -# -# x = { -# ('this is the first element of a tuple', -# 'this is the second element of a tuple'): -# value, -# } -allow_multiline_dictionary_keys=False - -# Allow lambdas to be formatted on more than one line. -allow_multiline_lambdas=False - -# Insert a blank line before a class-level docstring. -blank_line_before_class_docstring=False - -# Insert a blank line before a 'def' or 'class' immediately nested -# within another 'def' or 'class'. For example: -# -# class Foo: -# # <------ this blank line -# def method(): -# ... -blank_line_before_nested_class_or_def=False - -# Do not split consecutive brackets. Only relevant when -# dedent_closing_brackets is set. For example: -# -# call_func_that_takes_a_dict( -# { -# 'key1': 'value1', -# 'key2': 'value2', -# } -# ) -# -# would reformat to: -# -# call_func_that_takes_a_dict({ -# 'key1': 'value1', -# 'key2': 'value2', -# }) -coalesce_brackets=False - -# The column limit. -column_limit=79 - -# Indent width used for line continuations. -continuation_indent_width=4 - -# Put closing brackets on a separate line, dedented, if the bracketed -# expression can't fit in a single line. Applies to all kinds of brackets, -# including function definitions and calls. For example: -# -# config = { -# 'key1': 'value1', -# 'key2': 'value2', -# } # <--- this bracket is dedented and on a separate line -# -# time_series = self.remote_client.query_entity_counters( -# entity='dev3246.region1', -# key='dns.query_latency_tcp', -# transform=Transformation.AVERAGE(window=timedelta(seconds=60)), -# start_ts=now()-timedelta(days=3), -# end_ts=now(), -# ) # <--- this bracket is dedented and on a separate line -dedent_closing_brackets=False - -# Place each dictionary entry onto its own line. -each_dict_entry_on_separate_line=True - -# The regex for an i18n comment. The presence of this comment stops -# reformatting of that line, because the comments are required to be -# next to the string they translate. -i18n_comment= - -# The i18n function call names. The presence of this function stops -# reformattting on that line, because the string it has cannot be moved -# away from the i18n comment. -i18n_function_call= - -# Indent the dictionary value if it cannot fit on the same line as the -# dictionary key. For example: -# -# config = { -# 'key1': -# 'value1', -# 'key2': value1 + -# value2, -# } -indent_dictionary_value=True - -# The number of columns to use for indentation. -indent_width=4 - -# Join short lines into one line. E.g., single line 'if' statements. -join_multiple_lines=True - -# Use spaces around default or named assigns. -spaces_around_default_or_named_assign=False - -# Use spaces around the power operator. -spaces_around_power_operator=True - -# The number of spaces required before a trailing comment. -spaces_before_comment=2 - -# Insert a space between the ending comma and closing bracket of a list, -# etc. -space_between_ending_comma_and_closing_bracket=True - -# Split before arguments if the argument list is terminated by a -# comma. -split_arguments_when_comma_terminated=False - -# Set to True to prefer splitting before '&', '|' or '^' rather than -# after. -split_before_bitwise_operator=False - -# Split before a dictionary or set generator (comp_for). For example, note -# the split before the 'for': -# -# foo = { -# variable: 'Hello world, have a nice day!' -# for variable in bar if variable != 42 -# } -split_before_dict_set_generator=True - -# If an argument / parameter list is going to be split, then split before -# the first argument. -split_before_first_argument=False - -# Set to True to prefer splitting before 'and' or 'or' rather than -# after. -split_before_logical_operator=False - -# Split named assignments onto individual lines. -split_before_named_assigns=True - -# The penalty for splitting right after the opening bracket. -split_penalty_after_opening_bracket=30 - -# The penalty for splitting the line after a unary operator. -split_penalty_after_unary_operator=10000 - -# The penalty for splitting right before an if expression. -split_penalty_before_if_expr=0 - -# The penalty of splitting the line around the '&', '|', and '^' -# operators. -split_penalty_bitwise_operator=300 - -# The penalty for characters over the column limit. -split_penalty_excess_character=4500 - -# The penalty incurred by adding a line split to the unwrapped line. The -# more line splits added the higher the penalty. -split_penalty_for_added_line_split=30 - -# The penalty of splitting a list of "import as" names. For example: -# -# from a_very_long_or_indented_module_name_yada_yad import (long_argument_1, -# long_argument_2, -# long_argument_3) -# -# would reformat to something like: -# -# from a_very_long_or_indented_module_name_yada_yad import ( -# long_argument_1, long_argument_2, long_argument_3) -split_penalty_import_names=0 - -# The penalty of splitting the line around the 'and' and 'or' -# operators. -split_penalty_logical_operator=300 - -# Use the Tab character for indentation. -use_tabs=False - diff --git a/CONTRIBUTORS.rst b/CONTRIBUTORS.rst index e239d5f..00ca971 100644 --- a/CONTRIBUTORS.rst +++ b/CONTRIBUTORS.rst @@ -4,7 +4,7 @@ Contributors Development & Technical Support ------------------------------- -- **Thomas Mansencal**, *Visual Effects Artist @ Weta Digital* +- **Thomas Mansencal**, *Lead Pipeline Developer @ WetaFX* Project coordination, overall development. @@ -30,6 +30,6 @@ About ----- | **Colour - Demosaicing** by Colour Developers -| Copyright © 2015-2020 – Colour Developers – `colour-developers@colour-science.org `__ +| Copyright 2015 Colour Developers – `colour-developers@colour-science.org `__ | This software is released under terms of New BSD License: https://opensource.org/licenses/BSD-3-Clause | `https://github.com/colour-science/colour-demosaicing `__ diff --git a/LICENSE b/LICENSE index 09d34c5..f63ef1d 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2015-2020, Colour Developers +Copyright 2015 Colour Developers All rights reserved. Redistribution and use in source and binary forms, with or without diff --git a/README.rst b/README.rst index 00c3297..5f98465 100644 --- a/README.rst +++ b/README.rst @@ -30,7 +30,7 @@ It is open source and freely available under the .. contents:: **Table of Contents** :backlinks: none - :depth: 3 + :depth: 2 .. sectnum:: @@ -39,12 +39,21 @@ Features The following CFA (Colour Filter Array) demosaicing algorithms are implemented: -- Bilinear -- Malvar (2004) -- DDFAPD - Menon (2007) +- Bilinear +- Malvar (2004) +- DDFAPD - Menon (2007) + +Examples +^^^^^^^^ + +Various usage examples are available from the +`examples directory `__. + +User Guide +---------- Installation ------------- +^^^^^^^^^^^^ Because of their size, the resources dependencies needed to run the various examples and unit tests are not provided within the Pypi package. They are @@ -54,66 +63,67 @@ when cloning the `repository `__. Primary Dependencies -^^^^^^^^^^^^^^^^^^^^ +~~~~~~~~~~~~~~~~~~~~ **Colour - Demosaicing** requires various dependencies in order to run: -- `python>=2.7 `__ or - `python>=3.5 `__ -- `colour-science `__ +- `python >= 3.8, < 4 `__ +- `colour-science `__ Pypi -^^^^ +~~~~ Once the dependencies are satisfied, **Colour - Demosaicing** can be installed from the `Python Package Index `__ by issuing this command in a shell:: - pip install --user colour-demosaicing + pip install --user colour-demosaicing The overall development dependencies are installed as follows:: pip install --user 'colour-demosaicing[development]' -Usage ------ - -API -^^^ - -The main reference for `Colour - Demosaicing `__ -is the `Colour - Demosaicing Manual `__. - -Examples -^^^^^^^^ - -Various usage examples are available from the -`examples directory `__. - Contributing ------------- +^^^^^^^^^^^^ If you would like to contribute to `Colour - Demosaicing `__, please refer to the following `Contributing `__ guide for `Colour `__. Bibliography ------------- +^^^^^^^^^^^^ The bibliography is available in the repository in `BibTeX `__ format. +API Reference +------------- + +The main technical reference for `Colour - Demosaicing `__ +is the `API Reference `__. + Code of Conduct --------------- The *Code of Conduct*, adapted from the `Contributor Covenant 1.4 `__, is available on the `Code of Conduct `__ page. +Contact & Social +---------------- + +The *Colour Developers* can be reached via different means: + +- `Email `__ +- `Facebook `__ +- `Github Discussions `__ +- `Gitter `__ +- `Twitter `__ + About ----- | **Colour - Demosaicing** by Colour Developers -| Copyright © 2015-2020 – Colour Developers – `colour-developers@colour-science.org `__ +| Copyright 2015 Colour Developers – `colour-developers@colour-science.org `__ | This software is released under terms of New BSD License: https://opensource.org/licenses/BSD-3-Clause | `https://github.com/colour-science/colour-demosaicing `__ diff --git a/TODO.rst b/TODO.rst index 5f5ab17..449cd38 100644 --- a/TODO.rst +++ b/TODO.rst @@ -6,12 +6,12 @@ TODO - colour_demosaicing/__init__.py - - Line 66 : # TODO: Remove legacy printing support when deemed appropriate. + - Line 81 : # TODO: Remove legacy printing support when deemed appropriate. About ----- | **Colour - Demosaicing** by Colour Developers -| Copyright © 2015-2020 – Colour Developers – `colour-developers@colour-science.org `__ +| Copyright 2015 Colour Developers – `colour-developers@colour-science.org `__ | This software is released under terms of New BSD License: https://opensource.org/licenses/BSD-3-Clause | `https://github.com/colour-science/colour-demosaicing `__ diff --git a/colour_demosaicing/__init__.py b/colour_demosaicing/__init__.py index 01fb626..614f0fa 100644 --- a/colour_demosaicing/__init__.py +++ b/colour_demosaicing/__init__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- """ Colour - Demosaicing ==================== @@ -10,7 +9,7 @@ - bayer: *Bayer* CFA mosaicing and demosaicing computations. """ -from __future__ import absolute_import +from __future__ import annotations import numpy as np import os @@ -19,53 +18,68 @@ import colour from .bayer import ( - demosaicing_CFA_Bayer_bilinear, demosaicing_CFA_Bayer_DDFAPD, - demosaicing_CFA_Bayer_Malvar2004, demosaicing_CFA_Bayer_Menon2007, - masks_CFA_Bayer, mosaicing_CFA_Bayer) + demosaicing_CFA_Bayer_bilinear, + demosaicing_CFA_Bayer_DDFAPD, + demosaicing_CFA_Bayer_Malvar2004, + demosaicing_CFA_Bayer_Menon2007, + masks_CFA_Bayer, + mosaicing_CFA_Bayer, +) -__author__ = 'Colour Developers' -__copyright__ = 'Copyright (C) 2015-2020 - Colour Developers' -__license__ = 'New BSD License - https://opensource.org/licenses/BSD-3-Clause' -__maintainer__ = 'Colour Developers' -__email__ = 'colour-developers@colour-science.org' -__status__ = 'Production' +__author__ = "Colour Developers" +__copyright__ = "Copyright 2015 Colour Developers" +__license__ = "New BSD License - https://opensource.org/licenses/BSD-3-Clause" +__maintainer__ = "Colour Developers" +__email__ = "colour-developers@colour-science.org" +__status__ = "Production" __all__ = [ - 'demosaicing_CFA_Bayer_bilinear', 'demosaicing_CFA_Bayer_DDFAPD', - 'demosaicing_CFA_Bayer_Malvar2004', 'demosaicing_CFA_Bayer_Menon2007', - 'masks_CFA_Bayer', 'mosaicing_CFA_Bayer' + "demosaicing_CFA_Bayer_bilinear", + "demosaicing_CFA_Bayer_DDFAPD", + "demosaicing_CFA_Bayer_Malvar2004", + "demosaicing_CFA_Bayer_Menon2007", + "masks_CFA_Bayer", + "mosaicing_CFA_Bayer", ] -RESOURCES_DIRECTORY = os.path.join(os.path.dirname(__file__), 'resources') -EXAMPLES_RESOURCES_DIRECTORY = os.path.join( - RESOURCES_DIRECTORY, 'colour-demosaicing-examples-datasets') -TESTS_RESOURCES_DIRECTORY = os.path.join(RESOURCES_DIRECTORY, - 'colour-demosaicing-tests-datasets') +RESOURCES_DIRECTORY: str = os.path.join(os.path.dirname(__file__), "resources") +EXAMPLES_RESOURCES_DIRECTORY: str = os.path.join( + RESOURCES_DIRECTORY, "colour-demosaicing-examples-datasets" +) +TESTS_RESOURCES_DIRECTORY: str = os.path.join( + RESOURCES_DIRECTORY, "colour-demosaicing-tests-datasets" +) -__application_name__ = 'Colour - Demosaicing' +__application_name__ = "Colour - Demosaicing" -__major_version__ = '0' -__minor_version__ = '1' -__change_version__ = '6' -__version__ = '.'.join( - (__major_version__, - __minor_version__, - __change_version__)) # yapf: disable +__major_version__ = "0" +__minor_version__ = "2" +__change_version__ = "0" +__version__ = ".".join( + (__major_version__, __minor_version__, __change_version__) +) try: - version = subprocess.check_output( # nosec - ['git', 'describe'], - cwd=os.path.dirname(__file__), - stderr=subprocess.STDOUT).strip() - version = version.decode('utf-8') + _version: str = ( + subprocess.check_output( # nosec + ["git", "describe"], + cwd=os.path.dirname(__file__), + stderr=subprocess.STDOUT, + ) + .strip() + .decode("utf-8") + ) except Exception: - version = __version__ + _version: str = __version__ # type: ignore[no-redef] -colour.utilities.ANCILLARY_COLOUR_SCIENCE_PACKAGES['colour-demosaicing'] = ( - version) +colour.utilities.ANCILLARY_COLOUR_SCIENCE_PACKAGES[ + "colour-demosaicing" +] = _version + +del _version # TODO: Remove legacy printing support when deemed appropriate. try: - np.set_printoptions(legacy='1.13') + np.set_printoptions(legacy="1.13") except TypeError: pass diff --git a/colour_demosaicing/bayer/__init__.py b/colour_demosaicing/bayer/__init__.py index 44e5382..c655646 100644 --- a/colour_demosaicing/bayer/__init__.py +++ b/colour_demosaicing/bayer/__init__.py @@ -1,13 +1,13 @@ -# -*- coding: utf-8 -*- - -from __future__ import absolute_import - from .masks import masks_CFA_Bayer from .mosaicing import mosaicing_CFA_Bayer from .demosaicing import * # noqa from . import demosaicing __all__ = [] -__all__ += ['masks_CFA_Bayer'] -__all__ += ['mosaicing_CFA_Bayer'] +__all__ += [ + "masks_CFA_Bayer", +] +__all__ += [ + "mosaicing_CFA_Bayer", +] __all__ += demosaicing.__all__ diff --git a/colour_demosaicing/bayer/demosaicing/__init__.py b/colour_demosaicing/bayer/demosaicing/__init__.py index 528854e..c04abac 100644 --- a/colour_demosaicing/bayer/demosaicing/__init__.py +++ b/colour_demosaicing/bayer/demosaicing/__init__.py @@ -1,13 +1,18 @@ -# -*- coding: utf-8 -*- - -from __future__ import absolute_import - from .bilinear import demosaicing_CFA_Bayer_bilinear from .malvar2004 import demosaicing_CFA_Bayer_Malvar2004 -from .menon2007 import (demosaicing_CFA_Bayer_DDFAPD, - demosaicing_CFA_Bayer_Menon2007) +from .menon2007 import ( + demosaicing_CFA_Bayer_DDFAPD, + demosaicing_CFA_Bayer_Menon2007, +) __all__ = [] -__all__ += ['demosaicing_CFA_Bayer_bilinear'] -__all__ += ['demosaicing_CFA_Bayer_Malvar2004'] -__all__ += ['demosaicing_CFA_Bayer_DDFAPD', 'demosaicing_CFA_Bayer_Menon2007'] +__all__ += [ + "demosaicing_CFA_Bayer_bilinear", +] +__all__ += [ + "demosaicing_CFA_Bayer_Malvar2004", +] +__all__ += [ + "demosaicing_CFA_Bayer_DDFAPD", + "demosaicing_CFA_Bayer_Menon2007", +] diff --git a/colour_demosaicing/bayer/demosaicing/bilinear.py b/colour_demosaicing/bayer/demosaicing/bilinear.py index de37226..56e921b 100644 --- a/colour_demosaicing/bayer/demosaicing/bilinear.py +++ b/colour_demosaicing/bayer/demosaicing/bilinear.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- """ Bilinear Bayer CFA Demosaicing ============================== @@ -12,40 +11,45 @@ Electron Physics (Vol. 162, pp. 173-265). doi:10.1016/S1076-5670(10)62005-8 """ -from __future__ import division, unicode_literals +from __future__ import annotations from scipy.ndimage.filters import convolve +from colour.hints import ArrayLike, Literal, NDArray, Union from colour.utilities import as_float_array, tstack from colour_demosaicing.bayer import masks_CFA_Bayer -__author__ = 'Colour Developers' -__copyright__ = 'Copyright (C) 2015-2020 - Colour Developers' -__license__ = 'New BSD License - https://opensource.org/licenses/BSD-3-Clause' -__maintainer__ = 'Colour Developers' -__email__ = 'colour-developers@colour-science.org' -__status__ = 'Production' +__author__ = "Colour Developers" +__copyright__ = "Copyright 2015 Colour Developers" +__license__ = "New BSD License - https://opensource.org/licenses/BSD-3-Clause" +__maintainer__ = "Colour Developers" +__email__ = "colour-developers@colour-science.org" +__status__ = "Production" -__all__ = ['demosaicing_CFA_Bayer_bilinear'] +__all__ = [ + "demosaicing_CFA_Bayer_bilinear", +] -def demosaicing_CFA_Bayer_bilinear(CFA, pattern='RGGB'): +def demosaicing_CFA_Bayer_bilinear( + CFA: ArrayLike, + pattern: Union[Literal["RGGB", "BGGR", "GRBG", "GBRG"], str] = "RGGB", +) -> NDArray: """ - Returns the demosaiced *RGB* colourspace array from given *Bayer* CFA using + Return the demosaiced *RGB* colourspace array from given *Bayer* CFA using bilinear interpolation. Parameters ---------- - CFA : array_like + CFA *Bayer* CFA. - pattern : unicode, optional - **{'RGGB', 'BGGR', 'GRBG', 'GBRG'}**, + pattern Arrangement of the colour filters on the pixel array. Returns ------- - ndarray + :class:`numpy.ndarray` *RGB* colourspace array. Notes @@ -95,15 +99,27 @@ def demosaicing_CFA_Bayer_bilinear(CFA, pattern='RGGB'): CFA = as_float_array(CFA) R_m, G_m, B_m = masks_CFA_Bayer(CFA.shape, pattern) - H_G = as_float_array( - [[0, 1, 0], - [1, 4, 1], - [0, 1, 0]]) / 4 # yapf: disable - - H_RB = as_float_array( - [[1, 2, 1], - [2, 4, 2], - [1, 2, 1]]) / 4 # yapf: disable + H_G = ( + as_float_array( + [ + [0, 1, 0], + [1, 4, 1], + [0, 1, 0], + ] + ) + / 4 + ) + + H_RB = ( + as_float_array( + [ + [1, 2, 1], + [2, 4, 2], + [1, 2, 1], + ] + ) + / 4 + ) R = convolve(CFA * R_m, H_RB) G = convolve(CFA * G_m, H_G) diff --git a/colour_demosaicing/bayer/demosaicing/malvar2004.py b/colour_demosaicing/bayer/demosaicing/malvar2004.py index 1a924ba..de40cb3 100644 --- a/colour_demosaicing/bayer/demosaicing/malvar2004.py +++ b/colour_demosaicing/bayer/demosaicing/malvar2004.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- """ Malvar (2004) Bayer CFA Demosaicing =================================== @@ -14,41 +13,46 @@ http://research.microsoft.com/apps/pubs/default.aspx?id=102068 """ -from __future__ import division, unicode_literals +from __future__ import annotations import numpy as np from scipy.ndimage.filters import convolve +from colour.hints import ArrayLike, Literal, NDArray, Union from colour.utilities import as_float_array, tstack from colour_demosaicing.bayer import masks_CFA_Bayer -__author__ = 'Colour Developers' -__copyright__ = 'Copyright (C) 2015-2020 - Colour Developers' -__license__ = 'New BSD License - https://opensource.org/licenses/BSD-3-Clause' -__maintainer__ = 'Colour Developers' -__email__ = 'colour-developers@colour-science.org' -__status__ = 'Production' +__author__ = "Colour Developers" +__copyright__ = "Copyright 2015 Colour Developers" +__license__ = "New BSD License - https://opensource.org/licenses/BSD-3-Clause" +__maintainer__ = "Colour Developers" +__email__ = "colour-developers@colour-science.org" +__status__ = "Production" -__all__ = ['demosaicing_CFA_Bayer_Malvar2004'] +__all__ = [ + "demosaicing_CFA_Bayer_Malvar2004", +] -def demosaicing_CFA_Bayer_Malvar2004(CFA, pattern='RGGB'): +def demosaicing_CFA_Bayer_Malvar2004( + CFA: ArrayLike, + pattern: Union[Literal["RGGB", "BGGR", "GRBG", "GBRG"], str] = "RGGB", +) -> NDArray: """ - Returns the demosaiced *RGB* colourspace array from given *Bayer* CFA using + Return the demosaiced *RGB* colourspace array from given *Bayer* CFA using *Malvar (2004)* demosaicing algorithm. Parameters ---------- - CFA : array_like + CFA *Bayer* CFA. - pattern : unicode, optional - **{'RGGB', 'BGGR', 'GRBG', 'GBRG'}**, + pattern Arrangement of the colour filters on the pixel array. Returns ------- - ndarray + :class:`numpy.ndarray` *RGB* colourspace array. Notes @@ -97,28 +101,46 @@ def demosaicing_CFA_Bayer_Malvar2004(CFA, pattern='RGGB'): CFA = as_float_array(CFA) R_m, G_m, B_m = masks_CFA_Bayer(CFA.shape, pattern) - GR_GB = as_float_array( - [[0, 0, -1, 0, 0], - [0, 0, 2, 0, 0], - [-1, 2, 4, 2, -1], - [0, 0, 2, 0, 0], - [0, 0, -1, 0, 0]]) / 8 # yapf: disable - - Rg_RB_Bg_BR = as_float_array( - [[0, 0, 0.5, 0, 0], - [0, -1, 0, -1, 0], - [-1, 4, 5, 4, - 1], - [0, -1, 0, -1, 0], - [0, 0, 0.5, 0, 0]]) / 8 # yapf: disable + GR_GB = ( + as_float_array( + [ + [0.0, 0.0, -1.0, 0.0, 0.0], + [0.0, 0.0, 2.0, 0.0, 0.0], + [-1.0, 2.0, 4.0, 2.0, -1.0], + [0.0, 0.0, 2.0, 0.0, 0.0], + [0.0, 0.0, -1.0, 0.0, 0.0], + ] + ) + / 8 + ) + + Rg_RB_Bg_BR = ( + as_float_array( + [ + [0.0, 0.0, 0.5, 0.0, 0.0], + [0.0, -1.0, 0.0, -1.0, 0.0], + [-1.0, 4.0, 5.0, 4.0, -1.0], + [0.0, -1.0, 0.0, -1.0, 0.0], + [0.0, 0.0, 0.5, 0.0, 0.0], + ] + ) + / 8 + ) Rg_BR_Bg_RB = np.transpose(Rg_RB_Bg_BR) - Rb_BB_Br_RR = as_float_array( - [[0, 0, -1.5, 0, 0], - [0, 2, 0, 2, 0], - [-1.5, 0, 6, 0, -1.5], - [0, 2, 0, 2, 0], - [0, 0, -1.5, 0, 0]]) / 8 # yapf: disable + Rb_BB_Br_RR = ( + as_float_array( + [ + [0.0, 0.0, -1.5, 0.0, 0.0], + [0.0, 2.0, 0.0, 2.0, 0.0], + [-1.5, 0.0, 6.0, 0.0, -1.5], + [0.0, 2.0, 0.0, 2.0, 0.0], + [0.0, 0.0, -1.5, 0.0, 0.0], + ] + ) + / 8 + ) R = CFA * R_m G = CFA * G_m diff --git a/colour_demosaicing/bayer/demosaicing/menon2007.py b/colour_demosaicing/bayer/demosaicing/menon2007.py index 4146928..4a131df 100644 --- a/colour_demosaicing/bayer/demosaicing/menon2007.py +++ b/colour_demosaicing/bayer/demosaicing/menon2007.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- """ DDFAPD - Menon (2007) Bayer CFA Demosaicing =========================================== @@ -13,62 +12,63 @@ doi:10.1109/TIP.2006.884928 """ -from __future__ import division, unicode_literals +from __future__ import annotations import numpy as np from scipy.ndimage.filters import convolve, convolve1d +from colour.hints import ArrayLike, Boolean, Literal, NDArray, Union from colour.utilities import as_float_array, tsplit, tstack from colour_demosaicing.bayer import masks_CFA_Bayer -__author__ = 'Colour Developers' -__copyright__ = 'Copyright (C) 2015-2020 - Colour Developers' -__license__ = 'New BSD License - https://opensource.org/licenses/BSD-3-Clause' -__maintainer__ = 'Colour Developers' -__email__ = 'colour-developers@colour-science.org' -__status__ = 'Production' +__author__ = "Colour Developers" +__copyright__ = "Copyright 2015 Colour Developers" +__license__ = "New BSD License - https://opensource.org/licenses/BSD-3-Clause" +__maintainer__ = "Colour Developers" +__email__ = "colour-developers@colour-science.org" +__status__ = "Production" __all__ = [ - 'demosaicing_CFA_Bayer_Menon2007', 'demosaicing_CFA_Bayer_DDFAPD', - 'refining_step_Menon2007' + "demosaicing_CFA_Bayer_Menon2007", + "demosaicing_CFA_Bayer_DDFAPD", + "refining_step_Menon2007", ] -def _cnv_h(x, y): - """ - Helper function for horizontal convolution. - """ +def _cnv_h(x: ArrayLike, y: ArrayLike) -> NDArray: + """Perform horizontal convolution.""" - return convolve1d(x, y, mode='mirror') + return convolve1d(x, y, mode="mirror") -def _cnv_v(x, y): - """ - Helper function for vertical convolution. - """ +def _cnv_v(x: ArrayLike, y: ArrayLike) -> NDArray: + """Perform vertical convolution.""" - return convolve1d(x, y, mode='mirror', axis=0) + return convolve1d(x, y, mode="mirror", axis=0) -def demosaicing_CFA_Bayer_Menon2007(CFA, pattern='RGGB', refining_step=True): +def demosaicing_CFA_Bayer_Menon2007( + CFA: ArrayLike, + pattern: Union[Literal["RGGB", "BGGR", "GRBG", "GBRG"], str] = "RGGB", + refining_step: Boolean = True, +): """ - Returns the demosaiced *RGB* colourspace array from given *Bayer* CFA using + Return the demosaiced *RGB* colourspace array from given *Bayer* CFA using DDFAPD - *Menon (2007)* demosaicing algorithm. Parameters ---------- - CFA : array_like + CFA *Bayer* CFA. - pattern : unicode, optional - **{'RGGB', 'BGGR', 'GRBG', 'GBRG'}**, + pattern Arrangement of the colour filters on the pixel array. - refining_step : bool + refining_step Perform refining step. Returns ------- - ndarray + :class:`numpy.ndarray` *RGB* colourspace array. Notes @@ -117,8 +117,8 @@ def demosaicing_CFA_Bayer_Menon2007(CFA, pattern='RGGB', refining_step=True): CFA = as_float_array(CFA) R_m, G_m, B_m = masks_CFA_Bayer(CFA.shape, pattern) - h_0 = np.array([0, 0.5, 0, 0.5, 0]) - h_1 = np.array([-0.25, 0, 0.5, 0, -0.25]) + h_0 = as_float_array([0.0, 0.5, 0.0, 0.5, 0.0]) + h_1 = as_float_array([-0.25, 0.0, 0.5, 0.0, -0.25]) R = CFA * R_m G = CFA * G_m @@ -133,22 +133,23 @@ def demosaicing_CFA_Bayer_Menon2007(CFA, pattern='RGGB', refining_step=True): C_V = np.where(R_m == 1, R - G_V, 0) C_V = np.where(B_m == 1, B - G_V, C_V) - D_H = np.abs(C_H - np.pad(C_H, ((0, 0), - (0, 2)), mode=str('reflect'))[:, 2:]) - D_V = np.abs(C_V - np.pad(C_V, ((0, 2), - (0, 0)), mode=str('reflect'))[2:, :]) + D_H = np.abs(C_H - np.pad(C_H, ((0, 0), (0, 2)), mode="reflect")[:, 2:]) + D_V = np.abs(C_V - np.pad(C_V, ((0, 2), (0, 0)), mode="reflect")[2:, :]) del h_0, h_1, CFA, C_V, C_H - k = np.array( - [[0, 0, 1, 0, 1], - [0, 0, 0, 1, 0], - [0, 0, 3, 0, 3], - [0, 0, 0, 1, 0], - [0, 0, 1, 0, 1]]) # yapf: disable + k = as_float_array( + [ + [0.0, 0.0, 1.0, 0.0, 1.0], + [0.0, 0.0, 0.0, 1.0, 0.0], + [0.0, 0.0, 3.0, 0.0, 3.0], + [0.0, 0.0, 0.0, 1.0, 0.0], + [0.0, 0.0, 1.0, 0.0, 1.0], + ] + ) - d_H = convolve(D_H, k, mode='constant') - d_V = convolve(D_V, np.transpose(k), mode='constant') + d_H = convolve(D_H, k, mode="constant") + d_V = convolve(D_V, np.transpose(k), mode="constant") del D_H, D_V @@ -163,7 +164,7 @@ def demosaicing_CFA_Bayer_Menon2007(CFA, pattern='RGGB', refining_step=True): # Blue rows. B_r = np.transpose(np.any(B_m == 1, axis=1)[np.newaxis]) * np.ones(B.shape) - k_b = np.array([0.5, 0, 0.5]) + k_b = as_float_array([0.5, 0, 0.5]) R = np.where( np.logical_and(G_m == 1, R_r == 1), @@ -224,22 +225,24 @@ def demosaicing_CFA_Bayer_Menon2007(CFA, pattern='RGGB', refining_step=True): demosaicing_CFA_Bayer_DDFAPD = demosaicing_CFA_Bayer_Menon2007 -def refining_step_Menon2007(RGB, RGB_m, M): +def refining_step_Menon2007( + RGB: ArrayLike, RGB_m: ArrayLike, M: ArrayLike +) -> NDArray: """ - Performs the refining step on given *RGB* colourspace array. + Perform the refining step on given *RGB* colourspace array. Parameters ---------- - RGB : array_like + RGB *RGB* colourspace array. - RGB_m : array_like + RGB_m *Bayer* CFA red, green and blue masks. - M : array_like + M Estimation for the best directional reconstruction. Returns ------- - ndarray + :class:`numpy.ndarray` Refined *RGB* colourspace array. Examples @@ -318,7 +321,7 @@ def refining_step_Menon2007(RGB, RGB_m, M): R_G = R - G B_G = B - G - k_b = np.array([0.5, 0, 0.5]) + k_b = as_float_array([0.5, 0.0, 0.5]) R_G_m = np.where( np.logical_and(G_m == 1, B_r == 1), diff --git a/colour_demosaicing/bayer/demosaicing/tests/__init__.py b/colour_demosaicing/bayer/demosaicing/tests/__init__.py index 40a96af..e69de29 100644 --- a/colour_demosaicing/bayer/demosaicing/tests/__init__.py +++ b/colour_demosaicing/bayer/demosaicing/tests/__init__.py @@ -1 +0,0 @@ -# -*- coding: utf-8 -*- diff --git a/colour_demosaicing/bayer/demosaicing/tests/test_bilinear.py b/colour_demosaicing/bayer/demosaicing/tests/test_bilinear.py index f9b55ad..9f43171 100644 --- a/colour_demosaicing/bayer/demosaicing/tests/test_bilinear.py +++ b/colour_demosaicing/bayer/demosaicing/tests/test_bilinear.py @@ -1,11 +1,10 @@ # !/usr/bin/env python -# -*- coding: utf-8 -*- """ -Defines unit tests for :mod:`colour_demosaicing.bayer.demosaicing.bilinear` -module. +Defines the unit tests for the +:mod:`colour_demosaicing.bayer.demosaicing.bilinear` module. """ -from __future__ import division, unicode_literals +from __future__ import annotations import numpy as np import os @@ -16,41 +15,51 @@ from colour_demosaicing import TESTS_RESOURCES_DIRECTORY from colour_demosaicing.bayer import demosaicing_CFA_Bayer_bilinear -__author__ = 'Colour Developers' -__copyright__ = 'Copyright (C) 2015-2020 - Colour Developers' -__license__ = 'New BSD License - https://opensource.org/licenses/BSD-3-Clause' -__maintainer__ = 'Colour Developers' -__email__ = 'colour-developers@colour-science.org' -__status__ = 'Production' +__author__ = "Colour Developers" +__copyright__ = "Copyright 2015 Colour Developers" +__license__ = "New BSD License - https://opensource.org/licenses/BSD-3-Clause" +__maintainer__ = "Colour Developers" +__email__ = "colour-developers@colour-science.org" +__status__ = "Production" -__all__ = ['BAYER_DIRECTORY', 'TestDemosaicing_CFA_Bayer_bilinear'] +__all__ = [ + "BAYER_DIRECTORY", + "TestDemosaicing_CFA_Bayer_bilinear", +] -BAYER_DIRECTORY = os.path.join(TESTS_RESOURCES_DIRECTORY, 'colour_demosaicing', - 'bayer') +BAYER_DIRECTORY: str = os.path.join( + TESTS_RESOURCES_DIRECTORY, "colour_demosaicing", "bayer" +) class TestDemosaicing_CFA_Bayer_bilinear(unittest.TestCase): """ - Defines :func:`colour_demosaicing.bayer.demosaicing.bilinear.\ + Define :func:`colour_demosaicing.bayer.demosaicing.bilinear.\ demosaicing_CFA_Bayer_bilinear` definition unit tests methods. """ def test_demosaicing_CFA_Bayer_bilinear(self): """ - Tests :func:`colour_demosaicing.bayer.demosaicing.bilinear.\ + Test :func:`colour_demosaicing.bayer.demosaicing.bilinear.\ demosaicing_CFA_Bayer_bilinear` definition. """ - for pattern in ('RGGB', 'BGGR', 'GRBG', 'GBRG'): - CFA = os.path.join(BAYER_DIRECTORY, 'Lighthouse_CFA_{0}.exr') - RGB = os.path.join(BAYER_DIRECTORY, 'Lighthouse_Bilinear_{0}.exr') + for pattern in ("RGGB", "BGGR", "GRBG", "GBRG"): + CFA = os.path.join( + BAYER_DIRECTORY, f"Lighthouse_CFA_{pattern}.exr" + ) + RGB = os.path.join( + BAYER_DIRECTORY, f"Lighthouse_Bilinear_{pattern}.exr" + ) np.testing.assert_almost_equal( demosaicing_CFA_Bayer_bilinear( - read_image(str(CFA.format(pattern)))[..., 0], pattern), - read_image(str(RGB.format(pattern))), - decimal=7) + read_image(str(CFA))[..., 0], pattern + ), + read_image(str(RGB)), + decimal=7, + ) -if __name__ == '__main__': +if __name__ == "__main__": unittest.main() diff --git a/colour_demosaicing/bayer/demosaicing/tests/test_malvar2004.py b/colour_demosaicing/bayer/demosaicing/tests/test_malvar2004.py index b8356b3..8a3d6e3 100644 --- a/colour_demosaicing/bayer/demosaicing/tests/test_malvar2004.py +++ b/colour_demosaicing/bayer/demosaicing/tests/test_malvar2004.py @@ -1,11 +1,10 @@ # !/usr/bin/env python -# -*- coding: utf-8 -*- """ -Defines unit tests for :mod:`colour_demosaicing.bayer.demosaicing.malvar2004` -module. +Defines the unit tests for the +:mod:`colour_demosaicing.bayer.demosaicing.malvar2004` module. """ -from __future__ import division, unicode_literals +from __future__ import annotations import numpy as np import os @@ -16,42 +15,51 @@ from colour_demosaicing import TESTS_RESOURCES_DIRECTORY from colour_demosaicing.bayer import demosaicing_CFA_Bayer_Malvar2004 -__author__ = 'Colour Developers' -__copyright__ = 'Copyright (C) 2015-2020 - Colour Developers' -__license__ = 'New BSD License - https://opensource.org/licenses/BSD-3-Clause' -__maintainer__ = 'Colour Developers' -__email__ = 'colour-developers@colour-science.org' -__status__ = 'Production' +__author__ = "Colour Developers" +__copyright__ = "Copyright 2015 Colour Developers" +__license__ = "New BSD License - https://opensource.org/licenses/BSD-3-Clause" +__maintainer__ = "Colour Developers" +__email__ = "colour-developers@colour-science.org" +__status__ = "Production" -__all__ = ['BAYER_DIRECTORY', 'TestDemosaicing_CFA_Bayer_Malvar2004'] +__all__ = [ + "BAYER_DIRECTORY", + "TestDemosaicing_CFA_Bayer_Malvar2004", +] -BAYER_DIRECTORY = os.path.join(TESTS_RESOURCES_DIRECTORY, 'colour_demosaicing', - 'bayer') +BAYER_DIRECTORY: str = os.path.join( + TESTS_RESOURCES_DIRECTORY, "colour_demosaicing", "bayer" +) class TestDemosaicing_CFA_Bayer_Malvar2004(unittest.TestCase): """ - Defines :func:`colour_demosaicing.bayer.demosaicing.malvar2004.\ + Define :func:`colour_demosaicing.bayer.demosaicing.malvar2004.\ demosaicing_CFA_Bayer_Malvar2004` definition unit tests methods. """ def test_demosaicing_CFA_Bayer_Malvar2004(self): """ - Tests :func:`colour_demosaicing.bayer.demosaicing.malvar2004.\ + Test :func:`colour_demosaicing.bayer.demosaicing.malvar2004.\ demosaicing_CFA_Bayer_Malvar2004` definition. """ - for pattern in ('RGGB', 'BGGR', 'GRBG', 'GBRG'): - CFA = os.path.join(BAYER_DIRECTORY, 'Lighthouse_CFA_{0}.exr') - RGB = os.path.join(BAYER_DIRECTORY, - 'Lighthouse_Malvar2004_{0}.exr') + for pattern in ("RGGB", "BGGR", "GRBG", "GBRG"): + CFA = os.path.join( + BAYER_DIRECTORY, f"Lighthouse_CFA_{pattern}.exr" + ) + RGB = os.path.join( + BAYER_DIRECTORY, f"Lighthouse_Malvar2004_{pattern}.exr" + ) np.testing.assert_almost_equal( demosaicing_CFA_Bayer_Malvar2004( - read_image(str(CFA.format(pattern)))[..., 0], pattern), - read_image(str(RGB.format(pattern))), - decimal=7) + read_image(str(CFA))[..., 0], pattern + ), + read_image(str(RGB)), + decimal=7, + ) -if __name__ == '__main__': +if __name__ == "__main__": unittest.main() diff --git a/colour_demosaicing/bayer/demosaicing/tests/test_menon2007.py b/colour_demosaicing/bayer/demosaicing/tests/test_menon2007.py index 7c73935..db1a964 100644 --- a/colour_demosaicing/bayer/demosaicing/tests/test_menon2007.py +++ b/colour_demosaicing/bayer/demosaicing/tests/test_menon2007.py @@ -1,11 +1,10 @@ # !/usr/bin/env python -# -*- coding: utf-8 -*- """ -Defines unit tests for :mod:`colour_demosaicing.bayer.demosaicing.menon2007` -module. +Defines the unit tests for the +:mod:`colour_demosaicing.bayer.demosaicing.menon2007` module. """ -from __future__ import division, unicode_literals +from __future__ import annotations import numpy as np import os @@ -16,51 +15,64 @@ from colour_demosaicing import TESTS_RESOURCES_DIRECTORY from colour_demosaicing.bayer import demosaicing_CFA_Bayer_Menon2007 -__author__ = 'Colour Developers' -__copyright__ = 'Copyright (C) 2015-2020 - Colour Developers' -__license__ = 'New BSD License - https://opensource.org/licenses/BSD-3-Clause' -__maintainer__ = 'Colour Developers' -__email__ = 'colour-developers@colour-science.org' -__status__ = 'Production' +__author__ = "Colour Developers" +__copyright__ = "Copyright 2015 Colour Developers" +__license__ = "New BSD License - https://opensource.org/licenses/BSD-3-Clause" +__maintainer__ = "Colour Developers" +__email__ = "colour-developers@colour-science.org" +__status__ = "Production" -__all__ = ['BAYER_DIRECTORY', 'TestDemosaicing_CFA_Bayer_Menon2007'] +__all__ = [ + "BAYER_DIRECTORY", + "TestDemosaicing_CFA_Bayer_Menon2007", +] -BAYER_DIRECTORY = os.path.join(TESTS_RESOURCES_DIRECTORY, 'colour_demosaicing', - 'bayer') +BAYER_DIRECTORY: str = os.path.join( + TESTS_RESOURCES_DIRECTORY, "colour_demosaicing", "bayer" +) class TestDemosaicing_CFA_Bayer_Menon2007(unittest.TestCase): """ - Defines :func:`colour_demosaicing.bayer.demosaicing.menon2007.\ + Define :func:`colour_demosaicing.bayer.demosaicing.menon2007.\ demosaicing_CFA_Bayer_Menon2007` definition unit tests methods. """ def test_demosaicing_CFA_Bayer_Menon2007(self): """ - Tests :func:`colour_demosaicing.bayer.demosaicing.menon2007.\ + Test :func:`colour_demosaicing.bayer.demosaicing.menon2007.\ demosaicing_CFA_Bayer_Menon2007` definition. """ - for pattern in ('RGGB', 'BGGR', 'GRBG', 'GBRG'): - CFA = os.path.join(BAYER_DIRECTORY, 'Lighthouse_CFA_{0}.exr') - RGB = os.path.join(BAYER_DIRECTORY, 'Lighthouse_Menon2007_{0}.exr') + for pattern in ("RGGB", "BGGR", "GRBG", "GBRG"): + CFA = os.path.join( + BAYER_DIRECTORY, f"Lighthouse_CFA_{pattern}.exr" + ) + RGB = os.path.join( + BAYER_DIRECTORY, f"Lighthouse_Menon2007_{pattern}.exr" + ) np.testing.assert_almost_equal( demosaicing_CFA_Bayer_Menon2007( - read_image(str(CFA.format(pattern)))[..., 0], pattern), - read_image(str(RGB.format(pattern))), - decimal=7) + read_image(str(CFA))[..., 0], pattern + ), + read_image(str(RGB)), + decimal=7, + ) - RGB = os.path.join(BAYER_DIRECTORY, - 'Lighthouse_Menon2007_NR_{0}.exr') + RGB = os.path.join( + BAYER_DIRECTORY, f"Lighthouse_Menon2007_NR_{pattern}.exr" + ) np.testing.assert_almost_equal( demosaicing_CFA_Bayer_Menon2007( - read_image(str(CFA.format(pattern)))[..., 0], + read_image(str(CFA))[..., 0], pattern, - refining_step=False), - read_image(str(RGB.format(pattern))), - decimal=7) + refining_step=False, + ), + read_image(str(RGB)), + decimal=7, + ) -if __name__ == '__main__': +if __name__ == "__main__": unittest.main() diff --git a/colour_demosaicing/bayer/masks.py b/colour_demosaicing/bayer/masks.py index 9148877..5ac7a18 100644 --- a/colour_demosaicing/bayer/masks.py +++ b/colour_demosaicing/bayer/masks.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- """ Bayer CFA Masks =============== @@ -6,35 +5,42 @@ *Bayer* CFA (Colour Filter Array) masks generation. """ -from __future__ import division, unicode_literals +from __future__ import annotations import numpy as np -__author__ = 'Colour Developers' -__copyright__ = 'Copyright (C) 2015-2020 - Colour Developers' -__license__ = 'New BSD License - https://opensource.org/licenses/BSD-3-Clause' -__maintainer__ = 'Colour Developers' -__email__ = 'colour-developers@colour-science.org' -__status__ = 'Production' +from colour.hints import Literal, NDArray, Tuple, Union +from colour.utilities import validate_method -__all__ = ['masks_CFA_Bayer'] +__author__ = "Colour Developers" +__copyright__ = "Copyright 2015 Colour Developers" +__license__ = "New BSD License - https://opensource.org/licenses/BSD-3-Clause" +__maintainer__ = "Colour Developers" +__email__ = "colour-developers@colour-science.org" +__status__ = "Production" +__all__ = [ + "masks_CFA_Bayer", +] -def masks_CFA_Bayer(shape, pattern='RGGB'): + +def masks_CFA_Bayer( + shape: Union[int, Tuple[int, ...]], + pattern: Union[Literal["RGGB", "BGGR", "GRBG", "GBRG"], str] = "RGGB", +) -> Tuple[NDArray, ...]: """ - Returns the *Bayer* CFA red, green and blue masks for given pattern. + Return the *Bayer* CFA red, green and blue masks for given pattern. Parameters ---------- - shape : array_like + shape Dimensions of the *Bayer* CFA. - pattern : unicode, optional - **{'RGGB', 'BGGR', 'GRBG', 'GBRG'}**, + pattern Arrangement of the colour filters on the pixel array. Returns ------- - tuple + :class:`tuple` *Bayer* CFA red, green and blue masks. Examples @@ -63,10 +69,14 @@ def masks_CFA_Bayer(shape, pattern='RGGB'): [ True, False, True]], dtype=bool)) """ - pattern = pattern.upper() + pattern = validate_method( + pattern, + ["RGGB", "BGGR", "GRBG", "GBRG"], + '"{0}" CFA pattern is invalid, it must be one of {1}!', + ).upper() - channels = dict((channel, np.zeros(shape)) for channel in 'RGB') + channels = {channel: np.zeros(shape) for channel in "RGB"} for channel, (y, x) in zip(pattern, [(0, 0), (0, 1), (1, 0), (1, 1)]): channels[channel][y::2, x::2] = 1 - return tuple(channels[c].astype(bool) for c in 'RGB') + return tuple(channels[c].astype(bool) for c in "RGB") diff --git a/colour_demosaicing/bayer/mosaicing.py b/colour_demosaicing/bayer/mosaicing.py index 9e0cee5..be36517 100644 --- a/colour_demosaicing/bayer/mosaicing.py +++ b/colour_demosaicing/bayer/mosaicing.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- """ Bayer CFA Mosaicing =================== @@ -6,37 +5,42 @@ *Bayer* CFA (Colour Filter Array) data generation. """ -from __future__ import division, unicode_literals +from __future__ import annotations +from colour.hints import ArrayLike, Literal, NDArray, Union from colour.utilities import as_float_array, tsplit from colour_demosaicing.bayer import masks_CFA_Bayer -__author__ = 'Colour Developers' -__copyright__ = 'Copyright (C) 2015-2020 - Colour Developers' -__license__ = 'New BSD License - https://opensource.org/licenses/BSD-3-Clause' -__maintainer__ = 'Colour Developers' -__email__ = 'colour-developers@colour-science.org' -__status__ = 'Production' +__author__ = "Colour Developers" +__copyright__ = "Copyright 2015 Colour Developers" +__license__ = "New BSD License - https://opensource.org/licenses/BSD-3-Clause" +__maintainer__ = "Colour Developers" +__email__ = "colour-developers@colour-science.org" +__status__ = "Production" -__all__ = ['mosaicing_CFA_Bayer'] +__all__ = [ + "mosaicing_CFA_Bayer", +] -def mosaicing_CFA_Bayer(RGB, pattern='RGGB'): +def mosaicing_CFA_Bayer( + RGB: ArrayLike, + pattern: Union[Literal["RGGB", "BGGR", "GRBG", "GBRG"], str] = "RGGB", +) -> NDArray: """ - Returns the *Bayer* CFA mosaic for a given *RGB* colourspace array. + Return the *Bayer* CFA mosaic for a given *RGB* colourspace array. Parameters ---------- - RGB : array_like + RGB *RGB* colourspace array. - pattern : unicode, optional - **{'RGGB', 'BGGR', 'GRBG', 'GBRG'}**, + pattern Arrangement of the colour filters on the pixel array. Returns ------- - ndarray + :class:`numpy.ndarray` *Bayer* CFA mosaic. Examples diff --git a/colour_demosaicing/bayer/tests/__init__.py b/colour_demosaicing/bayer/tests/__init__.py index 40a96af..e69de29 100644 --- a/colour_demosaicing/bayer/tests/__init__.py +++ b/colour_demosaicing/bayer/tests/__init__.py @@ -1 +0,0 @@ -# -*- coding: utf-8 -*- diff --git a/colour_demosaicing/bayer/tests/test_masks.py b/colour_demosaicing/bayer/tests/test_masks.py index 33836d8..7fe0bf9 100644 --- a/colour_demosaicing/bayer/tests/test_masks.py +++ b/colour_demosaicing/bayer/tests/test_masks.py @@ -1,10 +1,7 @@ # !/usr/bin/env python -# -*- coding: utf-8 -*- -""" -Defines unit tests for :mod:`colour_demosaicing.bayer.masks` module. -""" +"""Defines the unit tests for the :mod:`colour_demosaicing.bayer.masks` module.""" -from __future__ import division, unicode_literals +from __future__ import annotations import numpy as np import os @@ -16,38 +13,43 @@ from colour_demosaicing import TESTS_RESOURCES_DIRECTORY from colour_demosaicing.bayer import masks_CFA_Bayer -__author__ = 'Colour Developers' -__copyright__ = 'Copyright (C) 2015-2020 - Colour Developers' -__license__ = 'New BSD License - https://opensource.org/licenses/BSD-3-Clause' -__maintainer__ = 'Colour Developers' -__email__ = 'colour-developers@colour-science.org' -__status__ = 'Production' +__author__ = "Colour Developers" +__copyright__ = "Copyright 2015 Colour Developers" +__license__ = "New BSD License - https://opensource.org/licenses/BSD-3-Clause" +__maintainer__ = "Colour Developers" +__email__ = "colour-developers@colour-science.org" +__status__ = "Production" -__all__ = ['BAYER_DIRECTORY', 'TestMasks_CFA_Bayer'] +__all__ = [ + "BAYER_DIRECTORY", + "TestMasks_CFA_Bayer", +] -BAYER_DIRECTORY = os.path.join(TESTS_RESOURCES_DIRECTORY, 'colour_demosaicing', - 'bayer') +BAYER_DIRECTORY: str = os.path.join( + TESTS_RESOURCES_DIRECTORY, "colour_demosaicing", "bayer" +) class TestMasks_CFA_Bayer(unittest.TestCase): """ - Defines :func:`colour_demosaicing.bayer.masks.masks_CFA_Bayer` definition + Define :func:`colour_demosaicing.bayer.masks.masks_CFA_Bayer` definition unit tests methods. """ def test_masks_CFA_Bayer(self): """ - Tests :func:`colour_demosaicing.bayer.masks.masks_CFA_Bayer` + Test :func:`colour_demosaicing.bayer.masks.masks_CFA_Bayer` definition. """ - for pattern in ('RGGB', 'BGGR', 'GRBG', 'GBRG'): - mask = os.path.join(BAYER_DIRECTORY, '{0}_Masks.exr') + for pattern in ("RGGB", "BGGR", "GRBG", "GBRG"): + mask = os.path.join(BAYER_DIRECTORY, f"{pattern}_Masks.exr") np.testing.assert_almost_equal( tstack(masks_CFA_Bayer((8, 8), pattern)), - read_image(str(mask.format(pattern))), - decimal=7) + read_image(str(mask)), + decimal=7, + ) -if __name__ == '__main__': +if __name__ == "__main__": unittest.main() diff --git a/colour_demosaicing/bayer/tests/test_mosaicing.py b/colour_demosaicing/bayer/tests/test_mosaicing.py index 7b83899..62cfb91 100644 --- a/colour_demosaicing/bayer/tests/test_mosaicing.py +++ b/colour_demosaicing/bayer/tests/test_mosaicing.py @@ -1,10 +1,10 @@ # !/usr/bin/env python -# -*- coding: utf-8 -*- """ -Defines unit tests for :mod:`colour_demosaicing.bayer.mosaicing` module. +Defines the unit tests for the :mod:`colour_demosaicing.bayer.mosaicing` +module. """ -from __future__ import division, unicode_literals +from __future__ import annotations import numpy as np import os @@ -15,41 +15,49 @@ from colour_demosaicing import TESTS_RESOURCES_DIRECTORY from colour_demosaicing.bayer import mosaicing_CFA_Bayer -__author__ = 'Colour Developers' -__copyright__ = 'Copyright (C) 2015-2020 - Colour Developers' -__license__ = 'New BSD License - https://opensource.org/licenses/BSD-3-Clause' -__maintainer__ = 'Colour Developers' -__email__ = 'colour-developers@colour-science.org' -__status__ = 'Production' +__author__ = "Colour Developers" +__copyright__ = "Copyright 2015 Colour Developers" +__license__ = "New BSD License - https://opensource.org/licenses/BSD-3-Clause" +__maintainer__ = "Colour Developers" +__email__ = "colour-developers@colour-science.org" +__status__ = "Production" -__all__ = ['BAYER_DIRECTORY', 'TestMosaicing_CFA_Bayer'] +__all__ = [ + "BAYER_DIRECTORY", + "TestMosaicing_CFA_Bayer", +] -BAYER_DIRECTORY = os.path.join(TESTS_RESOURCES_DIRECTORY, 'colour_demosaicing', - 'bayer') +BAYER_DIRECTORY: str = os.path.join( + TESTS_RESOURCES_DIRECTORY, "colour_demosaicing", "bayer" +) class TestMosaicing_CFA_Bayer(unittest.TestCase): """ - Defines :func:`colour_demosaicing.bayer.mosaicing.mosaicing_CFA_Bayer` + Define :func:`colour_demosaicing.bayer.mosaicing.mosaicing_CFA_Bayer` definition unit tests methods. """ def test_mosaicing_CFA_Bayer(self): """ - Tests :func:`colour_demosaicing.bayer.mosaicing.mosaicing_CFA_Bayer` + Test :func:`colour_demosaicing.bayer.mosaicing.mosaicing_CFA_Bayer` definition. """ image = read_image( - str(os.path.join(BAYER_DIRECTORY, 'Lighthouse.exr'))) + str(os.path.join(BAYER_DIRECTORY, "Lighthouse.exr")) + ) - for pattern in ('RGGB', 'BGGR', 'GRBG', 'GBRG'): - CFA = os.path.join(BAYER_DIRECTORY, 'Lighthouse_CFA_{0}.exr') + for pattern in ("RGGB", "BGGR", "GRBG", "GBRG"): + CFA = os.path.join( + BAYER_DIRECTORY, f"Lighthouse_CFA_{pattern}.exr" + ) np.testing.assert_almost_equal( mosaicing_CFA_Bayer(image, pattern), - read_image(str(CFA.format(pattern)))[..., 0], - decimal=7) + read_image(str(CFA))[..., 0], + decimal=7, + ) -if __name__ == '__main__': +if __name__ == "__main__": unittest.main() diff --git a/colour_demosaicing/py.typed b/colour_demosaicing/py.typed new file mode 100644 index 0000000..e69de29 diff --git a/docs/_static/Logo_Dark_001.svg b/docs/_static/Logo_Dark_001.svg new file mode 100644 index 0000000..eb0ff27 --- /dev/null +++ b/docs/_static/Logo_Dark_001.svg @@ -0,0 +1,71 @@ + + + + + + + + + diff --git a/docs/_static/Logo_Light_001.svg b/docs/_static/Logo_Light_001.svg new file mode 100644 index 0000000..3d7da27 --- /dev/null +++ b/docs/_static/Logo_Light_001.svg @@ -0,0 +1,71 @@ + + + + + + + + + diff --git a/docs/_static/Logo_Medium_001.png b/docs/_static/Logo_Medium_001.png index 1cb6138..ca33043 100644 Binary files a/docs/_static/Logo_Medium_001.png and b/docs/_static/Logo_Medium_001.png differ diff --git a/docs/_static/Logo_Small_001.png b/docs/_static/Logo_Small_001.png index 42de30b..0fc3bb3 100644 Binary files a/docs/_static/Logo_Small_001.png and b/docs/_static/Logo_Small_001.png differ diff --git a/docs/_static/custom.css b/docs/_static/custom.css deleted file mode 100644 index e39ccc7..0000000 --- a/docs/_static/custom.css +++ /dev/null @@ -1,26 +0,0 @@ -p { - margin-bottom: 8px !important; -} - -.wy-table-responsive table td { - background-color: rgb(252, 252, 252) !important; - border: 0 !important; - padding: 2px 4px 2px 0px !important; - vertical-align: top !important; - white-space: normal !important; -} - -.wy-table-responsive { - overflow: visible !important; -} - -.wy-table-bordered-all, .rst-content table.docutils { - border: 0 !important; -} - -div.highlight-text { - background-color: rgb(252, 252, 252) !important; - font-family: monospace; - font-style: italic; - margin: -24px 0 24px 0; -} \ No newline at end of file diff --git a/docs/bibliography.rst b/docs/bibliography.rst index b8ea67e..9862a8c 100644 --- a/docs/bibliography.rst +++ b/docs/bibliography.rst @@ -3,4 +3,3 @@ Bibliography .. bibliography:: bibliography.bib :all: - :encoding: utf8 diff --git a/docs/colour_demosaicing.bayer.rst b/docs/colour_demosaicing.bayer.rst index bcc4cca..4c76589 100644 --- a/docs/colour_demosaicing.bayer.rst +++ b/docs/colour_demosaicing.bayer.rst @@ -1,8 +1,6 @@ Bayer CFA Demosaicing and Mosaicing =================================== -.. contents:: :local: - Demosaicing ----------- diff --git a/docs/conf.py b/docs/conf.py index 68b690b..9e0fb0e 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -1,215 +1,138 @@ -# -*- coding: utf-8 -*- -# -# colour-demosaicing documentation build configuration file, created by -# sphinx-quickstart on Tue Aug 5 14:31:53 2014. -# -# 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. +""" +Colour - Demosaicing - Documentation Configuration +================================================== +""" import re import colour_demosaicing as package -basename = re.sub('_(\\w)', lambda x: x.group(1).upper(), - package.__name__.title()) - -autodoc_member_order = 'bysource' -autodoc_mock_imports = ['colour', 'scipy', 'scipy.ndimage.filters'] - -autosummary_generate = True - -napoleon_custom_sections = ['Attributes', 'Methods'] - -# 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 -# documentation root, use os.path.abspath to make it absolute, like shown here. -# sys.path.insert(0, os.path.abspath('.')) +basename = re.sub( + "_(\\w)", lambda x: x.group(1).upper(), package.__name__.title() +) # -- General configuration ------------------------------------------------ - -# If your documentation needs a minimal Sphinx version, state it here. -# needs_sphinx = '1.0' - -# Add any Sphinx extension module names here, as strings. They can be -# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom -# ones. extensions = [ - 'sphinx.ext.autodoc', 'sphinx.ext.autosummary', 'sphinx.ext.coverage', - 'sphinx.ext.ifconfig', 'sphinx.ext.intersphinx', 'sphinx.ext.mathjax', - 'sphinx.ext.napoleon', 'sphinx.ext.todo', 'sphinx.ext.viewcode', - 'sphinxcontrib.bibtex' + "sphinx.ext.autodoc", + "sphinx.ext.autosummary", + "sphinx.ext.coverage", + "sphinx.ext.ifconfig", + "sphinx.ext.inheritance_diagram", + "sphinx.ext.intersphinx", + "sphinx.ext.mathjax", + "sphinx.ext.napoleon", + "sphinx.ext.todo", + "sphinx.ext.viewcode", + "sphinxcontrib.bibtex", ] -# Add any paths that contain templates here, relative to this directory. -templates_path = ['_templates'] - -# The suffix of source filenames. -source_suffix = '.rst' - -# The encoding of source files. -# source_encoding = 'utf-8-sig' - -# The master toctree document. -master_doc = 'index' - -# General information about the project. -project = package.__application_name__ -copyright = package.__copyright__.replace('Copyright (C)', '') - -# 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 = '{0}.{1}'.format(package.__major_version__, - package.__minor_version__) -# The full version, including alpha/beta/rc tags. -release = package.__version__ - -# The language for content autogenerated by Sphinx. Refer to documentation -# for a list of supported languages. -# language = None +intersphinx_mapping = { + "python": ("https://docs.python.org/3.8", None), + "matplotlib": ("https://matplotlib.org/stable", None), + "numpy": ("https://numpy.org/doc/stable", None), + "pandas": ("https://pandas.pydata.org/pandas-docs/dev", None), + "scipy": ("https://docs.scipy.org/doc/scipy-1.8.0/html-scipyorg", 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' +autodoc_member_order = "bysource" +autodoc_mock_imports = [ + "colour", + "scipy", + "scipy.ndimage.filters", +] +autodoc_typehints = "both" +autodoc_type_aliases = { + "ArrayLike": "ArrayLike", + "Boolean": "Boolean", + "BooleanOrArrayLike": "BooleanOrArrayLike", + "BooleanOrNDArray": "BooleanOrNDArray", + "DType": "DType", + "DTypeBoolean": "DTypeBoolean", + "DTypeComplex": "DTypeComplex", + "DTypeFloating": "DTypeFloating", + "DTypeInteger": "DTypeInteger", + "DTypeNumber": "DTypeNumber", + "Floating": "Floating", + "FloatingOrArrayLike": "FloatingOrArrayLike", + "FloatingOrNDArray": "FloatingOrNDArray", + "Integer": "Integer", + "IntegerOrArrayLike": "IntegerOrArrayLike", + "IntegerOrNDArray": "IntegerOrNDArray", + "NestedSequence": "NestedSequence", + "Number": "Number", + "NumberOrArrayLike": "NumberOrArrayLike", + "NumberOrNDArray": "NumberOrNDArray", + "StrOrArrayLike": "StrOrArrayLike", + "StrOrNDArray": "StrOrNDArray", +} +autodoc_preserve_defaults = True -# List of patterns, relative to source directory, that match files and -# directories to ignore when looking for source files. -exclude_patterns = ['_build'] +autoclass_content = "both" -# The reST default role (used for this markup: `text`) to use for all -# documents. -# default_role = None +autosummary_generate = True -# If true, '()' will be appended to :func: etc. cross-reference text. -# add_function_parentheses = True +bibtex_bibfiles = ["bibliography.bib"] +bibtex_encoding = "utf8" -# If true, the current module name will be prepended to all description -# unit titles (such as .. function::). -# add_module_names = True +napoleon_custom_sections = ["Attributes", "Methods"] -# If true, sectionauthor and moduleauthor directives will be shown in the -# output. They are ignored by default. -# show_authors = False +templates_path = ["_templates"] +source_suffix = ".rst" +master_doc = "index" -# The name of the Pygments (syntax highlighting) style to use. -pygments_style = 'lovelace' +project = package.__application_name__ +copyright = package.__copyright__.replace("Copyright (C)", "") +version = f"{package.__major_version__}.{package.__minor_version__}" +release = package.__version__ -# A list of ignored prefixes for module index sorting. -# modindex_common_prefix = [] +exclude_patterns = ["_build"] -# If true, keep warnings as 'system message' paragraphs in the built documents. -# keep_warnings = False +pygments_style = "lovelace" # -- 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_options = {} - -# 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 = {} - -# 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 - -# A shorter title for the navigation bar. Default is the same as html_title. -# html_short_title = None - -# The name of an image file (relative to this directory) to place at the top -# of the sidebar. -html_logo = '_static/Logo_Small_001.png' - -# The name of an image file (within the static path) to use as favicon of the -# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 -# 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'] - -# 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' - -# 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 = {} - -# 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 - -# If true, 'Created using Sphinx' is shown in the HTML footer. Default is 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 - -# Output file base name for HTML help builder. -htmlhelp_basename = '{0}Doc'.format(basename) +html_theme = "pydata_sphinx_theme" +html_theme_options = { + "show_nav_level": 2, + "icon_links": [ + { + "name": "Email", + "url": "mailto:colour-developers@colour-science.org", + "icon": "fas fa-envelope", + }, + { + "name": "GitHub", + "url": ( + f"https://github.com/colour-science/" + f"{package.__name__.replace('_', '-')}" + ), + "icon": "fab fa-github", + }, + { + "name": "Facebook", + "url": "https://www.facebook.com/python.colour.science", + "icon": "fab fa-facebook", + }, + { + "name": "Gitter", + "url": "https://gitter.im/colour-science/colour", + "icon": "fab fa-gitter", + }, + { + "name": "Twitter", + "url": "https://twitter.com/colour_science", + "icon": "fab fa-twitter", + }, + ], +} +html_logo = "_static/Logo_Light_001.svg" +html_static_path = ["_static"] +htmlhelp_basename = f"{basename}Doc" # -- Options for LaTeX output --------------------------------------------- - latex_elements = { - # The paper size ('letterpaper' or 'a4paper'). - 'papersize': - 'a4paper', - - # The font size ('10pt', '11pt' or '12pt'). - 'pointsize': - '10pt', - - # Additional stuff for the LaTeX preamble. - 'preamble': - """ + "papersize": "a4paper", + "pointsize": "10pt", + "preamble": """ \\usepackage{charter} \\usepackage[defaultsans]{lato} \\usepackage{inconsolata} @@ -226,151 +149,60 @@ \\makeatother """, } - -# 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 = [ - ('index', '{0}.tex'.format(basename), u'{0} Documentation'.format( - package.__application_name__), package.__author__, 'manual'), + ( + "index", + f"{basename}.tex", + f"{package.__application_name__} Documentation", + package.__author__, + "manual", + ), ] - -# The name of an image file (relative to this directory) to place at the top of -# the title page. -latex_logo = '_static/Logo_Medium_001.png' - -# 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 +latex_logo = "_static/Logo_Medium_001.png" # -- Options for manual page output --------------------------------------- - -# One entry per manual page. List of tuples -# (source start file, name, description, authors, manual section). -man_pages = [('index', basename, u'{0} Documentation'.format( - package.__application_name__), [package.__author__], 1)] - -# If true, show URL addresses after external links. -# man_show_urls = False +man_pages = [ + ( + "index", + basename, + f"{package.__application_name__} Documentation", + [package.__author__], + 1, + ) +] # -- Options for Texinfo output ------------------------------------------- - -# Grouping the document tree into Texinfo files. List of tuples -# (source start file, target name, title, author, -# dir menu entry, description, category) texinfo_documents = [ - ('index', basename, u'{0} Documentation'.format( - package.__application_name__), package.__author__, - package.__application_name__, basename, 'Miscellaneous'), + ( + "index", + basename, + f"{package.__application_name__} Documentation", + package.__author__, + package.__application_name__, + basename, + "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 = package.__application_name__ epub_author = package.__author__ epub_publisher = package.__author__ -epub_copyright = package.__copyright__.replace('Copyright (C)', '') - -# The basename for the epub file. It defaults to the project name. -# epub_basename = basename - -# 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' +epub_copyright = package.__copyright__.replace("Copyright (C)", "") +epub_exclude_files = ["search.html"] -# The language of the text. It defaults to the language option -# or en if the language is not set. -# epub_language = '' -# The scheme of the identifier. Typical schemes are ISBN or URL. -# epub_scheme = '' +def autodoc_process_docstring(app, what, name, obj, options, lines): + """Process the docstrings to remove the *# noqa* *flake8* pragma.""" -# 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 = '' - -# A tuple containing the cover image and cover page html template filenames. -# epub_cover = () - -# A sequence of (type, uri, title) tuples for the guide element of content.opf. -# epub_guide = () - -# 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 = [] - -# HTML files shat 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'] - -# The depth of the table of contents in toc.ncx. -# epub_tocdepth = 3 - -# Allow duplicate toc entries. -# epub_tocdup = True - -# Choose between 'default' and 'includehidden'. -# epub_tocscope = 'default' - -# Fix unsupported image types using the PIL. -# 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 - -autoclass_content = 'both' - -intersphinx_mapping = {'python': ('https://docs.python.org/3.7', None)} + for i, line in enumerate(lines): + lines[i] = line.replace("# noqa", "") -def _autodoc_process_docstring(app, what, name, obj, options, lines): +def setup(app): """ - Process the docstrings to remove the *# noqa* *flake8* pragma. + Prepare the extension and linking resources that Sphinx uses in the + build process. """ - for i, line in enumerate(lines): - lines[i] = line.replace('# noqa', '') - - -def setup(app): - app.add_stylesheet('custom.css') - app.connect('autodoc-process-docstring', _autodoc_process_docstring) + app.connect("autodoc-process-docstring", autodoc_process_docstring) diff --git a/docs/index.rst b/docs/index.rst index ab48907..33f9407 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -9,10 +9,6 @@ It is open source and freely available under the .. image:: https://raw.githubusercontent.com/colour-science/colour-demosaicing/master/docs/_static/Demosaicing_001.png -.. contents:: **Table of Contents** - :backlinks: none - :depth: 3 - .. sectnum:: Features @@ -20,64 +16,9 @@ Features The following CFA (Colour Filter Array) demosaicing algorithms are implemented: -- Bilinear -- Malvar (2004) -- DDFAPD - Menon (2007) - -Installation ------------- - -Because of their size, the resources dependencies needed to run the various -examples and unit tests are not provided within the Pypi package. They are -separately available as -`Git Submodules `__ -when cloning the -`repository `__. - -Primary Dependencies -^^^^^^^^^^^^^^^^^^^^ - -**Colour - Demosaicing** requires various dependencies in order to run: - -- `python>=2.7 `__ or - `python>=3.5 `__ -- `colour-science `__ - -Pypi -^^^^ - -Once the dependencies are satisfied, **Colour - Demosaicing** can be installed from -the `Python Package Index `__ by -issuing this command in a shell:: - - pip install --user colour-demosaicing - -The tests suite dependencies are installed as follows:: - - pip install --user 'colour-demosaicing[tests]' - -The documentation building dependencies are installed as follows:: - - pip install --user 'colour-demosaicing[docs]' - -The overall development dependencies are installed as follows:: - - pip install --user 'colour-demosaicing[development]' - -Usage ------ - -API -^^^ - -The main reference for -`Colour - Demosaicing `__ -is the manual: - -.. toctree:: - :maxdepth: 4 - - manual +- Bilinear +- Malvar (2004) +- DDFAPD - Menon (2007) Examples ^^^^^^^^ @@ -85,19 +26,21 @@ Examples Various usage examples are available from the `examples directory `__. -Contributing ------------- +User Guide +---------- -If you would like to contribute to `Colour - Demosaicing `__, -please refer to the following `Contributing `__ -guide for `Colour `__. +.. toctree:: + :maxdepth: 2 + + user-guide -Bibliography ------------- +API Reference +------------- + +.. toctree:: + :maxdepth: 2 -The bibliography is available in the repository in -`BibTeX `__ -format. + reference Code of Conduct --------------- @@ -105,10 +48,21 @@ Code of Conduct The *Code of Conduct*, adapted from the `Contributor Covenant 1.4 `__, is available on the `Code of Conduct `__ page. +Contact & Social +---------------- + +The *Colour Developers* can be reached via different means: + +- `Email `__ +- `Facebook `__ +- `Github Discussions `__ +- `Gitter `__ +- `Twitter `__ + About ----- | **Colour - Demosaicing** by Colour Developers -| Copyright © 2015-2020 – Colour Developers – `colour-developers@colour-science.org `__ +| Copyright 2015 Colour Developers – `colour-developers@colour-science.org `__ | This software is released under terms of New BSD License: https://opensource.org/licenses/BSD-3-Clause | `https://github.com/colour-science/colour-demosaicing `__ diff --git a/docs/installation.rst b/docs/installation.rst new file mode 100644 index 0000000..d9e1e5c --- /dev/null +++ b/docs/installation.rst @@ -0,0 +1,30 @@ +Installation Guide +================== + +Because of their size, the resources dependencies needed to run the various +examples and unit tests are not provided within the Pypi package. They are +separately available as +`Git Submodules `__ +when cloning the +`repository `__. + +Primary Dependencies +-------------------- + +**Colour - Demosaicing** requires various dependencies in order to run: + +- `python >= 3.8, < 4 `__ +- `colour-science `__ + +Pypi +---- + +Once the dependencies are satisfied, **Colour - Demosaicing** can be installed from +the `Python Package Index `__ by +issuing this command in a shell:: + + pip install --user colour-demosaicing + +The overall development dependencies are installed as follows:: + + pip install --user 'colour-demosaicing[development]' diff --git a/docs/manual.rst b/docs/manual.rst deleted file mode 100644 index 5223ce7..0000000 --- a/docs/manual.rst +++ /dev/null @@ -1,8 +0,0 @@ -Colour - Demosaicing Manual -=========================== - -.. toctree:: - :maxdepth: 3 - - reference - bibliography \ No newline at end of file diff --git a/docs/reference.rst b/docs/reference.rst index 62fe644..453c32a 100644 --- a/docs/reference.rst +++ b/docs/reference.rst @@ -1,5 +1,5 @@ -Reference -========= +API Reference +============= .. toctree:: :titlesonly: diff --git a/docs/user-guide.rst b/docs/user-guide.rst new file mode 100644 index 0000000..a72a033 --- /dev/null +++ b/docs/user-guide.rst @@ -0,0 +1,14 @@ +User Guide +========== + +The user guide provides an overview of **Colour - Demosaicing** and +explains important concepts and features, details can be found in the +`API Reference `__. + +.. toctree:: + :maxdepth: 1 + + Installation + Contributing + Changes + bibliography diff --git a/pyproject.toml b/pyproject.toml index cc3a568..33c56d2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "colour-demosaicing" -version = "0.1.6" +version = "0.2.0" description = "CFA (Colour Filter Array) Demosaicing Algorithms for Python" license = "BSD-3-Clause" authors = [ "Colour Developers " ] @@ -38,7 +38,6 @@ classifiers = [ "License :: OSI Approved", "Natural Language :: English", "Operating System :: OS Independent", - "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3", "Topic :: Scientific/Engineering", "Topic :: Software Development" @@ -49,74 +48,106 @@ exclude = [ ] [tool.poetry.dependencies] -python = "~2.7 || ^3.6" -colour-science = "^0.3.16" +python = ">= 3.8, < 3.11" +colour-science = ">= 0.4.0" -"backports.functools_lru_cache" = { version = "*", optional = true } biblib-simple = { version = "*", optional = true } # Development dependency. -coverage = { version = "*", optional = true } # Development dependency. +black = { version = "*", optional = true } # Development dependency. +coverage = { version = "!= 6.3", optional = true } # Development dependency. coveralls = { version = "*", optional = true } # Development dependency. flake8 = { version = "*", optional = true } # Development dependency. +flynt = { version = "*", optional = true } # Development dependency. invoke = { version = "*", optional = true } # Development dependency. jupyter = { version = "*", optional = true } # Development dependency. -matplotlib = { version = "*", optional = true } -mock = { version = "*", optional = true } # Development dependency. -nbformat = { version = "^4", optional = true } # Fixed development dependency for Python 2.7 support only. -nose = { version = "*", optional = true } # Development dependency. -numpy = { version = "*", optional = true } +matplotlib = { version = ">= 3.2, != 3.5.0, != 3.5.1", optional = true } +mypy = { version = "*", optional = true } # Development dependency. +numpy = { version = ">= 1.19, < 2", optional = true } pre-commit = { version = "*", optional = true } # Development dependency. +pydata-sphinx-theme = { version = "*", optional = true } # Development dependency. +pydocstyle = { version = "*", optional = true } # Development dependency. pytest = { version = "*", optional = true } # Development dependency. +pytest-cov = { version = "*", optional = true } # Development dependency. +pyupgrade = { version = "*", optional = true } # Development dependency. restructuredtext-lint = { version = "*", optional = true } # Development dependency. -sphinx = { version = "<=3.1.2", optional = true } # Development dependency. -sphinx_rtd_theme = { version = "*", optional = true } # Development dependency. +sphinx = { version = ">= 4, < 5", optional = true } # Development dependency. sphinxcontrib-bibtex = { version = "*", optional = true } # Development dependency. toml = { version = "*", optional = true } # Development dependency. twine = { version = "*", optional = true } # Development dependency. -yapf = { version = "0.23", optional = true } # Development dependency. [tool.poetry.dev-dependencies] biblib-simple = "*" -coverage = "*" +black = "*" +coverage = "!= 6.3" coveralls = "*" flake8 = "*" +flynt = "*" invoke = "*" jupyter = "*" -mock = "*" -nbformat = "^4" -nose = "*" +mypy = "*" pre-commit = "*" +pydata-sphinx-theme = "*" +pydocstyle = "*" pytest = "*" +pytest-cov = "*" +pyupgrade = "*" restructuredtext-lint = "*" -sphinx = "<=3.1.2" -sphinx_rtd_theme = "*" +sphinx = ">= 4, < 5" sphinxcontrib-bibtex = "*" toml = "*" twine = "*" -yapf = "0.23" [tool.poetry.extras] development = [ "biblib-simple", + "black", "coverage", "coveralls", "flake8", + "flynt", "invoke", "jupyter", - "mock", - "nbformat", - "nose", + "mypy", "pre-commit", + "pydata-sphinx-theme", + "pydocstyle", "pytest", + "pytest-cov", + "pyupgrade", "restructuredtext-lint", "sphinx", - "sphinx_rtd_theme", "sphinxcontrib-bibtex", "toml", "twine", - "yapf" ] -plotting = [ "backports.functools_lru_cache", "matplotlib" ] -read-the-docs = [ "mock", "numpy", "sphinxcontrib-bibtex" ] +plotting = [ "matplotlib" ] +read-the-docs = [ + "matplotlib", + "numpy", + "pydata-sphinx-theme", + "sphinxcontrib-bibtex" +] + +[tool.black] +line-length = 79 +exclude = ''' +/( + \.git + | \.mypy_cache + | build + | dist +)/ +''' + +[tool.flynt] +line_length=999 + +[tool.mypy] +plugins = "numpy.typing.mypy_plugin" +ignore_missing_imports = true + +[tool.pydocstyle] +convention = "numpy" +add-ignore = "D104,D200,D202,D205,D301,D400" [build-system] requires = [ "poetry>=0.12" ] diff --git a/requirements.txt b/requirements.txt index 12844bc..29f2b73 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,118 +1,145 @@ alabaster==0.7.12 -appdirs==1.4.4 -appnope==0.1.0 -argon2-cffi==20.1.0 -attrs==20.3.0 -Babel==2.9.0 +appnope==0.1.2 +argon2-cffi==21.3.0 +argon2-cffi-bindings==21.2.0 +astor==0.8.1 +asttokens==2.0.5 +attrs==21.4.0 +Babel==2.9.1 backcall==0.2.0 -backports.functools-lru-cache==1.6.1 +beautifulsoup4==4.10.0 biblib-simple==0.1.1 -bleach==3.2.1 -certifi==2020.11.8 -cffi==1.14.4 -cfgv==3.0.0 -chardet==3.0.4 +black==22.1.0 +bleach==4.1.0 +certifi==2021.10.8 +cffi==1.15.0 +cfgv==3.3.1 +charset-normalizer==2.0.12 +click==8.0.4 colorama==0.4.4 -colour-science==0.3.16 -coverage==5.3 -coveralls==2.2.0 -cycler==0.10.0 -decorator==4.4.2 -defusedxml==0.6.0 -distlib==0.3.1 +colour-science==0.4.0 +coverage==6.3.1 +coveralls==3.3.1 +cycler==0.11.0 +debugpy==1.5.1 +decorator==5.1.1 +defusedxml==0.7.1 +distlib==0.3.4 docopt==0.6.2 -docutils==0.16 -entrypoints==0.3 -filelock==3.0.12 -flake8==3.8.4 -identify==1.5.10 -idna==2.10 -imageio==2.9.0 -imagesize==1.2.0 +docutils==0.17.1 +entrypoints==0.4 +executing==0.8.2 +filelock==3.6.0 +flake8==4.0.1 +flynt==0.76 +identify==2.4.10 +idna==3.3 +imageio==2.16.0 +imagesize==1.3.0 +importlib-metadata==4.11.1 iniconfig==1.1.1 -invoke==1.4.1 -ipykernel==5.3.4 -ipython==7.16.1 +invoke==1.6.0 +ipykernel==6.9.1 +ipython==8.0.1 ipython-genutils==0.2.0 -ipywidgets==7.5.1 -jedi==0.17.2 -Jinja2==2.11.2 -jsonschema==3.2.0 +ipywidgets==7.6.5 +jedi==0.18.1 +Jinja2==3.0.3 +jsonschema==4.4.0 jupyter==1.0.0 -jupyter-client==6.1.7 -jupyter-console==6.2.0 -jupyter-core==4.7.0 -keyring==21.5.0 -kiwisolver==1.3.1 +jupyter-client==7.1.2 +jupyter-console==6.4.0 +jupyter-core==4.9.2 +jupyterlab-pygments==0.1.2 +jupyterlab-widgets==1.0.2 +keyring==23.5.0 +kiwisolver==1.3.2 latexcodec==2.0.1 -MarkupSafe==1.1.1 -matplotlib==3.3.3 +MarkupSafe==2.1.0 +matplotlib==3.4.3 +matplotlib-inline==0.1.3 mccabe==0.6.1 mistune==0.8.4 -mock==4.0.2 -nbconvert==5.6.1 -nbformat==4.4.0 -nodeenv==1.5.0 -nose==1.3.7 -notebook==6.1.5 -numpy==1.19.4 -oset==0.1.3 -packaging==20.4 -pandocfilters==1.4.3 -parso==0.7.1 +mypy==0.931 +mypy-extensions==0.4.3 +nbclient==0.5.11 +nbconvert==6.4.2 +nbformat==5.1.3 +nest-asyncio==1.5.4 +nodeenv==1.6.0 +notebook==6.4.8 +numpy==1.22.2 +packaging==21.3 +pandocfilters==1.5.0 +parso==0.8.3 +pathspec==0.9.0 pexpect==4.8.0 pickleshare==0.7.5 -Pillow==8.0.1 -pkginfo==1.6.1 -pluggy==0.13.1 -pre-commit==2.1.1 -prometheus-client==0.9.0 -prompt-toolkit==3.0.3 -ptyprocess==0.6.0 -py==1.9.0 -pybtex==0.23.0 -pybtex-docutils==0.2.2 -pycodestyle==2.6.0 -pycparser==2.20 -pyflakes==2.2.0 -Pygments==2.7.2 -pyparsing==2.4.7 -pyrsistent==0.17.3 -pytest==6.1.2 -python-dateutil==2.8.1 -pytz==2020.4 -PyYAML==5.3.1 -pyzmq==20.0.0 -qtconsole==5.0.1 -QtPy==1.9.0 -readme-renderer==28.0 -requests==2.25.0 +Pillow==9.0.1 +pip==21.3.1 +pkginfo==1.8.2 +platformdirs==2.5.1 +pluggy==1.0.0 +pre-commit==2.17.0 +prometheus-client==0.13.1 +prompt-toolkit==3.0.28 +ptyprocess==0.7.0 +pure-eval==0.2.2 +py==1.11.0 +pybtex==0.24.0 +pybtex-docutils==1.0.1 +pycodestyle==2.8.0 +pycparser==2.21 +pydata-sphinx-theme==0.8.0 +pydocstyle==6.1.1 +pyflakes==2.4.0 +Pygments==2.11.2 +pyparsing==3.0.7 +pyrsistent==0.18.1 +pytest==7.0.1 +pytest-cov==3.0.0 +python-dateutil==2.8.2 +pytz==2021.3 +pyupgrade==2.31.0 +PyYAML==6.0 +pyzmq==22.3.0 +qtconsole==5.2.2 +QtPy==2.0.1 +readme-renderer==32.0 +requests==2.27.1 requests-toolbelt==0.9.1 restructuredtext-lint==1.3.2 -rfc3986==1.4.0 -scipy==1.5.4 -Send2Trash==1.5.0 -six==1.15.0 -snowballstemmer==2.0.0 -Sphinx==3.1.2 -sphinx-rtd-theme==0.5.0 +rfc3986==2.0.0 +scipy==1.8.0 +Send2Trash==1.8.0 +setuptools==59.6.0 +six==1.16.0 +snowballstemmer==2.2.0 +soupsieve==2.3.1 +Sphinx==4.4.0 sphinxcontrib-applehelp==1.0.2 -sphinxcontrib-bibtex==1.0.0 +sphinxcontrib-bibtex==2.4.1 sphinxcontrib-devhelp==1.0.2 -sphinxcontrib-htmlhelp==1.0.3 +sphinxcontrib-htmlhelp==2.0.0 sphinxcontrib-jsmath==1.0.1 sphinxcontrib-qthelp==1.0.3 -sphinxcontrib-serializinghtml==1.1.4 -terminado==0.9.1 -testpath==0.4.4 +sphinxcontrib-serializinghtml==1.1.5 +stack-data==0.2.0 +terminado==0.13.1 +testpath==0.5.0 +tokenize-rt==4.2.1 toml==0.10.2 +tomli==2.0.1 tornado==6.1 -tqdm==4.54.0 -traitlets==4.3.3 -twine==3.2.0 -urllib3==1.26.2 -virtualenv==20.2.1 +tqdm==4.62.3 +traitlets==5.1.1 +twine==3.8.0 +types-setuptools==57.4.9 +typing_extensions==4.1.1 +urllib3==1.26.8 +virtualenv==20.13.1 wcwidth==0.2.5 webencodings==0.5.1 -widgetsnbextension==3.5.1 -yapf==0.23.0 +wheel==0.37.0 +widgetsnbextension==3.5.2 +zipp==3.7.0 diff --git a/setup.py b/setup.py index ce1df34..5c1b9bb 100644 --- a/setup.py +++ b/setup.py @@ -1,58 +1,75 @@ -# -*- coding: utf-8 -*- +""" +Colour - Demosaicing - Setup +============================ +""" + import codecs from setuptools import setup -packages = \ -['colour_demosaicing', - 'colour_demosaicing.bayer', - 'colour_demosaicing.bayer.demosaicing', - 'colour_demosaicing.bayer.demosaicing.tests', - 'colour_demosaicing.bayer.tests'] +packages = [ + "colour_demosaicing", + "colour_demosaicing.bayer", + "colour_demosaicing.bayer.demosaicing", + "colour_demosaicing.bayer.demosaicing.tests", + "colour_demosaicing.bayer.tests", +] -package_data = \ -{'': ['*'], - 'colour_demosaicing': ['examples/*', - 'resources/colour-demosaicing-examples-datasets/*', - 'resources/colour-demosaicing-tests-datasets/*']} +package_data = { + "": ["*"], + "colour_demosaicing": [ + "examples/*", + "resources/colour-demosaicing-examples-datasets/*", + "resources/colour-demosaicing-tests-datasets/*", + ], +} -install_requires = \ -['colour-science>=0.3.16,<0.4.0'] +install_requires = ["colour-science>=0.4.0"] -extras_require = \ -{'development': ['biblib-simple', - 'coverage', - 'coveralls', - 'flake8', - 'invoke', - 'jupyter', - 'mock', - 'nbformat>=4,<5', - 'nose', - 'pre-commit', - 'pytest', - 'restructuredtext-lint', - 'sphinx<=3.1.2', - 'sphinx_rtd_theme', - 'sphinxcontrib-bibtex', - 'toml', - 'twine', - 'yapf==0.23'], - 'plotting': ['backports.functools_lru_cache', 'matplotlib'], - 'read-the-docs': ['mock', 'numpy', 'sphinxcontrib-bibtex']} +extras_require = { + "development": [ + "biblib-simple", + "black", + "coverage!=6.3", + "coveralls", + "flake8", + "flynt", + "invoke", + "jupyter", + "mypy", + "pre-commit", + "pydata-sphinx-theme", + "pydocstyle", + "pytest", + "pytest-cov", + "pyupgrade", + "restructuredtext-lint", + "sphinx>=4,<5", + "sphinxcontrib-bibtex", + "toml", + "twine", + ], + "plotting": ["matplotlib>=3.2,!=3.5.0,!=3.5.1"], + "read-the-docs": [ + "matplotlib>=3.2,!=3.5.0,!=3.5.1", + "numpy>=1.19,<2", + "pydata-sphinx-theme", + "sphinxcontrib-bibtex", + ], +} setup( - name='colour-demosaicing', - version='0.1.6', - description='CFA (Colour Filter Array) Demosaicing Algorithms for Python', - long_description=codecs.open('README.rst', encoding='utf8').read(), - author='Colour Developers', - author_email='colour-developers@colour-science.org', - maintainer='Colour Developers', - maintainer_email='colour-developers@colour-science.org', - url='https://www.colour-science.org/', + name="colour-demosaicing", + version="0.2.0", + description="CFA (Colour Filter Array) Demosaicing Algorithms for Python", + long_description=codecs.open("README.rst", encoding="utf8").read(), + author="Colour Developers", + author_email="colour-developers@colour-science.org", + maintainer="Colour Developers", + maintainer_email="colour-developers@colour-science.org", + url="https://www.colour-science.org/", packages=packages, package_data=package_data, install_requires=install_requires, extras_require=extras_require, - python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*', + python_requires=">=3.8,<3.11", ) diff --git a/tasks.py b/tasks.py index 604495b..74dd9b0 100644 --- a/tasks.py +++ b/tasks.py @@ -1,348 +1,378 @@ -# -*- coding: utf-8 -*- """ Invoke - Tasks ============== """ -from __future__ import unicode_literals +from __future__ import annotations -import sys -try: - import biblib.bib -except ImportError: - pass +import biblib.bib import fnmatch import os import re import uuid -from invoke import task +from invoke import Context, task + +from colour.hints import Boolean import colour_demosaicing from colour.utilities import message_box -__author__ = 'Colour Developers' -__copyright__ = 'Copyright (C) 2015-2020 - Colour Developers' -__license__ = 'New BSD License - https://opensource.org/licenses/BSD-3-Clause' -__maintainer__ = 'Colour Developers' -__email__ = 'colour-developers@colour-science.org' -__status__ = 'Production' +__author__ = "Colour Developers" +__copyright__ = "Copyright 2015 Colour Developers" +__license__ = "New BSD License - https://opensource.org/licenses/BSD-3-Clause" +__maintainer__ = "Colour Developers" +__email__ = "colour-developers@colour-science.org" +__status__ = "Production" __all__ = [ - 'APPLICATION_NAME', 'APPLICATION_VERSION', 'PYTHON_PACKAGE_NAME', - 'PYPI_PACKAGE_NAME', 'BIBLIOGRAPHY_NAME', 'clean', 'formatting', 'tests', - 'quality', 'examples', 'preflight', 'docs', 'todo', 'requirements', - 'build', 'virtualise', 'tag', 'release', 'sha256' + "APPLICATION_NAME", + "APPLICATION_VERSION", + "PYTHON_PACKAGE_NAME", + "PYPI_PACKAGE_NAME", + "BIBLIOGRAPHY_NAME", + "clean", + "formatting", + "quality", + "precommit", + "tests", + "examples", + "preflight", + "docs", + "todo", + "requirements", + "build", + "virtualise", + "tag", + "release", + "sha256", ] -APPLICATION_NAME = colour_demosaicing.__application_name__ +APPLICATION_NAME: str = colour_demosaicing.__application_name__ + +APPLICATION_VERSION: str = colour_demosaicing.__version__ + +PYTHON_PACKAGE_NAME: str = colour_demosaicing.__name__ + +PYPI_PACKAGE_NAME: str = "colour-demosaicing" + +BIBLIOGRAPHY_NAME: str = "BIBLIOGRAPHY.bib" + + +def _patch_invoke_annotations_support(): + """See https://github.com/pyinvoke/invoke/issues/357.""" -APPLICATION_VERSION = colour_demosaicing.__version__ + import invoke + from unittest.mock import patch + from inspect import getfullargspec, ArgSpec -PYTHON_PACKAGE_NAME = colour_demosaicing.__name__ + def patched_inspect_getargspec(function): + spec = getfullargspec(function) + return ArgSpec(*spec[0:4]) -PYPI_PACKAGE_NAME = 'colour-demosaicing' + org_task_argspec = invoke.tasks.Task.argspec -BIBLIOGRAPHY_NAME = 'BIBLIOGRAPHY.bib' + def patched_task_argspec(*args, **kwargs): + with patch( + target="inspect.getargspec", new=patched_inspect_getargspec + ): + return org_task_argspec(*args, **kwargs) + + invoke.tasks.Task.argspec = patched_task_argspec + + +_patch_invoke_annotations_support() @task -def clean(ctx, docs=True, bytecode=False): +def clean( + ctx: Context, + docs: Boolean = True, + bytecode: Boolean = False, + mypy: Boolean = True, + pytest: Boolean = True, +): """ - Cleans the project. + Clean the project. Parameters ---------- - ctx : invoke.context.Context + ctx Context. - docs : bool, optional + docs Whether to clean the *docs* directory. - bytecode : bool, optional + bytecode Whether to clean the bytecode files, e.g. *.pyc* files. - - Returns - ------- - bool - Task success. + mypy + Whether to clean the *Mypy* cache directory. + pytest + Whether to clean the *Pytest* cache directory. """ - message_box('Cleaning project...') - patterns = ['build', '*.egg-info', 'dist'] + message_box("Cleaning project...") + + patterns = ["build", "*.egg-info", "dist"] if docs: - patterns.append('docs/_build') - patterns.append('docs/generated') + patterns.append("docs/_build") + patterns.append("docs/generated") if bytecode: - patterns.append('**/*.pyc') + patterns.append("**/__pycache__") + patterns.append("**/*.pyc") + + if mypy: + patterns.append(".mypy_cache") + + if pytest: + patterns.append(".pytest_cache") for pattern in patterns: - ctx.run("rm -rf {}".format(pattern)) + ctx.run(f"rm -rf {pattern}") @task -def formatting(ctx, yapf=True, asciify=True, bibtex=True): +def formatting( + ctx: Context, + asciify: Boolean = True, + bibtex: Boolean = True, +): """ - Formats the codebase with *Yapf*, converts unicode characters to ASCII and - cleanup the "BibTeX" file. + Convert unicode characters to ASCII and cleanup the *BibTeX* file. Parameters ---------- - ctx : invoke.context.Context + ctx Context. - yapf : bool, optional - Whether to format the codebase with *Yapf*. - asciify : bool, optional + asciify Whether to convert unicode characters to ASCII. - bibtex : bool, optional + bibtex Whether to cleanup the *BibTeX* file. - - Returns - ------- - bool - Task success. """ - if yapf: - message_box('Formatting codebase with "Yapf"...') - ctx.run('yapf -p -i -r --exclude \'.git\' .') - if asciify: - message_box('Converting unicode characters to ASCII...') - with ctx.cd('utilities'): - ctx.run('./unicode_to_ascii.py') + message_box("Converting unicode characters to ASCII...") + with ctx.cd("utilities"): + ctx.run("./unicode_to_ascii.py") - if bibtex and sys.version_info[:2] >= (3, 2): + if bibtex: message_box('Cleaning up "BibTeX" file...') bibtex_path = BIBLIOGRAPHY_NAME with open(bibtex_path) as bibtex_file: - bibtex = biblib.bib.Parser().parse( - bibtex_file.read()).get_entries() + entries = ( + biblib.bib.Parser().parse(bibtex_file.read()).get_entries() + ) - for entry in sorted(bibtex.values(), key=lambda x: x.key): + for entry in sorted(entries.values(), key=lambda x: x.key): try: - del entry['file'] + del entry["file"] except KeyError: pass + for key, value in entry.items(): - entry[key] = re.sub('(? requirements.txt') + ctx.run( + "poetry run pip list --format=freeze | " + 'egrep -v "colour-demosaicing=" ' + "> requirements.txt" + ) @task(clean, preflight, docs, todo, requirements) -def build(ctx): +def build(ctx: Context): """ - Builds the project and runs dependency tasks, i.e. *docs*, *todo*, and + Build the project and runs dependency tasks, i.e. *docs*, *todo*, and *preflight*. Parameters ---------- - ctx : invoke.context.Context + ctx Context. - - Returns - ------- - bool - Task success. """ - message_box('Building...') - ctx.run('poetry build') + message_box("Building...") + ctx.run("poetry build") - with ctx.cd('dist'): - ctx.run('tar -xvf {0}-{1}.tar.gz'.format(PYPI_PACKAGE_NAME, - APPLICATION_VERSION)) - ctx.run('cp {0}-{1}/setup.py ../'.format(PYPI_PACKAGE_NAME, - APPLICATION_VERSION)) + with ctx.cd("dist"): + ctx.run(f"tar -xvf {PYPI_PACKAGE_NAME}-{APPLICATION_VERSION}.tar.gz") + ctx.run(f"cp {PYPI_PACKAGE_NAME}-{APPLICATION_VERSION}/setup.py ../") - ctx.run('rm -rf {0}-{1}'.format(PYPI_PACKAGE_NAME, - APPLICATION_VERSION)) + ctx.run(f"rm -rf {PYPI_PACKAGE_NAME}-{APPLICATION_VERSION}") - with open('setup.py') as setup_file: + with open("setup.py") as setup_file: source = setup_file.read() setup_kwargs = [] @@ -350,161 +380,176 @@ def build(ctx): def sub_callable(match): setup_kwargs.append(match) - return '' + return "" template = """ setup({0} ) """ - source = re.sub('from setuptools import setup', - 'import codecs\nfrom setuptools import setup', source) source = re.sub( - 'setup_kwargs = {(.*)}.*setup\\(\\*\\*setup_kwargs\\)', + "from setuptools import setup", + ( + '"""\n' + "Colour - Demosaicing - Setup\n" + "============================\n" + '"""\n\n' + "import codecs\n" + "from setuptools import setup" + ), + source, + ) + source = re.sub( + "setup_kwargs = {(.*)}.*setup\\(\\*\\*setup_kwargs\\)", sub_callable, source, - flags=re.DOTALL)[:-2] + flags=re.DOTALL, + )[:-2] setup_kwargs = setup_kwargs[0].group(1).splitlines() for i, line in enumerate(setup_kwargs): - setup_kwargs[i] = re.sub('^\\s*(\'(\\w+)\':\\s?)', ' \\2=', line) - if setup_kwargs[i].strip().startswith('long_description'): - setup_kwargs[i] = (' long_description=' - 'codecs.open(\'README.rst\', encoding=\'utf8\')' - '.read(),') + setup_kwargs[i] = re.sub("^\\s*('(\\w+)':\\s?)", " \\2=", line) + if setup_kwargs[i].strip().startswith("long_description"): + setup_kwargs[i] = ( + " long_description=" + "codecs.open('README.rst', encoding='utf8')" + ".read()," + ) - source += template.format('\n'.join(setup_kwargs)) + source += template.format("\n".join(setup_kwargs)) - with open('setup.py', 'w') as setup_file: + with open("setup.py", "w") as setup_file: setup_file.write(source) - ctx.run('twine check dist/*') + ctx.run("poetry run pre-commit run --files setup.py || true") + + ctx.run("twine check dist/*") @task -def virtualise(ctx, tests=True): +def virtualise(ctx: Context, tests: Boolean = True): """ Create a virtual environment for the project build. Parameters ---------- - ctx : invoke.context.Context + ctx Context. - tests : bool, optional + tests Whether to run tests on the virtual environment. - - Returns - ------- - bool - Task success. """ - unique_name = '{0}-{1}'.format(PYPI_PACKAGE_NAME, uuid.uuid1()) - with ctx.cd('dist'): - ctx.run('tar -xvf {0}-{1}.tar.gz'.format(PYPI_PACKAGE_NAME, - APPLICATION_VERSION)) - ctx.run('mv {0}-{1} {2}'.format(PYPI_PACKAGE_NAME, APPLICATION_VERSION, - unique_name)) - ctx.run('rm -rf {0}/{1}/resources'.format(unique_name, - PYTHON_PACKAGE_NAME)) - ctx.run('ln -s ../../../{0}/resources {1}/{0}'.format( - PYTHON_PACKAGE_NAME, unique_name)) + unique_name = f"{PYPI_PACKAGE_NAME}-{uuid.uuid1()}" + with ctx.cd("dist"): + ctx.run(f"tar -xvf {PYPI_PACKAGE_NAME}-{APPLICATION_VERSION}.tar.gz") + ctx.run(f"mv {PYPI_PACKAGE_NAME}-{APPLICATION_VERSION} {unique_name}") + ctx.run(f"rm -rf {unique_name}/{PYTHON_PACKAGE_NAME}/resources") + ctx.run( + "ln -s ../../../{0}/resources {1}/{0}".format( + PYTHON_PACKAGE_NAME, unique_name + ) + ) with ctx.cd(unique_name): - ctx.run('poetry env use 3') - ctx.run('poetry install') - ctx.run('source $(poetry env info -p)/bin/activate') - ctx.run('python -c "import imageio;' - 'imageio.plugins.freeimage.download()"') + ctx.run('poetry install --extras "plotting"') + ctx.run("source $(poetry env info -p)/bin/activate") + ctx.run( + 'python -c "import imageio;' + 'imageio.plugins.freeimage.download()"' + ) if tests: - ctx.run('poetry run nosetests', env={'MPLBACKEND': 'AGG'}) + ctx.run( + "poetry run py.test " + "--disable-warnings " + "--doctest-modules " + f"--ignore={PYTHON_PACKAGE_NAME}/examples " + f"{PYTHON_PACKAGE_NAME}", + env={"MPLBACKEND": "AGG"}, + ) @task -def tag(ctx): +def tag(ctx: Context): """ - Tags the repository according to defined version using *git-flow*. + Tag the repository according to defined version using *git-flow*. Parameters ---------- - ctx : invoke.context.Context + ctx Context. - - Returns - ------- - bool - Task success. """ - message_box('Tagging...') - result = ctx.run('git rev-parse --abbrev-ref HEAD', hide='both') + message_box("Tagging...") + result = ctx.run("git rev-parse --abbrev-ref HEAD", hide="both") - assert result.stdout.strip() == 'develop', ( - 'Are you still on a feature or master branch?') + assert ( + result.stdout.strip() == "develop" + ), "Are you still on a feature or master branch?" - with open(os.path.join(PYTHON_PACKAGE_NAME, '__init__.py')) as file_handle: + with open(os.path.join(PYTHON_PACKAGE_NAME, "__init__.py")) as file_handle: file_content = file_handle.read() - major_version = re.search("__major_version__\\s+=\\s+'(.*)'", - file_content).group(1) - minor_version = re.search("__minor_version__\\s+=\\s+'(.*)'", - file_content).group(1) - change_version = re.search("__change_version__\\s+=\\s+'(.*)'", - file_content).group(1) - - version = '.'.join((major_version, minor_version, change_version)) - - result = ctx.run('git ls-remote --tags upstream', hide='both') - remote_tags = result.stdout.strip().split('\n') + major_version = re.search( + '__major_version__\\s+=\\s+"(.*)"', file_content + ).group( # type: ignore[union-attr] + 1 + ) + minor_version = re.search( + '__minor_version__\\s+=\\s+"(.*)"', file_content + ).group( # type: ignore[union-attr] + 1 + ) + change_version = re.search( + '__change_version__\\s+=\\s+"(.*)"', file_content + ).group( # type: ignore[union-attr] + 1 + ) + + version = ".".join((major_version, minor_version, change_version)) + + result = ctx.run("git ls-remote --tags upstream", hide="both") + remote_tags = result.stdout.strip().split("\n") tags = set() for remote_tag in remote_tags: tags.add( - remote_tag.split('refs/tags/')[1].replace('refs/tags/', '^{}')) - tags = sorted(list(tags)) - assert 'v{0}'.format(version) not in tags, ( - 'A "{0}" "v{1}" tag already exists in remote repository!'.format( - PYTHON_PACKAGE_NAME, version)) + remote_tag.split("refs/tags/")[1].replace("refs/tags/", "^{}") + ) + version_tags = sorted(list(tags)) + assert f"v{version}" not in version_tags, ( + f'A "{PYTHON_PACKAGE_NAME}" "v{version}" tag already exists in ' + f"remote repository!" + ) - ctx.run('git flow release start v{0}'.format(version)) - ctx.run('git flow release finish v{0}'.format(version)) + ctx.run(f"git flow release start v{version}") + ctx.run(f"git flow release finish v{version}") @task(build) -def release(ctx): +def release(ctx: Context): """ - Releases the project to *Pypi* with *Twine*. + Release the project to *Pypi* with *Twine*. Parameters ---------- - ctx : invoke.context.Context + ctx Context. - - Returns - ------- - bool - Task success. """ - message_box('Releasing...') - with ctx.cd('dist'): - ctx.run('twine upload *.tar.gz') - ctx.run('twine upload *.whl') + message_box("Releasing...") + with ctx.cd("dist"): + ctx.run("twine upload *.tar.gz") + ctx.run("twine upload *.whl") @task -def sha256(ctx): +def sha256(ctx: Context): """ - Computes the project *Pypi* package *sha256* with *OpenSSL*. + Compute the project *Pypi* package *sha256* with *OpenSSL*. Parameters ---------- - ctx : invoke.context.Context + ctx Context. - - Returns - ------- - bool - Task success. """ message_box('Computing "sha256"...') - with ctx.cd('dist'): - ctx.run('openssl sha256 {0}-*.tar.gz'.format(PYPI_PACKAGE_NAME)) + with ctx.cd("dist"): + ctx.run(f"openssl sha256 {PYPI_PACKAGE_NAME}-*.tar.gz") diff --git a/utilities/export_todo.py b/utilities/export_todo.py index 544ef63..03f420d 100755 --- a/utilities/export_todo.py +++ b/utilities/export_todo.py @@ -1,23 +1,25 @@ #!/usr/bin/env python -# -*- coding: utf-8 -*- """ Export TODOs ============ """ -from __future__ import division, unicode_literals +from __future__ import annotations import codecs import os -from collections import OrderedDict -__copyright__ = 'Copyright (C) 2015-2020 - Colour Developers' -__license__ = 'New BSD License - https://opensource.org/licenses/BSD-3-Clause' -__maintainer__ = 'Colour Developers' -__email__ = 'colour-developers@colour-science.org' -__status__ = 'Production' +__copyright__ = "Copyright 2015 Colour Developers" +__license__ = "New BSD License - https://opensource.org/licenses/BSD-3-Clause" +__maintainer__ = "Colour Developers" +__email__ = "colour-developers@colour-science.org" +__status__ = "Production" -__all__ = ['TODO_FILE_TEMPLATE', 'extract_todo_items', 'export_todo_items'] +__all__ = [ + "TODO_FILE_TEMPLATE", + "extract_todo_items", + "export_todo_items", +] TODO_FILE_TEMPLATE = """ Colour - Demosaicing - TODO @@ -32,92 +34,93 @@ ----- | **Colour - Demosaicing** by Colour Developers -| Copyright © 2015-2020 – Colour Developers – \ +| Copyright 2015 Colour Developers – \ `colour-developers@colour-science.org `__ | This software is released under terms of New BSD License: \ https://opensource.org/licenses/BSD-3-Clause | `https://github.com/colour-science/colour-demosaicing \ `__ -""" [1:] +"""[ + 1: +] -def extract_todo_items(root_directory): +def extract_todo_items(root_directory: str) -> dict: """ - Extracts the TODO items from given directory. + Extract the TODO items from given directory. Parameters ---------- - root_directory : unicode + root_directory Directory to extract the TODO items from. Returns ------- - OrderedDict + :class:`dict` TODO items. """ - todo_items = OrderedDict() - for root, dirnames, filenames in os.walk(root_directory): + todo_items = {} + for root, _dirnames, filenames in os.walk(root_directory): for filename in filenames: - if not filename.endswith('.py'): + if not filename.endswith(".py"): continue filename = os.path.join(root, filename) - with codecs.open(filename, encoding='utf8') as file_handle: + with codecs.open(filename, encoding="utf8") as file_handle: content = file_handle.readlines() in_todo = False - line_number = -1 + line_number = 1 todo_item = [] for i, line in enumerate(content): line = line.strip() - if line.startswith('# TODO:'): + if line.startswith("# TODO:"): in_todo = True - line_number = i + line_number = i + 1 todo_item.append(line) continue - if in_todo and line.startswith('#'): - todo_item.append(line.replace('#', '').strip()) + if in_todo and line.startswith("#"): + todo_item.append(line.replace("#", "").strip()) elif len(todo_item): - key = filename.replace('../', '') + key = filename.replace("../", "") if not todo_items.get(key): todo_items[key] = [] - todo_items[key].append((line_number, ' '.join(todo_item))) + todo_items[key].append((line_number, " ".join(todo_item))) in_todo = False - line_number todo_item = [] return todo_items -def export_todo_items(todo_items, file_path): +def export_todo_items(todo_items: dict, file_path: str): """ - Exports TODO items to given file. + Export TODO items to given file. Parameters ---------- - todo_items : OrderedDict + todo_items TODO items. - file_path : unicode + file_path File to write the TODO items to. """ todo_rst = [] for module, todo_items in todo_items.items(): - todo_rst.append('- {0}\n'.format(module)) + todo_rst.append(f"- {module}\n") for line_numer, todo_item in todo_items: - todo_rst.append(' - Line {0} : {1}'.format( - line_numer, todo_item)) + todo_rst.append(f" - Line {line_numer} : {todo_item}") - todo_rst.append('\n') + todo_rst.append("\n") - with codecs.open(file_path, 'w', encoding='utf8') as todo_file: - todo_file.write(TODO_FILE_TEMPLATE.format('\n'.join(todo_rst[:-1]))) + with codecs.open(file_path, "w", encoding="utf8") as todo_file: + todo_file.write(TODO_FILE_TEMPLATE.format("\n".join(todo_rst[:-1]))) -if __name__ == '__main__': +if __name__ == "__main__": export_todo_items( - extract_todo_items(os.path.join('..', 'colour_demosaicing')), - os.path.join('..', 'TODO.rst')) + extract_todo_items(os.path.join("..", "colour_demosaicing")), + os.path.join("..", "TODO.rst"), + ) diff --git a/utilities/unicode_to_ascii.py b/utilities/unicode_to_ascii.py index 1a99b26..c9a6fed 100755 --- a/utilities/unicode_to_ascii.py +++ b/utilities/unicode_to_ascii.py @@ -1,72 +1,72 @@ #!/usr/bin/env python -# -*- coding: utf-8 -*- """ Unicode to ASCII Utility ======================== """ -import sys -if sys.version_info[0] < 3: - # Smelly hack for Python 2.x: https://stackoverflow.com/q/3828723/931625 - reload(sys) # noqa - sys.setdefaultencoding('utf-8') - -import codecs # noqa -import os # noqa -import unicodedata # noqa - -__copyright__ = 'Copyright (C) 2015-2020 - Colour Developers' -__license__ = 'New BSD License - https://opensource.org/licenses/BSD-3-Clause' -__maintainer__ = 'Colour Developers' -__email__ = 'colour-developers@colour-science.org' -__status__ = 'Production' - -__all__ = ['SUBSTITUTIONS', 'unicode_to_ascii'] - -SUBSTITUTIONS = { - '–': '-', - '“': '"', - '”': '"', - '‘': "'", - '’': "'", - '′': "'", +from __future__ import annotations + +import codecs +import os +import unicodedata + +__copyright__ = "Copyright 2015 Colour Developers" +__license__ = "New BSD License - https://opensource.org/licenses/BSD-3-Clause" +__maintainer__ = "Colour Developers" +__email__ = "colour-developers@colour-science.org" +__status__ = "Production" + +__all__ = [ + "SUBSTITUTIONS", + "unicode_to_ascii", +] + +SUBSTITUTIONS: dict[str, str] = { + "–": "-", + "“": '"', + "”": '"', + "‘": "'", + "’": "'", + "′": "'", } -def unicode_to_ascii(root_directory): +def unicode_to_ascii(root_directory: str): """ - Recursively converts from unicode to ASCII *.py*, *.bib* and *.rst* files + Recursively convert from unicode to ASCII *.py*, *.bib* and *.rst* files in given directory. Parameters ---------- - root_directory : unicode + root_directory Directory to convert the files from unicode to ASCII. """ - for root, dirnames, filenames in os.walk(root_directory): + for root, _dirnames, filenames in os.walk(root_directory): for filename in filenames: - if (not filename.endswith('.tex') and - not filename.endswith('.py') and - not filename.endswith('.bib') and - not filename.endswith('.rst')): + if ( + not filename.endswith(".tex") + and not filename.endswith(".py") + and not filename.endswith(".bib") + and not filename.endswith(".rst") + ): continue - if filename == 'unicode_to_ascii.py': + if filename == "unicode_to_ascii.py": continue filename = os.path.join(root, filename) - with codecs.open(filename, encoding='utf8') as file_handle: + with codecs.open(filename, encoding="utf8") as file_handle: content = file_handle.read() - with codecs.open(filename, 'w', encoding='utf8') as file_handle: + with codecs.open(filename, "w", encoding="utf8") as file_handle: for key, value in SUBSTITUTIONS.items(): content = content.replace(key, value) - content = unicodedata.normalize('NFD', content) + content = unicodedata.normalize("NFD", content) file_handle.write(content) -if __name__ == '__main__': - unicode_to_ascii(os.path.join('..', 'colour_demosaicing')) +if __name__ == "__main__": + unicode_to_ascii(os.path.join("..", "colour_demosaicing"))