Coder Social home page Coder Social logo

sigma-py / orthopy Goto Github PK

View Code? Open in Web Editor NEW
181.0 9.0 18.0 4.37 MB

:triangular_ruler: Orthogonal polynomials in all shapes and sizes.

python mathematics engineering physics chemistry quadrature polynomials zernike-polynomials legendre-polynomials chebyshev-polynomials

orthopy's Introduction

orthopy

All about orthogonal polynomials.

PyPi Version PyPI pyversions GitHub stars Downloads

Discord orthogonal

orthopy provides various orthogonal polynomial classes for lines, triangles, disks, spheres, n-cubes, the nD space with weight function exp(-r2) and more. All computations are done using numerically stable recurrence schemes. Furthermore, all functions are fully vectorized and can return results in exact arithmetic.

Installation

Install orthopy from PyPI with

pip install orthopy

How to get a license

Licenses for personal and academic use can be purchased here. You'll receive a confirmation email with a license key. Install the key with

plm add <your-license-key>

on your machine and you're good to go.

For commercial use, please contact [email protected].

Basic usage

The main function of all submodules is the iterator Eval which evaluates the series of orthogonal polynomials with increasing degree at given points using a recurrence relation, e.g.,

import orthopy

x = 0.5

evaluator = orthopy.c1.legendre.Eval(x, "classical")
for _ in range(5):
     print(next(evaluator))
1.0          # P_0(0.5)
0.5          # P_1(0.5)
-0.125       # P_2(0.5)
-0.4375      # P_3(0.5)
-0.2890625   # P_4(0.5)

Other ways of getting the first n items are

evaluator = Eval(x, "normal")
vals = [next(evaluator) for _ in range(n)]

import itertools
vals = list(itertools.islice(Eval(x, "normal"), n))

Instead of evaluating at only one point, you can provide any array for x; the polynomials will then be evaluated for all points at once. You can also use sympy for symbolic computation:

import itertools
import orthopy
import sympy

x = sympy.Symbol("x")

evaluator = orthopy.c1.legendre.Eval(x, "classical")
for val in itertools.islice(evaluator, 5):
     print(sympy.expand(val))
1
x
3*x**2/2 - 1/2
5*x**3/2 - 3*x/2
35*x**4/8 - 15*x**2/4 + 3/8

All Eval methods have a scaling argument which can have three values:

  • "monic": The leading coefficient is 1.
  • "classical": The maximum value is 1 (or (n+alpha over n)).
  • "normal": The integral of the squared function over the domain is 1.

For univariate ("one-dimensional") integrals, every new iteration contains one function. For bivariate ("two-dimensional") domains, every level will contain one function more than the previous, and similarly for multivariate families. See the tree plots below.

Line segment (-1, +1) with weight function (1-x)α (1+x)β

Legendre Chebyshev 1 Chebyshev 2

Jacobi, Gegenbauer (α=β), Chebyshev 1 (α=β=-1/2), Chebyshev 2 (α=β=1/2), Legendre (α=β=0) polynomials.

import orthopy

orthopy.c1.legendre.Eval(x, "normal")
orthopy.c1.chebyshev1.Eval(x, "normal")
orthopy.c1.chebyshev2.Eval(x, "normal")
orthopy.c1.gegenbauer.Eval(x, "normal", lmbda)
orthopy.c1.jacobi.Eval(x, "normal", alpha, beta)

The plots above are generated with

import orthopy

orthopy.c1.jacobi.show(5, "normal", 0.0, 0.0)
# plot, savefig also exist

Recurrence coefficients can be explicitly retrieved by

import orthopy

rc = orthopy.c1.jacobi.RecurrenceCoefficients(
    "monic",  # or "classical", "normal"
    alpha=0, beta=0, symbolic=True
)
print(rc.p0)
for k in range(5):
    print(rc[k])
1
(1, 0, None)
(1, 0, 1/3)
(1, 0, 4/15)
(1, 0, 9/35)
(1, 0, 16/63)

1D half-space with weight function xα exp(-r)

(Generalized) Laguerre polynomials.

evaluator = orthopy.e1r.Eval(x, alpha=0, scaling="normal")

1D space with weight function exp(-r2)

Hermite polynomials come in two standardizations:

  • "physicists" (against the weight function exp(-x ** 2)
  • "probabilists" (against the weight function 1 / sqrt(2 * pi) * exp(-x ** 2 / 2)
evaluator = orthopy.e1r2.Eval(
    x,
    "probabilists",  # or "physicists"
    "normal"
)

Associated Legendre "polynomials"

Not all of those are polynomials, so they should really be called associated Legendre functions. The kth iteration contains 2k+1 functions, indexed from -k to k. (See the color grouping in the above plot.)

evaluator = orthopy.c1.associated_legendre.Eval(
    x, phi=None, standardization="natural", with_condon_shortley_phase=True
)

Triangle (T2)

orthopy's triangle orthogonal polynomials are evaluated in terms of barycentric coordinates, so the X.shape[0] has to be 3.

import orthopy

bary = [0.1, 0.7, 0.2]
evaluator = orthopy.t2.Eval(bary, "normal")

Disk (S2)

Xu Zernike Zernike 2

orthopy contains several families of orthogonal polynomials on the unit disk: After Xu, Zernike, and a simplified version of Zernike polynomials.

import orthopy

x = [0.1, -0.3]

evaluator = orthopy.s2.xu.Eval(x, "normal")
# evaluator = orthopy.s2.zernike.Eval(x, "normal")
# evaluator = orthopy.s2.zernike2.Eval(x, "normal")

Sphere (U3)

Complex-valued spherical harmonics, (black=zero, green=real positive, pink=real negative, blue=imaginary positive, yellow=imaginary negative). The functions in the middle are real-valued. The complex angle takes n turns on the nth level.

evaluator = orthopy.u3.EvalCartesian(
    x,
    scaling="quantum mechanic"  # or "acoustic", "geodetic", "schmidt"
)

evaluator = orthopy.u3.EvalSpherical(
    theta_phi,  # polar, azimuthal angles
    scaling="quantum mechanic"  # or "acoustic", "geodetic", "schmidt"
)

n-Cube (Cn)

C1 (Legendre) C2 C3

Jacobi product polynomials. All polynomials are normalized on the n-dimensional cube. The dimensionality is determined by X.shape[0].

evaluator = orthopy.cn.Eval(X, alpha=0, beta=0)
values, degrees = next(evaluator)

nD space with weight function exp(-r2) (Enr2)

E1r2 E2r2 E3r2

Hermite product polynomials. All polynomials are normalized over the measure. The dimensionality is determined by X.shape[0].

evaluator = orthopy.enr2.Eval(
    x,
    standardization="probabilists"  # or "physicists"
)
values, degrees = next(evaluator)

Other tools

  • Generating recurrence coefficients for 1D domains with Stieltjes, Golub-Welsch, Chebyshev, and modified Chebyshev.

  • The the sanity of recurrence coefficients with test 3 from Gautschi's article: computing the weighted sum of orthogonal polynomials:

    orthopy.tools.gautschi_test_3(moments, alpha, beta)
  • Clenshaw algorithm for computing the weighted sum of orthogonal polynomials:

    vals = orthopy.c1.clenshaw(a, alpha, beta, t)

Relevant publications

orthopy's People

Contributors

nschloe avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

orthopy's Issues

"barycentric" tensor

For higher-dimensional polynomials, the fitting data structure for each level would be a numpy.array of shape (n, n, ...), but only the lower (or upper) triangle of (n,n) is used. Perhaps even more fitting would be to address the entries in "barycentric" coordinates, such that the indices sum up to L. Check with the product scheme and, perhaps, ndim.

Zernike cosine polynomials should have switched sign

The polynomials generated by orthopy are not in accordance to the formal definition of the zernikes.

For example, $Z_{1}^{1} $ should be $2 \rho \cos \phi $ but the orthopy generated polynomial looks like $-2\rho \cos \phi $.

This is an issue with all polynomials with azimuthal degree $m &gt; 0$. Sadly, I do not fully understand the source code, so I can not easily spot the mistake.

An easy fix could be multiplying every output polynomial where $m > 0 $ by $-1 $ where $m $ can be calculated from the OSA/ANSI index $j $ (which I believe to be self.L in the zernike.py) by

n = int(sqrt(2*j+1) - 0.5)
m = int(2*j - n*(n+2))

Some tests are not passing (unexpected keyword argument 'colorspace')

Hi, from last friday the test were passing, but today when install I have this message. Thanks in advance for support. This is the full log.

===================================================================================== FAILURES ======================================================================================
_________________________________________________________________________________ code block check __________________________________________________________________________________
line 246, line 246:

import orthopy

orthopy.u3.write_tree("u3.vtk", 5, "quantum mechanic")


get_srgb1() got an unexpected keyword argument 'colorspace'
_________________________________________________________________________________ test_write_single _________________________________________________________________________________

n = 5, r = 3

    def test_write_single(n=5, r=3):
>       orthopy.u3.write_single(f"sph{n}{r}.vtk", n, r, "quantum mechanic")

tests/test_u3.py:142: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

filename = 'sph53.vtk', n = 5, r = 3, scaling = 'quantum mechanic', res = 20

    def write_single(filename, n, r, scaling, res=20):
        """This function creates a sphere mesh with "srgb1" values. Can be views in ParaView
        by disabling "Map Scalars".
        """
        import cplot
        import meshio
        import meshzoo
    
        points, cells = meshzoo.icosa_sphere(res)
    
        evaluator = EvalCartesian(points.T, scaling, complex_valued=True)
        vals = next(itertools.islice(evaluator, n, None))[r]
    
>       srgb1_vals = cplot.get_srgb1(vals, colorspace="cam16")
E       TypeError: get_srgb1() got an unexpected keyword argument 'colorspace'

tmp_install/usr/lib/python3.10/site-packages/orthopy/u3/tools.py:21: TypeError
__________________________________________________________________________________ test_write_tree __________________________________________________________________________________

n = 2

    def test_write_tree(n=2):
>       orthopy.u3.write_tree(f"sph{n}.vtk", n, "quantum mechanic")

tests/test_u3.py:146: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

filename = 'sph2.vtk', n = 2, scaling = 'quantum mechanic', res = 20

    def write_tree(filename, n, scaling, res=20):
        import cplot
        import meshio
        import meshzoo
    
        points, cells = meshzoo.icosa_sphere(res)
    
        evaluator = EvalCartesian(points.T, scaling, complex_valued=True)
        meshes = []
        for L, level in enumerate(itertools.islice(evaluator, n)):
            for k, vals in enumerate(level):
>               srgb1_vals = cplot.get_srgb1(vals, colorspace="cam16")
E               TypeError: get_srgb1() got an unexpected keyword argument 'colorspace'

tmp_install/usr/lib/python3.10/site-packages/orthopy/u3/tools.py:39: TypeError
================================================================================= warnings summary ==================================================================================
tests/test_cn.py::test_show_tree[2]
tests/test_cn.py::test_show_tree[2]
  /tmp/makepkg/python-orthopy/src/orthopy-0.9.5/tmp_install/usr/lib/python3.10/site-packages/orthopy/cn/tools.py:73: MatplotlibDeprecationWarning: Auto-removal of grids by pcolor() and pcolormesh() is deprecated since 3.5 and will be removed two minor releases later; please call grid(False) first.
    plt.colorbar()

tests/test_enr2.py::test_show_tree[2]
tests/test_enr2.py::test_show_tree[2]
  /tmp/makepkg/python-orthopy/src/orthopy-0.9.5/tmp_install/usr/lib/python3.10/site-packages/orthopy/enr2/tools.py:80: MatplotlibDeprecationWarning: Auto-removal of grids by pcolor() and pcolormesh() is deprecated since 3.5 and will be removed two minor releases later; please call grid(False) first.
    plt.colorbar()

tests/test_t2.py::test_show_tree
tests/test_t2.py::test_show_tree
  /tmp/makepkg/python-orthopy/src/orthopy-0.9.5/tmp_install/usr/lib/python3.10/site-packages/orthopy/t2/tools.py:112: MatplotlibDeprecationWarning: Auto-removal of grids by pcolor() and pcolormesh() is deprecated since 3.5 and will be removed two minor releases later; please call grid(False) first.
    plt.colorbar()

tests/test_s2/test_xu.py::test_show[degrees0]
tests/test_s2/test_xu.py::test_show[degrees0]
tests/test_s2/test_zernike.py::test_show[degrees0]
tests/test_s2/test_zernike2.py::test_show[degrees0]
  /tmp/makepkg/python-orthopy/src/orthopy-0.9.5/tmp_install/usr/lib/python3.10/site-packages/orthopy/s2/tools.py:32: MatplotlibDeprecationWarning: Auto-removal of grids by pcolor() and pcolormesh() is deprecated since 3.5 and will be removed two minor releases later; please call grid(False) first.
    plt.colorbar()

tests/test_s2/test_xu.py::test_show_tree[2]
tests/test_s2/test_xu.py::test_show_tree[2]
tests/test_s2/test_zernike.py::test_show_tree[2]
tests/test_s2/test_zernike.py::test_show_tree[2]
tests/test_s2/test_zernike2.py::test_show_tree[2]
tests/test_s2/test_zernike2.py::test_show_tree[2]
  /tmp/makepkg/python-orthopy/src/orthopy-0.9.5/tmp_install/usr/lib/python3.10/site-packages/orthopy/s2/tools.py:108: MatplotlibDeprecationWarning: Auto-removal of grids by pcolor() and pcolormesh() is deprecated since 3.5 and will be removed two minor releases later; please call grid(False) first.
    plt.colorbar()

-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html
============================================================================== short test summary info ==============================================================================
FAILED README.md::line 246
FAILED tests/test_u3.py::test_write_single - TypeError: get_srgb1() got an unexpected keyword argument 'colorspace'
FAILED tests/test_u3.py::test_write_tree - TypeError: get_srgb1() got an unexpected keyword argument 'colorspace'
========================================================= 3 failed, 237 passed, 10 skipped, 16 warnings in 65.79s (0:01:05) =========================================================

fix hermite polynomials

The scaling (monic, classical, normal) is orthogonal on the standardization (probabilist, physicist).

Hard dependency on matplotlib / tk?

It would be good if orthopy was usable in environments where matplotlib and/or tk is not installed. Currently it will attempt to import matplotlib, which attempts to set up the tkagg backend, failing to do so because I'm using a Python that was not compiled with tk. It seems a little counterintuitive that I need to have a GUI library compiled with Python for generating quadrature rules (via quadpy).

In the meantime I've had to lift the parts I need out of quadpy into my own modules. This is fine but not ideal. Please consider making the dependency on matplotlib optional.

Understanding outputs of the functions

I have a doubt about the inputs/outputs of the software. When I write:

x = np.linspace(-1,1,101)
evaluator = orthopy.c1.legendre.Eval(x, "classical")
for _ in range(5):
     print(next(evaluator)) 

what I get is the function legendre evaluated at x.
However, when I write:

x = [0.1, -0.3]
evaluator = orthopy.s2.zernike.Eval(x, "normal")
for _ in range(5):
     print(next(evaluator))

What am I getting here?

faster tests

Explicit polynomial integration helps, see, e.g., the e1r tests.

show depends on matplotx

import orthopy

orthopy.c1.jacobi.show(5, "normal", 0.0, 0.0)

gives,
ModuleNotFoundError: No module named 'matplotx'

matplotx is not installed by default when installing orthopy.

No setup.py

setup.py was removed in a recent commit. However, this makes it quite cumbersome to install the package by downloading the package and doing it manually (which is what I am doing).

I.e.

  1. Download from here
  2. Extract
  3. Do python setup.py install would fail.
  4. Then I found out that you are doing: python3 -m pep517.build --source --binary .

While pep517 may have gotten traction I would hope that you would re-enable the setup.py since it is quite convenient until pep517 has stabilized (the pep517.build documentation clearly states that this is not the final placement).

If you want a minimal setup.py you could do with:

#!/usr/bin/env python
from setuptools import setup

setup(use_scm_version=True)

and then amend your setup.cfg with

setup_requires =
    setuptools >= 41.2
    setuptools_scm

The reason is that I can't figure out how to customize --prefix with the pep517 command. And this is really necessary when trying to install in non-standard locations.

Basically I cannot do:

python3 -m pep517.build --source . --prefix=<>

Do you know of any other way?

PS. This issue would also apply to quadpy ;)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.