Summary
Makes an origin–destination (OD) cost matrix network analysis layer and sets its analysis properties. An OD cost matrix analysis layer is useful for representing a matrix of costs going from a set of origin locations to a set of destination locations. The layer can be created using a local network dataset or a service hosted online or in a portal.
Usage
After creating the analysis layer with this tool, you can add network analysis objects to it using the Add Locations tool, solve the analysis using the Solve tool, and save the results on disk using the Save To Layer File tool.
When using this tool in geoprocessing models, if the model is run as a tool, the output network analysis layer must be made a model parameter; otherwise, the output layer is not added to the contents of the map.
In ArcGIS Pro, network analysis layer data is stored on disk in file geodatabase feature classes. When creating a network analysis layer in a project, the layer's data will be created in a new feature dataset in the Current Workspace environment. When creating a network analysis layer in a Python script, you must first explicitly set the workspace environment to a file geodatabase where you want the layer's data to be stored using arcpy.env.workspace = "<path to file gdb>". When the layer is created, a new feature dataset containing the appropriate sublayer feature classes will be added to this file geodatabase.
Syntax
arcpy.na.MakeODCostMatrixAnalysisLayer(network_data_source, {layer_name}, {travel_mode}, {cutoff}, {number_of_destinations_to_find}, {time_of_day}, {time_zone}, {line_shape}, {accumulate_attributes})
Parameter | Explanation | Data Type |
network_data_source | The network dataset or service on which the network analysis will be performed. Use the portal URL for a service. | Network Dataset Layer;String |
layer_name (Optional) | The name of the network analysis layer to create. | String |
travel_mode (Optional) | The name of the travel mode to use in the analysis. The travel mode represents a collection of network settings, such as travel restrictions and U-turn policies, that determine how a pedestrian, car, truck, or other medium of transportation moves through the network. Travel modes are defined on your network data source. An arcpy.na.TravelMode object and a string containing the valid JSON representation of a travel mode can also be used as input to the parameter. | String |
cutoff (Optional) | The impedance value at which to stop searching for destinations for a given origin. This value will be in the units of the impedance attribute used by your chosen travel mode. No destinations beyond this limit will be found. This cutoff value can be overridden on a per-origin basis by specifying individual cutoff values in the origins sublayer. By default, no cutoff is used for the analysis. | Double |
number_of_destinations_to_find (Optional) | The number of destinations to find per origin. This default can be overridden by specifying an individual value for the TargetDestinationCount property in the origins sublayer. By default, no limit is used, and all destinations are found. | Long |
time_of_day (Optional) | Indicates the departure time from origins. If you have chosen a traffic-based impedance attribute, the solution will be generated given dynamic traffic conditions at the time of day specified here. A date and time can be specified as 5/14/2012 10:30 AM. Instead of using a particular date, a day of the week can be specified using the following dates:
| Date |
time_zone (Optional) | The time zone of the Time of Day parameter.
| String |
line_shape (Optional) |
No matter which output shape type is chosen, the best route is always determined by the network impedance, never Euclidean distance. This means that only the route shapes are different, not the underlying traversal of the network. | String |
accumulate_attributes [accumulate_attributes,...] (Optional) | A list of cost attributes to be accumulated during analysis. These accumulated attributes are for reference only; the solver only uses the cost attribute used by your designated travel mode when solving the analysis. For each cost attribute that is accumulated, a Total_[Impedance] property is populated in the network analysis output features. This parameter is not available if the network data source is an ArcGIS Online service or the network data source is a service on a version of Portal for ArcGIS that does not support accumulation. | String |
Derived Output
Name | Explanation | Data Type |
out_network_analysis_layer | The newly created network analysis layer. | Network Analyst Layer |
Code sample
Execute the tool using only the required parameters.
network = "C:/Data/Paris.gdb/Transportation/ParisMultimodal_ND"
arcpy.na.MakeODCostMatrixAnalysisLayer(network, "DrivetimeCosts")
Execute the tool using all parameters.
network = "C:/Data/Paris.gdb/Transportation/ParisMultimodal_ND"
arcpy.na.MakeODCostMatrixAnalysisLayer(network, "DrivetimeCosts",
"Driving Time", 10, 20, "1/1/1900 9:00 AM",
"UTC", "NO_LINES", ["Meters", "TravelTime"])
The following stand-alone Python script demonstrates how the MakeODCostMatrixAnalysisLayer tool can be used to create an origin-destination cost matrix for delivery of goods from the warehouses to all stores within a 10-minute drive time.
# Name: MakeODCostMatrixAnalysisLayer_Workflow.py
# Description: Create an origin-destination cost matrix for delivery of goods
# from the warehouses to all stores within a 10-minute drive time
# and save the results to a layer file on disk. Such a matrix can
# be used as an input for logistics, delivery and routing analyses.
# Requirements: Network Analyst Extension
#Import system modules
import arcpy
from arcpy import env
import os
try:
#Check out Network Analyst license if available. Fail if the Network Analyst license is not available.
if arcpy.CheckExtension("network") == "Available":
arcpy.CheckOutExtension("network")
else:
raise arcpy.ExecuteError("Network Analyst Extension license is not available.")
#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 local variables
input_gdb = "C:/Data/Paris.gdb"
network = os.path.join(input_gdb, "Transportation", "ParisMultimodal_ND")
layer_name = "WarehouseToStoreDrivetimeMatrix"
travel_mode = "Driving Time"
search_tolerance = "1000 Meters"
origins = os.path.join(input_gdb, "Analysis", "Warehouses")
destinations = os.path.join(input_gdb, "Analysis", "Stores")
output_layer_file = os.path.join(output_dir, layer_name + ".lyrx")
#Create a new OD Cost matrix layer. We wish to find all stores within a 10
#minute cutoff.
result_object = arcpy.na.MakeODCostMatrixAnalysisLayer(network, layer_name,
travel_mode, 10)
#Get the layer object from the result object. The OD cost matrix 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 cost matrix layer.
sublayer_names = arcpy.na.GetNAClassNames(layer_object)
#Stores the layer names that we will use later
origins_layer_name = sublayer_names["Origins"]
destinations_layer_name = sublayer_names["Destinations"]
#Load the warehouse locations as origins using a default field mappings and
#a search tolerance of 1000 Meters.
arcpy.na.AddLocations(layer_object, origins_layer_name, origins, "",
search_tolerance)
#Load the store locations as destinations and map the NOM field from stores
#features as Name property using field mappings
field_mappings = arcpy.na.NAClassFieldMappings(layer_object,
destinations_layer_name)
field_mappings["Name"].mappedFieldName = "NOM"
arcpy.na.AddLocations(layer_object, destinations_layer_name, destinations,
field_mappings, search_tolerance)
#Solve the OD cost matrix layer
arcpy.na.Solve(layer_object)
#Save the solved OD cost matrix layer as a layer file on disk
layer_object.saveACopy(output_layer_file)
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))
The following stand-alone Python script demonstrates how to access sublayers, join input and output layers, and transfer field values from input origins and destinations to the output Lines layer.
Legacy:
The GetNASublayer function can be used to retrieve the sublayers of a network analysis layer. It was introduced in ArcGIS Pro 2.7. In prior software versions, the best way to retrieve a sublayer object of a network analysis layer was to use the listLayers method of the network analysis Layer object using the sublayer name as a wildcard.
# Name: MakeODCostMatrixAnalysisLayer_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 datetime
import os
import arcpy
try:
# Check out Network Analyst license if available. Fail if the Network Analyst license is not available.
if arcpy.CheckExtension("network") == "Available":
arcpy.CheckOutExtension("network")
else:
raise arcpy.ExecuteError("Network Analyst Extension license is not available.")
# Set environment settings
output_dir = "C:/Data"
#The NA layer's data will be saved to the workspace specified here
arcpy.env.workspace = os.path.join(output_dir, "Output.gdb")
arcpy.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"
# User settings for driving
travel_mode = "Driving Time"
# 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.MakeODCostMatrixAnalysisLayer(network, layer_name,
travel_mode,
number_of_destinations_to_find=num_hospitals_to_find,
time_of_day=start_time, line_shape=out_lines,
accumulate_attributes=accumulate_attributes)
# 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, "")
# 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, "")
# Solve the OD layer
arcpy.na.Solve(layer_object)
# Get sublayers
origins_sublayer = arcpy.na.GetNASublayer(layer_object, "Origins")
destinations_sublayer = arcpy.na.GetNASublayer(layer_object, "Destinations")
lines_sublayer = arcpy.na.GetNASublayer(layer_object, "ODLines")
# 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, impedance attribute, and other
# accumulated costs) from the output Lines to a copy of the input census
# tracts feature class using the Tract_ID field
# Determine the impedance attribute
solver_props = arcpy.na.GetSolverProperties(layer_object)
impedance = solver_props.impedance
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))
The following stand-alone Python script demonstrates how to create a modified version of a travel mode from the network dataset and use this travel mode when creating a new OD Cost Matrix layer.
import json
network = r"C:/Data/SanFrancisco.gdb/Transportation/Streets_ND"
# Get all travel modes from the network dataset
travel_modes = arcpy.na.GetTravelModes(network)
# Get the Driving Distance travel mode
dd_travel_mode = travel_modes["Driving Distance"]
# Make a json representation of the travel mode
travel_mode_json = json.loads(str(dd_travel_mode))
# Modify the userHierarchy property to turn hierarchy off, and update the name
travel_mode_json["useHierarchy"] = False
travel_mode_json["name"] = "Driving Distance without Hierarchy"
# Create a new travel mode object from the modified json
new_travel_mode_object = arcpy.na.TravelMode(json.dumps(travel_mode_json))
# Use the new travel mode object to MakeODCostMatrixAnalysisLayer
# We could also pass in the json directly without first converting it to an object
arcpy.na.MakeODCostMatrixAnalysisLayer(network, "OD Without Hierarchy", new_travel_mode_object)
Environments
Licensing information
- Basic: Yes
- Standard: Yes
- Advanced: Yes