Skip to main content

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:

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

python -m pip install grays-tortuosity-model

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

Quick Example

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.

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:

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

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:

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.

Metadata

Release files for grays-tortuosity-model 0.3.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for grays-tortuosity-model 0.3.0
File Size Uploaded Provenance
grays_tortuosity_model-0.3.0.tar.gz 207.2 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for grays-tortuosity-model 0.3.0
File Interpreter ABI Platform
grays_tortuosity_model-0.3.0-py3-none-any.whl Python 3 none any Details

Total release size: 276.4 kB

Release files / grays_tortuosity_model-0.3.0.tar.gz

Download URL grays_tortuosity_model-0.3.0.tar.gz
Size 207.2 kB
Tags Source
SHA-256 checksum
How to use checksums
ac71f21ddd7ad4fa6d3a405a2ad080fdaa864059d8f6e132ed9fe54806b5fe5a
BLAKE2b-256 checksum
How to use checksums
9567cc4a61f76bfb990ab8299017036e37f7a5f5f6c5af73f20a4e4e2744fb53
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.12.10

Release files / grays_tortuosity_model-0.3.0-py3-none-any.whl

Download URL grays_tortuosity_model-0.3.0-py3-none-any.whl
Size 69.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
9cabd74bb49658daf53d1732f09cc9e1652d97794e2c5f8931d6ee3a55af9b4d
BLAKE2b-256 checksum
How to use checksums
c6c5e1412c7d06c2426a97f31411645a4de88ff73f6aa40e1a6f59433793f802
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.12.10

Security for grays-tortuosity-model 0.3.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page