Is it possible to multi-thread the following python script?
Background:
The script loops through a 3D point grid and assigns soil classification values to the points based on the presence of a list of soil-type raster datasets.
I have tried implementing pathos.multiprocessing, multiprocessing and concurrent.futures, but have failed due to limited knowledge of their capabilities.
Given that the point grid will eventually contain 1 million points, and the non-threaded tool runs at about 10 points per second, I would think there must be an efficient way to break up the point dataset into chunks based on a user defined number of cpu cores and have the function work on each chunk in parrallel and then rebuild the point datasets at the end?
import arcpy
# Parameters
point_fc = arcpy.GetParameterAsText(0) # Input point feature class
raster_list = arcpy.GetParameterAsText(1).split(";") # Semi-colon separated list of rasters
unit_field = "Unit"
# Ensure the 'Unit' field exists
if unit_field not in [field.name for field in arcpy.ListFields(point_fc)]:
arcpy.AddField_management(point_fc, unit_field, "TEXT", field_length=50)
# Initialize classification counter
classified_count = 0
# Start editing session
with arcpy.da.UpdateCursor(point_fc, ["SHAPE@X", "SHAPE@Y", "SHAPE@Z", unit_field]) as cursor:
for row in cursor:
point_x = row[0]
point_y = row[1]
point_z = row[2]
assigned_unit = "NoData"
# Check each raster to find the first one below the point
for raster_path in raster_list:
raster_name = arcpy.Describe(raster_path).name
try:
# Get the raster cell value at the (X, Y) location
raster_value = arcpy.GetCellValue_management(raster_path, f"{point_x} {point_y}")
raster_value = raster_value.getOutput(0)
# Skip if the raster value is 'NoData'
if raster_value == "NoData":
continue
# Convert to float and compare with point Z
raster_value = float(raster_value)
if point_z > raster_value:
assigned_unit = raster_name
classified_count += 1 # Increment counter for a valid classification
arcpy.AddMessage(f"Point classified as {assigned_unit} (Total classified: {classified_count})")
break # Stop at the first valid raster below the point
except Exception as e:
arcpy.AddMessage(f"Skipping raster {raster_name}: {e}")
# Update the Unit field
row[3] = assigned_unit
cursor.updateRow(row)
# Final message with total classified points
arcpy.AddMessage(f"Soil unit assignment complete. Total points classified: {classified_count}")