Pages

Monday, December 4, 2017

Lab 8: Geoprocessing Services and Web Tools

Introduction

The goals of this lab were to develop a geoprocessing (GP) service using ModelBuilder in ArcMap and publishing the model as a service to a local server, then using that service to create a web app using ESRI's Web AppBuilder. The scenario for these initiatives included developing a web app that will allow end-users to find optimal locations for establishing a manufacturing industry. The criteria for candidacy includes: proximity to a river(s) and railroads, allows the user to enter a minimum population for a city, and select an area of interest. The GP service creates a buffer polygon layer of optimal locations.

Methods

To start this lab railroads, rivers, and Wisconsin cities layers were added to a blank ArcMap document. A new geodatabase and layer were created to store data and provide a blank feature layer to use for the area of interest selection in the model. A New>Toolbox was made in the project folder and New>Model opened up a blank model window (figures 1 and 2).
Figure 1: Create new toolbox.

Figure 2: Create new model.

The model was built by adding all of the geoprocessing tasks that were necessary to generate results for optimal locations. Various parameters were set to ensure the end-user meets all of the inputs required by the tool. Figure 3 shows the layout of the various tools, inputs, and outputs of the model.

Figure 3: Geoprocessing model.
Once the model was made, all parameters were established, and the inputs were configured, the geoprocessing environments were set to overwrite and save output files to the project geodatabase (figures 4 and 5).

Figure 4: Configuring geoprocessing options.

Figure 5: Set output and scratch workspace.
Next, the model was executed and requested that the end-user input a point of interest on the map (figures 6, 7, and 8).
Figure 6: Model running.

Figure 7: Select area of interest.


Figure 8: Completed running model. 
The blue areas in figure 8 show optimal areas for establishing a manufacturing industry based on the blue point selected in figure 7. Since the model worked, it was published as a service to a local server (figure 9).

Figure 9: Publish model as geoprocessing service.
The GP service was published to the local class server, which would be accessed later in the assignment to create a web app with this service (figure 10).

Figure 10: REST service located on class server.


Another service ModelBuilder provides is the ability to export any model to a Python script (figure 11). See resulting code in results section.

Figure 11: Export model to Python script.
Once the GP service was published to the class server, the service was published to the developer edition of Web AppBuilder using the development server. To do this, a new 2-D map was made and given a title in the Web AppBuilder. Then the GP service data was selected for the Choose Web Map function of the application (figure 12).

Figure 12: Select web map containing necessary data layers for the service.
Then the GP widget was configured to bring in the GP service created earlier (figure 13).

Figure 13: Enter the URL of the server that hosts the GP service. 
The service was validated and used to then configure the tool tips for each tool parameters. The application was then tested and published as a web service in the development server (figures 14 and 15).

Figure 14: Running GP task from web app.

Figure 15: Results of GP task test.
Results

Figure 16: Finished Web App.
The resulting service has the same functionality as in ArcMap or the in the editing process of Web AppBuilder, but looks clean and professional as well as has tool tips for input values when running GP task.

Having worked with ModelBuilder before, adding tools, setting inputs, and establishing parameters were all comfortable practices for me. I did not know, however, that finished models/tools created in ModelBuilder could be converted to Python scripts. This could be extremely useful for someone attempting to develop this app using scripting. I also thought that publishing the GP model as a service from ArcMap was useful.

Overall, the program works smoothly and effectively while still being relatively easy to develop and use. 

Python Script

# -*- coding: utf-8 -*-
# ---------------------------------------------------------------------------
# TCF_SitesScript.py
# Created on: 2017-12-04 15:37:41.00000
#   (generated by ArcGIS/ModelBuilder)
# Usage: TCF_SitesScript <Input_DistanceToRivers> <Input_DistanceToRails> <Input_PopulationValue> <Input_Location_of_Interest> <Input_DistanceOfInterest> <Factory_Optimal_Location> 
# Description: 
# ---------------------------------------------------------------------------

# Import arcpy module
import arcpy

# Script arguments
Input_DistanceToRivers = arcpy.GetParameterAsText(0)
if Input_DistanceToRivers == '#' or not Input_DistanceToRivers:
    Input_DistanceToRivers = "5 Kilometers" # provide a default value if unspecified

Input_DistanceToRails = arcpy.GetParameterAsText(1)
if Input_DistanceToRails == '#' or not Input_DistanceToRails:
    Input_DistanceToRails = "5 Kilometers" # provide a default value if unspecified

Input_PopulationValue = arcpy.GetParameterAsText(2)
if Input_PopulationValue == '#' or not Input_PopulationValue:
    Input_PopulationValue = "4000" # provide a default value if unspecified

Input_Location_of_Interest = arcpy.GetParameterAsText(3)
if Input_Location_of_Interest == '#' or not Input_Location_of_Interest:
    Input_Location_of_Interest = "in_memory\\{C84ECC84-6AF1-46B9-B156-A2A9C9704F4B}" # provide a default value if unspecified

Input_DistanceOfInterest = arcpy.GetParameterAsText(4)
if Input_DistanceOfInterest == '#' or not Input_DistanceOfInterest:
    Input_DistanceOfInterest = "50 Kilometers" # provide a default value if unspecified

Factory_Optimal_Location = arcpy.GetParameterAsText(5)
if Factory_Optimal_Location == '#' or not Factory_Optimal_Location:
    Factory_Optimal_Location = "Z:\\MILLERZM\\Lab8\\Lab8.gdb\\Rivers_Clip_Buffer_Intersect2" # provide a default value if unspecified

# Local variables:
Rivers = "Rivers"
Point_Buffer = "Z:\\MILLERZM\\Lab8\\Lab8.gdb\\Buffer"
Rivers_Clip = "Z:\\MILLERZM\\Lab8\\Lab8.gdb\\Rivers_Clip"
River_Buffer = "Z:\\MILLERZM\\Lab8\\Lab8.gdb\\Rivers_Clip_Buffer"
Railroads = "Railroads"
Railroad_Clip = "Z:\\MILLERZM\\Lab8\\Lab8.gdb\\Railroads_Clip"
Rail_Buffer = "Z:\\MILLERZM\\Lab8\\Lab8.gdb\\Railroads_Clip_Buffer"
River_Rail_Int = "Z:\\MILLERZM\\Lab8\\Lab8.gdb\\Rivers_Clip_Buffer_Intersect"
Wisconsin_Cities = "Wisconsin_Cities"
Wisconsin_Cities_Select = "Z:\\MILLERZM\\Lab8\\Lab8.gdb\\Wisconsin_Cities_Select"
Required_Cities_Clip = "Z:\\MILLERZM\\Lab8\\Lab8.gdb\\Wisconsin_Cities_Select_Clip"
Wisconsin_Cities_Select_Clip1 = "Z:\\MILLERZM\\Lab8\\Lab8.gdb\\Wisconsin_Cities_Select_Clip1"
All_Criteria = "Z:\\MILLERZM\\Lab8\\Lab8.gdb\\Rivers_Clip_Buffer_Intersect1"

# Process: Buffer1
arcpy.Buffer_analysis(Input_Location_of_Interest, Point_Buffer, Input_DistanceOfInterest, "FULL", "ROUND", "NONE", "", "PLANAR")

# Process: Clip1
arcpy.Clip_analysis(Rivers, Point_Buffer, Rivers_Clip, "")

# Process: Buffer2
arcpy.Buffer_analysis(Rivers_Clip, River_Buffer, Input_DistanceToRivers, "FULL", "ROUND", "NONE", "", "PLANAR")

# Process: Clip2
arcpy.Clip_analysis(Railroads, Point_Buffer, Railroad_Clip, "")

# Process: Buffer3
arcpy.Buffer_analysis(Railroad_Clip, Rail_Buffer, Input_DistanceToRails, "FULL", "ROUND", "NONE", "", "PLANAR")

# Process: Intersect
arcpy.Intersect_analysis("Z:\\MILLERZM\\Lab8\\Lab8.gdb\\Rivers_Clip_Buffer #;Z:\\MILLERZM\\Lab8\\Lab8.gdb\\Railroads_Clip_Buffer #", River_Rail_Int, "ALL", "", "INPUT")

# Process: Select
arcpy.Select_analysis(Wisconsin_Cities, Wisconsin_Cities_Select, "POP2007 >= 4000")

# Process: Clip3
arcpy.Clip_analysis(Wisconsin_Cities_Select, Point_Buffer, Required_Cities_Clip, "")

# Process: Select2
arcpy.Select_analysis(Required_Cities_Clip, Wisconsin_Cities_Select_Clip1, "")

# Process: Spatial Join
arcpy.SpatialJoin_analysis(River_Rail_Int, Wisconsin_Cities_Select_Clip1, All_Criteria, "JOIN_ONE_TO_ONE", "KEEP_ALL", "FID_Rivers_Clip_Buffer \"FID_Rivers_Clip_Buffer\" true true false 0 Long 0 0 ,First,#,Z:\\MILLERZM\\Lab8\\Lab8.gdb\\Rivers_Clip_Buffer_Intersect,FID_Rivers_Clip_Buffer,-1,-1;IHABBSRF_I \"IHABBSRF_I\" true true false 8 Double 0 0 ,First,#,Z:\\MILLERZM\\Lab8\\Lab8.gdb\\Rivers_Clip_Buffer_Intersect,IHABBSRF_I,-1,-1;RR \"RR\" true true false 11 Text 0 0 ,First,#,Z:\\MILLERZM\\Lab8\\Lab8.gdb\\Rivers_Clip_Buffer_Intersect,RR,-1,-1;HUC \"HUC\" true true false 4 Long 0 0 ,First,#,Z:\\MILLERZM\\Lab8\\Lab8.gdb\\Rivers_Clip_Buffer_Intersect,HUC,-1,-1;TYPE \"TYPE\" true true false 1 Text 0 0 ,First,#,Z:\\MILLERZM\\Lab8\\Lab8.gdb\\Rivers_Clip_Buffer_Intersect,TYPE,-1,-1;PNAME \"PNAME\" true true false 30 Text 0 0 ,First,#,Z:\\MILLERZM\\Lab8\\Lab8.gdb\\Rivers_Clip_Buffer_Intersect,PNAME,-1,-1;OWNAME \"OWNAME\" true true false 30 Text 0 0 ,First,#,Z:\\MILLERZM\\Lab8\\Lab8.gdb\\Rivers_Clip_Buffer_Intersect,OWNAME,-1,-1;PNMCD \"PNMCD\" true true false 11 Text 0 0 ,First,#,Z:\\MILLERZM\\Lab8\\Lab8.gdb\\Rivers_Clip_Buffer_Intersect,PNMCD,-1,-1;OWNMCD \"OWNMCD\" true true false 11 Text 0 0 ,First,#,Z:\\MILLERZM\\Lab8\\Lab8.gdb\\Rivers_Clip_Buffer_Intersect,OWNMCD,-1,-1;DSRR \"DSRR\" true true false 8 Double 0 0 ,First,#,Z:\\MILLERZM\\Lab8\\Lab8.gdb\\Rivers_Clip_Buffer_Intersect,DSRR,-1,-1;DSHUC \"DSHUC\" true true false 4 Long 0 0 ,First,#,Z:\\MILLERZM\\Lab8\\Lab8.gdb\\Rivers_Clip_Buffer_Intersect,DSHUC,-1,-1;USDIR \"USDIR\" true true false 1 Text 0 0 ,First,#,Z:\\MILLERZM\\Lab8\\Lab8.gdb\\Rivers_Clip_Buffer_Intersect,USDIR,-1,-1;LEV \"LEV\" true true false 4 Long 0 0 ,First,#,Z:\\MILLERZM\\Lab8\\Lab8.gdb\\Rivers_Clip_Buffer_Intersect,LEV,-1,-1;J \"J\" true true false 4 Long 0 0 ,First,#,Z:\\MILLERZM\\Lab8\\Lab8.gdb\\Rivers_Clip_Buffer_Intersect,J,-1,-1;TERMID \"TERMID\" true true false 4 Long 0 0 ,First,#,Z:\\MILLERZM\\Lab8\\Lab8.gdb\\Rivers_Clip_Buffer_Intersect,TERMID,-1,-1;TRMBLV \"TRMBLV\" true true false 4 Long 0 0 ,First,#,Z:\\MILLERZM\\Lab8\\Lab8.gdb\\Rivers_Clip_Buffer_Intersect,TRMBLV,-1,-1;K \"K\" true true false 4 Long 0 0 ,First,#,Z:\\MILLERZM\\Lab8\\Lab8.gdb\\Rivers_Clip_Buffer_Intersect,K,-1,-1;Miles \"Miles\" true true false 8 Double 0 0 ,First,#,Z:\\MILLERZM\\Lab8\\Lab8.gdb\\Rivers_Clip_Buffer_Intersect,Miles,-1,-1;Shape_Length \"Shape_Length\" true true true 8 Double 0 0 ,First,#,Z:\\MILLERZM\\Lab8\\Lab8.gdb\\Rivers_Clip_Buffer_Intersect,Shape_Length,-1,-1;Shape_length_1 \"Shape_length_1\" true true false 0 Double 0 0 ,First,#,Z:\\MILLERZM\\Lab8\\Lab8.gdb\\Rivers_Clip_Buffer_Intersect,Shape_length_1,-1,-1;BUFF_DIST \"BUFF_DIST\" true true false 0 Double 0 0 ,First,#,Z:\\MILLERZM\\Lab8\\Lab8.gdb\\Rivers_Clip_Buffer_Intersect,BUFF_DIST,-1,-1;ORIG_FID \"ORIG_FID\" true true false 0 Long 0 0 ,First,#,Z:\\MILLERZM\\Lab8\\Lab8.gdb\\Rivers_Clip_Buffer_Intersect,ORIG_FID,-1,-1;FID_Railroads_Clip_Buffer \"FID_Railroads_Clip_Buffer\" true true false 0 Long 0 0 ,First,#,Z:\\MILLERZM\\Lab8\\Lab8.gdb\\Rivers_Clip_Buffer_Intersect,FID_Railroads_Clip_Buffer,-1,-1;ObjectID_1 \"ObjectID_1\" true true false 4 Long 0 0 ,First,#,Z:\\MILLERZM\\Lab8\\Lab8.gdb\\Rivers_Clip_Buffer_Intersect,ObjectID_1,-1,-1;ID \"ID\" true true false 4 Long 0 0 ,First,#,Z:\\MILLERZM\\Lab8\\Lab8.gdb\\Rivers_Clip_Buffer_Intersect,ID,-1,-1;RAILROAD \"RAILROAD\" true true false 31 Text 0 0 ,First,#,Z:\\MILLERZM\\Lab8\\Lab8.gdb\\Rivers_Clip_Buffer_Intersect,RAILROAD,-1,-1;RROWNER \"RROWNER\" true true false 4 Text 0 0 ,First,#,Z:\\MILLERZM\\Lab8\\Lab8.gdb\\Rivers_Clip_Buffer_Intersect,RROWNER,-1,-1;TR \"TR\" true true false 4 Text 0 0 ,First,#,Z:\\MILLERZM\\Lab8\\Lab8.gdb\\Rivers_Clip_Buffer_Intersect,TR,-1,-1;PASSENGER \"PASSENGER\" true true false 4 Text 0 0 ,First,#,Z:\\MILLERZM\\Lab8\\Lab8.gdb\\Rivers_Clip_Buffer_Intersect,PASSENGER,-1,-1;MILITARY \"MILITARY\" true true false 1 Text 0 0 ,First,#,Z:\\MILLERZM\\Lab8\\Lab8.gdb\\Rivers_Clip_Buffer_Intersect,MILITARY,-1,-1;FRA_REG \"FRA_REG\" true true false 2 Text 0 0 ,First,#,Z:\\MILLERZM\\Lab8\\Lab8.gdb\\Rivers_Clip_Buffer_Intersect,FRA_REG,-1,-1;CLASS \"CLASS\" true true false 1 Text 0 0 ,First,#,Z:\\MILLERZM\\Lab8\\Lab8.gdb\\Rivers_Clip_Buffer_Intersect,CLASS,-1,-1;MILES_1 \"MILES_1\" true true false 8 Double 0 0 ,First,#,Z:\\MILLERZM\\Lab8\\Lab8.gdb\\Rivers_Clip_Buffer_Intersect,MILES_1,-1,-1;Shape_Length_12 \"Shape_Length_12\" true true true 8 Double 0 0 ,First,#,Z:\\MILLERZM\\Lab8\\Lab8.gdb\\Rivers_Clip_Buffer_Intersect,Shape_Length_12,-1,-1;Shape_length_12_13 \"Shape_length_12_13\" true true false 0 Double 0 0 ,First,#,Z:\\MILLERZM\\Lab8\\Lab8.gdb\\Rivers_Clip_Buffer_Intersect,Shape_length_12_13,-1,-1;BUFF_DIST_1 \"BUFF_DIST_1\" true true false 0 Double 0 0 ,First,#,Z:\\MILLERZM\\Lab8\\Lab8.gdb\\Rivers_Clip_Buffer_Intersect,BUFF_DIST_1,-1,-1;ORIG_FID_1 \"ORIG_FID_1\" true true false 0 Long 0 0 ,First,#,Z:\\MILLERZM\\Lab8\\Lab8.gdb\\Rivers_Clip_Buffer_Intersect,ORIG_FID_1,-1,-1;Shape_length_12_13_14 \"Shape_length_12_13_14\" true true false 0 Double 0 0 ,First,#,Z:\\MILLERZM\\Lab8\\Lab8.gdb\\Rivers_Clip_Buffer_Intersect,Shape_length,-1,-1;Shape_area \"Shape_area\" true true false 0 Double 0 0 ,First,#,Z:\\MILLERZM\\Lab8\\Lab8.gdb\\Rivers_Clip_Buffer_Intersect,Shape_area,-1,-1;ObjectID \"ObjectID\" true true false 4 Long 0 0 ,First,#,Z:\\MILLERZM\\Lab8\\Lab8.gdb\\Wisconsin_Cities_Select_Clip1,ObjectID,-1,-1;FEATURE \"FEATURE\" true true false 21 Text 0 0 ,First,#,Z:\\MILLERZM\\Lab8\\Lab8.gdb\\Wisconsin_Cities_Select_Clip1,FEATURE,-1,-1;NAME \"NAME\" true true false 48 Text 0 0 ,First,#,Z:\\MILLERZM\\Lab8\\Lab8.gdb\\Wisconsin_Cities_Select_Clip1,NAME,-1,-1;ST_ABBREV \"ST_ABBREV\" true true false 2 Text 0 0 ,First,#,Z:\\MILLERZM\\Lab8\\Lab8.gdb\\Wisconsin_Cities_Select_Clip1,ST_ABBREV,-1,-1;FIPS \"FIPS\" true true false 5 Text 0 0 ,First,#,Z:\\MILLERZM\\Lab8\\Lab8.gdb\\Wisconsin_Cities_Select_Clip1,FIPS,-1,-1;PLACE_FIPS \"PLACE_FIPS\" true true false 5 Text 0 0 ,First,#,Z:\\MILLERZM\\Lab8\\Lab8.gdb\\Wisconsin_Cities_Select_Clip1,PLACE_FIPS,-1,-1;POP_2000 \"POP_2000\" true true false 4 Long 0 0 ,First,#,Z:\\MILLERZM\\Lab8\\Lab8.gdb\\Wisconsin_Cities_Select_Clip1,POP_2000,-1,-1;POP2007 \"POP2007\" true true false 4 Long 0 0 ,First,#,Z:\\MILLERZM\\Lab8\\Lab8.gdb\\Wisconsin_Cities_Select_Clip1,POP2007,-1,-1;STATUS \"STATUS\" true true false 30 Text 0 0 ,First,#,Z:\\MILLERZM\\Lab8\\Lab8.gdb\\Wisconsin_Cities_Select_Clip1,STATUS,-1,-1", "INTERSECT", "", "")

# Process: Dissolve
arcpy.Dissolve_management(All_Criteria, Factory_Optimal_Location, "", "", "MULTI_PART", "DISSOLVE_LINES")


Sources

Zach Miller
Dr. Cyril Wilson
ESRI