Ag-Analytics® - Cropland Data Layers API

The Cropland Data Layer (CDL), produced by the USDA, provides a raster, geo-referenced, crop-specific land cover map for the continental United States. The CDL also includes a crop mask layer and planting frequency layers, as well as boundary, water and road layers. The Boundary Layer options provided are County, Agricultural Statistics Districts (ASD), State, and Region. The data is created annually using moderate resolution satellite imagery and extensive agricultural ground truth.

CDL Service provides an API for requesting CDL layer as a GeoTIFF of the area of interest(AOI) passed by the user and the summary of the majoy crops planted on the area of interest. To request the CDL layer, the user will pass the AOI as one of the following format: GeoJSON, Shapefile(.SHP, .shp), or GeoTIFF(.TIFF, tif) and the calender year of the CDL layer as parameters in the POST request. The response of POST request includes the crop summary of the AOI and a file name of the GeoTIFF saved on the Ag-Analytics server. Then, user can send a GET request that includes the file name from POST request to download the GeoTIFF of the CDL layer.

Post Request Parameters

1). aoi (GeoJSON String): Area of interest as Geojson string containing boundary coordinates. file(GeoTiff or Shapfile in Zip): Alternative AOI format when GeoJSON is not available. A GeoTiff(.TIFF,.Tif, .etc) or a Shapefile in Zip (must include shp, shx, dbf, but others files such as .prj, .xml, .cpg are recommended for better processing)

2). years(List of integers as String):Call will return CDL or Cultivated Layer GeoTiffs and response from the given years. ex: "['2015','2016']"

3).product(List of integers as String):Get 'CultivatedLayer','CDL', or both products in the response. ex:"['CultivatedLayer','CDL']"

4).Projection(String):Output projection of result GeoTIFF.Provided as EPSG code, ex: "EPSG:4326"

5).Resolution(Float):Output resolution of result GeoTIFF.

Request Spatial Reference Handling

The CDL Service handles requests differently whether they contain a file as an aoi (shapefile/GeoTIFF) or the aoi as a GeoJSON. This is accomplished with a try-catch where the service attempts to extract a file from the request first, and if this is not possible, it falls through to accepting a fully JSON request with GeoJSON as the aoi. Please see the Request Handling Table in CDL API documentation for detailed description.

Library

In [1]:
import requests
import json
import os
from collections import defaultdict
import pandas as pd
from IPython.display import Image

%matplotlib inline
%autosave 0
Autosave disabled

POST Request API Fuction

In [2]:
def cdl_service(values, files, headers):
    try:
        url = 'https://ag-analytics.azure-api.net/cdl-range-read'
        
        if files == None:
            response = requests.post(url, data=values,headers = headers).json()
        else:
            response = requests.post(url, files = files, data = values,headers = headers).json()
            
        print(response)
        
        return response
    
    except Exception as e:
        print(e)
        raise e

Headers and Subscription key

In [3]:
# Basic Header Pattern.
# headers=None
# Header for using a subscription key.
headers={'Content-Type':'application/x-www-form-urlencoded','Ocp-Apim-Subscription-Key': "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"}

Raster (.tif) as AOI for CDL

In [ ]:
cdl_response_raster = cdl_service(request_with_tif, gtiffs_files, headers)

GeoJSON as AOI for CDL

In [ ]:
#Parameters to call cdl API
aoi = "{\"type\":\"Feature\",\"properties\":{},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[-95.9148931503296,46.322452681104124],[-95.91476440429689,46.31674720419029],[-95.91442108154298,46.31682130510615],[-95.91399192810059,46.31673238399508],[-95.91360569000246,46.31648044006236],[-95.91345548629762,46.31630259658792],[-95.91388463974,46.3157838831528],[-95.91392755508424,46.31532444714701],[-95.91435670852661,46.314924290063686],[-95.91478586196901,46.31456859242209],[-95.91474294662476,46.31356076988237],[-95.91439962387085,46.313545948824185],[-95.91382026672365,46.31390165311263],[-95.91313362121583,46.314227713346064],[-95.91306924819948,46.314538950847584],[-95.91345548629762,46.31474644153189],[-95.9135413169861,46.31517624116103],[-95.91176033020021,46.315131779286965],[-95.91109514236452,46.31465751704923],[-95.91105222702028,46.314227713346064],[-95.91070890426637,46.3137682642754],[-95.9101939201355,46.31356076988237],[-95.90980768203735,46.31317542106524],[-95.90974330902101,46.312819712056545],[-95.90978622436523,46.31253810745169],[-95.91015100479126,46.31222685857106],[-95.90978622436523,46.31221203715164],[-95.90882062911987,46.3126270353782],[-95.90843439102173,46.312849354562246],[-95.90768337249756,46.312849354562246],[-95.90699672698975,46.312730784443126],[-95.90633153915405,46.31256775010992],[-95.90598821640015,46.31236025116524],[-95.90577363967897,46.311470961062994],[-95.90521574020387,46.31133756630139],[-95.9045934677124,46.311722928059],[-95.90403556823732,46.311722928059],[-95.90332746505739,46.31170810650312],[-95.90231895446779,46.311574712319505],[-95.90182542800903,46.3116191770835],[-95.90128898620607,46.31193042942004],[-95.90113878250122,46.31221203715164],[-95.90113878250122,46.31238989391975],[-95.90146064758301,46.31261221406715],[-95.9018898010254,46.31253810745169],[-95.9025549888611,46.31249364343426],[-95.90337038040163,46.31224167998646],[-95.90403556823732,46.31249364343426],[-95.90397119522096,46.312893818290675],[-95.9036707878113,46.31305685165256],[-95.9031128883362,46.313130957565605],[-95.90270519256593,46.31336809581297],[-95.90229749679567,46.31378308527336],[-95.90195417404176,46.31399057882352],[-95.90126752853395,46.31511695865424],[-95.90075254440308,46.31529480598191],[-95.90075254440308,46.31553193485307],[-95.90090274810792,46.315754242236565],[-95.90094566345216,46.31594690790508],[-95.90068817138673,46.31622849496964],[-95.90025901794435,46.31653972109205],[-95.90002298355103,46.316850945444386],[-95.90002298355103,46.31722144831783],[-95.90023756027223,46.31762158860345],[-95.89991569519044,46.31811064497894],[-95.89944362640382,46.31885163115864],[-95.89989423751832,46.3191035641739],[-95.9040141105652,46.319073925055825],[-95.9043574333191,46.31870343472544],[-95.9043574333191,46.31843668013423],[-95.90418577194215,46.31827366279941],[-95.90369224548341,46.318258843017624],[-95.90296268463136,46.318081005323016],[-95.90251207351685,46.317932806802666],[-95.90225458145143,46.317799427791165],[-95.90317726135254,46.315872805805164],[-95.90356349945068,46.31581352405298],[-95.90362787246706,46.31603583029254],[-95.90414285659791,46.31622849496964],[-95.90470075607301,46.316258135628985],[-95.9052586555481,46.316287776272304],[-95.90555906295778,46.31928139854511],[-95.90843439102173,46.31932585704758],[-95.90858459472658,46.322482318391906],[-95.9148931503296,46.322452681104124]]]}}"
request_with_GeoJSON = {"years": "['2015']",
                        "Resolution":"0.0001",
                        "Projection":"EPSG:4326",
                         "aoi":aoi,}
In [ ]:
cdl_response_geojson = cdl_service(request_with_GeoJSON, None, headers)

GeoJSON as AOI for Cultivated Layer

In [ ]:
#Parameters to call Cultivated Layer
aoi = "{\"type\":\"Feature\",\"properties\":{},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[-95.9148931503296,46.322452681104124],[-95.91476440429689,46.31674720419029],[-95.91442108154298,46.31682130510615],[-95.91399192810059,46.31673238399508],[-95.91360569000246,46.31648044006236],[-95.91345548629762,46.31630259658792],[-95.91388463974,46.3157838831528],[-95.91392755508424,46.31532444714701],[-95.91435670852661,46.314924290063686],[-95.91478586196901,46.31456859242209],[-95.91474294662476,46.31356076988237],[-95.91439962387085,46.313545948824185],[-95.91382026672365,46.31390165311263],[-95.91313362121583,46.314227713346064],[-95.91306924819948,46.314538950847584],[-95.91345548629762,46.31474644153189],[-95.9135413169861,46.31517624116103],[-95.91176033020021,46.315131779286965],[-95.91109514236452,46.31465751704923],[-95.91105222702028,46.314227713346064],[-95.91070890426637,46.3137682642754],[-95.9101939201355,46.31356076988237],[-95.90980768203735,46.31317542106524],[-95.90974330902101,46.312819712056545],[-95.90978622436523,46.31253810745169],[-95.91015100479126,46.31222685857106],[-95.90978622436523,46.31221203715164],[-95.90882062911987,46.3126270353782],[-95.90843439102173,46.312849354562246],[-95.90768337249756,46.312849354562246],[-95.90699672698975,46.312730784443126],[-95.90633153915405,46.31256775010992],[-95.90598821640015,46.31236025116524],[-95.90577363967897,46.311470961062994],[-95.90521574020387,46.31133756630139],[-95.9045934677124,46.311722928059],[-95.90403556823732,46.311722928059],[-95.90332746505739,46.31170810650312],[-95.90231895446779,46.311574712319505],[-95.90182542800903,46.3116191770835],[-95.90128898620607,46.31193042942004],[-95.90113878250122,46.31221203715164],[-95.90113878250122,46.31238989391975],[-95.90146064758301,46.31261221406715],[-95.9018898010254,46.31253810745169],[-95.9025549888611,46.31249364343426],[-95.90337038040163,46.31224167998646],[-95.90403556823732,46.31249364343426],[-95.90397119522096,46.312893818290675],[-95.9036707878113,46.31305685165256],[-95.9031128883362,46.313130957565605],[-95.90270519256593,46.31336809581297],[-95.90229749679567,46.31378308527336],[-95.90195417404176,46.31399057882352],[-95.90126752853395,46.31511695865424],[-95.90075254440308,46.31529480598191],[-95.90075254440308,46.31553193485307],[-95.90090274810792,46.315754242236565],[-95.90094566345216,46.31594690790508],[-95.90068817138673,46.31622849496964],[-95.90025901794435,46.31653972109205],[-95.90002298355103,46.316850945444386],[-95.90002298355103,46.31722144831783],[-95.90023756027223,46.31762158860345],[-95.89991569519044,46.31811064497894],[-95.89944362640382,46.31885163115864],[-95.89989423751832,46.3191035641739],[-95.9040141105652,46.319073925055825],[-95.9043574333191,46.31870343472544],[-95.9043574333191,46.31843668013423],[-95.90418577194215,46.31827366279941],[-95.90369224548341,46.318258843017624],[-95.90296268463136,46.318081005323016],[-95.90251207351685,46.317932806802666],[-95.90225458145143,46.317799427791165],[-95.90317726135254,46.315872805805164],[-95.90356349945068,46.31581352405298],[-95.90362787246706,46.31603583029254],[-95.90414285659791,46.31622849496964],[-95.90470075607301,46.316258135628985],[-95.9052586555481,46.316287776272304],[-95.90555906295778,46.31928139854511],[-95.90843439102173,46.31932585704758],[-95.90858459472658,46.322482318391906],[-95.9148931503296,46.322452681104124]]]}}"
request_with_GeoJSON_cl = {"years": "['2015']",
                             "aoi":aoi,
                           "Resolution":"0.0001",
                        "Projection":"EPSG:4326",
                        "product":"['CultivatedLayer']"}
In [ ]:
CultivatedLayer_response_geojson = cdl_service(request_with_GeoJSON_cl, None, headers)

Visualize the response png

Visualize CDL

In [ ]:
# pngb64
attributes =cdl_response_geojson['2015']['attributes']
pngb64cdl = attributes['pngb64']
#Image Legend
df=defaultdict(list)

Legend = attributes['Legend']
    
for val in Legend:
    df['Acres'].append(float(val['Acres']))
    df['Area'].append(val['Area'])
    df['Count'].append(float(val['Count']))
    df['CountAllPixels'].append(val['CountAllPixels'])
    df['CropCode'].append(val['CropCode'])
    df['CropName'].append(val['CropName'])
    df['color'].append(val['color'])

    
legenddf = pd.DataFrame.from_dict(df)    
legenddf.style.applymap(lambda x:"background-color: %s"%x, subset=['color'])
In [ ]:
# Visualize CDL
Image(url = pngb64cdl, width = 400, height = 400)

Visualize Cultivated Layer

In [ ]:
# pngb64 for cultivated Layer
attributes_cl =CultivatedLayer_response_geojson['CultivatedLayer']['attributes']
pngb64cl = attributes_cl['pngb64']

#Image Legend
df_cl=defaultdict(list)
Legend_cl = attributes_cl['Legend']
    
for val in Legend_cl:
    df_cl['Acres'].append(float(val['Acres']))
    df_cl['Area'].append(val['Area'])
    df_cl['Count'].append(float(val['Count']))
    df_cl['CountAllPixels'].append(val['CountAllPixels'])
    df_cl['Cultivated'].append(val['Cultivated'])
    df_cl['color'].append(val['color'])

    
legenddf_cl = pd.DataFrame.from_dict(df_cl)    
legenddf_cl.style.applymap(lambda x:"background-color: %s"%x, subset=['color'])
In [ ]:
# Visualize cultivated Layer
Image(url = pngb64cl, width = 400, height = 400)

GET Request

In [ ]:
# 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"
local_path = r'C:'
# Create GET request payload.
values = {'filename': [cdl_response_geojson['2015']['filename'],]}
print(values)
In [ ]:
# Get CDL file 
def CDL_get(values, local_path):
    try:
        url = 'https://ag-analytics.azure-api.net/cdl-range-read'
    
        download_path = os.path.join(local_path, values['filename'][0])
        print(values)
     
        response = requests.get(url, params=values)
        open(download_path, 'wb').write(response.content)
        
        print(response.url)

        return response
    
    except Exception as e:
        print(e)
        raise e
In [ ]:
CDL_get(values, local_path)
In [ ]: