Skip to content

Commit

Permalink
[25, 28, 30, 33] Merge develop into main (#35)
Browse files Browse the repository at this point in the history
* BLD:
- first test of a GitHub CI for testing

* FIX:
- fixed wrong pip install and python versions in CI ?

* FIX:
- fixed loading of test files that do not contain test but dependencies that cannot be loaded ?

* BUG:
- escaped imports of unaccessible dependencies for test-file generation in GitHub CI tests by making the `if __name__ == "__main__"` include these imports and function definitions

* TST:
- test whether Cython build can be removed from GitHub actions for testing ?

* TST:
- reverted removal of Cython for testing

* PKG:
- moved the full package back into an `src`-folder

BLD:
- updated `pyproject.toml` and `setup.py` to account for the movement to the `src`-folder
- removed dedicated Cython build from CI test pipeline

* BLD:
- changed CI pipeline target branches

* BLD:
- augmented CI checks with format, type, and lint checks

* BUG:
- fixed CI pipeline wrong folder include ?

BLD:
- added isort check

* BUG:
- fixed broken `isort` usage in CI?

* FIX:
- fixed missing `isort` dependency in CI?
- fixed wrong import sort order in Cython Hermite functions

* FIX:
- fixed missing `colorama` dependency for `isort` in CI ?

* FIX:
- type-ignored Cython import that was not properly resolved by `pyright` ?

* FIX:
- fixed missing import of Cython module for `pyright`  in CI ?

* FIX:
- again trying to resolve the wrong import error of Cython module by `pyright` in CI ?

* FIX:
- fixed wrong `pyright` Cython import error of Cython import in CI

* BLD:
- removed pushes to `develop` from the GitHub CI actions

* BLD:
- added missing comma to the name of the GitHub CI action

* [10 develop] Add coverage to CI pipeline (#11)

* DOC:
- added Python versions and `black` code style to `README`

* DOC:
- added `isort` badge to `README`

* TST:
- added `--no-jit`-flag to `pytest` to enable proper coverage of Numba functions

* tmp:
- first test of CI with coverage report ?

* BUG:
- fixed failure of `pytest-xdist` and `pytest-cov` in GitHub CI (works locally) ?

* BUG:
- fixed accidentally placed `\` for `./tests` in coverage CI action ?

* BUG:
- added codecov to CI pipeline ?

* TST:
- tried to readd `pytest-xdist` for coverage reports ?

* wip:
- reset example Jupyter notebook number 3

* MAINT:
- made `_get_num_workers` a function of the `_utils`-model

TST:
- increased coverage to 100% by testing `np.float32` x-values for the Hermite functions was well as super negative numbers of requested workers

* DOC:
- added setup, installation, and development instructions to `README`

* DOC:
- switched back from `README.rst` to `README.md`

BLD:
- made CI pipeline push actions apply to the main branch only

* [Pre-16] Add Makefile (#17)

* BLD:
- added initial version of Makefile and based GitHub CI on it ?

* BUG:
- fixed type in `pip install` in `Makefile` for GitHub CI

* BLD:
- added plain install to Makefile
- removed current branch from GitHub CI trigger on push

DOC:
- added Makefile instructions to `README`

* [13-2] Implement class interface to Hermite functions (#18)

* BLD:
- added `mypy` to CI pipeline

BUG:
- fixed type error that `mypy` uncovered for the `filename_parameters_mapping` for the Hermite function reference generation

* wip:
- test if CI can still pass ?

* wip:
- CI apparently still runs; removed check

* BLD:
- added `pycodestyle` as a part of the CI checks

BUG:
- fixed a line too long error revealed by `pycodestyle`

* DOC:
- added CI test status to `README` ?

* ENH:
- added functions that help for computing discrete/continuous Fourier transforms (`fourier_transform._fft_utils`)

TST:
- implemented a test suite for `fourier_transform._fft_utils`

* Issue 14 #14
DOC:
- updated equations with new definitions of $\alpha$
- updated `README` with new equations and added respective reference that these definitions are based on

* Issue 14 #14
MAINT:
- removed redundant Numba version of the legacy Hermite functions and `jit`-compiled the NumPy-version instead
- fixed minor documentation issues

* Issue 14 #14
MAINT:
- adapted interface to Hermite functions to the new definition of $\alpha$ in terms of both implementation and docs

* Issue 14 #14
DOC:
- updated example scripts and resulting plots with new definition of $\alpha$

* Issue 14 #14
TST:
- generated new references files for testing the new definition of $\alpha$ for the Hermite functions
- adapted Hermite function tests to properly run for the new definition of $\alpha$
- configured Hermite function tests via global constants and kept comments in them more vague
- made test for Cramér's inequality of the Hermite functions ensure that the boundary value is not only an upper bound but actually reached
- changed `requirements` for GitHub CI because with a re-arrangement of the `if __name__ == "__main__"` in the Hermite function reference generation file, `sympy` and `tqdm` became CI requirements as well

* BUG:
- fixed failing `ruff` for too long line in docstring of new `_fft_utils`

BLD:
- temporarily enabled CI on push to current branch to check if it still passes after an adaption in `pyright`

* Issue 14 #14
BLD:
- disabled GitHub CI on push to the current branch again after verifying that it still runs

* Issue 13 #13 (3)
ENH:
- added `x_center` to the Hermite function basis for shifting the Hermite functions in x-direction
- added input validation for `x_center`

MAINT:
- renamed `hermite_functions._interface` to `hermite_functions._func_interface` to prepare for the class interface
- made type handling of Hermite function input validation smarter and safer by first converting to the target type and then testing only for this one
- made argument types for `x` of the Hermite functions broader by also including lists and tuples

TST:
- made input validation tests for Hermite functions be executed before the Hermite function reference tests
- made input validation tests for Hermite functions not only check failure but also success cases
- added tests for the new `x_center` and ensured that it does not modify the original `x`-values for the Hermite functions (after this causes some problems)

DOC:
- updated all equations and the `README` to clarify the new `x_center` for the Hermite functions
- updated installation commands (also mentioned venv activation) and test/check commands in `README`

* DOC:
- added y-axis to Hermite-function-scale-effect-plot
- fixed first vertical x-axis for order `n=0` not showing in the plot at all

* Issue #13 (3)
MAINT:
- moved Hermite function input validation to dedicated file

ENH:
- pushed forgotten files that add `x_center` to Hermite functions

TST:
- pushed forgotten files that test the new `x_center` of the Hermite functions and improved the testing of the Hermite function input validation

* TST:
- split up tests for Hermite functions into dedicated test files to be more flexible

* Issue #13 (3)
DOC:
- added common matplotlib style to unify all plots
- updated example scripts with new matplotlib style
- added shifted center to Hermite function example 01

* DOC:
- made example plots 01 and 02 for Hermite functions more visually appealing/less overwhelming

* Issue #13 (6.1)
ENH:
- added auxiliary script that auto-generates a Python file with spline coefficients for almost exactly evaluating the largest zero (= outermost roots) of the Hermite functions up to order ~100_000

* Issue #13 (6.1)
MAINT:
- refactored the reference creation for the largest roots of the Hermite functions to not minimize the relative but the absolute error
- relaxed permitted absolute error in reference creation for the largest roots of the Hermite functions because the SciPy-reference is not that accurate

DOC:
- mentioned that the SciPy-reference for the largest roots of the Hermite functions is not perfectly accurate

* Issue #13 (6)
ENH:
- added script to create reference data for the largest extrema of the Hermite functions
- added new `_approximations`-module for Hermite functions that offers approximations for their largest roots, largest extrema, and fadeout points

TST:
- added tests for the new `_approximations`-module

DOC:
- added legend to first plot in script that creates reference data for the largest roots of the Hermite functions

* MAINT:
- refactored the reference data generation for the largest roots and extrema of the Hermite functions to fit the splines based on relative errors
- updated reference data and plots created by these scripts
- made this reference data generation a developer-only script

TST:
- made test for largest root of Hermite functions more meaningful by adapting the tolerance for checking to the actual magnitude of the root position
- made test for largest extremum of Hermite functions more meaningful by checking the y-values (and not the x-values) of the extremum against a numerical optimisation (also with magnitude-adaptive tolerances)

* DOC:
- made all plot saves in examples available for developers only
- aligned plots in terms of visuals (especially titles and sizes)
- updated `README` with new plots and developer-only environment variable

* BLD:
- added additional scripts checks to GitHub CI
- made all tools cause actual failures rather than just printing test output ?
- broke CI on purpose, by badly formatting `auxiliary_scripts\02_hermite_functions_largest_extremum.py` and `src\robust_hermite_ft\hermite_functions\_c_hermite.pyx`

* BLD:
- CI tests fixed `black` formatting after confirming that it works
- `isort` is the next to check

* BLD:
- fixed `isort` CI failure after confirming that it works
- `pyright` is the next to check

* BLD:
- temporarily broke `isort` CI check again to check its output

* BLD:
- fixed `isort` problem again
- checking for reasons why `pyright`-check fails by running it separately without output ?

* BLD:
- fixed `pyright` error handling in CI
- `mypy` is the next one to check, but for now it's checked whether it just runs through even though there is an error

* BLD:
- pushing updated CI workflow file for properly testing that `mypy` just runs through
- added `matplotlib` to CI requirements to avoid `pyright` from throwing an error ?

* BLD:
- going back to the start for tests after `mypy` also stopped CI correctly
- starting with `black` test

* BLD:
- `black` successfully stopped the CI without customised handling
- `isort` is the next to check without customised handling

* BLD:
- also `isort` stops the CI on failure
- next to check is `pyright`

* BLD:
- reverted GitHub CI to its original working state

* DOC:
- updated `README` with new CI commands

* ENH:
- Hermite functions now support all kinds of real numeric scalars/Arrays as `x`-values, integer scalars as `n`-values, and real numeric scalars for `alpha` and `x_center` after making the input validation way more relaxed and smarter

TST:
- test for Hermite function input validation now covers Python and Numpy scalars individually and on top of that also includes Pandas series and Python Arrays
- test for data link to original `x` in Hermite functions now evaluates dynamically whether memory is shared by checking if changes in the copy/view are reflected in the original
- added a completely new test set whether the Hermite functions yield the same results for all different kinds of `x`-values, `n`-values, `alpha`- and `x-center` values

* BUG:
- fixed missing `pandas` dependency for GitHub CI

* BUG:
- fixed type incompatibility that caused `mypy` to crash the GitHub CI

* TST:
- fixed missing coverage for default and error handling of FFT utility functions

* DOC:
- arranged legend of plot for special points of Hermite functions in a better position

* TST:
- removed unnecessary list parametrization for orthonormality test of Hermite functions

* DEV:
- fixed wrong wording of static type check in Makefile
- added combined check for all checks to Makefile

* ENH:
- improved typing to given `dtype` type hint for Arrays in Hermite functions

* ENH:
- added check that the `x` for Hermite function computations holds at least 1 entry

TST:
- extended input validation test for Hermite functions to cover the "at least 1 element in x" failure case

* ENH:
- made integer type hinting of Hermite functions more consistent
- added option to disable input validation of Hermite functions

* DOC:
- added complete check make command to `README`

* Issue #13 (7, 8)
ENH:
- made `x_center` a float-only in the internals of the Hermite functions

TST:
- moved tests for function interface of the Hermite functions to a dedicated test file that can be distinguished from the tests for the class interface

DEV:
- added make command for running a single test

* DEV:
- made names of test commands in Makefile more descriptive in terms of coverage
- updated GitHub CI and `README` accordingly

* ENH:
- finalised proper type handling of the parameters of the Hermite functions in `_func_interface` and `_approximations`
- removed checks for `x_center is None`  for the Hermite function that are now obsolete given that it's always a float

* Issue #13 (7, 9)
ENH:
- implemented a class interface to the Hermite functions that can compute them in the time/space and frequency domain with in principle arbitrary parameters

Issue #13 (8)
TST:
- added extensive tests for the new class interface to the Hermite functions

* Issue #13 (7, 9)
ENH:
- added static method `eval` to `HermiteFunctionBasis` and made this the central computation method where `HermiteFunctionsBasis` (especially `__call__`) wraps around

Issue #13 (8)
TST:
- made tests for `HermiteFunctionBasis` properly cover both the static method `eval` and the magic method `__call__` via the parametrised tests

* [19] Rechange definition of `alpha` in Hermite functions back to a denominator; made Hermite function definition only real for the time/space domain (#20)

* # Issue 19
MAINT:
- refactored all Hermite functions computations (except for the class interface) to handle the new old definition of the scaling parameter alpha for `x / alpha` rather than the former `alpha * x`

TST:
- regenerated symbolic reference files for Hermite functions to reflect the new definition of alpha
- reflected new definition of alpha in all Hermite function tests
- improved test variable naming of global constants
- made x-value computation of the orthonormality test of the Hermite functions based on an approximation of the fadeout points and the order to lower the computational load while ensuring that the x-values are always properly created in a dynamic fashion
- made Cramér's inequality check for Hermite functions checked with relative rather than absolute tolerance

* Issue #19
DEV:
- added auxiliary script that creates images of the equations used for documenting the package
- added a make command to update all the equation images via this script

DOC:
- incorporated the new definition of the scaling factor alpha of the Hermite functions (not `alpha * x` but now `alpha / x` again) in the documentation
- cleaned up documentation equation images and plots
- linked all new equations and plots properly in the `README` and docstrings

* BUG:
- updated fontsize of equations to ensure they are properly rendered in `README` (not pixely) ?

* BUG:
- made equation images in `README` not pixely ?

* BUG:
- made equation images in `README` not pixely (new resolution) ?

* BUG:
- made equation images in `README` not pixely pt.3 ?

* BUG:
- made equation images in `README` not pixely pt.4 ?

* BUG:
- made equation images in `README` not pixely pt.5 (transition to SVG) ?

* BUG:
- made equation images in `README` not pixely pt.5 (SVG with reduced fontsize) ?

* BUG:
- made equation images in `README` not pixely pt.6 (SVG with even more fontsize reduction) ?

* BUG:
- made equation images in `README` not pixely pt.7 (SVG with even more fontsize reduction) ?

* DOC:
- fully transitioned to `.svg` instead of `.png` based documentation
- added plain definition of Hermite functions and polynomials to script that creates/updates equation images

* BUG:
- fixed too small equations in `README` ?

* BUG:
- fixed too small font of equation images in `README`

* Issue #19
MAINT:
- adapted definition of the Hermite function class interface to make the time/space domain real-valued only

TST:
- adapted output dtypes of the Hermite class interface to the new definition that the time/space domain has to be real-valued only

DOC:
- added LaTeX equation images for the Hermite functions and their Fourier transforms

* Issue #19
DOC:
- added example for the Fourier transforms of the Hermite functions with the new definition of `alpha`
- made the Fourier transform of the Hermite functions part of the `README`
- updated all plots because an axis label size changed

* BUG:
- fixed typo in `README`

* ENH:
- made validation functions for Hermite function input public
- made validation input for `x_center` for Hermite functions more generic

* ENH:
- made typing of input validation of Hermite functions indicate `Any` instead of any specified types

* DOC:
- changed colors of example 4 plots

* DOC:
- removed Fourier transform of Hermite functions from examples and `README`

* ENH:
- made input validation of Hermite functions more flexible for the `x_center` by just handling it as an offset of a certain axis

* Issue #13 (7 - 9)
ENH:
- actually a downwards enhancement
- removed the direct Fourier transform of the Hermite function class interface
- adapted all implementations, documentations, and tests to this new stripped down version of the class interface
- included class interface into function interface test for the Hermite functions and therefore renamed the test file from `function_interface` to `implementations`

* [21, 22] Remaned package to `robust_fourier`; dropped Cython implementation of Hermite functions (#23)

* Issue #22
MAINT:
- dropped Cython implementation of Hermite functions (also `cython-lint` as a check in the CI)

* Issue #22
MAINT:
- removed `Cython` and `psutil` from the requirements

* Issue #22
MAINT:
- completely dropped Cython implementation of all Hermite functions in the whole package

Issue #23
MAINT:
- renamed package from `robust_hermite_ft` to `robust_fourier`

* BUG:
- raised coverage to 100% again by conducting type error check for the `jit` property of the Hermite function class interface

* BUG:
- fix `black` check crashing the CI because of missing empty line

* Issue #22
MAINT:
- relaxed upper bound on NumPy version (now also v2 will be allowed)

* BUG:
- fixed wrong hashtag in test file

* BUG:
- fixed NumPy v2 deprecated `trapz`

* BUG:
- fixed wrong `README`-file in `pyproject.toml`

* [25] Add Chebyshev basis (#27)

* Issue #25
MAINT:
- made `_validate` that was part of the Hermite functions a part of the general `_utils` to enable easy generalization

* Issue #25
MAINT:
- refactored the normalisation of the x-values of the Hermite functions to be part of the general `_utils._x_preprocessing` to make them generally available

TST:
- made tests for `_utils._validate` and `_utils._x_preprocessing` standalone tests

DOC:
- improved docstrings of the Hermite functions

* DEV:
- added make command for selected parallelized tests to `Makefile`

Issue #25
TST:
- renamed test files for Hermite functions to be less repetitive in terms of their naming to enable similar structures in the future

* Issue 25
ENH:
- added Chebyshev polynomial implementations in NumPy and Numba

TST:
- added working version of tests for the Chebyshev polynomials

* Issue #25
TST:
- added tests for correct handling of different inputs of the Chebyshev polynomials

* Issue #25
ENH:
- implemented class interface to Chebyshev polynomials

TST:
- added tests for class interface to Chebyshev polynomials

DEV:
- fixed `pycodestyle` not handling `overload`s properly

* Issue #25
DOC:
- added tiny examples and equations for the Chebyshev polynomials and updated the `README`

* MAINT:
- made `numba_helpers` private
- fixed wrong import of the package itself in `numba_funcs` of the Chebyshev polynomials
- `type: ignore`d kind assignments in Chebyshev polynomial class tests
- fixed missing comma in `Makefile` print statement

* Issue #25
BUG:
- fixed wrong type hint in `kind` property of Chebyshev polynomial class

* [28] Row-wise basis evaluation (#29)

* Issue #28
ENH:
- switched from column-wise to row-wise computation of the Hermite function and Chebyshev polynomial basis to enhance the computation speed

* Issue #28
DOC:
- added performance test for Chebyshev polynomials
- updated performance test for Hermite functions

* [30] Rename basis function function interface to `vander` (#32)

* Issue #30
ENH:
- renamed Hermite function basis to `vander` to be more consistent with NumPy

* Issue #30
ENH:
- renamed Chebyshev basis to `vander` to be more consistent with NumPy

* [33] Find Hermite Tail Approximations (#34)

* DEV:
- made LaTeX equation writer the first script in the auxiliary scripts to keep a logical order

* ENH:
- made `dtype`-conversion for the x-value checking of the Hermite functions and the Chebyshev polynomials more generic
- renamed x-value checking to grid point checking and made names more generic to handle cases when other values that are not x need to be checked

* Issue #33
MAINT:
- restructured the use of the approximation functions for the Hermite functions
- it is now recommended to use the `hermite_approx` module that was exposed
- the approximation functions within there now have way more descriptive names that avoid confusion (between x and y which is no longer written in the back of the name)
- cleaned up auxiliary script for largest root pre-computation for the Hermite functions

ENH:
- added y-position of largest extremum of Hermite functions to the auxiliary script that already pre-computes the respective x-position
- added an approximation function for the y- and the combined x-and y-position of the largest extremum of the Hermite functions
- added an auxiliary script that pre-computes a CRUDE Gaussian peak fit for the outermost oscillations of the Hermite functions
- implemented a class-based function to approximate the outermost Hermite function oscillations with 2 Gaussian peaks

DOC:
- updated `README` with new approximations

* Issue #33
ENH:
- added a convenience function to get the x-solution of the Gaussian tail approximation
- updated example 04 and `README` with this new function

* DOC:
- slightly shortened Hermite function approximation example in the `README`

* DEV:
- removed `TODO`s

* Issue #33
TST:
- added parametrized test for the Gaussian approximation of the outermost oscillations of the Hermite functions

* BUG:
- check why `pyright` fails in CI for unrelated file ?
- hoping that `mypy` will give a better error message

* BUG:
- check if changing overload order of Chebyshev polynomial function interface fixed `pyright problem` ?

* BUG:
- fixed overload of Chebyshev polynomial Vandermonde function interface to avoid `pyright` from failing in the CI (`kind` is now a keyword-only argument)

* DEV:
- made auxiliary scripts parse their own script name automatically to the created files
- fixed minor errors in their descriptions

* DOC:
- fixed typo in comment
  • Loading branch information
MothNik authored Sep 4, 2024
1 parent 22702bc commit 2e0fc02
Show file tree
Hide file tree
Showing 63 changed files with 24,010 additions and 4,789 deletions.
14 changes: 10 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ SRC_DIRS = ./auxiliary_scripts ./examples ./src ./tests
# Upgrading pip, setuptools and wheel
.PHONY: upgrade-pip
upgrade-pip:
@echo Upgrading pip, setuptools and wheel ...
@echo Upgrading pip, setuptools, and wheel ...
python -m pip install --upgrade pip setuptools wheel

# Installing the required dependencies and building the package
Expand Down Expand Up @@ -57,7 +57,7 @@ mypy-check:
.PHONY: pycodestyle-check
pycodestyle-check:
@echo Checking code style with 'pycodestyle' ...
pycodestyle $(SRC_DIRS) --max-line-length=88 --ignore=E203,W503
pycodestyle $(SRC_DIRS) --max-line-length=88 --ignore=E203,W503,E704

# ruff lint checking
.PHONY: ruff-check
Expand All @@ -71,12 +71,18 @@ check: black-check isort-check pyright-check mypy-check pycodestyle-check ruff-c

# === Test Commands ===

# Running a single test
# Running a selected test (serial)
.PHONY: test
test:
@echo Running specific test with pytest ...
pytest -k "$(TEST)" -x

# Running a selected test (parallel)
.PHONY: test-parallel
test-parallel:
@echo Running specific test with pytest in parallel ...
pytest -k "$(TEST)" -n="auto" -x

# Running the tests
.PHONY: test-htmlcov
test-htmlcov:
Expand All @@ -95,4 +101,4 @@ test-xmlcov:
.PHONY: update-equations
update-equations:
@echo Updating the LaTeX equations ...
python ./auxiliary_scripts/03_write_docs_equations.py
python ./auxiliary_scripts/00_write_docs_equations.py
86 changes: 68 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ isort --check --diff --color ./auxiliary_scripts ./examples ./src ./tests
pyright ./auxiliary_scripts ./examples ./src ./tests
mypy ./auxiliary_scripts ./examples ./src ./tests
ruff check ./auxiliary_scripts ./examples ./src ./tests
pycodestyle ./auxiliary_scripts ./examples ./src ./tests --max-line-length=88 --ignore=E203,W503
pycodestyle ./auxiliary_scripts ./examples ./src ./tests --max-line-length=88 --ignore=E203,W503,E704
```

### ✅❌ Tests
Expand Down Expand Up @@ -166,37 +166,81 @@ special points of the Hermite functions, namely the x-positions of their
- the point where they numerically fade to zero.

```python
from robust_fourier import (
approximate_hermite_funcs_fadeout_x,
approximate_hermite_funcs_largest_extrema_x,
approximate_hermite_funcs_largest_zeros_x,
)
from robust_fourier import hermite_approx

N = 25
ALPHA = 20.0
MU = 150.0

# 1) the x-positions at which the outermost oscillation fades below machine
# precision
x_fadeout = approximate_hermite_funcs_fadeout_x(
n=25,
alpha=20.0,
x_center=150.0,
x_fadeout = hermite_approx.x_fadeout(
n=ORDER,
alpha=ALPHA,
x_center=MU,
)
# 2) the x-positions of the largest zeros
x_largest_zero = approximate_hermite_funcs_largest_zeros_x(
n=25,
alpha=20.0,
x_center=150.0,
x_largest_zero = hermite_approx.x_largest_zeros(
n=ORDER,
alpha=ALPHA,
x_center=MU,
)
# 3) the x-positions of the largest extrema
x_largest_extremum = approximate_hermite_funcs_largest_extrema_x(
n=25,
alpha=20.0,
x_center=150.0,
x_largest_extremum = hermite_approx.x_largest_extrema(
n=ORDER,
alpha=ALPHA,
x_center=MU,
)

# 4) the Gaussian approximation of the outermost oscillation ...
left_gaussian, right_gaussian = hermite_approx.get_tail_gauss_fit(
n=ORDER,
alpha=ALPHA,
x_center=MU,
)
# ... which is solved for the 50% level
x_left_fifty_percent = left_gaussian.solve_for_y_fraction(y_fraction=0.5)
x_right_fifty_percent = right_gaussian.solve_for_y_fraction(y_fraction=0.5)

# 5) the Gaussian approximation is also solved for the 1% interval as a more
# realistic (less conservative) approximation of the fadeout point
x_one_percent = hermite_approx.x_tail_drop_to_fraction(
n=ORDER,
y_fraction=0.01,
alpha=ALPHA,
x_center=MU,
).ravel()

```

<p align="center">
<img src="docs/hermite_functions/EX-04-HermiteFunctions_SpecialPoints.svg" width="1000px" />
</p>

## 🧮 Chebyshev Polynomials

Even though the [Hermite functions](#〰️-hermite-functions) have some nice properties,
they are not necessarily the best choice for the Fourier transform. Choosing their
scaling parameter $\alpha$ can be a bit tricky.
Therefore [[3]](#references) suggests using Chebyshev polynomials instead. They are
only defined on the interval $[-1, 1]$ and can be scaled and shifted to fit the
interval $[\mu - \alpha, \mu + \alpha]$ like

<p align="center">
<img src="docs/chebyshev_polynomials/equations/CP-01-Chebyshev_Polynomials_Recurrence_Relation_First_Kind.svg" />

for the first kind and

<p align="center">
<img src="docs/chebyshev_polynomials/equations/CP-02-Chebyshev_Polynomials_Recurrence_Relation_Second_Kind.svg" />

for the second kind. In [[3]](#references) the second kind $U$ is used, but the first
kind $T$ is also implemented in `robust_fourier`.

<p align="center">
<img src="docs/chebyshev_polynomials/EX-05-DilatedChebyshevPolynomials_DifferentScales.svg" width="1000px" />
</p>

## 📖 References

- [1] Dobróka M., Szegedi H., and Vass P., Inversion-Based Fourier Transform as a New
Expand All @@ -205,3 +249,9 @@ x_largest_extremum = approximate_hermite_funcs_largest_extrema_x(
- [2] Bunck B. F., A fast algorithm for evaluation of normalized Hermite functions,
_BIT Numer Math_ (2009), 49, pp. 281–295, DOI:
[https://doi.org/10.1007/s10543-009-0216-1](https://doi.org/10.1007/s10543-009-0216-1)
- [3] Al Marashly, O., Dobróka, M., Chebyshev polynomial-based Fourier transformation
and its use in low pass filter of gravity data, _Acta Geod Geophys_ (2024), 59,
pp. 159–181 DOI: [https://doi.org/10.1007/s40328-024-00444-z](https://doi.org/10.1007/s40328-024-00444-z)
- [4] Hrycak T., Schmutzhard S., Accurate evaluation of Chebyshev polynomials in
floating-point arithmetic, _BIT Numer Math_ (2019), 59, pp. 403–416,
DOI: [https://doi.org/10.1007/s10543-018-0738-5](https://doi.org/10.1007/s10543-018-0738-5)
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,37 @@ def __iter__(self):
# the paths to there the images will be stored (relative to the current file) and their
# respective LaTeX expressions
EQUATION_SPECIFICATIONS = {
"chebyshev_polynomials_recurrence_relation_first_kind": EquationSpecification(
image_path=(
"../docs/chebyshev_polynomials/equations"
"/CP-01-Chebyshev_Polynomials_Recurrence_Relation_First_Kind.svg"
),
latex_expression=(
r"$T_{n+1}^{\left(\alpha;\mu\right)}\left(x\right)=2\cdot "
r"\frac{x-\mu}{\alpha}\cdot T_{n}^{\left(\alpha;\mu\right)}\left(x\right)-"
r"T_{n-1}^{\left(\alpha;\mu\right)}\left(x\right)$"
+ "\n\n"
+ r"$T_{0}^{\left(\alpha;\mu\right)}\left(x\right)=1$"
+ "\n\n"
+ r"$T_{1}^{\left(\alpha;\mu\right)}\left(x\right)=\frac{x-\mu}{\alpha}$"
),
),
"chebyshev_polynomials_recurrence_relation_second_kind": EquationSpecification(
image_path=(
"../docs/chebyshev_polynomials/equations"
"/CP-02-Chebyshev_Polynomials_Recurrence_Relation_Second_Kind.svg"
),
latex_expression=(
r"$U_{n+1}^{\left(\alpha;\mu\right)}\left(x\right)=2\cdot "
r"\frac{x-\mu}{\alpha}\cdot U_{n}^{\left(\alpha;\mu\right)}\left(x\right)-"
r"U_{n-1}^{\left(\alpha;\mu\right)}\left(x\right)$"
+ "\n\n"
+ r"$U_{0}^{\left(\alpha;\mu\right)}\left(x\right)=1$"
+ "\n\n"
+ r"$U_{1}^{\left(\alpha;\mu\right)}\left(x\right)="
r"2\cdot\frac{x-\mu}{\alpha}$"
),
),
"hermite_functions_time_space_domain": EquationSpecification(
image_path=(
"../docs/hermite_functions/equations"
Expand Down
44 changes: 28 additions & 16 deletions auxiliary_scripts/01_hermite_functions_largest_zeros.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,12 +56,13 @@
# the template for storing the spline specifications in the Python file
SPLINE_SPECS_TEMPLATE = """
\"\"\"
Module :mod:`hermite_functions._hermite_largest_roots_spline`
Module :mod:`hermite_functions.{file_name}`
This file is auto-generated by the script ``auxiliary_scripts/01_hermite_functions_largest_zeros.py``.
This file is auto-generated by the script ``{generator_file}``.
This module stores the B-spline specifications for the largest zeros (= outermost roots)
of the first ``{order_stop}`` Hermite functions.
The spline is a quintic B-spline with ``{num_knots}`` knots and its maximum absolute relative
error is ``{max_abs_rel_error:.2e}`` with respect to ``scipy.special.roots_hermite``.
It should be noted that ``scipy.special.roots_hermite`` only gives roots whose y-values
Expand Down Expand Up @@ -130,7 +131,7 @@
raise FileNotFoundError()

reference_data = np.load(reference_file_path, allow_pickle=False)
orders, outerm_root_x_positions = (
orders, outermost_root_x_positions = (
reference_data[::, 0],
reference_data[::, 1],
)
Expand All @@ -144,17 +145,17 @@
order_start = order_end

orders = np.array(orders, dtype=np.int64)
outerm_root_x_positions = np.empty_like(orders, dtype=np.float64)
outermost_root_x_positions = np.empty_like(orders, dtype=np.float64)

progress_bar = tqdm(total=len(orders), desc="Computing outermost roots")
for idx, n in enumerate(orders):
outerm_root_x_positions[idx] = roots_hermite(n=n)[0][-1]
outermost_root_x_positions[idx] = roots_hermite(n=n)[0][-1]
progress_bar.update(1)

# the reference data is stored
np.save(
reference_file_path,
np.column_stack((orders, outerm_root_x_positions)),
np.column_stack((orders, outermost_root_x_positions)),
allow_pickle=False,
)

Expand All @@ -164,26 +165,26 @@
# maximum absolute error drops below the threshold
max_abs_rel_error = np.inf
s_value = 1e-10
weights = np.reciprocal(outerm_root_x_positions) # all > 0
weights = np.reciprocal(outermost_root_x_positions) # all > 0
tck = None
outerm_root_x_positions_approx = None
outermost_root_x_positions_approx = None
while max_abs_rel_error > X_MAX_RTOL and s_value > 1e-30:
tck = splrep(
x=orders,
y=outerm_root_x_positions,
y=outermost_root_x_positions,
w=weights,
k=SPLINE_DEGREE,
s=s_value,
)
outerm_root_x_positions_approx = splev(x=orders, tck=tck)
outermost_root_x_positions_approx = splev(x=orders, tck=tck)

max_abs_rel_error = np.abs(
(outerm_root_x_positions - outerm_root_x_positions_approx) * weights
(outermost_root_x_positions - outermost_root_x_positions_approx) * weights
).max()
s_value /= 10.0**0.25

assert (
tck is not None and outerm_root_x_positions_approx is not None
tck is not None and outermost_root_x_positions_approx is not None
), "No spline was fitted, please re-adjust the tolerances and smoothing values."
print(
f"\nFinal number of spline knots: {len(tck[0])} for smoothing value "
Expand All @@ -200,10 +201,14 @@
with open(spline_specs_file_path, "w") as spline_specs_file:
spline_specs_file.write(
SPLINE_SPECS_TEMPLATE.format(
generator_file="/".join(
__file__.replace("\\", "/").split("/")[-2::]
),
file_name=SPLINE_SPECS_FILE_PATH.split("/")[-1].split(".")[0],
order_stop=round(orders[-1]),
num_knots=len(tck[0]),
max_abs_rel_error=X_MAX_RTOL,
diagnostic_plot_file_path=DIAGNOSTIC_PLOT_FILE_PATH,
diagnostic_plot_file_path=DIAGNOSTIC_PLOT_FILE_PATH.split("/")[-1],
knots=json.dumps(tck[0].tolist()), # type: ignore
coefficients=json.dumps(tck[1].tolist()),
degree=SPLINE_DEGREE,
Expand All @@ -223,21 +228,23 @@

ax[0].plot( # type: ignore
orders,
outerm_root_x_positions,
outermost_root_x_positions,
color="red",
label="SciPy Accurate Roots",
)
ax[0].plot( # type: ignore
orders,
outerm_root_x_positions_approx,
outermost_root_x_positions_approx,
color="#00CCCC",
label="Spline Approximation",
)

ax[1].axhline(0.0, color="black", linewidth=0.5) # type: ignore
ax[1].plot( # type: ignore
orders,
100.0 * weights * (outerm_root_x_positions - outerm_root_x_positions_approx),
100.0
* weights
* (outermost_root_x_positions - outermost_root_x_positions_approx),
color="#00CCCC",
zorder=2,
label="Difference",
Expand Down Expand Up @@ -277,6 +284,11 @@
ax[0].legend() # type: ignore
ax[1].legend() # type: ignore

fig.suptitle(
"Approximation of the Largest Zeros of the Hermite Functions",
fontsize=18,
)

# the plot is stored (if the spline coefficients were stored)
if OVERWRITE_SPLINE_SPECS:
diagnostic_plot_file_path = os.path.join(
Expand Down
Loading

0 comments on commit 2e0fc02

Please sign in to comment.