cuProj Python User’s Guide#

cuProj is a GPU-accelerated Python library for cartographic coordinate projection and coordinate transformations between coordinate reference systems (CRS). The cuProj Python API provides an accessible interface to high-performance projections accelerated by CUDA-enabled GPUs. The API closely follows the PyProj API.


This guide provides a working example for all of the python API components of cuProj.
The following list links to each subsection.

Installing cuProj#

Read the RAPIDS Quickstart Guide to learn more about installing all RAPIDS libraries, including cuProj.

If you are working on a system with a CUDA-enabled GPU and have CUDA installed, uncomment the following cell and install cuSpatial:

# !conda create -n rapids-23.08 --solver=libmamba -c rapidsai -c conda-forge -c nvidia \
#     cuproj=23.08 python=3.10 cuda-version=12.0
For other options to create a RAPIDS environment, such as docker or build from source, see

We welcome contributions to cuProj. To do so, first create a source build using the included Dev Container. Simply clone the github repository and open the folder in VSCode. VSCode will prompt you to install the Dev Container extension if not installed, then open the folder in a Dev Container.

Transformations with Transformer#

The primary class in cuProj is the Transformer class, which is used to transform coordinates from one CRS to another. The Transformer class is created from a source CRS and a destination CRS, which can be specified using a CRS string, an EPSG code, or an (<authority>, code) tuple. The Transformer class can then be used to transform coordinates from the source CRS to the destination CRS.

Currently only the EPSG authority is supported, and only a subset of the EPSG codes are supported. The following EPSG codes are supported:

  • WGS84 (EPSG:4326)

  • UTM (EPSG:32600-32660 and EPSG:32700-32760)

The following simple example transforms a single (lat, lon) coordinate from WGS84 to UTM.

from cuproj.transformer import Transformer

# Tower of London latitude and longitude
lat = 51.5081
lon = -0.0761

# Transform to UTM (x, y) in meters using CuProj
cu_transformer = Transformer.from_crs("epsg:4326", "EPSG:32630")
x, y = cu_transformer.transform(lat, lon)

print(f"WGS84 (lat,lon): ({lat:.2f}, {lon:.2f}) degrees")
print(f"UTM Zone 30N (x,y): ({x:.2f}, {y:.2f}) meters")

WGS84 (lat,lon): (51.51, -0.08) degrees
UTM Zone 30N (x,y): (702900.15, 5710383.71) meters

Transforming Arrays of Coordinates#

cuProj really shines when you have a large number of points to transform. The following code transforms 10,000 (lat, lon) points in a grid around Sydney, Australia.

import cupy as cp

# (lat, lon) box around Sydney, NSW, Australia
min_corner = (-34.2, 150.5)
max_corner = (-33.5, 151.5)

crs_to = "EPSG:32756"

num_points_x = 100
num_points_y = 100

# A grid of 100x100 points in the bounding box of London in WGS84 (lat/lon)
# stored as a list of two arrays (x, y) in device memory (cupy)
x, y = cp.meshgrid(
    cp.linspace(min_corner[0], max_corner[0], num_points_y),
    cp.linspace(min_corner[1], max_corner[1], num_points_x))
grid = [x.reshape(-1), y.reshape(-1)]

transformer = Transformer.from_crs("EPSG:4326", crs_to)
x, y = transformer.transform(*grid)

print(f"min_corner in UTM zone 56S: ({x[0]}, {y[0]}) in meters")
print(f"max_corner in UTM zone 56S: ({x[-1]}, {y[-1]}) in meters")
min_corner in UTM zone 56S: (269645.77400353167, 6212842.207954117) in meters
max_corner in UTM zone 56S: (360665.66806726344, 6292273.972689628) in meters