<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" version="2.0">
  <channel>
    <title>topic Re: Python to tool in Python Questions</title>
    <link>https://community.esri.com/t5/python-questions/python-to-tool/m-p/1538274#M72832</link>
    <description>&lt;P&gt;&lt;SPAN&gt;Thank you very much Hayden, &amp;nbsp;I will check it and update&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
    <pubDate>Fri, 13 Sep 2024 14:04:00 GMT</pubDate>
    <dc:creator>MordehayAv-revaya</dc:creator>
    <dc:date>2024-09-13T14:04:00Z</dc:date>
    <item>
      <title>Python to tool</title>
      <link>https://community.esri.com/t5/python-questions/python-to-tool/m-p/1538164#M72823</link>
      <description>&lt;P&gt;&lt;SPAN&gt;I have a script in python that works well in Arcpro on layers found in sql in cooperation with our portal. When I turn the script into a geoprocessing tool, it doesn't work. It seems it doesn't find the layers it needs if I give a route (maybe an incorrect route). or the layer type is not appropriate. And even when I work with parameters it doesn't work. Is this the forum for this question to upload code? Or another group?&lt;/SPAN&gt;&lt;/P&gt;</description>
      <pubDate>Fri, 13 Sep 2024 08:46:57 GMT</pubDate>
      <guid>https://community.esri.com/t5/python-questions/python-to-tool/m-p/1538164#M72823</guid>
      <dc:creator>MordehayAv-revaya</dc:creator>
      <dc:date>2024-09-13T08:46:57Z</dc:date>
    </item>
    <item>
      <title>Re: Python to tool</title>
      <link>https://community.esri.com/t5/python-questions/python-to-tool/m-p/1538176#M72824</link>
      <description>&lt;P&gt;Happy to help if you post up what you have&lt;/P&gt;</description>
      <pubDate>Fri, 13 Sep 2024 10:14:42 GMT</pubDate>
      <guid>https://community.esri.com/t5/python-questions/python-to-tool/m-p/1538176#M72824</guid>
      <dc:creator>RichardHowe</dc:creator>
      <dc:date>2024-09-13T10:14:42Z</dc:date>
    </item>
    <item>
      <title>Re: Python to tool</title>
      <link>https://community.esri.com/t5/python-questions/python-to-tool/m-p/1538203#M72825</link>
      <description>&lt;P&gt;&lt;SPAN&gt;Thanks Richard, Here is the code, the code places a point at the starting point of the line - in the points layer, calculates an angle and transfers information. My problem is just to understand how to make it so that the reference to the layers and the possibility to edit them, will be preserved in the transition from the script in Arcpro to the tool in the portal.&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;import arcpy&lt;BR /&gt;import math&lt;/P&gt;&lt;P&gt;def LinesToPoints(line_layer="TheLines", point_layer="ThePoints"):&lt;BR /&gt;# Activate layers&lt;BR /&gt;lines = arcpy.management.MakeFeatureLayer(line_layer, "lines_lyr")&lt;BR /&gt;points = arcpy.management.MakeFeatureLayer(point_layer, "points_lyr")&lt;BR /&gt;&lt;BR /&gt;# Add fields if they do not exist&lt;BR /&gt;required_fields_lines = ["TheAngle", "TransferredToPoint", "PointCode", "PointOrder", "PointNumber"]&lt;BR /&gt;required_fields_points = ["TheAngle", "PointCode", "PointOrder", "PointNumber"]&lt;/P&gt;&lt;P&gt;for field in required_fields_lines:&lt;BR /&gt;if field not in [f.name for f in arcpy.ListFields("lines_lyr")]:&lt;BR /&gt;arcpy.management.AddField(lines, field, "DOUBLE" if field == "TheAngle" else "SHORT")&lt;/P&gt;&lt;P&gt;for field in required_fields_points:&lt;BR /&gt;if field not in [f.name for f in arcpy.ListFields("points_lyr")]:&lt;BR /&gt;arcpy.management.AddField(points, field, "DOUBLE" if field == "TheAngle" else "SHORT")&lt;BR /&gt;&lt;BR /&gt;# List to store point data for later creation&lt;BR /&gt;points_data = []&lt;/P&gt;&lt;P&gt;# Calculate the angle and store the value in the field&lt;BR /&gt;with arcpy.da.UpdateCursor(lines, ["SHAPE@", "TheAngle", "TransferredToPoint", "PointCode", "PointOrder", "PointNumber"]) as cursor:&lt;BR /&gt;for row in cursor:&lt;BR /&gt;line_geom = row[0]&lt;BR /&gt;start_point = line_geom.firstPoint&lt;BR /&gt;end_point = line_geom.lastPoint&lt;BR /&gt;&lt;BR /&gt;# Calculate the angle&lt;BR /&gt;delta_x = end_point.X - start_point.X&lt;BR /&gt;delta_y = end_point.Y - start_point.Y&lt;BR /&gt;angle = math.degrees(math.atan2(delta_y, delta_x))&lt;BR /&gt;row[1] = angle&lt;BR /&gt;&lt;BR /&gt;# Update the TransferredToPoint field&lt;BR /&gt;row[2] = 1&lt;BR /&gt;&lt;BR /&gt;cursor.updateRow(row)&lt;/P&gt;&lt;P&gt;# Add the data to the points list&lt;BR /&gt;point_geom = arcpy.PointGeometry(start_point)&lt;BR /&gt;points_data.append([point_geom, angle, row[3], row[4], row[5]]) # Collecting data for later addition&lt;/P&gt;&lt;P&gt;# Add the points to the ThePoints layer&lt;BR /&gt;with arcpy.da.InsertCursor(points, ["SHAPE@", "TheAngle", "PointCode", "PointOrder", "PointNumber"]) as insert_cursor:&lt;BR /&gt;for point_data in points_data:&lt;BR /&gt;insert_cursor.insertRow(point_data)&lt;/P&gt;&lt;P&gt;print("The code has completed successfully")&lt;/P&gt;&lt;P&gt;# Call the function&lt;BR /&gt;LinesToPoints()&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Fri, 13 Sep 2024 11:59:45 GMT</pubDate>
      <guid>https://community.esri.com/t5/python-questions/python-to-tool/m-p/1538203#M72825</guid>
      <dc:creator>MordehayAv-revaya</dc:creator>
      <dc:date>2024-09-13T11:59:45Z</dc:date>
    </item>
    <item>
      <title>Re: Python to tool</title>
      <link>https://community.esri.com/t5/python-questions/python-to-tool/m-p/1538207#M72826</link>
      <description>&lt;P&gt;So in order to add a geoprocessing tool front end to this, you would create a script tool in a toolbox and name it approrpriately.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;You should have a couple of parameters by my reckoning:&lt;BR /&gt;&lt;BR /&gt;Input lines layer and input points layer&lt;/P&gt;&lt;P&gt;I generally advise people to make the data type as "Feature layer" as this will allow drag/drop inputs from the TOC in Pro, but also allow you to navigate to a feature class via the little folder button. Consider it a best of both worlds input. Both would be of type "Required"&lt;BR /&gt;&lt;BR /&gt;Right-click your tool and edit, pasting your code in.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;You then need to create reference to your input parameters in the script, so it knows where the data is coming from via the &lt;A href="https://pro.arcgis.com/en/pro-app/latest/arcpy/functions/getparameterastext.htm" target="_self"&gt;GetParameterAsText&lt;/A&gt;&amp;nbsp;function. The number that follows in brackets denotes the order in which your parameters are stored in the tool properties, and as ever python starts counting at zero.&lt;/P&gt;&lt;P&gt;I would suggest lines as below:&lt;/P&gt;&lt;P&gt;&lt;SPAN&gt;&lt;BR /&gt;line_layer = arcpy.GetParameterAsText(0)&lt;BR /&gt;&lt;/SPAN&gt;&lt;SPAN&gt;point_layer = arcpy.GetParameterAsText(1)&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;Just above your #Activate Lines comment&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;And that should be it...&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Fri, 13 Sep 2024 12:17:09 GMT</pubDate>
      <guid>https://community.esri.com/t5/python-questions/python-to-tool/m-p/1538207#M72826</guid>
      <dc:creator>RichardHowe</dc:creator>
      <dc:date>2024-09-13T12:17:09Z</dc:date>
    </item>
    <item>
      <title>Re: Python to tool</title>
      <link>https://community.esri.com/t5/python-questions/python-to-tool/m-p/1538230#M72827</link>
      <description>&lt;P&gt;&lt;SPAN&gt;Thanks a lot Richard, I'll try it on Sunday when I get back to work and I'll let you know. Have a great weekend!&lt;/SPAN&gt;&lt;/P&gt;</description>
      <pubDate>Fri, 13 Sep 2024 12:47:34 GMT</pubDate>
      <guid>https://community.esri.com/t5/python-questions/python-to-tool/m-p/1538230#M72827</guid>
      <dc:creator>MordehayAv-revaya</dc:creator>
      <dc:date>2024-09-13T12:47:34Z</dc:date>
    </item>
    <item>
      <title>Re: Python to tool</title>
      <link>https://community.esri.com/t5/python-questions/python-to-tool/m-p/1538271#M72831</link>
      <description>&lt;P&gt;Went ahead and helped translate your code to a PYT toolbox. Tried to mark up the code with comments and reasons for why I did things in certain ways. Also added progress bar and messaging for you. It's vital when making tools to make sure the user is able to tell that it's actually working and not hung. Especially if it's updating data and will cause errors if cancelled halfway.&lt;/P&gt;&lt;LI-CODE lang="python"&gt;import arcpy
import math


class Toolbox:
    def __init__(self) -&amp;gt; None:
        self.label = "Lines to Points"
        self.alias = "Lines to Points"
        self.tools = [LinesToPoints]

class LinesToPoints:
    def __init__(self) -&amp;gt; None:
        self.label = "Lines to Points"
        self.description = "Converts lines to points at a specified interval"
        self.canRunInBackground = False
        #self.category = "Analysis"
        
        self.required_point_fields = ["TheAngle", "PointCode", "PointOrder", "PointNumber"]
        self.required_line_fields = ["TheAngle", "TransferredToPoint", "PointCode", "PointOrder", "PointNumber"]
    
    def getParameterInfo(self) -&amp;gt; list:
        
        in_lines = arcpy.Parameter(
            displayName="Input Lines",
            name="in_lines",
            datatype="DEFeatureClass",
            parameterType="Required",
            direction="Input"
        )
        in_lines.filter.list = ["Polyline"]
        
        in_points = arcpy.Parameter(
            displayName="Input Points",
            name="in_points",
            datatype="DEFeatureClass",
            parameterType="Required",
            direction="Input"
        )
        in_points.filter.list = ["Point"]
        
        return [in_lines, in_points]
    
    def isLicensed(self) -&amp;gt; bool:
        return True
    
    def updateParameters(self, parameters: list) -&amp;gt; None:
        return
    
    def updateMessages(self, parameters: list) -&amp;gt; None:
        return
    
    def execute(self, parameters: list, messages: list) -&amp;gt; None:
        
        # This allows you to re-order the parameters without breaking the code
        # when you use an index you can't re-order the parameters without updating the indexes
        # inthe execute method
        param_dict = {param.name: param for param in parameters}
        
        in_points = param_dict["in_points"].valueAsText
        in_lines = param_dict["in_lines"].valueAsText
        
        in_points_layer = arcpy.management.MakeFeatureLayer(in_points, "memory/in_points_layer")
        in_lines_layer = arcpy.management.MakeFeatureLayer(in_lines, "memory/in_lines_layer")
        
        line_count, *_ = arcpy.management.GetCount(in_lines_layer)
        line_count = int(line_count)
        
        # Add the required fields to the points layer
        point_fields = arcpy.ListFields(in_points_layer)
        for field in filter(lambda fld: fld not in point_fields, self.required_point_fields):
            fld_type = "DOUBLE" if field == "TheAngle" else "SHORT"
            arcpy.management.AddField(in_points_layer, field, fld_type)
        
        # Add the required fields to the lines layer
        line_fields = arcpy.ListFields(in_lines_layer)
        for field in filter(lambda fld: fld not in line_fields, self.required_line_fields):
            fld_type = "DOUBLE" if field == "TheAngle" else "SHORT"
            arcpy.management.AddField(in_lines_layer, field, fld_type)
        
        points_to_insert = []
        
        # Start a Progressor
        arcpy.SetProgressor("step", "Transferring points from lines", 0, line_count, 1)
        with arcpy.da.UpdateCursor(in_lines_layer, ['SHAPE@'] + self.required_line_fields) as cursor:
            for idx, row in enumerate(as_dict(cursor), 1):
                arcpy.SetProgressorLabel(f"Transferring points from line ({idx} of {line_count})")
                
                line_geom: arcpy.Polyline = row["SHAPE@"]
                start_point: arcpy.Point = line_geom.firstPoint
                end_point: arcpy.Point = line_geom.lastPoint
        
            delta_x = end_point.X - start_point.X
            delta_y = end_point.Y - start_point.Y
            angle = math.degrees(math.atan2(delta_y, delta_x))
            row["TheAngle"] = angle
            row["TransferredToPoint"] = 1
            
            # Match the way we're setting up the field list so we can modify the script behavior without
            # worrying about the order of the fields
            
            # Shape@ is always the first field in the list
            point_data = [arcpy.PointGeometry(start_point, line_geom.spatialReference)]
            
            # self.required_point_fields sets the order and name of the remaining fields
            point_data.extend([row[field] for field in self.required_point_fields])
            
            # Need to convert the dictionary values back to a list to update the row
            # This only works in Python 3 because dictionaries are ordered
            try:
                cursor.updateRow(list(row.values()))
            except Exception as e:
                arcpy.AddError(f"Error updating row: {e}")
            arcpy.SetProgressorPosition()
        
        arcpy.ResetProgressor()
        arcpy.SetProgressor("step", "Inserting points", 0, len(points_to_insert), 1)
        with arcpy.da.InsertCursor(in_points_layer, ['SHAPE@'] + self.required_point_fields) as cursor:
            for idx, point in enumerate(points_to_insert, 1):
                arcpy.SetProgressorLabel(f"Inserting point ({idx} of {len(points_to_insert)})")
                try:
                    cursor.insertRow(point)
                except Exception as e:
                    arcpy.AddError(f"Error inserting point: {e}")
                arcpy.SetProgressorPosition()
        return


def as_dict(cursor: arcpy.da.SearchCursor):
    """ Converts a search cursor to a dictionary generator so rows can be accessed by field name """
    for row in cursor:
        yield dict(zip(cursor.fields, row))&lt;/LI-CODE&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Fri, 13 Sep 2024 13:51:00 GMT</pubDate>
      <guid>https://community.esri.com/t5/python-questions/python-to-tool/m-p/1538271#M72831</guid>
      <dc:creator>HaydenWelch</dc:creator>
      <dc:date>2024-09-13T13:51:00Z</dc:date>
    </item>
    <item>
      <title>Re: Python to tool</title>
      <link>https://community.esri.com/t5/python-questions/python-to-tool/m-p/1538274#M72832</link>
      <description>&lt;P&gt;&lt;SPAN&gt;Thank you very much Hayden, &amp;nbsp;I will check it and update&lt;/SPAN&gt;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Fri, 13 Sep 2024 14:04:00 GMT</pubDate>
      <guid>https://community.esri.com/t5/python-questions/python-to-tool/m-p/1538274#M72832</guid>
      <dc:creator>MordehayAv-revaya</dc:creator>
      <dc:date>2024-09-13T14:04:00Z</dc:date>
    </item>
    <item>
      <title>Re: Python to tool</title>
      <link>https://community.esri.com/t5/python-questions/python-to-tool/m-p/1538415#M72840</link>
      <description>&lt;P&gt;You might find this tutorial helpful:&lt;/P&gt;&lt;P&gt;&lt;A href="https://learn.arcgis.com/en/projects/create-a-python-script-tool/" target="_blank"&gt;https://learn.arcgis.com/en/projects/create-a-python-script-tool/&lt;/A&gt;&lt;/P&gt;</description>
      <pubDate>Fri, 13 Sep 2024 17:48:48 GMT</pubDate>
      <guid>https://community.esri.com/t5/python-questions/python-to-tool/m-p/1538415#M72840</guid>
      <dc:creator>BobBooth1</dc:creator>
      <dc:date>2024-09-13T17:48:48Z</dc:date>
    </item>
    <item>
      <title>Re: Python to tool</title>
      <link>https://community.esri.com/t5/python-questions/python-to-tool/m-p/1538707#M72856</link>
      <description>&lt;P&gt;I did me up the indentation in the UpdateCursor so you'll have to make sure you fix that.&lt;/P&gt;</description>
      <pubDate>Sat, 14 Sep 2024 22:47:30 GMT</pubDate>
      <guid>https://community.esri.com/t5/python-questions/python-to-tool/m-p/1538707#M72856</guid>
      <dc:creator>HaydenWelch</dc:creator>
      <dc:date>2024-09-14T22:47:30Z</dc:date>
    </item>
  </channel>
</rss>

