# Name: MakeODCostMatrixLayer_Workflow2.py
# Description: Find the travel time to the closest hospital from each census
# tract and join the travel time and hospital name to the input
# tracts.
# Requirements: Network Analyst Extension
#Import system modules
import arcpy
from arcpy import env
import datetime
import os
try:
#Set environment settings
output_dir = "C:/Data"
#The NA layer's data will be saved to the workspace specified here
env.workspace = os.path.join(output_dir, "Output.gdb")
env.overwriteOutput = True
#Set inputs and outputs
input_gdb = "C:/Data/SanFrancisco.gdb"
network = os.path.join(input_gdb, "Transportation", "Streets_ND")
origins = os.path.join(input_gdb, "Analysis", "TractCentroids")
destinations = os.path.join(input_gdb, "Analysis", "Hospitals")
output_features = "TractCentroids_withOD"
#Define some OD cost matrix analysis settings
layer_name = "HospitalsOD"
#Optimize based on travel time
impedance = "TravelTime"
#Calculate the total distance, even though the analysis is optimizing time
accumulate_attributes = ["Meters"]
#Find only the closest hospital
num_hospitals_to_find = 1
#Set the time of day for the analysis to 6PM on a generic Monday.
start_time = datetime.datetime(1900, 1, 1, 18, 0, 0)
#Don't output line shapes (output Lines will still list travel times)
out_lines = "NO_LINES"
#Create a new OD cost matrix layer.
result_object = arcpy.na.MakeODCostMatrixLayer(network, layer_name,
impedance,
default_number_destinations_to_find=num_hospitals_to_find,
accumulate_attribute_name=accumulate_attributes,
output_path_shape=out_lines, time_of_day=start_time)
#Get the layer object from the result object. The OD layer can
#now be referenced using the layer object.
layer_object = result_object.getOutput(0)
#Get the names of all the sublayers within the OD layer.
sublayer_names = arcpy.na.GetNAClassNames(layer_object)
#Store the layer names for later use
origins_layer_name = sublayer_names["Origins"]
destinations_layer_name = sublayer_names["Destinations"]
#The input census tract data has a unique ID field that can be transferred
#to the analysis layer. Add the field, and then use field mapping to
#transfer the values.
arcpy.na.AddFieldToAnalysisLayer(layer_object, origins_layer_name,
"Tract_ID", "TEXT")
field_mappings = arcpy.na.NAClassFieldMappings(layer_object,
origins_layer_name)
field_mappings["Tract_ID"].mappedFieldName = "ID"
#Load the census tracts as origins.
arcpy.na.AddLocations(layer_object, origins_layer_name, origins,
field_mappings, "",
exclude_restricted_elements = "EXCLUDE")
#Map the input hospital NAME field to a new Hospital_Name field in
#Destinations
arcpy.na.AddFieldToAnalysisLayer(layer_object, destinations_layer_name,
"Hospital_Name", "TEXT")
field_mappings = arcpy.na.NAClassFieldMappings(layer_object,
destinations_layer_name)
field_mappings["Hospital_Name"].mappedFieldName = "NAME"
#Load the hospitals as desinations.
arcpy.na.AddLocations(layer_object, destinations_layer_name, destinations,
field_mappings, "",
exclude_restricted_elements = "EXCLUDE")
#Solve the OD layer
arcpy.na.Solve(layer_object)
#Get sublayers
#listLayers returns a list of sublayer layer objects contained in the NA
#group layer, filtered by layer name used as a wildcard. Use the sublayer
#name from GetNAClassNames as the wildcard string in case the sublayers
#have non-default names.
origins_sublayer = layer_object.listLayers(origins_layer_name)[0]
destinations_sublayer = layer_object.listLayers(destinations_layer_name)[0]
lines_sublayer = layer_object.listLayers(sublayer_names["ODLines"])[0]
#Use the JoinField tool to transfer OD Cost Matrix information to the
#output feature class
#Transfer the tract ID from the input Origins to the output Lines
arcpy.management.JoinField(lines_sublayer, "OriginID",
origins_sublayer, "ObjectID", "Tract_ID")
#Transfer the hospital name from the input Destinations to the output Lines
arcpy.management.JoinField(lines_sublayer, "DestinationID",
destinations_sublayer, "ObjectID", "Hospital_Name")
#Transfer fields of interest (hospital name, TravelTime cost, and other
#accumulated costs) from the output Lines to a copy of the input census
#tracts feature class using the Tract_ID field
output_impedance_fieldname = "Total_" + impedance
fields_to_transfer = ["Hospital_Name", output_impedance_fieldname]
for field in accumulate_attributes:
fields_to_transfer.append("Total_" + field)
arcpy.management.CopyFeatures(origins, output_features)
arcpy.management.JoinField(output_features, "ID",
lines_sublayer, "Tract_ID", fields_to_transfer)
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 occurred on line %i" % tb.tb_lineno)
print(str(e))