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
Solved! Go to Solution.
For those curious, it was the dictionary causing the issue. I was updating the dictionary, not the parameters themselves.
For those curious, it was the dictionary causing the issue. I was updating the dictionary, not the parameters themselves.