0

I am attempting to write a python tool that uses the create routes, locate features along routes, and make route event layer tools (in that order). Essentially this is a three step process that I want to streamline.

I have a "source script" that I have written and runs just like I want to in a python window. It creates a route, table, and event layer that are all added to the current map.

Example of the source script:

import arcpy
from arcpy import env
from arcpy.lr import*

###-------------------------------------------###
###-------------------Inputs------------------###
###-------------------------------------------###

input_line = r'C:\Example\line.shp'
input_points = r'C:\Example\points.shp'
route_ID_field = "CONT_CODE"
radius = "2 Feet"
save_location = r'C:\Example\output'

###-------------------------------------------###
###--------------Source Script----------------###
###-------------------------------------------###

arcpy.lr.CreateRoutes(
    in_line_features = input_line,
    route_id_field = route_ID_field,
    out_feature_class = save_location + "\\route_from_pov",
    measure_source="LENGTH",
    from_measure_field=None,
    to_measure_field=None,
    coordinate_priority="UPPER_LEFT",
    measure_factor=1,
    measure_offset=0,
    ignore_gaps="IGNORE",
    build_index="INDEX"
)

arcpy.lr.LocateFeaturesAlongRoutes(
    in_features = input_points,
    in_routes = save_location + "\\route_from_pov",
    route_id_field = route_ID_field,
    radius_or_tolerance = radius,
    out_table = save_location + "\\table_from_pov",
    out_event_properties="RID; POINT; FMEAS",
    route_locations="FIRST",
    distance_field="DISTANCE",
    zero_length_events="ZERO",
    in_fields="FIELDS",
    m_direction_offsetting="M_DIRECTON"
)

arcpy.lr.MakeRouteEventLayer(
    in_routes = save_location + "\\route_from_pov",
    route_id_field = route_ID_field,
    in_table = save_location + "\\table_from_pov",
    in_event_properties="RID; POINT; FMEAS",
    out_layer = save_location + "\\SP_from_pov",
    offset_field=None,
    add_error_field="NO_ERROR_FIELD",
    add_angle_field="ANGLE_FIELD",
    angle_type="NORMAL",
    complement_angle="ANGLE",
    offset_direction="LEFT",
    point_event_type="POINT"
)

However, when I modify this for use within the arcpy python tool template, the only output is the first one (route) and it does not add it to the current map. The table and route event layer are nowhere to be found.

Example script:

import arcpy
from arcpy import env
from arcpy.lr import*

class Toolbox(object):
    def __init__(self):
        """Define the toolbox (the name of the toolbox is the name of the
        .pyt file)."""
        self.label = "Toolbox"
        self.alias = "toolbox"

        # List of tool classes associated with this toolbox
        self.tools = [Create_Perpendicular_Station_Points]


class Create_Perpendicular_Station_Points(object):
    def __init__(self):
        """Define the tool (tool name is the name of the class)."""
        self.label = "Create Perpendicular Station Points"
        self.description = "Create Perpendicular Station Points"
        self.canRunInBackground = False

    def getParameterInfo(self):
        """Define parameter definitions"""
        param0 = arcpy.Parameter(
            displayName="Input Line",
            name="in_line",
            datatype="DEFeatureClass",
            parameterType="Required",
            direction="Input")
        
        param1 = arcpy.Parameter(
            displayName="Input Points",
            name="input_points",
            datatype="DEFeatureClass",
            parameterType="Required",
            direction="Input")

        param2 = arcpy.Parameter(
            displayName="Route Identifier Field",
            name="route_ID_field",
            datatype="Field",
            parameterType="Required",
            direction="Input")
                
        param3 = arcpy.Parameter(
            displayName="Search Radius",
            name="search_radius",
            datatype="GPLinearUnit",
            parameterType="Optional",
            direction="Input")

        param4 = arcpy.Parameter(
            displayName="Output Save Location",
            name="Save_Path",
            datatype="DEFolder",
            parameterType="Required",
            direction="Input") 

        params = [param0,param1,param2,param3,param4]

        return params

    def isLicensed(self):
        """Set whether tool is licensed to execute."""
        return True

    def updateParameters(self, parameters):
        """Modify the values and properties of parameters before internal
        validation is performed.  This method is called whenever a parameter
        has been changed."""
        return

    def updateMessages(self, parameters):
        """Modify the messages created by internal validation for each tool
        parameter.  This method is called after internal validation."""
        return

    def execute(self, parameters, messages):
        """The source code of the tool."""


        ###-------------------------------------------###
        ###--------------Source Script----------------###
        ###-------------------------------------------###

        arcpy.lr.CreateRoutes(
            in_line_features = parameters[0].valueAsText,
            route_id_field = parameters[2].valueAsText,
            out_feature_class = parameters[4].valueAsText + r"\route_from_pov",
            measure_source="LENGTH",
            from_measure_field=None,
            to_measure_field=None,
            coordinate_priority="UPPER_LEFT",
            measure_factor=1,
            measure_offset=0,
            ignore_gaps="IGNORE",
            build_index="INDEX"
        )

        arcpy.lr.LocateFeaturesAlongRoutes(
            in_features = parameters[1].valueAsText,
            in_routes = parameters[4].valueAsText + r"\route_from_pov.shp", # internal_route, 
            route_id_field = parameters[2].valueAsText,
            radius_or_tolerance = parameters[3].valueAsText,
            out_table = parameters[4].valueAsText + r"\table_from_pov",
            out_event_properties="RID; POINT; FMEAS",
            route_locations="FIRST",
            distance_field="DISTANCE",
            zero_length_events="ZERO",
            in_fields="FIELDS",
            m_direction_offsetting="M_DIRECTON"
        )

        arcpy.lr.MakeRouteEventLayer(
            in_routes = parameters[4].valueAsText + r"\route_from_pov", #internal_route, 
            route_id_field = parameters[2].valueAsText,
            in_table = parameters[4].valueAsText + r"\table_from_pov", #internal_table,
            in_event_properties="RID; POINT; FMEAS",
            out_layer = parameters[4].valueAsText + r"\SP_from_pov",
            offset_field=None,
            add_error_field="NO_ERROR_FIELD",
            add_angle_field="ANGLE_FIELD",
            angle_type="NORMAL",
            complement_angle="ANGLE",
            offset_direction="LEFT",
            point_event_type="POINT"
        )
        return

    def postExecute(self, parameters):
        """This method takes place after outputs are processed and
        added to the display."""
        return
5
  • 1
    From a quick read, all 3 of your tools are writing to the same index output parameter (4). You said only the route is added to the display? Well route was the last tool to run, so it took the place of the 2 outputs before it. If you want 3 outputs from 3 tools, you need to have 3 output parameters. Commented Dec 22, 2023 at 19:28
  • Well theoretically they are saving to the same folder with different names. It would be easiest for me if there were one output folder and name to specify. I will try that out. Additionally, the route output comes from the first tool, not the last. Commented Dec 22, 2023 at 20:27
  • 1
    The GP Framework and creating tools doesn't work like that. You can't dump everything to a folder and hope that everything you generated there will show up in your map because they all point to the same parameter. Looking closer, I'm surprised anything actually added to your map when the parameter is defined as a Folder. Commented Dec 22, 2023 at 20:38
  • 1
    Relying on implicit file types is a bad practice. Currently, you are passing names for feature classes and tables that are going to a folder, not a geodatabase, and I suspect some of the output isn't what you want. For example, it is better to have out_feature_class = parameters[4].valueAsText + r"\route_from_pov.shp" because it is clear the type of output you are expecting. In the case of your tables, you are actually creating ArcInfo tables in a coverage by leaving a file name extension off the table, and I doubt anyone wants to work with ArcInfo coverages today. Commented Dec 24, 2023 at 18:05
  • Are you using ArcPy with ArcGIS Pro or with ArcMap when you try to do this? Commented Jan 13, 2024 at 3:06

0

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.