I am trying to build a script tool for my job that takes any vector feature (roads, rails, land cover, water polygons etc) and clips it to selected geocells. The geocells are one feature with a field (ID) that displays the name of each geocell. I have used the blog post here:
https://www.arcgis.com/home/item.html?id=91501d56a92e4534a16054554ac9f6d1
to allow users of the tool to be able to select one or more geocells of their choosing to perform the clip. I want the tool built this way so that essentially any boundary type polygon can be used as the clipping feature where you can select portions of the boundary polygon based on a field value.
Here is my code:
# Import libraries and set environments
import os
import arcpy
from arcpy import env
from arcpy.sa import *
from arcpy.ddd import *
env.overwriteOutput = True
# Set the parameters
InputBoundary = arcpy.GetParameterAsText(0)
InputField = arcpy.GetParameterAsText(1)
InputValue = arcpy.GetParameterAsText(2)
selection = arcpy.SetParameter(3, InputValue)
InputFeature = arcpy.GetParameterAsText(4)
Output = arcpy.GetParameterAsText(5)
# Perform the Clip
arcpy.PairwiseClip_analysis(InputFeature, selection, Output)
As written the tool will fail and say that I am not honoring all of the parameters of the clip analysis. That has to to with having "selection" as the clip feature. If I change "selection" to be "InputBoundary" the tool will work but instead of honoring the selection of individual geocells, the tool is clipping the features to the full extent of all geocells
The GUI of my tool looks like how I want it to and lets me select individual geocells:
As described in the link above, I am trying to expand upon the example tool to create a MULTIVALUE parameter choice list from an input feature class/table automatically.
In ArcGIS Pro, that example tool's parameters and code look like this:
I have attempted to expand upon that example tool's setup like this:
I just want to be able to input a boundary polygon, select certain parts of that polygon, and use that selection to clip out portions of another feature.
-
1Do you really have 6 parameters? I only see 5. If I understand correctly, 'selection' isn't a parameter but rather should be defined as a feature layer of parameter(0) with a query where the field parameter(1) includes the values of parameter(2).Brennan– Brennan2022年08月10日 16:00:22 +00:00Commented Aug 10, 2022 at 16:00
-
@Brennan Yes, I have edited my question to include screenshots of what the parameters look like for the example tool I am attempting to expand from and what the parameters are of my current tool attempt. The example tool uses this script as a part in a larger model builder setup so in the mean time I am going to do the same and see if that provides a solution, however, I would like the whole tool to just run in pythonFerenczi– Ferenczi2022年08月11日 14:47:14 +00:00Commented Aug 11, 2022 at 14:47
1 Answer 1
Save this code as a Python Toolbox (ExtractFeatures.pyt). It should provide the functionality you are describing, and you can re-purpose as needed to work within your model.
# -*- coding: utf-8 -*-
import arcpy
class Toolbox(object):
def __init__(self):
"""Define the toolbox (the name of the toolbox is the name of the
.pyt file)."""
self.label = "Extract Features"
self.alias = "pytbx"
# List of tool classes associated with this toolbox
self.tools = [extractor]
class extractor(object):
def __init__(self):
self.label = "Feature Extraction Tool"
self.description = "Performs a clip based on selected values"
self.canRunInBackground = False
def getParameterInfo(self):
InputBoundary = arcpy.Parameter( #0
displayName="Input Boundary Features",
name="InputBoundary",
datatype="GPFeatureLayer",
parameterType="Required",
direction="Input")
InputBoundary.filter.list = ["Polygon"]
InputField = arcpy.Parameter( #1
displayName="Input Field",
name="InputField",
datatype="GPString",
parameterType="Required",
direction="Input")
Values = arcpy.Parameter( #2
displayName = "Select Values in Field",
name = "Values",
datatype="GPString",
parameterType="Required",
direction = "Input",
multiValue = True)
InputFeatures = arcpy.Parameter( #3
displayName="Input Features to Clip",
name="InputFeatures",
datatype="GPFeatureLayer",
parameterType="Required",
direction="Input")
Output = arcpy.Parameter( #4
displayName="Output Feature Class",
name="Output",
datatype="DEFeatureClass",
parameterType="Required",
direction="Output")
parameters = [InputBoundary,InputField,Values,InputFeatures,Output]
return parameters
def updateParameters(self, parameters):
#if InputBoundary is defined/changed, clear subsequent values and populate InputField list
if parameters[0].value and not parameters[0].hasBeenValidated:
parameters[1].value = ''
parameters[1].filter.list = [f.name for f in arcpy.ListFields(parameters[0].value) if f.type not in ['Blob','Geometry']]
parameters[2].value = None
parameters[2].filter.list = []
#if InputField is defined/changed, clear and populate Values list
if parameters[1].value and not parameters[1].hasBeenValidated:
parameters[2].value = None
parameters[2].filter.list = list(set(str(row[0]) for row in arcpy.da.SearchCursor(parameters[0].valueAsText, parameters[1].valueAsText)))
return
def execute(self, parameters, messages):
InputBoundary = parameters[0].valueAsText
InputField = parameters[1].valueAsText
Values = parameters[2].values
InputFeatures = parameters[3].valueAsText
Output = parameters[4].valueAsText
#Define the selection query based on if InputField is numeric or string
InType = arcpy.ListFields(InputBoundary,InputField)[0].type
if InType.lower() in ('string','guid','globalid'):
query = InputField+" IN ({:s})".format(','.join(f"'{x}'" for x in Values))
else:
query = InputField+" IN ({:s})".format(','.join(f"{x}" for x in Values))
#select by attribute and clip
arcpy.management.SelectLayerByAttribute(InputBoundary, 'NEW_SELECTION', query)
arcpy.analysis.Clip(InputFeatures, InputBoundary, Output)
return
Explore related questions
See similar questions with these tags.