{
 "cells": [
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "c5fdf490-fa77-4e56-92d1-53101fff75ba",
   "metadata": {},
   "source": [
    "# cuProj Python User's Guide\n",
    "\n",
    "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](https://pyproj4.github.io/pyproj/stable/) API."
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "caadf3ca-be3c-4523-877c-4c35dd25093a",
   "metadata": {},
   "source": [
    "## Contents\n",
    "\n",
    "This guide provides a working example for all of the python API components of cuProj.  \n",
    "The following list links to each subsection.\n",
    "\n",
    "* [Installing cuProj](#Installing-cuProj)\n",
    "* [Transformations with Transformer](#Transformations-with-Transformer)"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "115c8382-f83f-476f-9a26-a64a45b3a8da",
   "metadata": {},
   "source": [
    "## Installing cuProj\n",
    "Read the [RAPIDS Quickstart Guide](https://docs.rapids.ai/install) to learn more about installing all RAPIDS libraries, including cuProj.\n",
    "\n",
    "If you are working on a system with a CUDA-enabled GPU and have CUDA installed, uncomment the following cell and install cuSpatial:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "7265f9d2-9203-4da2-bbb2-b35c7f933641",
   "metadata": {},
   "outputs": [],
   "source": [
    "# !conda create -n rapids-24.04 --solver=libmamba -c rapidsai -c conda-forge -c nvidia \\ \n",
    "#     cuproj-23.12 python=3.10 cuda-version=12.0"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "051b6e68-9ffd-473a-89e2-313fe1c59d18",
   "metadata": {},
   "source": [
    "For other options to create a RAPIDS environment, such as docker or build from source, see  \n",
    "[RAPIDS Release Selector](  https://docs.rapids.ai/install#selector). \n",
    "\n",
    "We welcome contributions to cuProj. To do so, first create a source build using the included\n",
    "[Dev Container](https://github.com/rapidsai/cuspatial/tree/branch-23.08/.devcontainer). Simply clone the github repository and open the folder in VSCode. VSCode will prompt\n",
    "you to install the [Dev Container extension](https://code.visualstudio.com/docs/devcontainers/tutorial#_install-the-extension) if not installed, then open the folder in a Dev Container."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "cfb1e810",
   "metadata": {},
   "source": [
    "## Transformations with Transformer\n",
    "\n",
    "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.\n",
    "\n",
    "Currently only the EPSG authority is supported, and only a subset of the EPSG codes are supported. The following EPSG codes are supported:\n",
    "\n",
    "- WGS84 (EPSG:4326)\n",
    "- UTM (EPSG:32600-32660 and EPSG:32700-32760)\n",
    "\n",
    "The following simple example transforms a single (lat, lon) coordinate from WGS84 to UTM."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "8fdfa2bf",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "WGS84 (lat,lon): (51.51, -0.08) degrees\n",
      "UTM Zone 30N (x,y): (702900.15, 5710383.71) meters\n"
     ]
    }
   ],
   "source": [
    "from cuproj.transformer import Transformer\n",
    "\n",
    "# Tower of London latitude and longitude\n",
    "lat = 51.5081\n",
    "lon = -0.0761\n",
    "\n",
    "# Transform to UTM (x, y) in meters using CuProj\n",
    "cu_transformer = Transformer.from_crs(\"epsg:4326\", \"EPSG:32630\")\n",
    "x, y = cu_transformer.transform(lat, lon)\n",
    "\n",
    "print(f\"WGS84 (lat,lon): ({lat:.2f}, {lon:.2f}) degrees\")\n",
    "print(f\"UTM Zone 30N (x,y): ({x:.2f}, {y:.2f}) meters\")\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "fa80e822",
   "metadata": {},
   "source": [
    "### Transforming Arrays of Coordinates\n",
    "\n",
    "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."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "fd2b4b88",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "min_corner in UTM zone 56S: (269645.77400353167, 6212842.207954117) in meters\n",
      "max_corner in UTM zone 56S: (360665.66806726344, 6292273.972689628) in meters\n"
     ]
    }
   ],
   "source": [
    "import cupy as cp\n",
    "\n",
    "# (lat, lon) box around Sydney, NSW, Australia\n",
    "min_corner = (-34.2, 150.5)\n",
    "max_corner = (-33.5, 151.5)\n",
    "\n",
    "crs_to = \"EPSG:32756\"\n",
    "\n",
    "num_points_x = 100\n",
    "num_points_y = 100\n",
    "\n",
    "# A grid of 100x100 points in the bounding box of London in WGS84 (lat/lon)\n",
    "# stored as a list of two arrays (x, y) in device memory (cupy)\n",
    "x, y = cp.meshgrid(\n",
    "    cp.linspace(min_corner[0], max_corner[0], num_points_y),\n",
    "    cp.linspace(min_corner[1], max_corner[1], num_points_x))\n",
    "grid = [x.reshape(-1), y.reshape(-1)]\n",
    "\n",
    "transformer = Transformer.from_crs(\"EPSG:4326\", crs_to)\n",
    "x, y = transformer.transform(*grid)\n",
    "\n",
    "print(f\"min_corner in UTM zone 56S: ({x[0]}, {y[0]}) in meters\")\n",
    "print(f\"max_corner in UTM zone 56S: ({x[-1]}, {y[-1]}) in meters\")"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.12"
  },
  "vscode": {
   "interpreter": {
    "hash": "ef2a625a21f49284d4111fd61c77079c8ec37c2ac9f170a08eb051e93ed3e888"
   }
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}