eldang / elevation_lookups

Takes an input file of paths described as series of points, outputs a file of data about the elevation changes along those paths.
Apache License 2.0
3 stars 2 forks source link

elevation

All Contributors

Takes an input file of paths described as series of points, outputs a file of data about the elevation changes along those paths.

This is intended as a way of addressing https://github.com/a-b-street/abstreet/issues/82 but may be more broadly useful.

Installation / requirements

This utility is being developed and tested in Python 3.9.2 on a Mac & 3.8.5 on Linux, and should in theory work with older versions of Python 3. Before installing the modules listed in requirements.txt, make sure the following are present in the environment in which it will run:

Then install the Python modules with:

pip3 install -r requirements.txt --no-binary pygeos --no-binary shapely

to make sure that they are built with the exact versions of the above dependencies that are present in the environment. This makes spatial lookups significantly faster.

Docker

If you're having trouble getting dependencies installed, you can try Docker. Build the image locally by doing docker build -t elevation_lookups .. You can then use it by binding directories on your filesystem to the Docker container. Assuming you've created a file called input/my_query:

docker run \
  --mount type=bind,source=`pwd`/input,target=/elevation/input,readonly \
  --mount type=bind,source=`pwd`/data,target=/elevation/data \
  --mount type=bind,source=`pwd`/output,target=/elevation/output \
  -t elevation_lookups python3 main.py my_query

The output should appear in your local output directory.

Basic usage

  1. Put an input file in input/, and make sure output/ and data/ folders exist
  2. python3 main.py inputfilename

To specify how many parallel processes will be spawned to process the input, add the argument --n_threads=X. If X == 1 then parallel processing will be sidestepped entirely; this can be useful for debugging. If this argument is not set, then the script will default to using as many processes as CPUs are present. Note that parallel raster processing can have a heavy memory footprint: specifically, each parallel process loads its own copy of the elevation data source, windowed to the bounding box of the input data. So for a large area and a high resolution raster data source, memory may be a tighter practical constraint on parallel processing than CPU availability.

Data source options

By default, this project will use SRTM data to look up elevations. This dataset has the advantage of global availability and ease of use, but it is limited by a coarse pixel size and 1m vertical resolution. The pixel size between 56S and 60N is 0.00027̅°, which equates to 30m E-W at the equator and 15m E-W at 60N, and 30m N-S at any latitude. In theory, the pixels triple in size at latitudes outside the range (56S, 60N), though in testing we are still finding 0.00027̅° pixels for Anchorage, Alaska, USA (> 61N).

It is also possible to configure locally preferred data sources. See below for details on how to do so. These are the available types and examples that are preconfigured in this project:

Contour lines

Data files may be in any of the vector formats supported by GDAL, though note that for formats not marked as "Built-in by default" you may need to install additional prerequisites. All common vector formats are supported by default.

The enclosed datasources.json sets up Seattle's open 2ft contour dataset as an example. Because it is defined after the LIDAR data, the LIDAR dataset is used if it covers the required area, falling back to this contour set for input files that are covered by it but not the LIDAR. In practice this means it will very rarely be used; consider it more a demo than a practical feature. In our testing we've found that the LIDAR data gets us very similar results in a fraction of the processing time.

Important note: a point's elevation is taken only from the nearest contour to it, with no attempt to interpolate. This works well for 2ft contours in a hilly area, but may become a significant source of error for flatter regions or more widely spaced contours.

Raster elevation data

Data files may be in any of the raster formats supported by GDAL, though note that for formats not marked as "Built-in by default" you may need to install additional prerequisites. All common raster formats are supported by default.

The enclosed datasources.json sets up "Delivery 1" from the Puget Sound LiDAR Consortium's 2016 King County data as an example. It covers Seattle as well as some additional area S and E of Seattle.

Input format

A text file in which each row is one path, and each row consists of tab-separated x,y coordinate pairs in order to describe a path, in unprojected decimal degrees. The file should contain no blank lines until the end, as input parsing will stop at the first blank line it encounters.

Output format

A text file in which each row corresponds to a row of the input, with order preserved, and consists of 4 tab-separated values that describe the elevation of the path in the input file, in metres rounded to the nearest mm:

start_elevation end_elevation total_climb total_descent

Some things to note:

Adding or editing data sources

Data sources are defined in datasources.json. The order of entries in that file matters, because the first data source that covers all points in the input file will be used. Each source is defined as an object in the JSON, with the following fields in any order (all fields are required, just set them to null when they don't apply):

Contributors ✨

Thanks goes to these wonderful people (emoji key):


Eldan Goldenberg

🐛 💻 📖 📆 👀

Dustin Carlino

🐛 💻 🔣 💵 🤔 📦 👀

This project follows the all-contributors specification. Contributions of any kind welcome!