How do I delete a network analyst layer (i.e., Service Area, Closest Facility) using python 3 (ArcGIS Pro)?

425
13
Jump to solution
07-13-2019 06:23 PM
Highlighted
New Contributor II

Hi,

I am building a toolbox using Python 3 in ArcGIS Pro 2.4. It involves a series of network analysis processes, including closest facility and service area. I am using arcpy.na.MakeClosestFacilityAnalysisLayer and arcpy.na.MakeServiceAreaAnalysisLayer. I am able to create them no problem, but I am having lots of trouble with manipulating them, including: 

  • I cannot select the location where they are stored - they always get placed in the default GDB even though I am trying to put them "in_memory";
  • I cannot name them something meaningful - They always are named ServiceArea1, Service Area2; and 
  • I cannot delete the final layer using python (arcpy.Delete_management) once I am done with it - so every time I rerun the syntax it adds a new file with the wrong name (e.g., ServiceArea2) and my tool crashes. 

Anyone have any suggestion on how to fix this and make it work correctly? I want to be able to create it in a specified location, name it something that is meaningful and then delete the file when it is done.

Thanks!

Andrew

Reply
0 Kudos
1 Solution

Accepted Solutions
Highlighted
Esri Regular Contributor

Hi Andrew.  Your script works fine with the addition of this line:

ServArea.defaultImpedanceCutoffs = [1]

Seems like you shouldn't need this because all your facilities have explicitly-set break values in the Breaks field, but for some reason it's getting confused.  I'll log a bug on our end to address this item of confusion, but I think if you add this to your code in the part where you're setting the service area properties, you should be good to go.

View solution in original post

Reply
0 Kudos
13 Replies
Highlighted
MVP Esteemed Contributor

If you are using ArcGIS Pro 2.4, there is a new arcpy network analysis module

What is the Network Analyst module (arcpy.na)—Network Analyst module | ArcGIS Desktop 

The differences between the *.na and *.nax module are briefly discussed here

Choosing between the modules (arcpy.na and arcpy.nax)—Network Analyst module | ArcGIS Desktop 

Migration differences, here

Migrating arcpy.na to ArcGIS Pro—Network Analyst module | ArcGIS Desktop 

And of course the one you aren't going to like

Write geoprocessing output to memory—ArcGIS Pro | ArcGIS Desktop 

But I can't remember if this was the same for pre-2.4

Memory-based workspaces do not support geodatabase elements such as feature datasets, subtypes, domains, representations, topologies, geometric networks, or network datasets.

So file geodatabases are a need.

Highlighted
New Contributor II

Hi Dan.

Thanks so much for sharing and I think I figured out most of the conversion to the arcpy.nax module. I was wondering if you can point me to anything that can provide a list of fields for the fieldmapping associated with service area facilities? 

My original code added locations as follows and note that I assigned "Breaks_Meters" to the variable cutoff:

arcpy.na.AddLocations(layer_object, facilities_layer_name, facilities, "Name CentreID #;CurbApproach # 0;Attr_Minutes # 0;Attr_Meters # 1;Breaks_Minutes # #;Breaks_Meters cutoff 1", "5000 Meters", None, "RoadsNetwork SHAPE;NetworkDataSet_Junctions NONE", "MATCH_TO_CLOSEST", "APPEND", "NO_SNAP", "5 Meters", "EXCLUDE", "RoadsNetwork #;NetworkDataSet_Junctions #")

When I tried to use a similar code below I get an error message: File "<string>", line 12, in <module> KeyError: 'Breaks_Meters'

arcpy.nax.MakeNetworkDatasetLayer(nds, nd_service_area)
ServArea = arcpy.nax.ServiceArea(nd_service_area)

ServArea.distanceUnits = arcpy.nax.DistanceUnits.Meters
ServArea.travelMode = travel_mode
ServArea.outputType = arcpy.nax.ServiceAreaOutputType.Polygons
ServArea.geometryAtOverlap = arcpy.nax.ServiceAreaOverlapGeometry.Overlap


# MAP FIELDS FOR FACILITIES
fm_sa = ServArea.fieldMappings(arcpy.nax.ServiceAreaInputDataType.Facilities, True)
fm_sa["Name"].mappedFieldName = "CentreID"
fm_sa["Breaks_Meters"].mappedFieldName = "cutoff"

ServArea.load(arcpy.nax.ServiceAreaInputDataType.Facilities, Scratch + r"\fac_p", fm_sa)


result_sa = ServArea.solve()

result_sa.export(arcpy.nax.ServiceAreaOutputDataType.Polygons, gdb + "\FinalAnalysis\SrvArea_Final")

Reply
0 Kudos
Highlighted
MVP Esteemed Contributor

Network Analyst‌ shared to there to see if some of the experts can follow up

Reply
0 Kudos
Highlighted
New Contributor II

Hey Network AnalystPython‌ experts. Does anyone have any suggestions for me to accomplish this? I am using NAX.

Thanks!

Reply
0 Kudos
Highlighted
Esri Regular Contributor

Hi Andrew.  Glad you're putting nax to good use.

Documentation for the Service Area input fields is here: https://pro.arcgis.com/en/pro-app/arcpy/network-analyst/servicearea-input-data-types.htm

Reply
0 Kudos
Highlighted
New Contributor II

Just to confirm. If I want to assign dynamic buffer sizes, I need to assign

the field name to breaks? Or do I need to cursor through each row of

facilities and place the actual value in the breaks field?

Just want to make sure I understand the process correctly.

Andrew

Reply
0 Kudos
Highlighted
Esri Regular Contributor

When you use the load() method to load your input features into Facilities, use field mapping to assign your breaks field to the Breaks field in Facilities.

Alternatively, if you are loading facilities using an insert cursor, you just need to set the desired values directly into the Breaks field.

load() and insert cursor are just two ways of accomplishing the same thing - inserting facilities.

Reply
0 Kudos
Highlighted
New Contributor II

This makes perfect sense to me Melinda Morang‌. I am still getting an error for some reason. 

'''python

import arcpy
from arcpy import env
import os, datetime
import numpy as np
import math

arcpy.CheckOutExtension("network")


path = r"C:\afclark82\ChildCare_Final"
gdb = r"C:\afclark82\ChildCare_Final\ChildCare_Final.gdb"
nds = gdb + r"\Network\NetworkDataSet"
facilities = gdb + r"\Locations\ChildCareLocations"
incidents = gdb + r"\Locations\ChildHomeLocations"
nd_close_fac = "ShortRoute"
nd_service_area = "ServiceArea"
Scratch = r"C:\afclark82\ChildCare_Final\Scratch.gdb"
shortPath = Scratch + r"\ShortestPaths"
serviceAreas = Scratch + r"\ServiceAreas"
travel_mode = "Driving"

if arcpy.Exists(shortPath)==False:
   arcpy.CreateFeatureDataset_management(path+ r"\Scratch.gdb", "ShortestPaths")

if arcpy.Exists(Scratch + r"\ServiceAreas")==False:
   arcpy.CreateFeatureDataset_management(Scratch,"ServiceAreas")

########################################
### CALCULATE SERVICE AREAS FOR MAPS ###
########################################
if len(arcpy.ListFields(facilities,"cutoff"))==0:
   arcpy.AddField_management(facilities, "cutoff", "TEXT")

   arcpy.management.CalculateField(facilities, "Per50", "np.around(!Per50!,2)", "PYTHON3", "import numpy as np")
   arcpy.management.CalculateField(facilities, "Per62", "np.around(!Per62!,2)", "PYTHON3", "import numpy as np")
   arcpy.management.CalculateField(facilities, "Per75", "np.around(!Per75!,2)", "PYTHON3", "import numpy as np")

   arcpy.management.CalculateField(facilities, "cutoff", '"{} {} {}".format(!Per50!,!Per62!,!Per75!)', "PYTHON3", None)

   print("Create a new service area")

#############################
## INITIALIZE THE ANALYSIS ###
##############################

arcpy.nax.MakeNetworkDatasetLayer(nds, nd_service_area)
ServArea = arcpy.nax.ServiceArea(nd_service_area)

#####################
## SET PROPERTIES ###
#####################

ServArea.distanceUnits = arcpy.nax.DistanceUnits.Kilometers
ServArea.travelMode = travel_mode
ServArea.outputType = arcpy.nax.ServiceAreaOutputType.Polygons
ServArea.geometryAtOverlap = arcpy.nax.ServiceAreaOverlapGeometry.Overlap

######################
## LOAD THE INPUTS ###
######################

# MAP FIELDS FOR FACILITIES
fm_sa = ServArea.fieldMappings(arcpy.nax.ServiceAreaInputDataType.Facilities, True)
fm_sa["Name"].mappedFieldName = "CentreID"
fm_sa["Breaks"].mappedFieldName = "cutoff"

whereclause = "cutoff <> 'None None None'"
fac = arcpy.SelectLayerByAttribute_management(facilities,"NEW_SELECTION", whereclause)
arcpy.CopyFeatures_management(fac, Scratch + r"\fac_p")

ServArea.load(arcpy.nax.ServiceAreaInputDataType.Facilities, Scratch + r"\fac_p", fm_sa)

#########################
## SOLVE THE ANALYSIS ###
#########################
result_sa = ServArea.solve()

result_sa.export(arcpy.nax.ServiceAreaOutputDataType.Facilities,gdb + "\FinalAnalysis\SrvArea_Facil")

# Export the results to a feature class
if result_sa.solveSucceeded:
   result_sa.export(arcpy.nax.ServiceAreaOutputDataType.Polygons,gdb + "\FinalAnalysis\SrvArea_Final")
else:
   arcpy.AddMessage("Solved failed")
   arcpy.AddMessage(result_sa.solverMessages(arcpy.nax.MessageSeverity.All))

'''

Reply
0 Kudos
Highlighted
New Contributor II

Here is the error: 

Running script Service ARea Testing...
Solved failed
[[30194, 'Data values longer than 128 characters for field [Facilities:Breaks_Meters] are truncated.'], [30024, 'Solve returned a failure.'], [-2147200977, 'Invalid break values.']]
Completed script Service ARea Testing...

The issue is that there are no long fields as I truncated the values to 2 decimal places. The longest current format is 14 characters long. So something weird is going on.

Reply
0 Kudos