How to: Replace Auto-Increment start with variable; pStart = (variable) ??

3524
11
Jump to solution
08-23-2016 01:36 PM
ReedDavis1
New Contributor III

Is it possible to replace the pStart in the code with a variable? In other words I have a value that I need to start from however the code is part of a model and the value may change every time the model is run so I cannot simply replace the "1" with whatever the value is(I have tried this and it works) because the model will be run on many datasets with different values. Here is my logic, I need to pass a value into "pStart =," what I have tried is to define a function and pass that as the pStart value. so that pStart = getfieldvalue then auto increment from this value. I need to replace the "1" with the value that my model has found,  here is my logic that does not work...

def getfieldvalue():
 import arcpy
 arcpy.ImportToolbox("Model Functions")
 arcpy.GetFieldValue_mb("QueryTable_Statistics", "MAX_FEATURE_NUM", "String", "")
 return

rec=0  
def autoIncrement():  
 global rec  
 pStart = getfieldvalue(MAX_FEATURE_NUM)  
 pInterval = 1 
 if (rec == 0):   
  rec = pStart   
 else:   
  rec = rec + pInterval   
 return rec  

Rough working model...

0 Kudos
1 Solution

Accepted Solutions
ReedDavis1
New Contributor III

After a week of intensive Model Building we have come up with a solution, we did not need to use python except the autoIncrement() function in pre-logic code of our final Calculate Field tool seen in the model. The simple solution was to create a new integer field and populate every record in that field with the MAX value derived from the Summary Statistics tool then use a simple expression: autoIncrement + [MAXvalueField] we then iterate the entire function for every grid block and viola we have an incrementing field starting at the highest pre-existing number. Now that we have our incrementing value we concatenate a new field with that number and our area code(found by a separate model) and we have a unique identifier for every feature in our dataset. The script looks remarkably simple for such a long model...

# Import arcpy module
import arcpy

# Load required toolboxes
arcpy.ImportToolbox("Model Functions")

# Script arguments
Select_Feature_Class = arcpy.GetParameterAsText(0)
if Select_Feature_Class == '#' or not Select_Feature_Class:
    Select_Feature_Class = "" # provide a default value if unspecified

# Local variables:
Feature_Layer = Select_Feature_Class
I_Feature_Layer_FEATURE_ID = Feature_Layer
QueryTable_Statistics = I_Feature_Layer_FEATURE_ID
Feature_Class_w_MAX = QueryTable_Statistics
FeatureClassNewNumber__2_ = Feature_Class_w_MAX
FeatureClassNewNumber = FeatureClassNewNumber__2_
SCleanoutApppended__2_ = FeatureClassNewNumber
NULL_FEATURENUM = I_Feature_Layer_FEATURE_ID
Value = Feature_Layer
scratch_gdb = ""

# Process: Make Feature Layer
arcpy.MakeFeatureLayer_management(Select_Feature_Class, Feature_Layer, "", scratch_gdb, "OBJECTID OBJECTID VISIBLE NONE;Shape Shape VISIBLE NONE;Enabled Enabled VISIBLE NONE;Location Location VISIBLE NONE;InstallContractor InstallContractor VISIBLE NONE;Condition Condition VISIBLE NONE;PrimaryImage PrimaryImage VISIBLE NONE;Size_ Size_ VISIBLE NONE;FACILITYID FACILITYID VISIBLE NONE;FEATURE_ID FEATURE_ID VISIBLE NONE;FEATURE_NUM FEATURE_NUM VISIBLE NONE;OLD_FACILITY_ID OLD_FACILITY_ID VISIBLE NONE;GPS_Date GPS_Date VISIBLE NONE;Datafile Datafile VISIBLE NONE;LifeCycleStatus LifeCycleStatus VISIBLE NONE;FACILITYIDAUTO FACILITYIDAUTO VISIBLE NONE;NewNumber NewNumber VISIBLE NONE;test test VISIBLE NONE")

# Process: Iterate Feature Selection
arcpy.IterateFeatureSelection_mb(Feature_Layer, "FEATURE_ID #", "true")

# Process: Select (2)
arcpy.Select_analysis(I_Feature_Layer_FEATURE_ID, NULL_FEATURENUM, "FEATURE_NUM ='0' AND FACILITYID IS NULL")

# Process: Summary Statistics
arcpy.Statistics_analysis(I_Feature_Layer_FEATURE_ID, QueryTable_Statistics, "FEATURE_NUM MAX", "FEATURE_ID")

# Process: Join Field
arcpy.JoinField_management(NULL_FEATURENUM, "FEATURE_ID", QueryTable_Statistics, "FEATURE_ID", "")

# Process: Calculate Field (2)
arcpy.CalculateField_management(Feature_Class_w_MAX, "test", "!MAX_FEATURE_NUM!", "PYTHON", "")

# Process: Calculate Field
arcpy.CalculateField_management(FeatureClassNewNumber__2_, "NewNumber", "autoIncrement()+ !test!", "PYTHON", "rec=0  \\ndef autoIncrement():  \\n global rec  \\n pStart = 1\\n pInterval = 1 \\n if (rec == 0):   \\n  rec = pStart   \\n else:   \\n  rec = rec + pInterval   \\n return rec\\n")

# Process: Append
arcpy.Append_management("") #data paths

View solution in original post

0 Kudos
11 Replies
DanPatterson_Retired
MVP Emeritus

my guess would be to replace rec above the def with the max value, since it is made the global value within the def

DarrenWiens2
MVP Honored Contributor

Your function returns 'None', not the value. Return the value you want to sub in for pStart.

>>> def something():
...     x = 5
...     return # returns None
... print something()
... 
None
>>> def something():
...     x = 5
...     return x # returns value of x
... print something()
... 
5
ReedDavis1
New Contributor III

EDIT: Since "Get Field Value" is a "model only tool", I think this is at least part of the reason my code is not running, python is not able to find the tool because to it (python) the tool does not exist... Maybe someone can confirm...

0 Kudos
DarrenWiens2
MVP Honored Contributor

It looks like the GetFieldValue_mb tool returns the first value in a given field, which you can also do like the following, and get rid of the getFieldValue function altogether:

import arcpy # still have to import
pStart = [i[0] for i in arcpy.da.SearchCursor("QueryTable_Statistics", "MAX_FEATURE_NUM")][0] ‍‍‍‍‍
ReedDavis1
New Contributor III

Pardon my ignorance, I am quite green in python. This is the way I am running the code I have tried to place the import both before and inside the recursive as well as placing your entire snippet outside and inside of the autoIncrement function, several variations have been unsuccessful, perhaps there is something obvious I am doing wrong:

import arcpy

rec=0  
def autoIncrement():  
 global rec  
 pStart = [i[0] for i in arcpy.da.SearchCursor("QueryTable_Statistics", "MAX_FEATURE_NUM")][0] 
 pInterval = 1 
 if (rec == 0):   
  rec = pStart   
 else:   
  rec = rec + pInterval   
 return rec  


   

I am running this as Pre-logic script code in the Calculate field tool of my model. I was thinking the code would assume the environment of the model and dataset in which it is working but maybe I need to define an environment in the code?

0 Kudos
JoeBryant2
Occasional Contributor II

It sounds like you solved this using another method, Reed. But this method seemed so close to working I had to try it. I am even more green when it comes to Python than you, but I was able to get this Pre-logic script code to work in the Calculate Field tool in ModelBuilder. I did not have to define an environment using code - it honered the Model Environment settings.

I DID have to investigate what the actual name of my table output from the Summary_Statistics tool was named. It did not match the name in the model, but instead was assigned the generic intermediate feature root name when it was written to my default GDB. I also had to set this variable as a precondition to the Calculate Field Tool, which it looks like you had already done in your model.

Hopefully this Model will continue to work for me - I am using it to update our District Parcel polygons every month when the County makes the new Parcels for the whole County available. 

ReedDavis1
New Contributor III

So you were able to pass the output of your summary stats into the autoIncrement function?!? I would love to see the code; if I could make this work in my model it would greatly simplify my logic...

Also, how did you track down the actual name of the summary stats table?

0 Kudos
JoeBryant2
Occasional Contributor II

'Guess I spoke too soon: the code worked when I ran the tool in a ModelBuilder edit session, but after I saved the model and tried to run it as a stand alone tool from my Toolbox, the AutoIncrement tool failed.
The results appear to imply that pStart cannot = a string value. I am currently trying to find why it worked initially in ModelBuilder.

To check the Output Table Name I just opened the Summary Statistics tool and inspected the Output Table Path. Maybe this is normal, but I was under the impression the name would follow the name assigned to the output variable in the ModelBuilder Display.
Mine was named "PARCELS2_Statistics" instead of "AssetID_MAX".


Here is the code (forgive my formatting - I'm a noob. Any recommendations appreciated!)

>>> # -*- coding: utf-8 -*-
... # ---------------------------------------------------------------------------
... # ParcelUpdate.py
... # Created on: 2016-09-02 14:05:20.00000
... # (generated by ArcGIS/ModelBuilder)
... # Usage: ParcelUpdate <County_Parcels_Update> <PARCELS_REBUILD_shp>
... # Description:
... # ---------------------------------------------------------------------------
...
... # Import arcpy module
... import arcpy
...
... # Script arguments
... County_Parcels_Update = arcpy.GetParameterAsText(0)
... if County_Parcels_Update == '#' or not County_Parcels_Update:
... County_Parcels_Update = "PARCELS_County_Sept2016" # provide a default value if unspecified
...
... PARCELS_REBUILD_shp = arcpy.GetParameterAsText(1)
... if PARCELS_REBUILD_shp == '#' or not PARCELS_REBUILD_shp:
... PARCELS_REBUILD_shp = "Z:\\Parcel Updates\\parcels_rebuild_2016_08_30\\PARCELS_REBUILD.shp" # provide a default value if unspecified
...
... # Local variables:
... NEW_CWD_Parcels_SELECTED = County_Parcels_Update
... CWD_Boundary = "CWDGIS.DBO.cwd_boundary"
... NEW_CWD_Parcels_COPIED = "Z:\\Parcel Updates\\ParcelUpdates.gdb\\PARCELS2"
... Parcels_with_AssetID = NEW_CWD_Parcels_COPIED
... Current_CWD_Parcels = "CWDGIS.DBO.PARCELS"
... Parcels_w_FullAddr_NULL = Parcels_with_AssetID
... PARCELS_w_FullAddr = Parcels_w_FullAddr_NULL
... PARCELSwFullAddr_Lyr = "PARCELSwFullAddr_Lyr"
... PARCELS_AssetID_NULL = PARCELSwFullAddr_Lyr
... PARCELS_w_AssetIDs = PARCELS_AssetID_NULL
... AssetID_MAX = "Z:\\Parcel Updates\\ParcelUpdates.gdb\\PARCELS2_Statistics"
... PARCELS_w_APN_DASH = PARCELS_w_AssetIDs
... CWDGIS_DBO_PARCELS_1 = "Database Connections\\Connection to CWDGIS01.sde\\CWDGIS.DBO.PARCELS_1"
...
... # Process: Select - CWD
... arcpy.SelectLayerByLocation_management(County_Parcels_Update, "HAVE_THEIR_CENTER_IN", CWD_Boundary, "", "NEW_SELECTION", "NOT_INVERT")
...
... # Process: Copy Features
... arcpy.CopyFeatures_management(NEW_CWD_Parcels_SELECTED, NEW_CWD_Parcels_COPIED, "", "0", "0", "0")
...
... # Process: Join - AssetID
... arcpy.JoinField_management(NEW_CWD_Parcels_COPIED, "APN", Current_CWD_Parcels, "APN", "AssetID")
...
... # Process: Add Field - FullAddr
... arcpy.AddField_management(Parcels_with_AssetID, "Full_Address", "TEXT", "", "", "255", "", "NULLABLE", "NON_REQUIRED", "")
...
... # Process: Calc Field - FullAddr
... arcpy.CalculateField_management(Parcels_w_FullAddr_NULL, "Full_Address", "!STREET_NBR!+\" \"+ !STREET_NAM!", "PYTHON_9.3", "")
...
... # Process: Make Feature Layer
... arcpy.MakeFeatureLayer_management(PARCELS_w_FullAddr, PARCELSwFullAddr_Lyr, "", "", "FID FID VISIBLE NONE;Shape Shape VISIBLE NONE;AREA AREA VISIBLE NONE;PERIMETER PERIMETER VISIBLE NONE;APN APN VISIBLE NONE;LANDUSE LANDUSE VISIBLE NONE;LOT_SIZE LOT_SIZE VISIBLE NONE;NEIBRHC NEIBRHC VISIBLE NONE;STREET_NBR STREET_NBR VISIBLE NONE;STREET_NAM STREET_NAM VISIBLE NONE;CITY CITY VISIBLE NONE;ZIP ZIP VISIBLE NONE;ZONE ZONE VISIBLE NONE;NAME NAME VISIBLE NONE;MAIL_ADDRE MAIL_ADDRE VISIBLE NONE;MAIL_CITY MAIL_CITY VISIBLE NONE;MAIL_STATE MAIL_STATE VISIBLE NONE;MAIL_ZIP MAIL_ZIP VISIBLE NONE;TRA TRA VISIBLE NONE;SUBDIVISIO SUBDIVISIO VISIBLE NONE;LOT LOT VISIBLE NONE;AssetID AssetID VISIBLE NONE;Full_Address Full_Address VISIBLE NONE")
...
... # Process: Select AssetID NULL
... arcpy.SelectLayerByAttribute_management(PARCELSwFullAddr_Lyr, "NEW_SELECTION", "AssetID IS NULL")
...
... # Process: Summary Statistics
... arcpy.Statistics_analysis(PARCELSwFullAddr_Lyr, AssetID_MAX, "AssetID MAX", "")
...
... # Process: Calc AssetID
... arcpy.CalculateField_management(PARCELS_AssetID_NULL, "AssetID", "autoIncrement()", "PYTHON_9.3", "import arcpy\\n\\nrec=0\\ndef autoIncrement():\\n global rec\\n pStart = [i[0] for i in arcpy.da.SearchCursor(\"PARCELS2_Statistics\", \"MAX_AssetID\")][0]\\n pInterval = 1\\n if (rec == 0): \\n rec = pStart \\n else: \\n rec = rec + pInterval \\n return rec\\n\\n")
...
... # Process: Join APN_DASH
... arcpy.JoinField_management(PARCELS_w_AssetIDs, "APN", PARCELS_REBUILD_shp, "APN", "APN_DASH")
...
... # Process: Copy Features (2)
... arcpy.CopyFeatures_management(PARCELS_w_APN_DASH, CWDGIS_DBO_PARCELS_1, "", "0", "0", "0")
...
...

JoeBryant2
Occasional Contributor II

Shoot, I should have kept the output the first time when it worked! But instead I wanted to run the whole thing from scratch and now, of course it doesn't work.

Here's a screen shot of the results now when I run the tool in ModelBuilder:

autoIncrement () ERROR 000539

I have no formal training in code: what is this saying? How do I know which lines are 1 and 11? Do I need to export the script to Python?

It's weird that it worked the first time. The only thing wrong with it was that I had inadvertently disabled the Select <NULL> before hand and it wrote new AssetIDs to the whole feature class, instead of just the missing values. But it did start with the MAX value.