ArcGIS API for Python

Goals

This workshop will introduce you to using the ArcGIS API for Python.

  • Define Esri's ArcGIS API for Python.

  • Connect to ArcGIS Online using ArcGIS API for Python.

  • Create Features and add them to a map.

  • Demonstrate Spatial Analysis using the API and ArcGIS Notebooks.

    • Search and load data from available online resources.

    • Manipulate online data and store it within variables.

    • Visualize online data through maps and charts.

1. What is ArcGIS API for Python

1.1 Definition

The ArcGIS API for Python is a powerful, modern and easy to use Pythonic library to perform GIS

visualization and analysis, spatial data management

and GIS system administration tasks that can run

both interactively, and using scripts.

The ArcGIS API for Python is just another platform for

accessing GIS content that is on the web.

* Image taken from Esri's site.

1.2 Architecture of the API

Blue modules: These provide additional functionality for your workflows. They include the

geocoding module which is for creating geolocations from addresses, the geometry module

for representing the geometries of feature data and functions for working with them, the

geoprocessing module that makes it easy to import third party geoprocessing tools and work

with them and the geoenrichment module that helps you enrich your datasets with thematic

information.

Orange modules: These allow you to visualize and disseminate your GIS data and analysis.

The widgets module includes the MapView Jupyter notebook widget for visualizing maps and

layers, the mapping module has types and functions for working with web maps and web layers

and the apps module helps you create and manage web applications built with ArcGIS.

Green modules: These are used to access the various spatial functions or geographic datasets

in the GIS. These modules include a family of geoprocessing functions, types and other helper

objects for working with spatial data of a particular type.

Light green module: This gis module provides the entry point into the ArcGIS online universe.

It's the module which is used to connect to ArcGIS online resources.

1.3 What's the difference between ArcPy and the ArcGIS API?

ArcPy:

  • Is a Python site-package that contains many geospatial methods and classes (geoprocessing tools).

  • This allows a python coder to work with, and manipulate, GIS data in many different ways.

  • Has access to data and maps within ArcGIS Pro and on the local machine, but does not have access

    • to online GIS resources (ie. ArcGIS Online content).

  • Allows users to perform geographic data analysis, data conversion, data management, and map

    • automation on GIS Data.

ArcGIS API for Python:

  • Can directly access ArcGIS data that resides on a web platform.

    • This includes: loading, updating, saving, and deleting

  • Cannot directly access local GIS data.

    • Local geodatabases

    • Maps within ArcGIS Pro or stored locally

  • Has many tools for analyzing GIS data.

    • Buffers

    • Hotspots

    • Aggregation

    • Many others

  • Allows for easy visualization of data and goes hand in hand with many Python packages that work with

  • statistical data as well as GIS data.

    • MatPlotLib

    • Pandas and Spatial Data Frames (SDFs)

    • Many others

  • Allows for easy visual mapping of GIS data

    • Utilizes layers (feature, image)

    • Can customize symbology

    • Can display analyzed GIS data.

1.4 ArcPy and ArcGIS API are complementary libraries.

They both work together to give a complete and comprehensive set of tools for

working with GIS data either online or locally.

Example 1: You have a feature layer on your local geodatabase that you'd like to analyze for hotspots.

ArcPy can load the feature layer into python object.

ArcGIS API for Python can run the hotspots method on that feature layer

ArcGIS API for Python can display that map within an ArcGIS Notebook.

1.5 Where can we use the ArcGIS API?

We will be demonstrating the ArcGIS API for Python within an ArcGIS Notebook,

but this library can be used outside of ArcGIS Pro as well.

ArcGIS API for Python can be installed in any python environment.

ArcGIS Pro does not have to be installed to use the ArcGIS API for Python.

It is freely available from Python's popular software repository PyPI and can be installed with PIP or Conda.

1.6 Where can we use the ArcPy library?

The ArcPy library can also be used outside of ArcIGS Pro,

but unlike the ArcGIS API for Python, ArcPy must be run

on a machine that also has ArcGIS Pro installed. ArcPy must be

run from the Python environment installed with ArcGIS Pro.

ArcGIS Pro doesn't have to be open though.

2. Using ArcGIS API for Python

2.1 Connecting to ArcGIS Online (AGOL)

2.1.1 Importing the API and connecting to the ArcGIS Online.

In order to start using the ArcGIS API for Python we need to connect to our ArcGIS online content.

"arcgis" is the root package name for the ArcGIS API for Python. This is what we'll import into our scripts

We'll use the "gis" module defined within python's arcgis package to connect to AGOL.

2.1.2 Practice

  • Make sure you have ArcGIS Pro open, and are signed into your AGOL account.

  • Create a new ArcGIS Notebook in ArcGIS Pro.

  • You can do this in your currently open ArcGIS Pro project or create a new project and create a new Notebook within it.

  • Copy and paste the following line into the first cell in your Notebook

from arcgis.gis import GIS

  • Run the cell

  • Here, we are loading the ArcGIS API for Python package so that our script can use it.

  • Copy and paste the following line of code into the new cell in your Notebook

gis = GIS("home")

  • Run the cell

  • This is where we attempt to connect to the ArcGIS Online site and store that connection in the

  • variable "gis"

  • GIS("home") says you want to use your ArcGIS Pro signon session as the credentials to access AGOL.

  • Whatever this account has access to is the what you can access through this GIS connection.

  • A python object representing the GIS connection has been assigned to the variable "gis"

  • Copy and paste the following line of code into the new cell in your Notebook.

gis.users.me

  • Run the cell

  • This is a property of the UserManager object within GIS. We're just displaying our account information.

  • This should match your current login credentials within ArcGIS Pro.

  • We're now ready to start using the ArcGIS API for Python in earnest.

  • Keep your Notebook open.

2.2 Displaying a Map

2.2.1 Overview - Map display

With the ArcGIS API for Python library, we can create a map widget, and display it within our Notebook.

The map widget is a python object that allows for a map object to be generated and displayed

within an ArcGIS Notebook.

You can use map widgets outside of ArcGIS Notebooks, but you lose the visualization aspect.

2.2.2 Practice

      • There should be a new cell below the last cell you ran. Copy and paste the following code

my_map = gis.map("Charleston, SC")

my_map.basemap = "streets"

  • Run the cell

  • We've now created a ArcGIS Map object and specified that we want to center the map around Charleston.

  • The map widget is stored in the variable name: "my_map".

  • Let's display the map. Copy and paste the following code into the new cell

my_map

  • Run the cell

  • This adds a map of Clemson to the output window of the previously run cell.

  • Let's change the basemap. But what should we change it to?

  • There is a property in the map widget which contains a python list of available basemaps.

  • Copy and paste the following code into the new cell

my_map.basemaps

  • Run the cell.

  • We should see a python list of all the available basemaps.

  • Lets change the basemap in my_map to 'satellite'

  • click on the cell's content box which you ran in the previous step.

  • Insert a line by hitting enter at the end of the last line of code, then copy and paste the following code

my_map.basemap = 'satellite'

  • Run the cell

  • One thing to notice, our map that is being displayed in the cell output above, automatically changed with the

  • updated basemap property.

  • Explanation: All variables and objects in a notebook are global in scope regardless of the cell in which

  • they are declared. The MapView widget, which is responsible for displaying the map, recognized the

  • change in the my_map object property and automatically updated the map.

  • Another thing to notice, the cell we just ran is no longer displaying a list of available basemaps even though we

  • still have it coded to do so.

  • Explanation: When wanting to display an object such as a map or object property in a Notebook cell.

  • The code needs to either, be in a cell by itself, or the last line of code within the cell.

  • Because we have a line of code below the basemaps property, the list of basemaps will not be displayed

  • in the cell output.

2.2.3 Summary

We've just lightly poked a small part of the map widget which is available within the ArcGIS API for Python.

When you want to learn more about what the ArcGIS API for Python has to offer,

One of your best companions will be using the <shift>-<tab> when the cursor is on a gis method.

If you still need more details with the GIS object or method you can go to Esri's online reference:

Esri's ArcGIS Python API reference. It has everything you need to know about all the modules and

classes within the ArcGIS API.

2.3 Adding Graphic Locations to a Map

2.3.1 Map draw method

We can add location points to our map by using the draw method within our map widget.

Before we do that we need to get some locations to draw. We'll use the geocoding module within

the ArcGIS API for Python to translate a POI (Point of Interest) to a geographic location. The geocoding

modules allows for many types of POI categories to be specifed.

2.3.2 Practice

  • Create a new notebook within the same project.

  • In the newly created notebook, copy and paste the following two code blocks into separate cells

# Establishing a connection to ArcGIS online and creating a map widget to display.

from arcgis.gis import GIS

gis = GIS("home")

charleston_map = gis.map("Charleston, SC")

charleston_map.basemap = "streets"

  • Run the cell

  • Copy the paste the following code into the new cell

charleston_map

  • Run the cell

  • We're just running code that we've already talked about in the previous section.

  • You should have a map displayed in the cell output centered around the city of Charleston.

  • Lets get a list of all the parks and schools located in the Charleston area using the geocode method.

  • Copy and paste the following code in the new cell.

from arcgis.geocoding import geocode

charleston_parks = geocode("Parks Charleston SC")

charleston_schools = geocode("Schools Charleston SC")

  • Run the cell.

  • The geocode method returns a python list of geolocations for all the parks and schools found in the Charleston area.

  • Let's draw these locations on our map using the draw method of our map widget.

  • Copy an paste the following code in the new cell, then, run the cell

for cp in charleston_parks:

charleston_map.draw(cp['location'])

for cs in charleston_schools:

charleston_map.draw(cs['location'])

2.3.3 Marker symbols

We have created two for..loops that will draw on our map all of the parks and schools we found.

But, all the locations are a plain hollow black circle. In fact, we can't distinguish whether a location is a

park or school. The geolocations we received from the geocode method didn't contain any symbology information

on how to visually represent the location. By default, each location symbol will be displayed as a black hollow circle.

Fortunately, the draw method allows you to specify different symbol types either as a basic geometric shape or

as a graphical icon.

2.3.4 Practice

  • In the next new cell copy and paste the following code block. Then, run the cell.

# Define a symbol that looks like an orange diamond with a purple border.

sym_diamond = {

"type": "esriSMS",

"style": "esriSMSDiamond",

"color": [245,102,0,255], # RGBA Clemson Orange

"size": 14,

"angle": 0,

"xoffset": 0,

"yoffset": 0,

"outline": {

"color": [82, 45, 128, 255], # RGBA Clemson Purple

"width": 2

}

}

# Define a symbol that uses a school graphical icon.

sym_school = {

"type": "esriPMS",

"url": "http://static.arcgis.com/images/Symbols/PeoplePlaces/School.png",

"contentType": "image/png",

"width": 24,

"height": 24,

"angle": 0,

"xoffset": 0,

"yoffset": 0

}

  • click on the cell with the two for..loops above and replace (delete previous for..loops)

  • that code with the following code:

for cp in charleston_parks:

charleston_map.draw(cp['location'], symbol=sym_diamond)

for cs in charleston_schools:

charleston_map.draw(cs['location'], symbol=sym_school)

  • Run the cell

  • Look at your map in the cell above

  • We've now populated the map with school icons to represent school locations and

  • orange diamonds to represent parks.

2.3.5 Marker symbol resources

Esri provides resources for selecting and incorporating graphical marker symbols on

you maps: Esri's Symbol Selection Page Just select the symbol you want to use and the

necessary python dictionary pops into the window below. This can be copied

into your code to be used with the draw() method.For basic polygon shapes,

Esri has a Shape Reference Page you can look through to create different types of shapes

to be used as marker symbols.

2.3.6 Clear the map

If you were to keep changing the symbols and redrawing them on the map you might

notice that the previous symbols are not disappearing, but instead, the new symbols

are stacking on top of the old symbols. This is because the draw method does not

delete any of the previous graphics that have been added to the map. If we want to

clear the map we need to use the map widget's clear_graphics() method.

2.3.7 Practice

  • Copy and paste the following line of code in the cell that contains the two for..loops.

  • Paste it so that it's the first line in the cell (before the two for..loops)

charleston_map.clear_graphics()

  • Run the cell that you just modified.

  • Now the map clear's all the graphics before we issue more drawing commands.

2.3.8 Interactive popup windows

We can make our map interactive by adding popup windows to the marker locations that

we've added. We'll add the name of the school or park and the address to our popup.

Within each location that we've geocoded there are properties that describe the location.

We want to use. The properties we'll use are 'ShortLabel' which is basically the name of

the location and 'Place_addr' which is the specific address of the location.

2.3.9 Practice

  • Replace the two for loops in the previous cell with the following code.

  • Make sure to keep the clear_graphics() method above the for..loops.

for cp in charleston_parks:

popup = {

"title" : cp['attributes']['ShortLabel'],

"content" : cp['attributes']['Place_addr']

}

charleston_map.draw(cp['location'], symbol=sym_diamond, popup=popup)

for cs in charleston_schools:

popup = {

"title" : cs['attributes']['ShortLabel'],

"content" : cs['attributes']['Place_addr']

}

charleston_map.draw(cs['location'], symbol=sym_school, popup=popup)

  • Run the cell.

  • Now if you click on any of the graphics, in the map above, you should get a popup for

    • that location.

3.3.10 The draw() method is not permanent.

If you were to code "charleston_map" in the bottom most cell and run that cell you would notice that

when the new map is displayed all the locations that we added to the map are gone. This is because

the locations that we added are not actually incorporated into the map. Rather they are just placed on

top. In order to have a map that actually contains features we need to add "layers" to the map.

3.4 Adding layers to a map

3.4.1 What are layers

Layers are logical collections of geographic data that are used to create maps.

With layers we can apply spatial analysis and geoprocessing functions to our geographic data.

Within the ArcGIS API for Python Esri provides the arcgis.features module which allows us to

create, read, update, append, and delete layers within our script.

the arcgis.features module recognizes the following data types:

  • Feature - Entity located in space with a set of properties.

  • FeatureLayer - A collection of features that have geospatial properties along with normal tabular data.

  • FeatureSet - A subset of features from a FeatureLayer. Features you get from a query are put into

  • a FeatureSet.

  • FeatureCollection - A collection of features represented as a GeoJSON object. Can also be used as a layer for your maps.

  • FeatureLayerCollection - A collection of FeatureLayers and Tables. As well, as their relationships to

  • each other.

  • Table - Data that is structured into rows, each of which contains information about some entity.

  • SpatialDataFrames - An specially formatted table object to manipulate, manage and translate data into new forms of information.

    • Also contains geometric data.

We can create feature sets from other types of data outside of ArcGIS:

  • CSV files

  • XSL tables

  • Shapefiles

  • GeoJSON

Once we have a feature set we can apply all the different types of analysis and geoprocessing functions available within

the ArcGIS API for Python.

3.4.2 Adding layer(s) from Esri's online repository

Esri's online resources include:

  • Any AGOL layers that you have specific access to based on your ArcGIS Online credentials.

  • Any AGOL layers created by anyone person or company and shared as publicly available to anyone.

  • Esri's Living Atlas is a collection of professional and authoritative layers of high quality geographic information

Using the ArcGIS Python API we can search ArcGIS Online repositories above for feature layers in which we might be interested.

We can use a search() method from the ContentManager object within the gis module.

3.4.2.1 Practice

    • Open a new notebook.

    • Copy and paste this familiar code into snippet into the first cell. Then, run the cell.

from arcgis import GIS

gis = GIS()

mymap = gis.map("USA", zoomlevel=3)

mymap

    • Copy and paste the following into the new cell below the map.

historical_search = gis.content.search("title: Historical Hurricane ", outside_org=True, item_type="Feature *")

historical_search

  • my_search now contains a python list of arcgis Item objects that point to FeatureLayers

  • and FeatureLayerCollections.

  • We can add a for loop to print out specific details of each item return from the search.

  • Copy and paste the following into the new cell.

for idx, itm in enumerate(historical_search):

display(itm)

print(f"[{idx:<2}] {itm.title:55} {itm.id}\t{itm.type}\n")

    • The enumerate() python function allows you to create an index within the current loop.

    • The display() method allows you to specify a widget with which you'd like to display in the

    • output cell.This allows you to work around the rule where you can only specify a widget name

    • at the end of the code cell.

  • Finally we're printing out a formatted string with the properties we want from each item from

    • our historical_search results.

    • If we see our needed feature layer in our search result list we can retrieve it in 2 ways.

    • copy and paste the following into the new cell.

historical_hurricanes = historical_search[7]

display(historical_hurricanes)

hitorical_hurricanes = gis.content.get("30f720afacc64dfd9d651c91cd15d6d6")

display(historical_hurricanes)

    • We can use the list index to specify the wanted Feaure Layer

    • We can the get() method within the gis.content object

    • To add the feature layer to our map we simply use the map.add_layer() method.

    • Copy and paste the following copde into the new cell

mymap.add_layer(historical_hurricanes)

display(mymap)

    • You can see that we've added that Feature Service to our map

    • Let's look at active hurricanes

    • Copy and paste the following code into a new cell

active_search = gis.content.search("title: Active Hurricane ", outside_org=True, item_type="Feature *")

for idx, itm in enumerate(active_search):

display(itm)

print(f"[{idx:<2}] {itm.title:55} {itm.id}\t{itm.type}\n")

active_hurricanes = active_search[0]

activemap = gis.map("USA", zoomlevel=1)

activemap.add_layer(active_hurricanes)

display(activemap)

    • Why can't we see the other features from the active_hurricanes feature layer?

    • The type of feature class we retrieved is of type "feature service" which is just a feature layer collection.

    • This means it can contain more than one layer. We need to add all the layers to our map.

    • Copy and paste the following code into the new cell.

mymap.remove_layers() # remove any layers that are apart of the map.

for layer in active_hurricanes.layers:

mymap.add_layer(layer)

        • We should now see that all the layers have been added to our map.

3.4.3 Create layer to add to map

Let's revisit to where we geocoded the schools and parks. We added

those features to the map using the draw() method, But that didn't allow us to actually

include those features within the map as a layer. If we refreshed the display of the map

then the features would disappear. Let's see how we can actually make those features

apart of our map by creating a featureset.

3.4.3.1 Practice

We want to add a layer to our map that shows all the evacuation routes from coastal

cities within Charleston, South Carolina. Then, we want to geocode all the gas stations

in that area and place those on the map as well. Open a new notebook within your current

project. Copy and paste the following code into the first cell of your new notebook.

from arcgis import GIS

from arcgis.geocoding import geocode

from arcgis.features import FeatureSet

from IPython.core.display import display, HTML

gis = GIS()

mymap = gis.map("Charleston", zoomlevel=11)

mymap.basemap = "gray"

  • Same old same old.

  • Copy and paste the following code into the new cell

charleston_sc = geocode("Charleston SC")[0]

# display(charleston_sc)

# gas_stations1 = geocode("Gas Stations Charleston SC")

gas_stations1 = geocode("Gas Stations Charleston SC", max_locations=200, as_featureset=True)

gas_stations2 = geocode("Gas Stations SC", location=[charleston_sc['location']['x'], charleston_sc['location']['y']],

max_locations=200, distance=50000, as_featureset=True)

gas_stations3 = geocode("Gas Stations SC", search_extent=charleston_sc['extent'], max_locations=200, as_featureset=True)

mymap.add_layer(gas_stations1)

  • We can geocode the gas stations in a couple of different ways. The first way is to specify the POI

    • and the location withoutany other parameters.

  • We could geocode our location as a center and then specify a radius in meters retrieving everything

    • within that radius.

  • We could use the defined extent for charleston and find everything within that extent.

  • Also notice the use of the parameter "as_featureset". This parameter allows us to retrieve our

    • locations not as a simple python list but as a layer object that we can easily add to our map without

    • having to loop through the draw() method.

  • Finally, we can add the featureset layer to our map with the add_layer() method.

    • Copy and paste the follow cell into the new cell in the notebook.

display(mymap.layers)

mymap.remove_layers(mymap.layers)

display(mymap.layers)

# mymap = gis.map("Charleston", zoomlevel=11)

# mymap.basemap = "gray"

mymap

  • We can remove all layers from the map by using the remove_layers() method.

    • it accepts a python list of feature layers that you want removed.

    • Unfortunately, it doesn't seem to work on my notebook so I had to recreate the map and the redraw it.

    • Let's re-add the layers from above and define the icon for the gas stations.

    • Copy and paste the following code into a new cell.

# Define a symbol that uses a school graphical icon.

sym_gas = {

"angle":0,

"xoffset":0,

"yoffset":0,

"type":"esriPMS",

"url":"http://static.arcgis.com/images/Symbols/Transportation/Fuel.png",

"contentType":"image/png",

"width":24,"height":24

}

mymap.add_layer(gas_stations1, options={'symbol': sym_gas})

        • Popups are defined by default to show all values in the layer, but we could customize them

        • if we wanted to.

        • Now let's add our evacuations routes feature layer

        • Copy and paste the following code into a new cell

evac_routes_search = gis.content.search(query="title: Hurricane Evacuation Routes",

outside_org=True, item_type="Feature *",max_items=20)

for ers in evac_routes_search:

display(ers)

# print(f"{ers.title:55} {ers.id}")

# print(f"{ers.url}\n")

      • We can use the content.search() method to search Esri's Online site and it's Living Atlas to

        • look for data that we might want to use.

      • We can get the content we want with the content.get() method and specifying either the URL

        • of the feature layer or it's item ID.

      • Copy and paste the following code into a new cell

evac_route = gis.content.get("29f5a1e6bf1e4394a692ba633d5c8af6")

display(evac_route.layers)

mymap.add_layer(evac_route.layers[0])

mymap

Appendix A - Installing Jupyter Notebooks and ArcGIS API for Python

  • Install Anaconda

    • Run Anaconda Prompt (found in start menu under Anaconda3 folder)

    • Type the following command to install Jupyter Notebook:

    • conda install -c conda-forge jupyterlab (This might take a few minutes)

    • To install ArcGIS API for Python type the following command in the Anaconda Prompt:

  • conda install -c esri arcgis

    • When install is complete start Jupyter Notebook by clicking on Jupyter Notebook icon

    • either under Anaconda3 folder within Start Menu or on Desktop.

    • The Jupyter Hub should open up within your browser (should be Firefox, Chrome, or Safari).

    • From here you can either open a Notebook file or create a new notebook.