Arcattr

From DreamsteepWiki

Jump to: navigation, search


This is my python code to manipulate attributes on GIS datasets via com32 and the arcscripting module , I am looking at using free tools instead Arc seems to be clunky and comercial (it has some good stuff though here and there , I have to admit)

Written by Keith Legg August 2007

#import sys_file_io
import sys_data_tree
#i think this is the first experimental use of data tree
#written around nov 07 (for autodesk data transport)

import sys_arrays

import string,sys,os,traceback
#gp = win32com.client.Dispatch("esriGeoprocessing.GpDispatch.1")

try:
  #import relevant modules, create geoprocessing dispatch object
  import win32com.client
  gp = win32com.client.Dispatch("esriGeoprocessing.gpDispatch.1")

except:
  print 'WARN NO ESRI SUPPORT FROM CURRENT SHELL '
  

def AddPrintMessage(msg, severity):
    print msg
    if severity == 0: gp.AddMessage(msg)
    elif severity == 1: gp.AddWarning(msg)
    elif severity == 2: gp.AddError(msg)
"""

a python class to handle all operations pertaining to feature classes and the
creation/modification of attribute tables
keith legg , Sep 29 ,Nov 17 2007

"""
########################
"""
USAGE

import sys_arclink_ATTRS
#BEGIN
#foo = ESRI_ATTR_EDIT()

#SHAPEFILE = 'C:/data/Creswell_ForSale_W10.shp'
#DATABASE = 'C:/data/fucker.mdb'


###########################################
#READ ATTRNAMES,ATTRTYPES,AND ALL VALUES , INTO MEMORY FROM A FEATURE CLASS
#foo.readAttrs(SHAPEFILE)
#foo.export_to_data_tree(SHAPEFILE,'C:/reportt.txt')


##
#GET NUM ATTRS (SET FROM READ)
#print foo.NUMATTRS

#SHOW ALL ATTRTYPES
#print foo.ATTRTYPES
#SHOW ATTRNAME BY INDEX
#print foo.ATTRNAMES[3]
#SHOW ATTRVALUES BY INDEX
#print foo.ATTRVALUES[3]

#SHOW ALL FIELDS IN AN ARRAY
#print foo.ATTRNAMES
#print foo.ATTRVALUES
###################################

#TO CLEAR ALL MEMORY (BEFORE LOADING NEXT ATTR)
#foo.clearAllInternals()

###########################################
#ADD ATTR
#foo.addAttr(SHAPEFILE,'butrocker','text')
#foo.addAttr(SHAPEFILE,'ewew','float')
#foo.addAttr(SHAPEFILE,'ewew','long')
#foo.addAttr(SHAPEFILE,'ewew','double')
###########################################
#DELETE AN ATTR
#foo.delAttr(SHAPEFILE,'ewew')

###########################################

#WRITE ATTR

#inserttable = ['a','b','c','d','e','f','g','h','i','j','k','l','m','n','m']
#inserttable = [1.3,2.3,3.3,4.3,5.3,6.3,7.3,8.3,9.3,10.3,11.3,12.3,13.3,14.3,15.3]
#inserttable = [12,23,19,22,25,618,76,83,93,103,113,123,133,143,153]
#foo.writeAttrs(SHAPEFILE,'butrocker',inserttable)

###########################################
#GET GEOMETRY INFO
#foo.getGeoInfo(SHAPEFILE)
#####################################
#GET FIELD INFO
#foo.getFieldInfo(SHAPEFILE)

###########################################
#GET AN ATTRIBUTE (VALUE TABLE) BY NAME
#print foo.getFeatureAttr(SHAPEFILE,'NAME')

#GET AN ATTRIBUTE BY NAME AND VALUE ID
#print foo.getFeatureAttrValue(SHAPEFILE,'FID',5)

#GET AN ATTRIBUTE BY PART ?
#foo.getPartAttr(SHAPEFILE)



"""
####################################################################################
class ESRI_ATTR_EDIT:

  def __init__(self):
  
    self.NUMATTRS       = 0
    self.ATTRVALUES     = [[]]
    #
    self.ATTRNAMES      = []
    self.ATTRTYPES      = []
    self.Editable       = []
    self.Length         = []
    self.Type           = []
    self.Scale          = []
    self.Domain         = []
    self.isMultiPart    = []
    self.partCount      = []
    self.centroid       = []
    self.length         = []
    self.firstPoint     = []
    self.lastPoint      = []
    self.area           = []
    self.length         = []
    self.firstPoint     = []
    self.lastPoint      = []
    ########################
  ###########################
  ###########################
  def clearAllInternals(self):
    self.NUMATTRS       = 0
    self.ATTRVALUES     = []
    self.ATTRNAMES      = []
    self.ATTRTYPES      = []
    self.Editable       = []
    self.Length         = []
    self.Type           = []
    self.Scale          = []
    self.Domain         = []
    self.isMultiPart    = []
    self.partCount      = []
    self.centroid       = []
    self.length         = []
    self.firstPoint     = []
    self.lastPoint      = []
    self.area           = []
    self.length         = []
    self.firstPoint     = []
    self.lastPoint      = []
  ###########################
  def checkfileexists(self,obj):
     if os.path.lexists(obj):
       return 1
     if os.path.lexists(obj)==0:
       return 0
  #####################
  def checkfieldexists(self,obj,field):
    attrs = []
    attrs = self.listAttrs(obj)
    for attr in attrs:
      if attr == field:
        return 1
    return 0
  #####################
  def getnumattrs(self,obj):
    attrs = []
    attrs = self.listAttrs(obj)
    count = 0
    for attr in attrs:
      count=count+1
    return count
  #####################
  #def getnumattrs(self,obj):
  #  attrs = []
   # attrs = self.listParts(obj)
    #count = 0
    #for attr in attrs:
    #  count=count+1
    #return count
  #####################
  #def addSubType
  #def removeSubType
  #def setdefualtsubtype
  #def setDefualt ()
  #####################
#  def createEmpty_MDB():
#  def createEmpty_SHP():


  #####################
  """
  as a matter of triva this was the first use of the data graph
  it was made around August 2007, just prior to the Autodesk UVIZ 360 challenge
  in fact the output of this is seen, imported in maya at the end of the video
  """
  def export_to_data_tree (self,feature,filename):
     if self.checkfileexists(feature)==0:
       raise (feature+' DOES NOT EXIST ')
     
     if self.checkfileexists(feature):
       ###CLEAR MEMORY TO BEGIN
       self.clearAllInternals()
       ###READ FEATURE ATTRS
       self.readAttrs(feature)
       #print foo.ATTRVALUES
       #test = self.ATTRVALUES[0]
       names = self.ATTRNAMES
       #print 'DEBUG '
       #print names
       
       cleanname =   feature.replace('.','')
       cleanname = cleanname.replace(':','')
       cleanname = cleanname.replace('/','')
       cleanname = cleanname.replace('\\','')
       
       DG = sys_data_tree.data_graph( ('FC_'+cleanname) )
       ###
       countme = 0
       for name in names:
          ATR = []
          temps = self.ATTRVALUES[countme]
          for temp in  temps:
            ATR.append('_')
          ATR2 = self.ATTRVALUES[countme]
          newnode = sys_data_tree.node_base((name+'_FIELD'),ATR,ATR2)
          DG.add(newnode)
          countme=countme+1
          
       ###
       #DG.dumpall()
       DG.save_graph_file(filename)

  #####################
  
  
  
  

  #####################
#  def insertRow(self,fc,attrname,fieldtype):
  #####################
  def deleteRow (self,feature):
     # Create update cursor for feature class
     rows = gp.UpdateCursor(feature)
     row = rows.Next()
     while row: # Delete all rows that have a roads type of 4
        #if row.road_type == 4:
        #   rows.DeleteRow(row)
        row = rows.Next()
     if rows:
       del rows
     if row:
       del row
       
  #####################
  """
  DEBUG UNIMPLEMENTED
  
  this will look for a field and matching field
  then attempt to find value of first field in a list and apply a corresponding value to a second field
  this is to match different tables in arbitrary order

  DEBUG UNIMPLEMENTED
  
  """
  #match_tables(SHAPEFILE,'FS_ML_NUM','LEGAL',VALID_ML,VALID_LEG )
  
  def match_tables(self,featureclass,field1,field2,table1,table2):
     if  self.checkfileexists(featureclass)==0:
        print featureclass+' DOES NOT EXIST '
     if  self.checkfileexists(featureclass):
       if len(table1) == 0:
         print 'ERROR table1 IS EMPTY '
       if len(table2) == 0:
         print 'ERROR table2 IS EMPTY '
       ###
       if self.checkfieldexists(featureclass,field1)==0:
         print 'field1 does not exist '
       if self.checkfieldexists(featureclass,field2)==0:
         print 'field2 does not exist '

       ##
       #self.
       SETONE = self.getFeatureAttr(featureclass,field1)
       SETTWO = self.getFeatureAttr(featureclass,field2)
       
       #print SETONE
       #print SETTWO
       #raw_input()
       
       #LOOKUP =
       #RETRNVAL = sys_arrays.lookupMatchedValues( LOOKUP,table1,table2)
       

        
     #############DEBUG UNTESTED , LINKED IN THE ATTR VARIABLE NOV,1 2007
     #for value in valuetable:
     #     print 'SORTING POLYGON '+ '  #'+str(count)+'#  ' + str(value)
     #     gp.SelectLayerByAttribute( "lyr","ADD_TO_SELECTION",(attr+'= '+str(value) ) )
     #     count = count +1
     #gp.CopyFeatures("lyr", output)
     
       
  #####################
  """
   this function "filters" a shapefile based on matching attributes

   (attr is the attribute to look for (MAKE SURE IT EXISTS !)
    valuetable is the list of values to attempt to match
    input_objects = exsisting shapefile (database) to sort
    output = shape file to create
   )

  """
  
  def filter_layers(self,attr,valuetable,input_objects,output):
     if  self.checkfileexists(input_objects[0]):
        gp.MakeFeatureLayer(input_objects[0],"lyr")
     elif  self.checkfileexists(input_objects):
        gp.MakeFeatureLayer(input_objects,"lyr")
     else :
        print 'ESRI_ATTR_EDIT.filter_layers: error no type defined '+input_objects
     count = 0
     if len(valuetable) == 0:
       print 'ERROR valuetable IS EMPTY '
     #############
     for value in valuetable:
          print 'SORTING POLYGON '+ '  #'+str(count)+'#  ' + str(value)
          gp.SelectLayerByAttribute( "lyr","ADD_TO_SELECTION",(attr+'= '+str(value) ) )
          count = count +1
     gp.CopyFeatures("lyr", output)

  ###QUEREY ATTR EXISTS
  ########################################
  
  ########################################
  ##QUEREY VALUES FOR AN ATTRIBUTE
  def getFeatureAttr(self,fc,attrname):
    OUTPUT = []
    rows = gp.searchCursor(fc)
    row = rows.Next()
    while row:
       foo = ''
       exec ('foo=row.'+attrname)
       OUTPUT.append( foo  )
       row = rows.Next()
    #########
    if row:
     del row
    if rows:
     del rows
    ##########
    return OUTPUT
  ########################################
  ###CREATE AN ATTRIBUTE
  """
  TYPES ARE
    Text - Names or other textual qualities.
    Float - Numeric values with fractional values within a specific range.
    Double - Numeric values with fractional values within a specific range.
    Short - Numeric values without fractional values within a specific range; coded values.
    Long - Numeric values without fractional values within a specific range.
    Date - Date and/or Time.
    Blob - images or other multimedia.
  """

  def addAttr(self,fc,attrname,fieldtype):
      try :
        gp.addfield(str(fc),str(attrname),str(fieldtype))
        #keep count
        self.NUMATTRS=self.NUMATTRS+1
        
      except:
         print '## ESRI_ATTR_EDIT.addAttr : FAILED '
         tb = sys.exc_info()[2]
         tbinfo = traceback.format_tb(tb)[0]
         pymsg = "PYTHON ERRORS:\nTraceback Info:\n" + tbinfo + "\nError Info:\n    " + str(sys.exc_type)+ ": " + str(sys.exc_value) + "\n"
         AddPrintMessage(pymsg, 2)
         msgs = "GP ERRORS:\n" + gp.GetMessages(2) + "\n"
         AddPrintMessage(msgs, 2)
  ####################################################################
  
  ##DELETE AN ATTRIBUTE
  def delAttr(self,fc,attrname):
      gp.deletefield(str(fc),str(attrname))
      #keep count
      self.NUMATTRS=self.NUMATTRS-1
      
  ####################################################################
  def listAttrs(self,fcname):
       OUTPUT =[]
       fieldlist = gp.ListFields(fcname)
       fieldlist.reset()
       field = fieldlist.next()

       while field:
         OUTPUT.append(str(field.Name) )
         field = fieldlist.next()
       if fieldlist:
         del fieldlist
       if field:
         del field
         
       return OUTPUT
  ####################################################################
  def listParts(self,fcname):
       OUTPUT =[]
       fieldlist = gp.ListFields(fcname)
       fieldlist.reset()
       field = fieldlist.next()

       while field:
         OUTPUT.append(str(field.Name) )
         field = fieldlist.next()
       if fieldlist:
         del fieldlist
       if field:
         del field

       return OUTPUT
  ####################################################################
  ###LOAD ATTRIBUTES INTO MEMORY
  def readAttrs(self,fcname):
       self.clearAllInternals()
       ###
       FCOUNT = 0
       
       fields = gp.ListFields(fcname)     #sys.argv[1]
       fields.reset()
       fld = fields.next()
       while fld:
         self.ATTRNAMES.append( str(fld.Name )  )
         self.ATTRTYPES.append( str(fld.Type )  )
         fld = fields.next()
         FCOUNT=FCOUNT+1
       ###
       if fields:
         del fields
       if fld:
         del fld
         
       self.NUMATTRS = FCOUNT
       ######################
       #MAKE AN ATTR MATRIX BASED ON FIELDS, ACCESS THEM IN ORDER
       for ADDFIELD in  self.ATTRNAMES:
           tempbuffertwo = []
           tempbuffer    = []
           rows=gp.SearchCursor(fcname)
           row=rows.Next()
           while row:
              #if ADDFIELD != 'Shape':
              exec ('tempbuffer=row.'+ADDFIELD)
              tempbuffertwo.append(tempbuffer)
              # tempbuffertwo.append(tempbuffer)
              row=rows.Next()
           ####
           if rows:
             del rows
           if row:
             del row
           ########
           self.ATTRVALUES.append(tempbuffertwo)
  ###SAVE AN ATTRIBUTE TABLE TO A FEATURE
  def writeAttrs(self,fcname,field,valuetable):
     if self.checkfieldexists(fcname,field)==0:
        raise 'ERROR "'+fcname+'" FIELD "'+field +'" DOES NOT EXIST '
     ########
     numattrs  = self.countparts(fcname)
     numvalues = len(valuetable)
     
     #DEBUG
     #print '\n  #DEBUG NUMATTRS'
     #print numattrs
     #print '  #DEBUG NUMVALUES'
     #print numvalues
     #raw_input()
     
     
     if self.checkfieldexists(fcname,field):
        try:
           countaddattr=0
           cur = gp.UpdateCursor(fcname,'')
           row = cur.Next()
           while row:
             #row.SetValue('id', 33)
             #  print 'ERROR writeAttrs EMPTY TABLE INDEXED'
               row.SetValue(field, valuetable[countaddattr])
               cur.UpdateRow(row)
               row = cur.Next()
               countaddattr=countaddattr+1
           ####
           if cur:
             del cur
           if row:
             del row
        except:
         tb = sys.exc_info()[2]
         tbinfo = traceback.format_tb(tb)[0]
         pymsg = "PYTHON ERRORS:\nTraceback Info:\n" + tbinfo + "\nError Info:\n    " + str(sys.exc_type)+ ": " + str(sys.exc_value) + "\n"
         AddPrintMessage(pymsg, 2)
         msgs = "GP ERRORS:\n" + gp.GetMessages(2) + "\n"
         AddPrintMessage(msgs, 2)
  ####################################################################
  ###GET AN ATTRIBUTE'S DATA
  def getAttrlist(self,fc,attr):
      self.clearAllInternals()
      ##
      OUTPUT = []
      rows=gp.SearchCursor(fc)
      row=rows.Next()
      while row:
        foo = ''
        exec ('foo=row.'+attr)
        #print 'FOO '
        OUTPUT.append(int(foo)) #DEBUG  THIS IS NOT TYPLESS!!
        row=rows.Next()
      return OUTPUT

      #DELETE CURSOR OBJECT TO RELESE LOCKING
      if rows:
         del rows
      if row:
         del row
      ######
  def loadAll(self,shapefile):
       self.clearAllInternals()
       self.readAttrs(shapefile)
       
  ############################
  
  ###GET GEOMETRY TYPE
  def getFieldInfo(self,fc):
       self.clearAllInternals()
       ##
       fields = gp.ListFields(fc)     #sys.argv[1]
       fields.reset()
       fld = fields.next()

    #self.ATTRVALUES     = []

       while fld:
         print '\n'
         print '##FIELD #########################'
         print 'Name          ' +str(fld.Name     )
         print 'Editable      ' +str(fld.Editable )
         print 'Length        ' +str(fld.Length   )
         print 'Type          ' +str(fld.Type     )
         print 'Scale         ' +str(fld.Scale    )
         print 'Domain        ' +str(fld.Domain   )
         
         self.ATTRNAMES.append(str(fld.Name ))
         self.ATTRTYPES.append(str(fld.Type ))
         #OTHER
         self.Scale.append(str(fld.Scale ))
         
         fld = fields.next()
       ########
       if fields:
         del fields
       if fld:
         del fld
  ############################

  ###GET GEOMETRY TYPE
  def getGeoInfo(self,fc):
       self.clearAllInternals()
       desc = gp.Describe(fc)
       typeoffeature= str(desc.DataType )
       #print 'TYPE IS ' +  typeoffeature
       ##
       if typeoffeature == 'RasterDataset':
        print '#getGeoInfo RASTER FILE DETECTED, SKIPPING \n'
       ##
       if typeoffeature == 'Tin':
        print '#getGeoInfo TIN FILE DETECTED, SKIPPING \n'
       ##
       #if typeoffeature == 'ShapeFile':
       #  print ' SHAPE FILE DETECTED \n'
       ##
       if typeoffeature == 'ShapeFile' :
          rows = gp.SearchCursor(fc)
          row = rows.Next()
          countparts = 0
          countpartswithgeo =0
          while row:
              feat = row.shape
              shapetype= str(feat.Type)
              print '\n'
              if shapetype == 'polygon':
                 print '#POLYGON DETECTED '
              if shapetype == 'polyline':
                 print '#LINE DETECTED '
              if shapetype == 'point':
                 print '#POINT DETECTED '

              #LOOK AT PARTCOUNT FOR GEOMETRY
              checkforgeometry = feat.partCount
              #IF PART HAS GEOMETRY
              if checkforgeometry !=0:
                print '#IS MULTIPART  : '+ str(feat.isMultiPart)
                print '#PARTCOUNT     : '+ str(feat.partCount)
                print '#CENTROID      : '+ str(feat.centroid)
                #NOT ALL FIELDS EXSISTS FOR ALL TYPES
                ##LINE FIELDS
                if shapetype == 'polyline':
                  print '#LENGTH        : '+ str(feat.length)
                  print '#FIRST POINT   : '+ str(feat.firstPoint)
                  print '#LAST POINT    : '+ str(feat.lastPoint)
                ##POLY FIELDS
                if shapetype == 'polygon':
                  print '#AREA          : '+ str(feat.area)
                  print '#LENGTH        : '+ str(feat.length)
                  print '#FIRST POINT   : '+ str(feat.firstPoint)
                  print '#LAST POINT    : '+ str(feat.lastPoint)
                ##POINT FIELDS
                if shapetype == 'point':
                  print '#FIRST POINT   : '+ str(feat.firstPoint)
                  print '#LAST POINT    : '+ str(feat.lastPoint)


         
                ##########
                countpartswithgeo=countpartswithgeo+1
              if checkforgeometry==0:
                print 'NO GEOMETRY IN PART ' +str(countparts)
           
              countparts=countparts+1
              row = rows.Next()
          print '#########################'
          print 'TOTAL NUMBER OF PARTS '+str(countparts)
          print 'TOTAL NUMBER OF PARTS WITH GEOMETRY '+str(countpartswithgeo)
          #DELETE CURSOR OBJECT TO RELESE LOCKING
          if rows:
            del rows
          if row:
            del row
         
  ############################
  ###GET COUNT
  #first arg is total count(fields) , second is parts with geometry
  def countparts(self,fc):
       OUTPUT = [] #first arg is total, second is parts with geometry
       self.clearAllInternals()
       desc = gp.Describe(fc)
       typeoffeature= str(desc.DataType )
       countparts = 0
       ##
       if typeoffeature == 'ShapeFile' :
          rows = gp.SearchCursor(fc)
          row = rows.Next()
          countpartswithgeo =0
          while row:
              feat = row.shape
              shapetype= str(feat.Type)
              checkforgeometry = feat.partCount
              if checkforgeometry !=0:
                 countpartswithgeo=countpartswithgeo+1
              ##
              countparts=countparts+1
              row = rows.Next()
          #DELETE CURSOR OBJECT TO RELESE LOCKING
          if rows:
            del rows
          if row:
            del row
          OUTPUT.append(countparts)
          OUTPUT.append(countpartswithgeo)
          return OUTPUT
          
  ###
  def gatherCommonAttr(self):
     pass


########################################################################



#BEGIN
#foo = ESRI_ATTR_EDIT()

#SHAPEFILE = 'C:/data/Creswell_ForSale_W10.shp'
#DATABASE = 'C:/data/fucker.mdb'


###########################################
#READ ATTRNAMES,ATTRTYPES,AND ALL VALUES , INTO MEMORY FROM A FEATURE CLASS
#foo.readAttrs(SHAPEFILE)
#foo.export_to_data_tree(SHAPEFILE,'C:/reportt.txt')


##
#GET NUM ATTRS (SET FROM READ)
#print foo.NUMATTRS

#SHOW ALL ATTRTYPES
#print foo.ATTRTYPES
#SHOW ATTRNAME BY INDEX
#print foo.ATTRNAMES[3]
#SHOW ATTRVALUES BY INDEX
#print foo.ATTRVALUES[3]

#SHOW ALL FIELDS IN AN ARRAY
#print foo.ATTRNAMES
#print foo.ATTRVALUES
###################################

#TO CLEAR ALL MEMORY (BEFORE LOADING NEXT ATTR)
#foo.clearAllInternals()

###########################################
#ADD ATTR
#foo.addAttr(SHAPEFILE,'butrocker','text')
#foo.addAttr(SHAPEFILE,'ewew','float')
#foo.addAttr(SHAPEFILE,'ewew','long')
#foo.addAttr(SHAPEFILE,'ewew','double')
###########################################
#DELETE AN ATTR
#foo.delAttr(SHAPEFILE,'ewew')

###########################################

#WRITE ATTR

#inserttable = ['a','b','c','d','e','f','g','h','i','j','k','l','m','n','m']
#inserttable = [1.3,2.3,3.3,4.3,5.3,6.3,7.3,8.3,9.3,10.3,11.3,12.3,13.3,14.3,15.3]
#inserttable = [12,23,19,22,25,618,76,83,93,103,113,123,133,143,153]
#foo.writeAttrs(SHAPEFILE,'butrocker',inserttable)

###########################################
#GET GEOMETRY INFO
#foo.getGeoInfo(SHAPEFILE)
#####################################
#GET FIELD INFO
#foo.getFieldInfo(SHAPEFILE)

###########################################
#GET AN ATTRIBUTE (VALUE TABLE) BY NAME
#print foo.getFeatureAttr(SHAPEFILE,'NAME')

#GET AN ATTRIBUTE BY NAME AND VALUE ID
#print foo.getFeatureAttrValue(SHAPEFILE,'FID',5)

#GET AN ATTRIBUTE BY PART ?
#foo.getPartAttr(SHAPEFILE)

###########################################


###########################################

























###########################################


##MAPLOT STUFF

#objects   =['C:data/linez.shp'] #append list of objects
#attrtable =['1803071404700']   #list of numbers
#foo.filter_layers('MAPLOT',attrtable,objects)
#foo.getPartAttr
#foo.getAttrs('C:/data/linez.shp')









<pre>
Personal tools