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

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions .github/workflows/publish.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
name: Publish Python package

on:
push:
tags:
- "v*.*.*" # Manual tagging of the commit on the main branch should trigger publish action

permissions:
contents: read
id-token: write

jobs:
publish:
runs-on: ubuntu-latest

environment:
name: pypi

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.11"

- name: Install build tools
run: |
python -m pip install --upgrade pip
python -m pip install build twine

- name: Build package
run: python -m build

- name: Check package
run: twine check dist/*

- name: Publish package
uses: pypa/gh-action-pypi-publish@release/v1
10 changes: 6 additions & 4 deletions .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,22 @@ name: Run Python tests

on:
push:
branches: [ main ] # - add for limiting it only to pushes on a main branch
paths: # triggers testing action if only any python / 2 other files have been changed
branches: [ main ] # - add for limiting it to be triggered only by pushes to the main branch
paths: # triggers testing action if only any Python / listed files have been changed
- '**.py'
- 'requirements.txt'
- 'pyproject.toml'
- '.github/workflows/test.yaml'
pull_request:
branches: [ main ]

jobs:
test:
runs-on: windows-latest

strategy:
matrix:
python-version: ["3.8", "3.9", "3.10", "3.11"]
python-version: ["3.8", "3.11", "3.12", "3.13"]

steps:
- name: Checkout code # loads code from a repo
Expand All @@ -31,7 +33,7 @@ jobs:
python -m pip install --upgrade pip
pip install pytest
pip install -e .
pip install numba
pip install "numba>=0.57.1"

- name: Run tests
run: pytest
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@ Documents/
.idea/
.vscode/
src/zernpy/calculations/*.jpg
src/zernpy/ignored/
!Command_Hints_Mypy_Ruff.txt

# tests bound to the local environments
run_all_local_tests.cmd

# Byte-compiled / optimized / DLL files
__pycache__/
Expand Down
3 changes: 3 additions & 0 deletions Command_Hints_Mypy_Ruff.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
mypy src/zernpy - command for checking files for comforming to typing rules
ruff check src tests - command for checking files for comforming to formatting rules
ruff check --fix - command for checking + fixing found formatting issues
5 changes: 2 additions & 3 deletions MANIFEST.in
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
exclude src/zernpy/*.png

recursive-exclude src/zernpy/readme_images *
recursive-exclude tests *
recursive-exclude src/zernpy/tests *
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
### 'zernpy' - Python package for calculation real-valued Zernike polynomials and associated 2D PSF kernels
[![Tests](https://github.com/sklykov/zernpy/actions/workflows/test.yaml/badge.svg)](https://github.com/sklykov/zernpy/actions/workflows/test.yaml)
[![PyPI](https://img.shields.io/pypi/v/zernpy)](https://pypi.org/project/zernpy/)
[![License](https://img.shields.io/github/license/sklykov/zernpy)](https://github.com/sklykov/zernpy/blob/main/LICENSE)
[![Lint](https://img.shields.io/badge/lint-ruff-informational)](https://github.com/astral-sh/ruff)

#### Project description and references
This project is designed to compute the parameters, real values, and properties of Zernike polynomials using both exact (analytical) and recursive equations.
Expand Down
2 changes: 1 addition & 1 deletion build_api_dict_pdoc.bat → build_api_dict_pdoc.cmd
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
pdoc ./src/zernpy/zernikepol.py ./src/zernpy/zernpsf.py -o ./docs/api --logo ../for_favicon.png --logo ../for_favicon.png --no-show-source --footer-text "zernpy ver. 0.1.0, 2026 Sergei Klykov"
pdoc ./src/zernpy/zernikepol.py ./src/zernpy/zernpsf.py -o ./docs/api --logo ../for_favicon.png --logo ../for_favicon.png --no-show-source --footer-text "zernpy ver. 0.1.1, 2026 Sergei Klykov"
timeout /t 25
2 changes: 1 addition & 1 deletion docs/api/search.js

Large diffs are not rendered by default.

34 changes: 17 additions & 17 deletions docs/api/zernpy/zernikepol.html

Large diffs are not rendered by default.

151 changes: 29 additions & 122 deletions docs/api/zernpy/zernpsf.html

Large diffs are not rendered by default.

68 changes: 59 additions & 9 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,31 @@
name = "zernpy"
dynamic = ["version"] # Discovering of the version by the setuptools (see below: in the 'file' or 'attr')
authors = [
{name = "Sergei Klykov"},
{email = "sergej.klykow@gmail.com"}
{ name = "Sergei Klykov" },
{ email = "sergej.klykow@gmail.com" }
]
description = "Calculation of real Zernike polynomials values, associated PSFs, plotting of their profiles in polar coordinates"
readme = "README.md"
# license = {file = "LICENSE"} # includes the whole text in METADATA, maybe not so convienient
requires-python = ">=3.8"
classifiers = [
"Programming Language :: Python :: 3",
"Operating System :: OS Independent",
]

dependencies = [
"numpy",
"matplotlib",
"scipy",
"scipy",
]
[project.optional-dependencies]
performance = ["numba>=0.57.1"]
dev = ["ruff", "mypy", "pytest"]
all = ["numba>=0.57.1"]

keywords = ["zernike-polynomials", "zernike-psf"]

[project.urls] # METADATA in wheel file will represent the data below by using pip show zernpy -v
# But the the links themselves are mapped / parced by the PyPi website
# But the links themselves are mapped / parsed by the PyPi website
"Homepage" = "https://pypi.org/project/zernpy/"
"Repository" = "https://github.com/sklykov/zernpy/"
"Bug Tracker" = "https://github.com/sklykov/zernpy/issues/"
Expand All @@ -31,14 +36,59 @@ keywords = ["zernike-polynomials", "zernike-psf"]
[tool.setuptools.packages.find] # Manifest.in file is only required for adding some package-data
where = ["src"]
include = ["zernpy*"]
exclude = ["tests"]
exclude = ["zernpy.tests*"] # only packages should be specified, folders - exclude in MANIFEST.in
namespaces = false # forbid treating a folder as a module without explicit __init__.py presence

[tool.setuptools.exclude-package-data]
zernpy = ["*.png"] # should exclude image files from distribution
[tool.setuptools]
include-package-data = false # forbid to make a confusion on the src/zernpy/tests folder presence
# confusion is produced because it is an importable module

[tool.setuptools.dynamic]
version = {attr = "zernpy.__version__"} # Variable set in the __init__.py
version = { attr = "zernpy.__version__" } # Variable set in the __init__.py

[build-system]
requires = ["setuptools>=75.0"]
build-backend = "setuptools.build_meta"

[tool.mypy]
python_version = "3.11"
warn_unused_configs = true # mypy will warn if any of options below not valid
warn_redundant_casts = true # warn about unnecessary cast(): from typing import cast
warn_unused_ignores = true # warn about unused comments '# type: ignore'
show_error_codes = true # enables error code in a report
pretty = true # better formatted report in a console
strict_equality = true # checks proper usage of ==, !=, in
no_implicit_optional = true # throws error on: def f(x: int = None): ...
# Note: flags below introduces too strict type checks
# disallow_untyped_defs = true # all parameters and return types must be fully annotated
check_untyped_defs = true # mypy checks untyped expressions and tries to infer types
# warn_return_any = true # Any couldn't be used as return type
# disallow_any_generics = true # forbid bare generics like list, dict, tuple... -> instead List[float]
exclude = [
'^tests/',
'^build/',
'^dist/',
'^src/zernpy/tests/'
]
[[tool.mypy.overrides]] # for ignoring warning about not checked imported libraries
module = ["numba", "joblib"]
ignore_missing_imports = true
# [[tool.mypy.overrides]] # ignore any errors in specific test files - retained for ref.
# module = ["zernpy.run_zernpsf_as_main"]
# ignore_errors = true

[tool.ruff]
line-length = 145 # my own preference
indent-width = 4
target-version = "py311"
[tool.ruff.lint]
select = ["E4", "E7", "E9", "F", "I", "B", "SIM"]
ignore = ["E702", "E402", # used in the IDE
"SIM108", # many ternany operator replacements in a code
"SIM113", # potentially can break logic in a loop
]
[tool.ruff.format]
quote-style = "double"
indent-style = "space"
line-ending = "auto"
docstring-code-format = true
22 changes: 6 additions & 16 deletions src/zernpy/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,11 @@

"""

__version__ = "0.1.0" # Straightforward way of specifying package version and including it to the package attributes
__version__ = "0.1.1" # Straightforward way of specifying package version and including it to the package attributes

if __name__ == "__main__":
# use absolute imports for importing as module
__all__ = ['zernikepol', 'zernpsf'] # for specifying from zernpy import * if package imported from some script
elif __name__ == "zernpy":
pass # do not add module "zernikepol" to __all__ attribute, because it demands to construct explicit path
# Univesal logic for making all main classes and functions available after calling 'from project import *'
from .zernikepol import ZernPol, fit_polynomials, fit_polynomials_vectors, generate_phases_image, generate_polynomials, generate_random_phases
from .zernpsf import ZernPSF, clean_zernpy_cache, force_get_psf_compilation

# Automatically bring the main class and some methods to the name space when one of import command is used commands:
# 1) from zernpy import ZernPol, ... functions; 2) from zernpy import *
if __name__ != "__main__" and __name__ != "__mp_main__":
from .zernikepol import ZernPol # main class auto export on the import call of the package
# functions auto export - when everything imported from the module
from .zernikepol import generate_polynomials, fit_polynomials, generate_random_phases, fit_polynomials_vectors, generate_phases_image
from .zernpsf import ZernPSF # class for ZernPSF auto export on the import call of the package
from .zernpsf import force_get_psf_compilation # function for precompile functions by numba library
__all__ = ["ZernPol", "generate_polynomials", "fit_polynomials", "generate_random_phases", "fit_polynomials_vectors",
"generate_phases_image", "ZernPSF", "force_get_psf_compilation"]
__all__ = ["ZernPol", "generate_polynomials", "fit_polynomials", "generate_random_phases", "fit_polynomials_vectors",
"generate_phases_image", "ZernPSF", "force_get_psf_compilation", "clean_zernpy_cache"]
Loading
Loading