Melinda,
Thank you! This is exactly what I needed. Now I can get the routes' total miles and total minutes into variables and write to an output file. Whoot!
John
layer1 = "MyRouteLayer" #an open in-memory layer
for row in arcpy.da.SearchCursor(layer1 + "\\Routes", ["Total_Minutes", "Total_Miles"]): travel_minutes = row[0] travel_miles = row[1]
print travel_miles
First, I encourage you to use arcpy.da.SearchCursor instead of the old arcpy.SearchCursor, which is deprecated and slow.
SearchCursor—Help | Documentation
With arcpy.da.SearchCursor, you specify explicitly which fields you want to retrieve from the data.
<SPAN class="keyword token">for</SPAN> row <SPAN class="keyword token">in</SPAN> arcpy<SPAN class="punctuation token">.</SPAN>da<SPAN class="punctuation token">.</SPAN>SearchCursor<SPAN class="punctuation token">(</SPAN><SPAN class="operator token"><</SPAN>your layer<SPAN class="operator token">></SPAN><SPAN class="punctuation token">,</SPAN> <SPAN class="punctuation token">[</SPAN>python list of field names<SPAN class="punctuation token">]</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">:</SPAN> <SPAN class="keyword token">print</SPAN><SPAN class="punctuation token">(</SPAN>row<SPAN class="punctuation token">)</SPAN><SPAN class="line-numbers-rows"><SPAN></SPAN><SPAN></SPAN></SPAN>
The field name to retrieve depends on your network dataset and the output you care about. In the example script you're looking at, I guess the impedance attribute being used for the analysis was called "TravelTime", so the output field in the output routes sublayer was "Total_TravelTime". Basically you need to retrieve a field called "Total_[name of impedance attribute]".
Let's say you solved using an impedance attribute called TravelTime. Then do this:
<SPAN class="keyword token">for</SPAN> row <SPAN class="keyword token">in</SPAN> arcpy<SPAN class="punctuation token">.</SPAN>da<SPAN class="punctuation token">.</SPAN>SearchCursor<SPAN class="punctuation token">(</SPAN><SPAN class="operator token"><</SPAN>your layer<SPAN class="operator token">></SPAN><SPAN class="punctuation token">,</SPAN> <SPAN class="punctuation token">[</SPAN><SPAN class="string token">"Total_TravelTime"</SPAN><SPAN class="punctuation token">]</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">:</SPAN> <SPAN class="keyword token">print</SPAN><SPAN class="punctuation token">(</SPAN>row<SPAN class="punctuation token">[</SPAN><SPAN class="number token">0</SPAN><SPAN class="punctuation token">]</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="line-numbers-rows"><SPAN></SPAN><SPAN></SPAN></SPAN>
Let's say you additionally accumulated a field called "Miles". Then you can also do this:
<SPAN class="keyword token">for</SPAN> row <SPAN class="keyword token">in</SPAN> arcpy<SPAN class="punctuation token">.</SPAN>da<SPAN class="punctuation token">.</SPAN>SearchCursor<SPAN class="punctuation token">(</SPAN><SPAN class="operator token"><</SPAN>your layer<SPAN class="operator token">></SPAN><SPAN class="punctuation token">,</SPAN> <SPAN class="punctuation token">[</SPAN><SPAN class="string token">"Total_TravelTime"</SPAN><SPAN class="punctuation token">,</SPAN> <SPAN class="string token">"Total_Miles"</SPAN><SPAN class="punctuation token">]</SPAN><SPAN class="punctuation token">)</SPAN><SPAN class="punctuation token">:</SPAN> travel_time <SPAN class="operator token">=</SPAN> row<SPAN class="punctuation token">[</SPAN><SPAN class="number token">0</SPAN><SPAN class="punctuation token">]</SPAN> travel_distance <SPAN class="operator token">=</SPAN> row<SPAN class="punctuation token">[</SPAN><SPAN class="number token">1</SPAN><SPAN class="punctuation token">]</SPAN><SPAN class="line-numbers-rows"><SPAN></SPAN><SPAN></SPAN><SPAN></SPAN></SPAN>
An explanation of all input and output fields for a Route analysis is here: Route analysis—Help | Documentation
I could use some help on the python above. I am being asked to run 2000 routes from an input file and record info about each trip. The above appears to be exactly what I need....but.....the script fails around:
rows = arcpy.SearchCursor(lyrName + "\\Routes")
I think this occurs this "lyrName" is actually set at "layer1" further up in the script. But when I make such an adjustment it still fails. Seems the field "row.Total_TravelTime" does not exists in the array.
BTW, when I step through this script, I can load stops and solve the route. I just can't figure out how to get the results back out so I can write out.
Any help offered to get this to work, and run a batch of routes would be greatly appreciated!
Thanks.
ArcGIS 10.6.1
I'm hoping someone could modify the code so this could be used as a stand-alone script. Currently it relies on a route layer being in an ArcMap session. I'd appreciate any advice. Thanks in advance.
Hi Jay,
Thanks for you replies.
I tried to get the distances for 36 shipping routes (36 origin ports and 36 destinations), I get a reasonable map, but only get one route solved, from port 1 to port 72. Do you know why?
Also, can CF or OD matrix do the same thing for every port pair? instead of the closest one/all the combinations between those ports, but to the designated port within each port pair?
Best,
Zhaojun
Hi Jay
Thank you for the response.
I'm actually looking for a combination of the OD Cost Matrix and Closest Facility solvers. The OD Cost Matrix gives me everything I need except the actual routes. The resulting attribute table is perfect and if I could get the actual routes then I would be a very happy man.
I have tried the Closest Facility solver as well but experienced the same problem as with the python code in my original post (i.e. no routes were generated, just points). I suspect this is because the origins and destinations are the same points and are all located on the same layer. I could go through the process of moving each of the points onto a new layer and then solving the routes between a single origin on one layer and multiple destinations on another but this is extremely time consuming, especially if there are lots of points.
Is there any way to use the OD Cost Matrix coding but to change to the output shape from a STRAIGHT_LINE to a TRUE_LINE_WITH_MEASURES?
Regards,
Mike
What are you trying to achieve? Are you trying to get a distance matrix for all points that you have? In that case the route solver is the wrong approach. It will only solve the routes for stop pairs loaded with the same ROUTENAME property, which I think in your case is stop A to stop A and then then Stop B to Stop B, etc. It is not going to solve Stop A to Stop B, unless you load that pair as well. So if you want all pairs, use the OD Cost Matrix and load your locations as origins and destinations and solve. It will solve and give you a complete matrix of travel times. But it only computes a straight line route shape (for speed). And in case you need the actual route geometry of the shortest paths, then use the Closest Facility solver.
Jay Sandhu
Hi Anna
I'm hoping you can help. I am new to python coding and have tried to create a script to solve and display multiple routes between OD pairs simultaneously. In my particular case the origins are also the destinations. The script used is as shown below.
# Name: MakeRouteLayer_MultiRouteWorkflow.py# Description: Calculate the home-work commutes for cyclists and save# the output to a feature class# Requirements: Network Analyst Extension
#Import system modulesimport arcpyfrom arcpy import env
try: #Check out the Network Analyst extension license arcpy.CheckOutExtension("Network")
#Set environment settings env.overwriteOutput = True
#Set local variables inNetworkDataset = "C:/Users/michael.vorster/Google Drive/Masters/Thesis/Model Info/NMBM Roads/5km Zone/roads_in_5km_classification/Commuter_Perspective_ND.nd" inStops_Home = "C:/Users/michael.vorster/Google Drive/Masters/Thesis/Model Info/Cadastral/ArcGIS/Allotment Centroids/Allotment_Centroids.shp" inStops_Work = "C:/Users/michael.vorster/Google Drive/Masters/Thesis/Model Info/Cadastral/ArcGIS/Allotment Centroids/Allotment_Centroids.shp" outNALayerName = "CycleRoutes" outRoutesFC = "C:/Users/michael.vorster/Google Drive/Masters/Thesis/Model Info/Route Data/outRoutes" impedanceAttribute = "Commuter"
#Create a new Route layer. Optimize on Commuter, but compute the #distance travelled by accumulating the Length attribute. outRouteResultObject = arcpy.na.MakeRouteLayer(inNetworkDataset, outNALayerName, impedanceAttribute, "FIND_BEST_ORDER", "PRESERVE_BOTH", "", ["Commuter", "Length"], "NO_UTURNS", "", "NO_HIERARCHY", "", "TRUE_LINES_WITH_MEASURES","")
#Get the layer object from the result object. The route layer can now be #referenced using the layer object. outNALayer = outRouteResultObject.getOutput(0)
#Get the names of all the sublayers within the route layer. subLayerNames = arcpy.na.GetNAClassNames(outNALayer) #Store the layer names that we will use later stopsLayerName = subLayerNames["Stops"] routesLayerName = subLayerNames["Routes"]
#Before loading the commuters' home and work locations as route stops, set #up field mapping. Map the "ALLOTMENT" field from the input data to #the RouteName property in the Stops sublayer, which ensures that each #unique ALLOTMENT will be placed in a separate route. Matching #ALLOTMENT from inStops_Home and inStops_Work will end up in the same #route. fieldMappings = arcpy.na.NAClassFieldMappings(outNALayer, stopsLayerName) fieldMappings["RouteName"].mappedFieldName = "ALLOTMENT"
#Add the commuters' home and work locations as Stops. The same field mapping #works for both input feature classes because they both have a field called #"ALLOTMENT" arcpy.na.AddLocations(outNALayer, stopsLayerName, inStops_Home, fieldMappings, "300 meters", "FID", [["Commuter_Perspective_ND", "SHAPE"], ["Commuter_Perspective_ND_Junctions", "NONE"]], "", "", "SNAP", "", "", "") arcpy.na.AddLocations(outNALayer, stopsLayerName, inStops_Work, fieldMappings, "300 meters", "FID", [["Commuter_Perspective_ND", "SHAPE"], ["Commuter_Perspective_ND_Junctions", "NONE"]], "", "", "SNAP", "", "", "")
#Solve the route layer. arcpy.na.Solve(outNALayer)
# Get the output Routes sublayer and save it to a feature class RoutesSubLayer = arcpy.mapping.ListLayers(outNALayer, routesLayerName)[0] arcpy.management.CopyFeatures(RoutesSubLayer, outRoutesFC)
print "Script completed successfully"
except Exception as e: # If an error occurred, print line number and error message import traceback, sys tb = sys.exc_info()[2] print "An error occured on line %i" % tb.tb_lineno print str(e)
The script runs through the python window and the route layer is created. The stops are added to the map but there are no routes displayed. There is also no route information in the attribute table. I suspect this has to do with the fact that the origins and destinations are the same points. I understand that the route info from point "A" to point "A" is zero (0) but there should be info for "A to B" and "A to C", "A to D"....etc.
Any help with the above would be greatly appreciated.
Thanks,
Hi,You can throw an exception when no solution is found: try: arcpy.Solve_na(layer1) except (RuntimeError): print "No solution is found for " + str(layer1) Thanks.Anna
try: arcpy.Solve_na(layer1) except (RuntimeError): print "No solution is found for " + str(layer1)
import arcpy, os, sys arcpy.env.overwriteOutput = True try: costDic1 = {} f = open(r"C:\temp\OriginDestinations.txt", 'r+') layer1 = "MyRouteLayer" #an open in-memory layer for line in f: twoPs = line.split(",") # if the line contains number if twoPs[0].isdigit(): OPoint = arcpy.Point() DPoint = arcpy.Point() pointGeometryList = [] OPoint.X = twoPs[1] OPoint.Y = twoPs[2] DPoint.X = twoPs[3] DPoint.Y = twoPs[4] pointGeometry = arcpy.PointGeometry(OPoint) pointGeometryList.append(pointGeometry) pointGeometry = arcpy.PointGeometry(DPoint) pointGeometryList.append(pointGeometry) myPoints = "Mypoints" arcpy.CopyFeatures_management(pointGeometryList, myPoints) arcpy.na.AddLocations(layer1,"Stops",myPoints) arcpy.Solve_na(layer1) # get the cost info from the layer rows = arcpy.SearchCursor(lyrName + "\\Routes") for row in rows: costDic1[twoPs[0]] = row.Total_TravelTime # delete stops and route from the layer arcpy.DeleteRows_management(lyrName + "\\Stops") arcpy.DeleteRows_management(lyrName + "\\Routes") f.close # Output the result to a txt file fOut = open(r"C:\temp\Out.txt", 'w') for costKey in costDic1.keys(): line = str(costKey) + "," + str(costDic1[costKey]) fOut.writelines(line) fOut.close except: print "Exception"
Les membres connectés peuvent publier, suivre les mises à jour, et plus encore. Nouveau ici ? Inscrivez-vous gratuitement.
Find useful guides, FAQs, and documents to help you navigate and make the most of Esri Community.