Practical Use¶
These recipes use the supported public API. Distances are metres, positions store decimal degrees, and generated bearings are true degrees clockwise from north.
Install¶
The one installation includes every shipped feature and its GeographicLib, NumPy, and SciPy dependencies.
Parse coordinate text safely¶
from nautipy import parse_position
position = parse_position("N 50° 7' 21.252\"; E 8° 39' 56.52\"")
print(position.latitude, position.longitude)
For an unmarked longitude-first pair, say so:
Use order="auto" only when the input contains hard axis evidence. It refuses
to guess when both orders are valid places.
Inspect unfamiliar input¶
from nautipy import inspect_position
result = inspect_position("5007.3542,N,00839.9420,E")
print(result.position)
print(result.format)
print(result.source_order)
print(result.evidence)
print(result.normalizations)
print(result.latitude_resolution)
The inspection result records how the position was selected. Ambiguity remains an exception because there is no safe selected position to return.
Inspect a CSV column without dropping rows¶
Keep the source rows when importing a coordinate column. The batch result's zero-based indices then provide a stable link back to both accepted and rejected records:
import csv
from nautipy import BatchInspectionSuccess, inspect_positions
with open("positions.csv", newline="", encoding="utf-8") as stream:
rows = list(csv.DictReader(stream))
batch = inspect_positions(
(row["position"] for row in rows),
order="auto",
)
accepted = []
rejected = []
for item in batch.items:
source_row = rows[item.index]
if isinstance(item, BatchInspectionSuccess):
accepted.append((source_row, item.result.position))
else:
rejected.append(
(
source_row,
item.error_type.__name__,
item.message,
)
)
print(batch.parsed_count, batch.ambiguous_count, batch.invalid_count)
Use order="auto" only when records contain hard axis evidence. If the column
contract says that unmarked values are latitude/longitude, retain the
order="latlon" default instead.
The default errors="collect" inspects every yielded record and stores each
public coordinate exception type and message. Set errors="raise" for an
all-or-nothing workflow; it stops at the first coordinate failure, raises the
same exception subclass, and identifies its positions[index]. An exception
from the CSV or another source iterator is not a coordinate record and
propagates unchanged in either mode.
Pass an iterable of records, not one scalar or structured value. A string,
mapping, Position, bytes, or bytearray value is rejected as the outer batch
argument. Every other sequence is treated as the collection itself, so numeric
position pairs must be nested, for example [(50.12257, 8.66570)]. To format
an accepted position without parsing it again, pass item.result.position to
format_position.
Convert without losing the intended order¶
from nautipy import convert_position
converted = convert_position(
"50.12257, 8.66570",
to="dms",
)
assert converted == "50° 7′ 21.25″ N; 8° 39′ 56.52″ E"
For a machine-oriented representation:
ISO 6709 output is always latitude/longitude. output_order independently
controls human-format output.
Calculate a journey¶
from nautipy import destination, inverse, interpolate
start = "50.12257, 8.66570"
end = destination(start, bearing=90, distance=12_000)
route = inverse(start, end)
midpoint = interpolate(start, end)
print(route.distance)
print(route.initial_bearing)
print(route.final_bearing)
print(midpoint)
Every location argument accepts the same unambiguous position-like forms as
parse_position. Parse specialized order explicitly before handing a value to
navigation functions.
Exchange GeoJSON points¶
GeoJSON helpers live in nautipy.geojson. They work with ordinary Python
mappings; use the standard-library json module for text or files.
import json
from nautipy import Position
from nautipy.geojson import from_geojson_point, to_geojson_point
position = Position(50.12257, 8.66570)
point = to_geojson_point(position)
assert point == {
"type": "Point",
"coordinates": [8.6657, 50.12257],
}
text = json.dumps(point)
restored = from_geojson_point(json.loads(text))
assert restored == position
GeoJSON’s coordinate order is longitude, latitude. NautiPy supports two-dimensional Points and Point FeatureCollections, not arbitrary geometry.
Use a FeatureCollection to preserve identifiers and descriptions:
from nautipy.geojson import (
from_geojson_feature_collection,
to_geojson_feature_collection,
)
stations = [
Position(
50.116135,
8.670277,
identifier="station-1",
description="Reference station",
),
]
collection = to_geojson_feature_collection(stations)
restored = from_geojson_feature_collection(collection)
assert restored == tuple(stations)
Estimate a position from ranges¶
from nautipy import Position, RangeObservation, solve_fix
references = (
Position(50.116135, 8.670277),
Position(50.112836, 8.666753),
Position(50.110347, 8.659873),
)
ranges = tuple(
RangeObservation(reference, measured, uncertainty=2.0)
for reference, measured in zip(
references,
(1_275.251, 1_599.237, 1_917.145),
)
)
result = solve_fix(ranges=ranges)
if result.success:
print(result.position)
print(result.residuals)
print(result.rank, result.condition_number)
print(result.uncertainty)
else:
print(result.status, result.message)
print(result.competing_positions)
Never discard status and diagnostics just to obtain a coordinate. See Can You Trust the Fix? for a reading checklist.
Convert or inspect at the command line¶
Output:
Request deterministic JSON diagnostics:
The module entry point is equivalent:
Run nautipy convert --help or nautipy inspect --help for choices and
defaults. Invalid input exits with status 2 and a concise message rather than a
traceback.
Handle caller errors¶
from nautipy import (
AmbiguousCoordinateError,
CoordinateError,
FixError,
NavigationError,
parse_position,
)
try:
parse_position("50, 8", order="auto")
except AmbiguousCoordinateError as error:
print(error)
print(error.candidates)
except CoordinateError as error:
print("Other coordinate problem:", error)
NavigationError covers invalid navigation scalars and undefined navigation
results. FixError covers invalid observations and solver configuration.
Invalid reference coordinates retain their applicable CoordinateError
subtype.
Before relying on a result¶
- Confirm latitude/longitude order and datum.
- Confirm distances are metres and bearings are true, not magnetic.
- Keep source precision separate from measurement accuracy.
- For a fix, inspect status, warnings, residuals, rank, condition number, competing positions, search domain, and uncertainty.
- Account separately for altitude, motion, current, refraction, timing, correlated errors, and common bias where they matter.
NautiPy is not certified navigation equipment. Use independent safeguards appropriate to the consequences of an error.
Exact behavior is defined by the coordinate, navigation, GeoJSON, and position-fix specifications.