Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update readme #1

Merged
merged 6 commits into from
Jul 8, 2022
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
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
*-f2pywrappers.f
*module.c

# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
Expand Down
105 changes: 72 additions & 33 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,34 +1,73 @@
# pytspack
Python Wrapper around the Fortran TSPACK.

The primary purpose of TSPACK is to construct a smooth
function which interpolates a discrete set of data points.
The function may be required to have either one or two con-
tinuous derivatives, and, in the C-2 case, several options
are provided for selecting end conditions. If the accuracy
of the data does not warrant interpolation, a smoothing func-
tion (which does not pass through the data points) may be
constructed instead. The fitting method is designed to avoid
extraneous inflection points (associated with rapidly varying
data values) and preserve local shape properties of the data
(monotonicity and convexity), or to satisfy the more general
constraints of bounds on function values or first derivatives.
The package also provides a parametric representation for con-
structing general planar curves and space curves.

The fitting function h(x) (or each component h(t) in the
case of a parametric curve) is defined locally, on each
interval associated with a pair of adjacent abscissae (knots),
by its values and first derivatives at the endpoints of the
interval, along with a nonnegative tension factor SIGMA
associated with the interval (h is a Hermite interpolatory
tension spline). With SIGMA = 0, h is the cubic function
defined by the endpoint values and derivatives, and, as SIGMA
increases, h approaches the linear interpolant of the endpoint
values. Since the linear interpolant preserves positivity,
monotonicity, and convexity of the data, h can be forced to
preserve these properties by choosing SIGMA sufficiently
large. Also, since SIGMA varies with intervals, no more
tension than necessary is used in each interval, resulting in
a better fit and greater efficiency than is achieved with a
single constant tension factor.

Python Wrapper around Robert J. Renka's [TSPACK](https://www.netlib.no/netlib/toms/716).
TSPACK

> TSPACK is a curve-fitting package based on exponential tension splines with automatic selection of tension factors.
## Installation

If you are lucky,
```
pip install https://github.com/noaa-oar-arl/pytspack/archive/master.zip --no-deps
```
will *just work*.

Otherwise, you can clone the repo and try to build the extension module
using [`f2py`](https://numpy.org/doc/stable/f2py/index.html) manually...

### Windows

On Windows, with a [GNU Fortran via MSYS2](https://numpy.org/doc/stable/f2py/windows/msys2.html)
setup, try the following:

1. Clone the repo
```powershell
git clone https://github.com/noaa-oar-arl/pytspack
cd pytspack
```

2. Build the extension, using one of these options

Using the `setup.py`:
```
python setup.py build_ext --fcompiler=gnu95 --compiler=mingw32 --build-lib=./pytspack
```

OR

Using `f2py` directly:
```powershell
cd pytspack
python -m numpy.f2py -c --fcompiler=gnu95 --compiler=mingw32 -m tspack tspack.f
cd ..
```

3. Link pytspack to your active Python environment.
```powershell
pip install -e .
```

### Linux

We have seen some issues where some `gcc`s do not want to compile the `fortranobject.c` [^a]

Follow the same general steps as above, but don't use `--compiler=mingw32`.

On NOAA Hera, the default GCC is currently v4.
Use `module load gnu` to get newer before attempting to install pytspack,
or use
```bash
OPT='-std=c99' python -m numpy.f2py -c -m tspack tspack.f
```
to configure `gcc`.

`OPT='-std=c99'` can also be prepended to [the `pip install` above](#installation),
enabling an installation without cloning the repo.


[^a]: As mentioned [here](https://mfix.netl.doe.gov/forum/t/strange-build-error-in-mfix-21-4/3923/3), for example.

## More information

For more information on TSPACK, see [the open-access paper](https://dl.acm.org/doi/10.1145/151271.151277) (Renka, 1993) or [the netlib page](https://www.netlib.no/netlib/toms/716).
38 changes: 30 additions & 8 deletions pytspack/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,24 @@
import tspack
from numpy import array, zeros

try:
# Installed extension module
import tspack
except Exception as e1:
try:
# Locally built extension module
from . import tspack
except Exception as e2:
raise RuntimeWarning(
"Unable to import the tspack extension module. "
f"Attempting to import installed tspack extension module failed ({e1}). "
f"Attempting to import local tspack extension module failed ({e2})."
)
else:
print(
f"Attempting to import installed tspack extension module failed ({e1}). "
"Using local."
)


def hval(xp, x, y, yp, sigma):
"""Function which evaluates a Hermite interpolatory ten-
Expand Down Expand Up @@ -65,7 +83,9 @@ def tspsi(x, y, ncd=1, slopes=None, curvs=None, per=0, tension=None):
sigma = 0.0 * x

if slopes is not None and curvs is not None:
raise ValueError("You can't constrain both the slopes and curvs at the endpoints")
raise ValueError(
"You can't constrain both the slopes and curvs at the endpoints"
)
if slopes is not None:
if type(slopes) is not type([]):
raise TypeError("slopes must be a list: [slope0,slope1]")
Expand Down Expand Up @@ -102,12 +122,12 @@ def tspsi(x, y, ncd=1, slopes=None, curvs=None, per=0, tension=None):
lwk = len(x)
else:
lwk = 2 * len(x)
wk = zeros((lwk,), 'd')
wk = zeros((lwk,), "d")

wk, yp, sigma, ier = tspack.tspsi(x, y, ncd, iendc, per, unifrm, wk, yp, sigma)

if ier >= 0:
return ((x, y, yp, sigma))
return (x, y, yp, sigma)
elif ier == -1:
raise RuntimeError("Error, N, NCD or IENDC outside valid range")
elif ier == -2:
Expand Down Expand Up @@ -143,9 +163,11 @@ def tspss(x, y, w, per=0, tension=None, s=None, stol=None, full_output=0):
lwk = 6 * len(x)
else:
lwk = 7 * len(x)
wk = zeros((lwk,), 'd')
wk = zeros((lwk,), "d")

wk, sigma, ys, yp, nit, ier = tspack.tspss(x, y, per, unifrm, w, s, stol, wk, sigma, ys, yp)
wk, sigma, ys, yp, nit, ier = tspack.tspss(
x, y, per, unifrm, w, s, stol, wk, sigma, ys, yp
)

if ier == 0:
mesg = "No errors and constraint is satisfied: chisquare ~ s"
Expand All @@ -162,9 +184,9 @@ def tspss(x, y, w, per=0, tension=None, s=None, stol=None, full_output=0):
elif ier == -4:
raise RuntimeError("Error, x-values are not strictly increasing")
if full_output:
return(xyds, nit, mesg)
return (xyds, nit, mesg)
else:
return(xyds)
return xyds


def tsval1(x, xydt, degree=0, verbose=0):
Expand Down
29 changes: 16 additions & 13 deletions setup.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
from numpy.distutils.core import Extension

ext2 = Extension(name='tspack',
sources=['pytspack/tspack.pyf', 'pytspack/tspack.f'])
ext = Extension(
name="tspack",
sources=["pytspack/tspack.pyf", "pytspack/tspack.f"],
)

if __name__ == "__main__":
from numpy.distutils.core import setup
setup(name='pytspack',
version='0.1',
description="Wrapper around Robert J. Renka's fortran TSPACK: Tension Spline Curve Fitting Package ",
author="Barry D. Baker",
lisense='MIT',
author_email="[email protected]",
source=['pytspack'],
packages=['pytspack'],
ext_modules=[ext2],
install_requires=['numpy']
)

setup(
name="pytspack",
version="0.1",
description="Wrapper around Robert J. Renka's fortran TSPACK: Tension Spline Curve Fitting Package",
author="Barry D. Baker",
license="MIT",
author_email="[email protected]",
packages=["pytspack"],
ext_modules=[ext],
install_requires=["numpy"],
)