Select to view content in your preferred language

Python Toolbox Parameter Validation Not running

392
1
Jump to solution
10-26-2024 08:39 PM
UnsoughtNine
Occasional Contributor

I have a long and complex python tool. In brief, I can't seem to get the default values for my tool, or any parameter updates for that matter, to work through my UpdateParameters definition. UpdateMessages for whatever reason, does seem to be functional in the full script. Thanks in advance for the insight.

Partial code below.

Sample Code

"""Imports and installs"""
import arcpy, pandas as pd, datetime as dt, numpy as np, os
from collections import namedtuple
from scipy.optimize import curve_fit
# from plotnine import ggplot, aes, geom_point
# from sklearn.metrics import r2_score, mean_squared_error

temp = "in_memory" # Using in-memory workspace for temporary processing
timestamp = dt.datetime.now().strftime("%Y_%m_%d_%H_%M") # Global timestamp in the format YYYY_MM_DD_HH_MM

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

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

class xyzx:
def __init__(self):
"""Define the tool (tool name is the name of the class)."""
self.label = "xyzx"
self.description = "xyzx"
self.param_dict = {} # Initialize empty parameter dictionary
self.getParameterInfo() # Call to initialize parameters

def create_parameter(self, param_displayname, param_name, param_datatype, param_type, param_direction, param_category, param_enabled=True, param_filtertype=None, param_filterlist=None, param_columns=None, param_values=None):
"""Helper function to create parameters for ArcGIS Pro toolbox."""

param = arcpy.Parameter(
displayName=param_displayname,
name=param_name,
datatype=param_datatype,
parameterType=param_type,
direction=param_direction,
category=param_category,
enabled=param_enabled
)

if param_filtertype:
param.filter.type = param_filtertype
param.filter.list = param_filterlist
if param_columns:
param.columns = param_columns
if param_values:
param.values = param_values

return param

def getParameterInfo(self):
"""Define the tool parameters."""

params = [
self.create_parameter("Model Initialization Year", "year_init", "GPLong", "Required", "Input", "Model Initialization Terms"),
self.create_parameter("Model Horizon Year", "year_hori", "GPLong", "Required", "Input", "Model Initialization Terms"),
self.create_parameter("Formatting Run", "trig_rmod", "GPBoolean", "Required", "Input", "Model Initialization Terms"),
self.create_parameter("Model Initialization Table", "init_tbl", "DETable", "Optional", "Input", "Model Initialization Terms"),
self.create_parameter("User Control Table", "uc_tbl", "DETable", "Optional", "Input", "Model Initialization Terms"),
self.create_parameter("Output Directory", "out_dir", "DEWorkspace", "Required", "Output", "Model Initialization Terms"),
]

# Create a dictionary for easy access
self.param_dict = {param.name: param for param in params}

return params

def isLicensed(self):
"""Set whether the 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."""

"""Set default values."""
default_values = {
'year_init': dt.date.today().year + 1,
'year_hori': dt.date.today().year + 41,
}

for param, default in default_values.items():
if self.param_dict[param].value is None:
self.param_dict[param].value = default

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 dir_setup(self, output_directory):
"""Setup the runtime directory in the specified location."""
print("Creating runtime directory...")

root_path = f"{output_directory}/xyzx_Run_{timestamp}"
plot_path = f"{root_path}/summary_plots"
gdb_path = f"{root_path}/xyzx_Run_{timestamp}"

try:
print("Creating runtime folders...")

os.makedirs(root_path, exist_ok=False) # create runtime root directory
os.makedirs(plot_path, exist_ok=False) # create runtime plot directory

print("Creating runtime geodatabase...")
arcpy.CreateFileGDB_management(*os.path.split(output_directory))

print(f"Runtime saved to: {root_path}")
except Exception as e:
print(f"Failed to create runtime directory: {e}")

return root_path, plot_path, gdb_path

def init_tbl(self, root_path):
"""Create the runtime initialization settings table."""
print("Creating a runtime initialization file...")

# Extract parameter names and values from param_dict
mi_data = [(name, param.value) for name, param in self.param_dict.items()]
mi_df = pd.DataFrame(mi_data, columns=['Parameter', 'Value'])

# Create an init filepath
filename = f"UrCGM_InitFile_{timestamp}.csv"
init_path = os.path.join(root_path, filename)

# Save the DataFrame to CSV
try:
mi_df.to_csv(init_path, sep='\t', encoding='utf-8', index=False)
print(f"Model initialization file saved to: {init_path}.")
except Exception as e:
print(f"Failed to save model initialization file: {e}")

return init_path

def uc_tbl(self, root_path):
"""Check if uct is provided; create the uct if not."""

# Access the 'uct' parameter from param_dict
uct_param = self.param_dict.get("uct")

if not uct_param or not uct_param.value:
print("User control table not provided. Creating the table...")

# Extract parameter names and values
uct_data = [(name, param.value) for name, param in self.param_dict.items()]
uct_df = pd.DataFrame(uct_data, columns=['Parameter', 'Value'])

# Create the uct file path
filename = "UrCGM_UCT.csv"
uct_path = os.path.join(root_path, filename)

try:
uct_df.to_csv(uct_path, sep='\t', encoding='utf-8', index=False)
print(f"User control table saved to: {uct_path}.")
except Exception as e:
print(f"Failed to save user control table: {e}")

else:
print(f"User control table provided: {uct_param.value}")

return uct_param.value if uct_param else None # Return the uct path


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

try:
# User-specified output directory
output_directory = next(p for p in parameters if p.name == "out_dir").valueAsText

# Call the dir_setup function with user output directory
root_path, plot_path, gdb_path = self.dir_setup(output_directory)

# Call the init_tbl function to create the initialization table
init_path = self.init_tbl(parameters, root_path)

# Call the uc_tbl function to create the initialization table
uct_path = self.uc_tbl(parameters, root_path)

# Only run the model where it is not a formatting run
if self.param_dict['trig_rmod'].value == 0:
None

except Exception as e:
print(f"An error occurred during execution: {e}")

return

def postExecute(self, parameters):
"""This method takes place after outputs are processed and
added to the display."""

return

0 Kudos
1 Solution

Accepted Solutions
UnsoughtNine
Occasional Contributor

For those curious, it was the dictionary causing the issue. I was updating the dictionary, not the parameters themselves.

View solution in original post

0 Kudos
1 Reply
UnsoughtNine
Occasional Contributor

For those curious, it was the dictionary causing the issue. I was updating the dictionary, not the parameters themselves.

0 Kudos