Metadata-Version: 2.4
Name: grays-tortuosity-model
Version: 0.3.0
Summary: Scale-dependent curvature-energy tortuosity model for sampled planar paths.
Author: Gray's Tortuosity Model contributors
License-Expression: MIT
Keywords: tortuosity,curvature,geometry,path-analysis,scale-space
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Science/Research
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Scientific/Engineering :: Mathematics
Classifier: Topic :: Scientific/Engineering :: Visualization
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: numpy>=1.24
Requires-Dist: matplotlib>=3.7
Provides-Extra: dev
Requires-Dist: build>=1.2; extra == "dev"
Requires-Dist: pytest>=7.4; extra == "dev"
Requires-Dist: twine>=5; extra == "dev"
Dynamic: license-file

# Gray's Tortuosity Model

Gray's Tortuosity Model (GTM) measures how much a sampled planar path turns at a chosen physical scale.

The core `p=2` model is a scale-normalized curvature-energy tortuosity:

```text
T_ell = (T_c / 2 pi) ell int kappa_ell(s)^2 ds
```

where `ell` is the object or observation scale and `kappa_ell` is curvature after scale-dependent smoothing.

Use GTM when you want to compare paths by turning load, local tortuosity density, polygon corner load, or scale response rather than by endpoint displacement alone.

## Install

```bash
python -m pip install grays-tortuosity-model
```

The package requires Python 3.10+ and depends on NumPy and Matplotlib.

## Quick Example

```python
import numpy as np
from grays_tortuosity import tortuosity_and_average

t = np.linspace(0.0, 4.0 * np.pi, 800)
path = np.column_stack((t, np.sin(t)))

result = tortuosity_and_average(path, ell=0.5)
print(result.total)
print(result.average)
```

`total` is accumulated tortuosity over the whole path. `average` is total tortuosity divided by path length, which is often easier to compare across paths of different lengths.

## Polygon And Polyline Inputs

For polygon vertices or sparse polylines, use `polygon_tortuosity`. Inputs are open by default; pass `closed=True` for closed polygons.

```python
from grays_tortuosity import polygon_tortuosity

vertices = [
    (0.0, 0.0),
    (2.0, 0.0),
    (2.0, 1.0),
    (0.0, 1.0),
]

midpoint = polygon_tortuosity(vertices, ell=0.25, closed=True)
fsad = polygon_tortuosity(vertices, ell=0.25, closed=True, smoothing="fsad")

print(midpoint.total, midpoint.average)
print(fsad.total, fsad.average)
```

Use `smoothing="midpoint"` for the default midpoint-quadratic corner smoothing. Use `smoothing="fsad"` for finite-scale angular density on the original polygon vertices, and `smoothing="chord"` for derivative-free finite-scale chord density.

## Finite-Scale Vector Relaxation

Version `0.3.0` adds the vector relaxation / vector RC diagnostics:

```python
from grays_tortuosity import polygon_vector_rc_state

vr = polygon_vector_rc_state(vertices, ell=0.25, closed=True, source="tangent_piecewise")

print(vr.total)
print(vr.min_radius)
print(vr.radial_total, vr.angular_total)
```

The canonical model uses zero lookahead, `ell * x'(s) = T(s) - x(s)`. The state is not unit norm;
its magnitude can collapse during opposing-direction transients. The density is
`q = (T_c/2*pi) * ell * ||x'||^2 / ||x||^2`, with radial/angular diagnostics exposed separately.

## Local Density

```python
import numpy as np
from grays_tortuosity import finite_difference_tortuosity_density, plot_density_path

t = np.linspace(0.0, 2.0 * np.pi, 600)
path = np.column_stack((np.cos(t), np.sin(t)))

density = finite_difference_tortuosity_density(path, ell=0.2, closed=True)
fig, ax, collection = plot_density_path(density.total.points, density.density, closed=True)
fig.savefig("density_path.png", dpi=180)
```

Density functions return sampled fields so you can inspect where the turning load is concentrated, integrate local windows, or plot density along the path.

## Command Line

Evaluate a CSV file with `x` and `y` columns:

```bash
grays-tortuosity path.csv --ell 0.5 --x-column x --y-column y --density-summary --json
```

## Common Entry Points

- `tortuosity(points, ell, ...)`: total GTM tortuosity for sampled planar points.
- `tortuosity_and_average(points, ell, ...)`: total plus length-normalized average.
- `tortuosity_density(points, ell, ...)`: local unsigned density from headings.
- `finite_difference_tortuosity_density(points, ell, ...)`: smooth-curve density from coordinate derivatives.
- `polygon_tortuosity(points, ell, closed=False, smoothing="midpoint")`: polygon/polyline-friendly wrapper.
- `polygon_finite_scale_angular_density(points, ell, window=None, closed=False)`: direct FSAD polygon density.
- `polygon_finite_scale_chord_density(points, h, closed=False)`: direct FSCD polygon density.
- `polygon_vector_rc_state(points, ell, closed=False, source="tangent_piecewise")`: vector relaxation / vector RC state and density diagnostics.
- `scale_sweep(points, ells, ...)`: evaluate a path across multiple scales.
- `plot_density_path(points, density, ...)`: Matplotlib helper for path-colored density plots.

## Notes

- `ell` is the most important parameter. It should represent the physical object scale, sensor scale, or observation scale relevant to the path.
- Open paths and closed paths are treated differently. Pass `closed=True` explicitly when the final point should connect back to the first.
- The package is research-facing and currently marked alpha. APIs are usable, tested, and documented, but the model is still evolving.
- Riemann/zeta experiments live outside the distributed package under the repository's `research/` tree and are not part of the PyPI API.

## More Documentation

The source repository contains a fuller README, API quick reference, examples, and theory notes. The PyPI page intentionally avoids embedded images so it renders cleanly without relying on repository-hosted assets.
