{
"cells": [
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"%matplotlib inline"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n\n# Overview\n\nVerde provides classes and functions for processing spatial data, like\nbathymetry, GPS, temperature, gravity, or anything else that is measured along\na surface. The main focus is on methods for gridding such data (interpolating\non a regular grid). You'll also find other analysis methods that are often used\nin combination with gridding, like trend removal and blocked operations.\n\n## Conventions\n\nBefore we get started, here are a few of the conventions we use across Verde:\n\n* Coordinates can be Cartesian or Geographic. We generally make no assumptions\n about which one you're using.\n* All functions and classes expect coordinates in the order: West-East and\n South-North. This applies to the actual coordinate values, bounding regions,\n grid spacing, etc. Exceptions to this rule are the ``dims`` and ``shape``\n arguments.\n* We don't use names like \"x\" and \"y\" to avoid ambiguity. Cartesian coordinates\n are \"easting\" and \"northing\" and Geographic coordinates are \"longitude\" and\n \"latitude\".\n* The term \"region\" means the bounding box of the data. It is ordered west,\n east, south, north.\n\n## The library\n\nMost classes and functions are available through the :mod:`verde` top level\npackage. The only exception is the :mod:`verde.synthetic` module that has\nfunctionality for generating synthetic data. Throughout the documentation we'll\nuse ``vd`` as the alias for :mod:`verde`.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"import matplotlib.pyplot as plt\n\nimport verde as vd"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"\n## The gridder interface\n\nAll gridding and trend estimation classes in Verde share the same interface\n(they all inherit from :class:`verde.base.BaseGridder`). Since most gridders\nin Verde are linear models, we based our gridder interface on the\n`scikit-learn `__ estimator interface: they all\nimplement a :meth:`~verde.base.BaseGridder.fit` method that estimates the\nmodel parameters based on data and a :meth:`~verde.base.BaseGridder.predict`\nmethod that calculates new data based on the estimated parameters.\n\nUnlike scikit-learn, our data model is not a feature matrix and a target\nvector (e.g., ``est.fit(X, y)``) but a tuple of coordinate arrays and a data\nvector (e.g., ``grd.fit((easting, northing), data)``). This makes more sense\nfor spatial data and is common to all classes and functions in Verde.\n\nAs an example, let's generate some synthetic data using\n:class:`verde.synthetic.CheckerBoard`:\n\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"data = vd.synthetic.CheckerBoard().scatter(size=500, random_state=0)\nprint(data.head())"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The data are random points taken from a checkerboard function and returned to\nus in a :class:`pandas.DataFrame`:\n\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"plt.figure()\nplt.scatter(data.easting, data.northing, c=data.scalars, cmap=\"RdBu_r\")\nplt.colorbar()\nplt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Now we can use the bi-harmonic spline method [Sandwell1987]_ to fit this\ndata. First, we create a new :class:`verde.Spline`:\n\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"spline = vd.Spline()\n# Printing a gridder shows the class and all of it's configuration options.\nprint(spline)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Before we can use the spline, we need to fit it to our synthetic data. After\nthat, we can use the spline to predict values anywhere:\n\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"spline.fit((data.easting, data.northing), data.scalars)\n\n# Generate coordinates for a regular grid with 100 m grid spacing (assuming\n# coordinates are in meters).\ngrid_coords = vd.grid_coordinates(region=(0, 5000, -5000, 0), spacing=100)\ngridded_scalars = spline.predict(grid_coords)\n\nplt.figure()\nplt.pcolormesh(grid_coords[0], grid_coords[1], gridded_scalars, cmap=\"RdBu_r\")\nplt.colorbar()\nplt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We can compare our predictions with the true values for the checkerboard\nfunction using the :meth:`~verde.Spline.score` method to calculate the\n`R\u00b2 coefficient of determination\n`__.\n\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"true_values = vd.synthetic.CheckerBoard().predict(grid_coords)\nprint(spline.score(grid_coords, true_values))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Generating grids and profiles\n\nA more convenient way of generating grids is through the\n:meth:`~verde.base.BaseGridder.grid` method. It will automatically generate\ncoordinates and output an :class:`xarray.Dataset`.\n\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"grid = spline.grid(spacing=30)\nprint(grid)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
":meth:`~verde.base.BaseGridder.grid` uses default names for the coordinates\n(\"easting\" and \"northing\") and data variables (\"scalars\"). You can overwrite\nthese names by setting the ``dims`` and ``data_names`` arguments.\n\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"grid = spline.grid(spacing=30, dims=[\"latitude\", \"longitude\"], data_names=\"gravity\")\nprint(grid)\n\nplt.figure()\ngrid.gravity.plot.pcolormesh()\nplt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Gridders can also be used to interpolate data on a straight line between two\npoints using the :meth:`~verde.base.BaseGridder.profile` method. The profile\ndata are returned as a :class:`pandas.DataFrame`.\n\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"prof = spline.profile(point1=(0, 0), point2=(5000, -5000), size=200)\nprint(prof.head())\n\nplt.figure()\nplt.plot(prof.distance, prof.scalars, \"-\")\nplt.show()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Wrap up\n\nThis covers the basics of using Verde. Most use cases and examples in the\ndocumentation will involve some variation of the following workflow:\n\n1. Load data (coordinates and data values)\n2. Create a gridder\n3. Fit the gridder to the data\n4. Predict new values (using :meth:`~verde.base.BaseGridder.predict` or\n :meth:`~verde.base.BaseGridder.grid`)\n\n"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"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.9.13"
}
},
"nbformat": 4,
"nbformat_minor": 0
}