Gray's Tortuosity Model
This repository develops a scale-dependent tortuosity model for sampled planar paths.
The baseline model is a scale-normalized curvature energy:
T_{p,\ell}[\gamma] = C_p \ell^{p-1} \int_0^L |\kappa_\ell(s)|^p ds
The first implemented version uses p = 2:
T_\ell[\gamma] = \frac{T_c}{2\pi}\ell \int_0^L \kappa_\ell(s)^2 ds
where ell is the characteristic length scale of the moving object, T_c is the tortuosity assigned to a reference circle of radius ell, and kappa_ell is curvature after heading smoothing at scale ell.
Current Status
Implemented:
- Equal-arc-length path resampling
- Segment heading calculation and unwrapping
- Causal exponential heading smoothing
- Curvature estimation from smoothed headings
- Normalized tortuosity calculation
- Analytic tests for lines and circles
- Initial polygon and stadium examples
- Four-panel closed-shape catalog generator
- Random-walk percentile catalog generator
- Circle analytic convergence figure
- Circle radius-by-scale validation figure
- Gaussian heading smoother and smoother comparison figure
- Corner-interaction figure for nearby turns
- Polygon catalog comparing numerical values to isolated-corner estimates
- Hypotrochoid and epicycloid generators and visual catalog
- Trochoid tortuosity-density profile catalog
- Local tortuosity density and windowed tortuosity profiles
- Average tortuosity, defined as total tortuosity divided by arc length
- Signed tortuosity density and curvature-based path reconstruction
- Reconstruction catalog from prescribed signed-density functions
- Signal-style signed-density reconstruction examples
- Growing oscillatory signed-density reconstruction example
- Growing oscillatory signed-density amplitude sweep
- Growing oscillatory signed-density sweep animation
- Signed-density signal amplitude atlas and response metrics
- Optional signed-density signal sweep animation
- Autoscaled signed-density signal sweep animation
- Damped oscillatory signed-density reconstruction example
- Constant-offset damped oscillatory reconstruction sweep
- Polar curve curvature and tortuosity-density catalog
- Density derivative utilities and profile catalog
- Speed-aware dynamics utilities and exposure figure
- Reference-speed traversal planner with tortuosity thresholding
- Provocation bridge utilities and memory-state figure
- Experienced load-change utility and feature figure
- Wheel-center transmission utilities and collision-check figure
- Motion-sickness bridge design roadmap
- Global geometry and curve-algebra planning notes
- Tangent-vector, affine-density, involute, and evolute curve-algebra utilities
- CSV command-line interface for path tortuosity reports and density export
- Reusable Matplotlib density-path and profile plotting helpers
- Display-only curve normalization for comparative plots with independent, global, shared-scale, fixed, grouped, pair-comparison, fixed-viewport, and auto-offset modes
- Reproducible scale-sweep utility with CSV output
- Midpoint-tangent quadratic smoothing for direct polyline edge-vector density
- Polygon-friendly tortuosity helper returning total and average tortuosity with midpoint, Gaussian, exponential, none, or custom smoothing
- Spiral divergence signatures for comparing infinite-tortuosity convergent spirals
- Complex-series partial-sum paths with direct adjacent-term density diagnostics
- Zeta Dirichlet partial-sum tail spiral diagnostics for
sigma > 1 - Zeta vertical-curve diagnostics pairing GTM density with
|zeta|and origin winding - Additional signed-density reconstruction sweep for
(0.5 sin(Ax)/A + 1)tanh(x) - Polygon midpoint-smoothing catalog with scale and corner-fraction comparison
- Optional Riemann-Siegel
Z(t)polar-curve tortuosity density through the first two zeros - Long Riemann-Siegel
Z(t)polar-density view throught=100 - Zeta tangent-oval radial sweep through a zero, with parameter-colored fixed-axis sheet/GIF evolution, radius diagnostics, and per-radius cache/progress reporting from
R=0.1toR=40 - Zeta tangent-oval boundary-layer collapse diagnostics separating seam tortuosity, zero-contact tortuosity, and zero-contact length scales
- Zeta-zero derivative-angle scan plotting
arg(-i zeta'(rho_n))over thousands of zeros - Tanh orbital-bridge diagnostics relating density, radius, cumulative turn, and accumulated tortuosity
Quick Start
Install the package in editable mode:
python -m pip install -e ".[dev]"
Run tests:
pytest
Evaluate a CSV path from the command line:
grays-tortuosity path.csv --ell 0.5 --x-column x --y-column y --density-summary --json
Evaluate polygon vertices directly from Python:
from grays_tortuosity import polygon_tortuosity
vertices = [(0.0, 0.0), (2.0, 0.0), (2.0, 1.0), (0.0, 1.0)]
result = polygon_tortuosity(vertices, ell=0.25)
print(result.value, result.average)
Passing two points is treated as a straight segment and returns exactly zero total and average tortuosity.
Plot local density from Python:
from grays_tortuosity import finite_difference_tortuosity_density, plot_density_path
result = finite_difference_tortuosity_density(path, ell=0.5)
fig, ax, collection = plot_density_path(result.total.points, result.density)
fig.savefig("density_path.png", dpi=180)
See docs/api_quick_reference.md for the main public APIs.
For notebook exploration, see docs/notebooks/gtm_quickstart.ipynb.
Smooth a polyline through its segment midpoints and compute density directly from adjacent edge vectors:
from grays_tortuosity import midpoint_quadratic_tortuosity_density
result = midpoint_quadratic_tortuosity_density(polyline, ell=0.5)
print(result.total, result.density.max())
Compare convergent spirals by cutoff divergence instead of total tortuosity alone:
from grays_tortuosity import fit_tortuosity_divergence, logarithmic_spiral_cutoff_tortuosity
values = logarithmic_spiral_cutoff_tortuosity(epsilons, pitch=0.25, ell=0.5)
fit = fit_tortuosity_divergence(epsilons, values, tail_fraction=0.4)
print(fit.delta, fit.coefficient)
Run examples:
python examples/core/evaluate_basic_shapes.py
python examples/core/scale_sweep_catalog.py
python examples/geometry/closed_shape_catalog.py
python examples/core/circle_scale_validation.py
python examples/core/polygon_catalog.py
python examples/core/local_tortuosity_profiles.py
python examples/core/signed_tortuosity_reconstruction.py
python examples/geometry/curve_algebra_scaling.py
python examples/geometry/density_self_intersection_criteria.py
python examples/geometry/closure_and_energy_bounds.py
python examples/geometry/tangent_vector_affine_density.py
python examples/geometry/involute_evolute_density.py
Additional examples are grouped under examples/applied/, examples/reconstruction/, examples/signals_and_animation/, examples/polar_spiral_series/, and examples/research_controls/.
Scale Sweep
Generate a reproducible scale-sweep figure and CSV table:
python examples/core/scale_sweep_catalog.py
The script writes docs/assets/scales/scale_sweep_catalog.png and docs/assets/scales/scale_sweep_catalog.csv. Smooth geometric curves grow roughly linearly with ell for p=2, while response-smoothed paths with nearby opposite turns can decrease at larger ell because smoothing merges local turn structure.
Spiral Divergence
Generate a logarithmic-spiral divergence signature figure and CSV table:
python examples/polar_spiral_series/spiral_divergence_signatures.py
The script writes docs/assets/spiral/spiral_divergence_signatures.png and docs/assets/spiral/spiral_divergence_signatures.csv. It compares spirals with the same divergence exponent but different coefficients, contraction per turn, and turns per e-fold.
Complex Series Paths
Generate a partial-sum path example for complex series terms:
python examples/polar_spiral_series/complex_series_paths.py
The script writes docs/assets/spiral/complex_series_paths.png and docs/assets/spiral/complex_series_paths.csv. It treats complex terms as polyline edge vectors, computes Im(conj(a_n) a_{n+1}), and evaluates midpoint-smoothed GTM density.
Zeta Research
Riemann/zeta tooling is kept as dependent research code under research/zeta/ rather than as part of the package quickstart path.
python -m pip install -e .
python -m pip install -r research/zeta/requirements.txt
python research/zeta/scripts/zeta_curves/zeta_curve_remapping_gallery.py
python research/zeta/scripts/critical_strip/zeta_horizontal_proof_certificates.py --zero-count 2000 --samples 81 --workers 0
Research entry points:
research/zeta/scripts/README.md: runnable zeta and Riemann-Siegel diagnostics.research/zeta/docs/README.md: current research reports and boundary notes.research/zeta/assets/README.md: curated generated figures; CSV/cache/frame outputs are ignored and regenerable.
The stable GTM package does not ship zeta-specific helpers; zeta research utilities live under research/zeta/lib/ and use the research requirements file.
Shape Catalog
Generate a small four-panel catalog of closed shapes and their average tortuosity values:
python examples/geometry/closed_shape_catalog.py
The script writes docs/assets/closed_shapes/closed_shape_catalog.png. The catalog uses average tortuosity so long straight sections reduce the path-level value instead of being hidden by total accumulated tortuosity.
Generate a six-panel catalog of non-backtracking random walks sampled at tortuosity percentiles:
python examples/applied/random_walk_percentiles.py
The script writes docs/assets/dynamics/random_walk_percentiles.png.
Generate the Phase 2 circle convergence check:
python examples/core/circle_convergence.py
The script writes docs/assets/scales/circle_convergence.png.
Generate the Phase 2 radius-by-scale validation grid:
python examples/core/circle_scale_validation.py
The script writes docs/assets/scales/circle_scale_validation.png.
Generate the heading smoother comparison figure:
python examples/core/smoother_comparison.py
The script writes docs/assets/scales/smoother_comparison.png.
Generate the Phase 3 corner-interaction figure:
python examples/geometry/corner_interactions.py
The script writes docs/assets/polygon/corner_interactions.png.
Generate the Phase 3 polygon catalog:
python examples/core/polygon_catalog.py
The script writes docs/assets/polygon/polygon_catalog.png.
Generate the midpoint-smoothed polygon catalog:
python examples/core/polygon_midpoint_smoothing_catalog.py
The script writes docs/assets/polygon/polygon_midpoint_smoothing_catalog.png and docs/assets/polygon/polygon_midpoint_smoothing_catalog.csv. The strict midpoint/tangent construction has no tightness knob: endpoint locations are fixed at segment midpoints. Smaller corner fractions hug vertices more tightly, but they change the constraint and require straight connectors between rounded corners. Scaling the polygon up at fixed ell lowers the midpoint-smoothed quadratic total approximately like 1/scale for p=2.
Generate a hypotrochoid and epicycloid catalog, including smooth hypotrochoids with d != r, the nonregular d = r hypocycloid case, average tortuosity values, and dashed Gaussian-response paths:
python examples/applied/trochoid_catalog.py
The script writes docs/assets/polar/trochoid_catalog.png.
Generate the matching trochoid density-profile catalog:
python examples/applied/trochoid_density_profiles.py
The script writes docs/assets/polar/trochoid_density_profiles.png. Density is plotted against normalized arc length so the profiles remain comparable across different radii and path lengths. For nonregular cusped curves, the raw sampled spike curve is omitted from the y-axis and replaced with spike-location markers plus the raw maximum.
Generate local tortuosity density profiles, with blue meaning low turning load and red meaning high turning load:
python examples/core/local_tortuosity_profiles.py
The script writes docs/assets/scales/local_tortuosity_profiles.png.
Generate the sign-preserving density and reconstruction example:
python examples/core/signed_tortuosity_reconstruction.py
The script writes docs/assets/reconstruction/signed_tortuosity_reconstruction.png.
Generate curves from prescribed signed tortuosity-density functions:
python examples/reconstruction/reconstruct_density_functions.py
The script writes docs/assets/reconstruction/reconstructed_density_functions.png.
Compare signal-style signed-density inputs:
python examples/reconstruction/reconstruct_density_signals.py
The script writes docs/assets/reconstruction/reconstructed_density_signals.png.
Reconstruct the growing oscillatory signed-density function amp*x*sin(x):
python examples/reconstruction/reconstruct_ax_sin_density.py
The script writes docs/assets/reconstruction/reconstructed_ax_sin_density.png.
Sweep the same growing oscillatory density over 0.01 <= amp <= 0.10:
python examples/reconstruction/reconstruct_ax_sin_density_sweep.py
The script writes docs/assets/reconstruction/reconstructed_ax_sin_density_sweep.png.
Sweep the tanh-modulated density (0.5 sin(Ax)/A + 1)tanh(x) over pi <= A <= 6pi:
python examples/reconstruction/reconstruct_tanh_modulated_density_sweep.py
The script writes docs/assets/reconstruction/reconstructed_tanh_modulated_density_sweep.png and docs/assets/reconstruction/reconstructed_tanh_modulated_density_sweep.csv.
Explore the orbital-bridge interpretation of the tanh-modulated density:
python examples/applied/tanh_orbital_bridge_diagnostics.py
The script writes docs/assets/reconstruction/tanh_orbital_bridge_diagnostics.png and docs/assets/reconstruction/tanh_orbital_bridge_diagnostics.csv. It compares reconstructed paths, prescribed density, instantaneous radius R=1/|kappa|, cumulative turn, cumulative tortuosity, and the phase relation between turn and accumulated tortuosity.
Generate an animated version of the tanh-modulated sweep:
python examples/signals_and_animation/animate_tanh_modulated_density_sweep.py
The script writes docs/assets/reconstruction/reconstructed_tanh_modulated_density_sweep.gif.
Generate an animated version of the same sweep:
python examples/signals_and_animation/animate_ax_sin_density_sweep.py
The script writes docs/assets/reconstruction/reconstructed_ax_sin_density_sweep.gif.
Sweep signal amplitude up to amp=2.0. The atlas includes the delayed-step case, while the response plot focuses on the periodic signals so the trivial Heaviside response does not dominate the axes:
python examples/reconstruction/reconstruct_density_signal_atlas.py
python examples/reconstruction/reconstruct_density_signal_response.py
The scripts write docs/assets/reconstruction/reconstructed_density_signal_amplitude_atlas.png and docs/assets/reconstruction/reconstructed_density_signal_response.png.
Generate an optional GIF animation of the periodic amplitude sweep:
python examples/signals_and_animation/animate_density_signal_sweep.py
The script writes docs/assets/reconstruction/reconstructed_density_signal_sweep.gif.
Generate a second autoscaled GIF that refits each periodic curve every frame so small folded motifs remain visible:
python examples/signals_and_animation/animate_density_signal_sweep_autoscale.py
The script writes docs/assets/reconstruction/reconstructed_density_signal_sweep_autoscale.gif.
Reconstruct the damped oscillatory signed-density function sin(4x) exp(-(x/4)^2):
python examples/reconstruction/reconstruct_damped_sinusoid_density.py
The script writes docs/assets/reconstruction/reconstructed_damped_sinusoid_density.png.
Sweep a constant offset in sin(4x) exp(-(x/4)^2) + C over 0 <= x <= 10, moving from a disturbed line-like case to disturbed circle-like cases:
python examples/reconstruction/reconstruct_damped_sinusoid_offset_sweep.py
The script writes docs/assets/reconstruction/reconstructed_damped_sinusoid_offset_sweep.png.
Generate an animated version of the same constant-offset sweep:
python examples/signals_and_animation/animate_damped_sinusoid_offset_sweep.py
The script writes docs/assets/reconstruction/reconstructed_damped_sinusoid_offset_sweep.gif.
Generate the polar curve catalog comparing curvature, density per arc length, and accumulation per polar angle:
python examples/polar_spiral_series/polar_curve_catalog.py
The script writes docs/assets/polar/polar_curve_catalog.png.
Generate the density-derivative profile catalog:
python examples/geometry/density_derivative_profiles.py
The script writes docs/assets/dynamics/density_derivative_profiles.png.
Generate the speed-aware dynamics example:
python examples/applied/speed_aware_dynamics.py
The script writes docs/assets/dynamics/speed_aware_dynamics.png.
Generate the tortuosity-constrained traversal planning example:
python examples/applied/tortuosity_constrained_traversal.py
The script writes docs/assets/dynamics/tortuosity_constrained_traversal.png.
Generate the spatiotemporal scale-frequency bridge example:
python examples/applied/spatiotemporal_scale_frequency_bridge.py
The script writes docs/assets/dynamics/spatiotemporal_scale_frequency_bridge.png and shows a scale-space density map Q(s, ell) together with speed-dependent temporal frequencies from f=v/lambda.
Generate the curve algebra and scaling example:
python examples/geometry/curve_algebra_scaling.py
The script writes docs/assets/closed_shapes/curve_algebra_scaling.png and shows the scalar multiplication law, synchronized curve-addition interference, and tangent-cancellation singularity.
Generate the density/self-intersection criteria example:
python examples/geometry/density_self_intersection_criteria.py
The script writes docs/assets/closed_shapes/density_self_intersection_criteria.png and compares a small-turning certified curve, a simple monotone spiral-type curve beyond the small-turning bound, and a non-monotone self-intersecting reconstruction.
Generate the signed-density closure and closed-curve energy-bound example:
python examples/geometry/closure_and_energy_bounds.py
The script writes docs/assets/closed_shapes/closure_and_energy_bounds.png and shows that heading closure and position closure are separate constraints, plus the fixed-perimeter lower bound attained by the circle.
Generate the tangent-vector algebra and affine-density example:
python examples/geometry/tangent_vector_affine_density.py
The script writes docs/assets/closed_shapes/tangent_vector_affine_density.png and shows velocity-field interference, affine tangent-stretch density modulation, and the drift transition from looped to cusped to unwound curves.
Generate the involute/evolute density example:
python examples/geometry/involute_evolute_density.py
The script writes docs/assets/closed_shapes/involute_evolute_density.png and shows the circle involute cusp law, the pulled-back density integrand, and ellipse evolute centers of curvature.
Generate the GTM provocation-memory bridge example:
python examples/applied/provocation_memory_bridge.py
The script writes docs/assets/dynamics/provocation_memory_bridge.png. This is a bridge signal and memory-state demonstration, not a validated physiological motion-sickness model.
Generate the experienced load-change feature example:
python examples/applied/provocation_load_change_features.py
The script writes docs/assets/dynamics/provocation_load_change_features.png and separates steady load P(t) from changing load C(t)=|dP/dt|.
Generate the wheel-center transmission example:
python examples/applied/wheel_center_transmission.py
The script writes docs/assets/dynamics/wheel_center_transmission.png and uses an open rectangle with wheel radius R=1/(2*pi), width 1+R, and height 1+2R to compare blind normal offsets, sampled collision-aware validity, circle-relative contact-coordinate jumps, and penetration depth.
Basic Usage
from grays_tortuosity import circle_points, tortuosity
path = circle_points(radius=2.0)
result = tortuosity(path, ell=0.5, closed=True)
print(result.value)
By default, tortuosity uses exponential heading smoothing. smoothing="gaussian" is available as a centered, non-causal alternative. Use smoothing="none" for continuously defined smooth paths such as circles, ellipses, and parametric curves when you want the geometric curvature-energy total without response filtering:
from grays_tortuosity import stadium_points, tortuosity
path = stadium_points(radius=1.0, straight=3.0)
geometric = tortuosity(path, ell=0.5, closed=True, smoothing="none")
filtered = tortuosity(path, ell=0.5, closed=True, smoothing="exponential")
print(geometric.value, filtered.value)
For polygonal or otherwise non-differentiable paths, use a smoother so sharp heading jumps produce finite values. Keep smoothing="exponential" for causal response-style interpretation; use smoothing="gaussian" for centered offline analysis. For a stadium with the same turn radius as a circle, the geometric total stays near the circle value as straight sections are added. Filtered values differ because smoothers attenuate curvature transitions between straight sections and circular caps.
For local profiles of smooth sampled curves, use the finite-difference local estimator rather than unsmoothed heading turns. It estimates curvature from coordinate derivatives, avoiding the fuzzy polyline turn-angle artifacts that appear when tiny heading discretization errors are squared.
Prototype 3D support uses Bishop-frame curvature components. The vector signed density is q=A||K||^(p-1)K, and sampled Bishop curvature can be reconstructed into a 3D path:
import numpy as np
from grays_tortuosity import reconstruct_path_from_bishop_curvature, signed_vector_tortuosity_density
curvature = np.column_stack([np.full(1000, 0.5), np.zeros(1000)])
density = signed_vector_tortuosity_density(curvature, ell=0.5)
path = reconstruct_path_from_bishop_curvature(curvature, ds=0.01).points
Wheel/tire harmonic smoothing is intentionally documented separately as an optional future transmission layer in docs/design/wheel_harmonic_tire_model.md.
Pose/vestibular bridge helpers expose kinematic inputs from sampled SE(3) trajectories:
import numpy as np
from grays_tortuosity import gravity_referenced_specific_force, head_angular_velocity
time = np.linspace(0.0, 1.0, 101)
positions = np.zeros((time.size, 3))
rotations = np.tile(np.eye(3), (time.size, 1, 1))
omega = head_angular_velocity(time, rotations)
specific_force = gravity_referenced_specific_force(time, positions, rotations)
The pose convention and future vestibular integration points are documented in docs/design/pose_and_vestibular_inputs.md.
For a circle of radius R, the continuum model predicts:
T = T_c \frac{\ell}{R}
for p = 2.
Random walks are available as a simple grid-path test case:
from grays_tortuosity import random_walk_points, tortuosity
path = random_walk_points(steps=12, seed=7)
result = tortuosity(path, ell=0.75)
print(result.value)
For well-separated polygon corners, compare against the isolated-corner approximation:
from grays_tortuosity import isolated_corner_approximation, regular_polygon_points, tortuosity
path = regular_polygon_points(4, radius=4.0)
numerical = tortuosity(path, ell=0.2, closed=True).value
approximation = isolated_corner_approximation(path, closed=True)
print(numerical, approximation)
Local tortuosity is available in two forms:
from grays_tortuosity import f_curve_points, finite_difference_windowed_tortuosity, tortuosity_density, windowed_tortuosity
path = f_curve_points()
density = tortuosity_density(path, ell=0.5)
local = windowed_tortuosity(path, ell=0.5, window=2.0, mode="centered")
smooth_local = finite_difference_windowed_tortuosity(path, ell=0.5, window=2.0, mode="centered")
print(density.density.max(), local.windowed.max())
tortuosity_density is the instantaneous local turning load dT/ds. windowed_tortuosity accumulates that density over a trailing or centered arc-length buffer. average_tortuosity reports total tortuosity per unit arc length.
Signed density preserves left-versus-right turning:
from grays_tortuosity import curvature_from_signed_density, finite_difference_signed_tortuosity_density, f_curve_points
path = f_curve_points()
signed = finite_difference_signed_tortuosity_density(path, ell=0.5)
curvature = curvature_from_signed_density(signed.density, ell=0.5)
Given an initial point, initial heading, and signed curvature as a function of arc length, reconstruct_path_from_curvature reconstructs the corresponding planar curve up to numerical integration error.
You can also reconstruct directly from signed density samples or a signed-density function:
import numpy as np
from grays_tortuosity import reconstruct_path_from_signed_density_function
curve = reconstruct_path_from_signed_density_function(
lambda s: 0.05 * np.sin(s),
s_max=2.0 * np.pi,
ds=0.01,
ell=1.0,
)
print(curve.points[-1])
Development Plan
See docs/development_plan.md.
Metadata
Release files for grays-tortuosity-model 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| grays_tortuosity_model-0.1.0.tar.gz | 147.5 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| grays_tortuosity_model-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 205.6 kB
Release files / grays_tortuosity_model-0.1.0.tar.gz
| Download URL | grays_tortuosity_model-0.1.0.tar.gz |
|---|---|
| Size | 147.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
9348a4f7568e9624e0706804ddad0a83971d43f1471632cfb7e0cfc8b6773888
|
|
BLAKE2b-256 checksum How to use checksums |
275dc4894ada7859f17388e60008dae56d5b352af0513c9968715e2b58c646f4
|
| 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.1.0-py3-none-any.whl
| Download URL | grays_tortuosity_model-0.1.0-py3-none-any.whl |
|---|---|
| Size | 58.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
4f67c933c0edc14ffe93a48a5b427074abb9d71daf744bb847629151c34e7fce
|
|
BLAKE2b-256 checksum How to use checksums |
f438b8f3b9f28150693c858c53598556b77c242fe94205c8ee7d11fc7daab9b4
|
| 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.1.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.