Import Modules: The following block of code imports all the modules necessary for the completion of the analysis. The multiprocessingWorker module and corresponding worker function are user defined and where the raster analysis occurs. Its contents (located in the multiprocessing folder of this tool) and how it functions can be viewed by opening it in an IDE or text editor of your choice.
import time
import os
import arcpy
import multiprocessingZ
from multiprocessingWorker_v2 import worker
Define Variables: The following variables must be defined or changed by the user for the tool to function properly or to customize the tool to your desired parameters. Comments in the code will help guide you on how to do this successfully.
'''Point the following variables to the proper location of the test data provided or your own dataset. The sourceWorkspace
is mandatory; however, the clipBoundaryLayer is optional and can be commented out if no boundary is desired for your dataset.'''
sourceWorkspace = r"C:\Users\kevin\Documents\Penn State GIS\Geog 489\Final Project\Test Data_Inyo NF" #Path of the folder that contains all the raster data that you want to process
clipBoundaryLayer = sourceWorkspace + r"\Inyo Boundary\InyoNF_Boundary.shp" #Path to boundary layer for extracting raster to desired area *comment out if no boundary desired
'''The elevCutoff variable requires 3 values in a tuple or list. The first value is a cutoff elevation.
The second is the new value for elevations below the cutoff and third for elevations above the cutoff.'''
elevCutoff = (3500,0,1)
'''The variables below must contain a Remap Table for the desired range of values and a new corresponding
value for the slope and aspect criteria. The predefined tables are for performing the Pika habitat
selection with the provided data.'''
aspectReclassTable = [[-1,-1,0],[0,67.5,1],[292.5,360,1],[67.5,292.5,0]]
slopeReclassTable = [[0,30,0],[30,40,1],[40,90,0]]
Criteria Explanation for Pika Habitat:
Set workspace, and populate raster list.
#Sets arcpy workspace to folder defined in variables block above
arcpy.env.workspace = sourceWorkspace
#Populates a list with all of the rasters that will be sent to workers for geoprocessing
rasterList = arcpy.ListRasters()
Define Multiprocessing Handler
def mp_handler():
try:
successList = []
failedList = []
jobs = []
'''If no boundary layer used, remove 'clipBoundaryLayer' from jobs.append list'''
for raster in rasterList:
jobs.append((raster, sourceWorkspace, elevCutoff, aspectReclassTable, slopeReclassTable, clipBoundaryLayer))
cpuNum = multiprocessing.cpu_count() # determine number of cores to use
print("There are " + str(cpuNum) + " cpu cores on this machine.")
print('---------------')
with multiprocessing.Pool(processes=cpuNum) as pool: # Create the pool object
returns = pool.starmap(worker, jobs) # run jobs in job list; returns is a list with return values of the worker function
# Append rasters that were successfully processed and those that failed to process to appropriate list.
for res in returns:
if res.get('result') != False:
successList.append(res.get('Raster'))
else:
print(res.get('Raster'))
print(res.get('error'))
failedList.append(res.get('Raster'))
#Print success and failed Lists
if bool(successList) != False:
print("Successfully processed: " + ', '.join(successList))
else:
pass
if bool(failedList) != False:
print('Failed to process: ' + ', '.join(failedList))
else:
print('No rasters failed to process.')
except Exception as e:
# Capture all other errors
print("Exception:", e)
Execute Analysis Process: Running the block of code below will call on the mp_handler that will generate a list of raster processing jobs that will then be passed to an individual worker. Once complete you can find the final shapefiles in the sourceWorkspace folder designated above. It will also log how long the process takes to complete.
start_time = time.time()
if __name__ == '__main__':
mp_handler()
print ("--- %s seconds ---" % (time.time() - start_time))
Sign in to ArcGIS Online Account
The default requires a Pennsylvania State Organizational account but can be changed to your organization's information
import arcgis
from arcgis.gis import GIS
#Define your AGOL Username
usernameAGOL = 'kap6389_pennstate'
#Login to AGOL and paste success code in box that appears below.
gis = GIS('https://pennstate.maps.arcgis.com', client_id='lDSJ3yfux2gkFBYc')
import zipfile
import re
# function to create zipped shapefile for a given filename without extension
def zipShapefile(name):
compiledRE = re.compile(name+'(?!.zip)\....')
with zipfile.ZipFile( os.path.join(sourceWorkspace, name + '.zip'), 'w', zipfile.ZIP_DEFLATED) as zf: # create zipfile
for file in os.listdir(sourceWorkspace): # go through files in workspace
if compiledRE.match(file): # test whether file is part of the shapefile to be zipped
zf.write(os.path.join(sourceWorkspace,file),file,zipfile.ZIP_DEFLATED) # add file to zipfile
# search for content in your gis with a query built from tilte, owner and item type
def searchAGOL(title, owner, itemType):
return gis.content.search(query='title:'+title+' owner:'+owner, item_type=itemType)
# test whether items exist on AGOL for given title, owner, and item type and if so, delete them from AGOL
def deleteIfExistsOnAGOL(title, owner, itemType):
result = searchAGOL(title, owner, itemType) # search item
print('Found items for title='+title+', owner='+owner+', itemType='+itemType+':')
print(result)
for item in result: # delete items found
item.delete()
print('Item ' + item.title + ' has been deleted.')
finalMap = gis.map()
finalMap
shapefileList = arcpy.ListFeatureClasses()
for shapefile in shapefileList:
name = (os.path.splitext(shapefile)[0])
zipShapefile(name)
deleteIfExistsOnAGOL(name, usernameAGOL, 'Shapefile')
deleteIfExistsOnAGOL(name, usernameAGOL, 'Feature Service')
Shapefile = gis.content.add({'type':'Shapefile'}, os.path.join(sourceWorkspace, name +'.zip')) #add shapefile to AGOL
FeatureService = Shapefile.publish() #Publish shapefile as Feature Service
print(searchAGOL(name, usernameAGOL, 'Shapefile')) #Check if Shapefile uploaded
print(searchAGOL(name, usernameAGOL, 'Feature Service')) #Check if feature service published
finalMap.add_layer(FeatureService,{
'renderer': 'ClassedColorRenderer',
'field_name': 'gridcode',
})