Select to view content in your preferred language

Need my output layers to display in my current map display

235
1
12-20-2024 11:34 AM
HeatherDulaney1
Emerging Contributor

Hi all, I am trying to figure out a way to add my outputs to the display after my python toolbox runs. I've tried multiple ways but can't seem to get it. Do I need to add the outputs as a parameter for this to occur? How would you go about it. Here is my code below.

import arcpy
import pandas as pd
from arcpy.sa import *

class Toolbox(object):
    def __init__(self):
        
        self.label = "Mapping Trees Model"
        self.alias = "mapping trees"

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


class MappingTrees(object):
    def __init__(self):

        self.label = "Mapping Trees Model"
        self.description = "This model analyzes information from a raster with tree data such as tree height, canopy cover percent, etc. for an area of interest defined by the user. "

    def getParameterInfo(self):

        #Define the parameters
        Extent = arcpy.Parameter(
            displayName = "Define Extent",
            name = "Extent",
            datatype = "GPExtent",
            parameterType = "Required",
            direction = "Input")
            
        Identify_Workspace = arcpy.Parameter(
            displayName = "Identify Workspace",
            name = "Identify_Workspace",
            datatype = "DEWorkspace",
            parameterType = "Required",
            direction = "Input")

        Study_Area = arcpy.Parameter(
            displayName="Study Area",
            name="Study_Area",
            datatype="GPFeatureLayer",
            parameterType="Required",
            direction="Input")
        Study_Area.controlCLSID = "{60061247-BCA8-473E-A7AF-A2026DDE1C2D}"

        Base_Raster = arcpy.Parameter(
            displayName="Base Tree Raster (such as tree height, canopy cover percentage, etc.)",
            name="Base_Raster",
            datatype="GPRasterLayer",
            parameterType="Required",
            direction="Input")
        
        #Base_Raster.filter.type = "ValueList"

        dBASE_file = arcpy.Parameter(
            displayName = "Class Ranges (dBASE file)",
            name = "dBASE_file",
            datatype = "GPTableView",
            parameterType = "Required",
            direction = "Input")

##        Patches = arcpy.Parameter(
##            displayName = "Raster to Polygon",
##            name = "Patches",
##            datatype = "GPLayer",
##            parameter = "Derived",
##            direction = "Output")
	
        parameters = [Extent, Identify_Workspace, Study_Area, Base_Raster, dBASE_file]
        return parameters

    def isLicensed(self):

        try:
            if arcpy.CheckExtension("Spatial") != "Available":
                raise Exception
            else:
                arcpy.CheckOutExtension("Spatial")
        except Exception:
            arcpy.AddMessage('Spatial Analyst Extension not available')
            return False  # tool cannot be executed
        return True  # tool can be executed

    def updateParameters(self, parameters):
        return

    def updateMessages(self, parameters):
        return

    def execute(self, parameters, messages):

        #allow tool to overwrite the layers in the file being used
        arcpy.env.overwriteOutput == True

        #Make it so I can use the parameters in the tool
        Extent = parameters[0].valueAsText
        Identify_Workspace = parameters[1].valueAsText
        Study_Area = parameters[2].valueAsText
        Base_Raster = parameters[3].valueAsText
        dBASE_file = parameters[4].valueAsText

        #Define workspace
        arcpy.env.workspace = Identify_Workspace

	# Extract by Mask: extract out the study area out of the base raster
        Extract_Mask = "Extract_Raster.tif"
        Extract_Mask1 = arcpy.sa.ExtractByMask(Base_Raster, Study_Area, "INSIDE")
        Extract_Mask1.save(Extract_Mask)
        
        # Reclassify: classify a raster with the range of what you would like it to be
        array = arcpy.da.TableToNumPyArray(dBASE_file, "*")
        df = pd.DataFrame(array)
        class_list = df.values.tolist()
    
        for i in range(len(class_list)):
            class_list[i] = class_list[i][1:-1]

        myRemapRange = arcpy.sa.RemapRange(class_list)
        User_Reclassified_Raster = "User_Reclassified_Raster.tif"
        reclassified_raster = arcpy.sa.Reclassify(Extract_Mask1, "Value", myRemapRange, "NODATA")
        reclassified_raster.save(User_Reclassified_Raster)

        # Add Field: add the field Range to the reclassified raster
        # to help user know what ranges go with what classified value
        arcpy.management.AddField(User_Reclassified_Raster, "Range", "TEXT", field_alias = "Height Range")

        # Join Field: join the from and to fields from the dBASE file
        arcpy.management.JoinField(User_Reclassified_Raster, "Value", dBASE_file, "OUT",["FROM_", "TO"])

        # Calculate Field
        arcpy.management.CalculateField(User_Reclassified_Raster,"Range", "\"!FROM_! - !TO!\"")

        # Delete Field
        arcpy.management.DeleteField(User_Reclassified_Raster, ["FROM_", "TO"])

        #List the fields in the Study Area polygon and if it does not have the fild ID, add it
        fields = arcpy.ListFields(Study_Area)

        if "Id" not in fields:
            arcpy.management.AddField(Study_Area, "Id", "LONG")
            arcpy.management.CalculateField(Study_Area, "Id", 0)

        # Tabulate Area: calculate the area of each range of heights, etc.
        Tabulate_Area = "Tabulate_Area.dbf"
        arcpy.sa.TabulateArea(User_Reclassified_Raster, "Range", Study_Area, "Id", Tabulate_Area, User_Reclassified_Raster, "CLASSES_AS_FIELDS")

        # Join, Add Field, Calculate Field, Delete Field: the tabulate area table to the reclassified raster, then add and calculate
        # the field Area so one knows what field they are looking at, Delete the field "ID_0"
        arcpy.management.JoinField(User_Reclassified_Raster, "Range", Tabulate_Area, "RANGE", ["ID_0"])
        arcpy.management.AddField(User_Reclassified_Raster, "Area", "DOUBLE")
        arcpy.management.CalculateField(User_Reclassified_Raster, "Area", "!ID_0!")
        arcpy.management.DeleteField(User_Reclassified_Raster, "ID_0")

        # Raster to Polygon: convert the reclassified raster to polygons
        R2P = "R2P"
        arcpy.conversion.RasterToPolygon(User_Reclassified_Raster, R2P,"NO_SIMPLIFY", "Range")

        # Dissolve: combine all the polygons together that touch
        Dissolve_Polys = "Dissolve_Polys"
        arcpy.management.Dissolve(R2P, Dissolve_Polys, "", "", "SINGLE_PART")

        #Eliminate: smooth out the polygons
        Patches = "Patches"
        arcpy.management.EliminatePolygonPart(Dissolve_Polys, Patches, "AREA", 1000)

        # Zonal Statistics: calculate the statistics (min, max, and mean) of the tree values
        ZonalStats = "ZonalStats.dbf"
        arcpy.sa.ZonalStatisticsAsTable(Patches, "ORIG_FID", Base_Raster, ZonalStats, "DATA", "MIN_MAX_MEAN")

        # Join Field: join the zonal stats fields to the smoothed out polygons
        arcpy.management.JoinField(Patches, "ORIG_FID", ZonalStats, "ORIG_FID", ["AREA", "MIN", "MAX", "MEAN"])
        arcpy.management.DeleteField(Patches, ["Id", "ORIG_FID"])

        arcpy.management.AddField(Patches, "Acres", "DOUBLE")
        arcpy.management.CalculateGeometryAttributes(Patches, [["Acres","AREA"]], area_unit="ACRES_US")

	# Delete: delete the following layers:
        arcpy.management.Delete(Extract_Mask1)
        arcpy.management.Delete(R2P)
        arcpy.management.Delete(Dissolve_Polys)
        arcpy.management.Delete(ZonalStats)
        arcpy.management.Delete(Tabulate_Area)

        c_project=arcpy.mp.ArcGISProject("CURRENT")


        return

    def postExecute(self, parameters):
        return
0 Kudos
1 Reply
SumitMishra_016
Frequent Contributor

Hi @HeatherDulaney1 ,

Could you make these changes and try:
1. 

 def getParameterInfo(self):

        #Define the parameters
        
        Patches = arcpy.Parameter(
            displayName="Final Output Patches",
            name="Patches",
            datatype="DEFeatureClass",
            parameterType="Derived",
            direction="Output")

	
        parameters = [Extent, Identify_Workspace, Study_Area, Base_Raster, dBASE_file, Patches]
        return parameters​

2. 

 def execute(self, parameters, messages):
        #Eliminate: smooth out the polygons
        Patches = os.path.join(arcpy.env.workspace, "Patches.shp")
        arcpy.management.EliminatePolygonPart(Dissolve_Polys, Patches, "AREA", 1000)

        # Set the Patches parameter as output
        arcpy.SetParameterAsText(5, Patches)

3. 

 def postExecute(self, parameters):
        patches_layer = parameters[5].valueAsText  # The "Patches" parameter defined above

        # Access the current project and map
        aprx = arcpy.mp.ArcGISProject("CURRENT")
        active_map = aprx.activeMap

        # Add the output feature class as a layer
        if patches_layer:
            active_map.addDataFromPath(patches_layer)
            arcpy.AddMessage(f"Added {patches_layer} to the map.")
        return
0 Kudos