The Ag-Analytics® DEM Service API allows for clipping boundaries to the 10 meter USGS DEM map of the United States. The service consists of a POST request where the user can pass a GeoJSON boundary, desired output projection as an EPSG code, and a resolution in degrees lat/lon. The result of the post request is a file name that is the result of the clip, reproject, and resample.
The file name can be used as the parameter in a GET request to the same endpoint. Doing so will download the file to the specified local path.
import requests
import json
import time
import os
from pandas.io.json import json_normalize
from collections import defaultdict
import pandas as pd
import zipfile, io
from IPython.display import Image
%matplotlib inline
%autosave 0
Request URL: https://ag-analytics.azure-api.net/dem-service
1). aoi (.tif, .shp, GeoJSON String): Area of interest as either TIFF file, shapefile, or Geojson string containing boundary coordinates. The maximum aoi area must be less than 200 square miles (518 sq km).
2). Projection (string): Projection of result GeoTiff.
Formatted as EPSG code, WKT, or PROJ.4.
3). Resolution (Float): Output GeoTIFF resolution.
Specified in the units of the projection. E.g., 8-meters in WGS84 ~0.0001 degrees.
4). Elevation_Index (True/False as string): Flag to return elevation indices along with DEM Raster when set to true.
Relative Elevation: Relative elevation of each pixel as compared to entire field.
Slope: Slope at each point.
Topographical Position Index: Index of how each pixel compares to a 5 pixel window of surrounding points.
Terrain Ruggedness Index: Measure of how hilly the area of interest is.
Computing Slope, TPI, and TRI are relatively computationally expensive, and therefore increase the response time significantly. If the DEM request takes ~2 seconds, including a elevation indices will increase the time to ~60 seconds. Since the time required increases as a square of time, the maximum allowable area is 1.5 square miles instead of the 200 square miles in the DEM request without elevation indices.
def DEM_Service(values, files, headers):
try:
url = 'https://ag-analytics.azure-api.net/dem-service'
# Geojson request or request with geotiff/shapefile.
if files == None:
response = requests.post(url, data=values, headers=headers).json()
else:
response = requests.post(url, files = files, data = values).json()
print(response)
return response
except Exception as e:
print(e)
raise e
The API service takes the request in Json format. Below are examples formatted in Json.
gjson_values = {
"aoi": "{\"type\":\"Feature\",\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[-76.5907145, 42.443918], [-76.5898132, 42.4224745], [-76.5699863, 42.4230447], [-76.5710592, 42.4443296], [-76.5907145, 42.443918]]]},\"properties\":{\"OBJECTID\":4944402,\"CALCACRES\":46.15999985,\"CALCACRES2\":null},\"id\":4944402}",
"Elevation_Index": "False",
"Legend_Ranges": "20"
}
gjson_files = None
# Basic header pattern.
gjson_headers={'Content-Type':'application/x-www-form-urlencoded'}
# Header for using a subscription key.
# headers={'Content-Type':'application/x-www-form-urlencoded','Ocp-Apim-Subscription-Key': '••••••••••••••••••••••••••••••••'}
gjson_dem_response=DEM_Service(gjson_values, gjson_files, gjson_headers)
#Path to raster on your local machine
gtiff_filepath = r"C:\<Path to GeoTIFF>"
gtiff_files = [('File',(open(gtiff_filepath, 'rb')))]
#Parameters to create index
gtiff_values = {"Elevation_Index": "False",
"Projection": "EPSG:4326",
"Resolution": "0.0001"}
# Header for using a subscription key.
# headers={'content-type': "application/json",'Ocp-Apim-Subscription-Key': "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"}
gtiff_dem_response=DEM_Service(gtiff_values, gtiff_files, gtiff_headers)
The AOI should be provided as a zipped file containing a .shp, .shx, .dbf, and .prj.
#Path to zipped shapefile directory on your local machine
shp_filepath = r"C:\<Path to shapefile zipped folder>"
shp_file = [('File',(open(shp_filepath, 'rb')))]
print(shp_file)
#Parameters to create index
shp_values = {"Elevation_Index": "False",
"Projection": "EPSG:4326",
"Resolution": "0.0001",
"Legend_Ranges": "20"}
shp_headers={'Content-Type':'application/json'}
# Header for using a subscription key.
# headers={'content-type': "application/json",'Ocp-Apim-Subscription-Key': "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"}
shp_dem_response=DEM_Service(shp_values, shp_file, shp_headers)
#################################################################
# Input boundary type from ['geojson', 'geotiff', 'shapefile']
boundary_type = 'geojson'
#################################################################
if boundary_type == 'geojson':
dem_response = gjson_dem_response
elif boundary_type == 'geotiff':
dem_response = gtiff_dem_response
elif boundary_type == 'shapefile':
dem_response = shp_dem_response
df=defaultdict(list)
for value in dem_response['Features']:
attributes = value['attributes']
df['Max'].append(float(attributes['Max']))
df['Mean'].append(float(attributes['Mean']))
df['Min'].append(float(attributes['Min']))
df['pngb64'].append(attributes['pngb64'])
indexdf=pd.DataFrame.from_dict(df)
indexdf
#Image Legend
df=defaultdict(list)
for product in dem_response['Features']:
Legend = product['attributes']['Legend']
for val in Legend:
df['Max'].append(float(val['Max']))
df['Mean'].append(float(val['Mean']))
df['Min'].append(float(val['Min']))
df['Color'].append(val['color'])
# df['Range'] = ['Low','Medium','High']
legenddf = pd.DataFrame.from_dict(df)
legenddf.style.applymap(lambda x:"background-color: %s"%x, subset=['Color'])
# IndexImage = indexdf.loc[indexdf['Index'] == 'POLARIS_Soils','pngb64'].iloc[0]
DEMImage = dem_response["Features"][0]['attributes']["pngb64"]
Image(url = DEMImage, width = 500, height = 500)
# Specify local path where file will be downloaded.
local_path = r"C:\<Path to download directory>" # E.g., r"C:\Users\John_Doe\Documents\rasters"
# Create GET request payload.
if 'Index_Files' in dem_response.keys():
files = []
files.append(dem_response['FileName'])
for file in dem_response['Index_Files']:
files.append(file)
values = {'FileNames': files}
else:
values = {'FileNames': [dem_response['FileName'],]}
print(values)
def DEM_get(values, local_path):
try:
url = 'https://ag-analytics.azure-api.net/dem-service'
print('values', values)
for file in values['FileNames']:
print('file', file)
download_path = os.path.join(local_path, file)
file_dict = {'FileName': file}
response = requests.get(url, params=file_dict)
open(download_path, 'wb').write(response.content)
print(response.url)
print(response)
except Exception as e:
print(e)
raise e
DEM_get(values, local_path)