Concepts#

GradeIT terms and important conventions.

Units#

GradeIT names show units:

Quantity

Unit

Suffix

Elevation

feet

_ft

Distance

feet

_ft

Grade

decimal rise/run

_dec

Latitude

decimal degrees, north positive

Longitude

decimal degrees, west negative

Note that grade is a decimal, not a percentage: a 6% grade is 0.06.

Coordinate#

A frozen dataclass with latitude and longitude:

from gradeit import Coordinate

point = Coordinate.from_lat_lon(39.7392, -105.0)

Note that you don't have to use this object directly; gradeit() will create Coordinate instances from your input as needed.

Coordinate input#

gradeit() accepts these different types of trace input:

  1. a numpy array of shape (n, 2) with (latitude, longitude) rows

  2. anything with a .columns attribute — a pandas DataFrame, duck-typed

  3. a mapping keyed by lat_col / lon_col

  4. any other iterable of Coordinate or (latitude, longitude) pairs

Use latitude first. GradeIT uses (lat, lon), not (x, y).

GradeResult#

A frozen dataclass of numpy arrays. All arrays have the same length as the input.

result.coordinates  # List[Coordinate]
result.elevation_ft_unfiltered  # np.ndarray, raw DEM lookup
result.distances_ft  # np.ndarray, distance from previous point
result.grade_dec_unfiltered  # np.ndarray, grade from the raw lookup
result.elevation_ft_filtered  # np.ndarray | None
result.grade_dec_filtered  # np.ndarray | None

Important conventions:

  • distances_ft carries a leading 0.0 so it aligns point-for-point with the elevation and grade arrays. The per-segment distances are distances_ft[1:], and distances_ft.sum() is the total trace length.

ElevationModel#

An abstract base class with one abstract method:

class ElevationModel(metaclass=ABCMeta):
    @abstractmethod
    def get_elevation(self, trace: List[Coordinate]) -> List[float]: ...

ElevationFilter#

Also one method:

class ElevationFilter(metaclass=ABCMeta):
    @abstractmethod
    def filter(
        self, elevation_profile: List[float], coordinates: List[Coordinate]
    ) -> List[float]: ...

A filter takes an elevation profile and returns an elevation profile. It does not return grade. You can pass a filter sequence. Each filter uses the output from the last filter. GradeIT calculates grade from final filtered elevation.

Built in: Wood2014Filter (the default) and BridgeFilter. See Filters.

Exceptions#

All GradeIT errors derive from GradeitError. Specific errors also subclass the matching built-in error. Existing except ValueError: handlers keep working:

Exception

Also a

Raised when

GradeitError

Exception

base class for everything below

InvalidInputError

ValueError

unsupported input form, fewer than 2 points

MissingDependencyError

ImportError

an optional extra is needed but not installed

ElevationLookupError

an elevation source returned something unusable

A missing raster tile raises FileNotFoundError, not a GradeIT error. A point without elevation data is NaN, not an exception.

Warnings derive from GradeitWarning. It is a UserWarning, not a GradeitError:

Warning

Raised when

GradeitWarning

base class for everything below

SparseGridWarning

Wood2014Filter's interval_ft is finer than the GPS points support

Escalate a category to an error with warnings.simplefilter("error", GradeitWarning), or silence it with "ignore".