Annotation and da.UpdateCursor

1719
8
11-04-2013 05:08 PM
AdamCrateau
New Contributor III
Hello,

Has anyone used da.UpdateCursor on annotation feature classes?

My workflow involves copying the fields <i>HorizontalAlignment</i> and <i>VerticalAlignment</i> into place holder fields, manipulating the annotation symbology, and then copying back in the original values from the place holder fields.

I've noticed a curious behavior. The following script using the old, 10.0 cursor works as expected:

cursor = arcpy.UpdateCursor(fc)
for row in cursor:
[INDENT]row.HorizontalAlignment = row.HorzAlign2 # where HorzAlign2 is the place holder field[/INDENT]
[INDENT]row.VerticalAlignment = row.VertAlign2[/INDENT]
[INDENT]cursor.update(row)[/INDENT]
del row, cursor

Whereas, the same logic with the data access cursor does not:

cursor = arcpy.UpdateCursor(fc, ["HorizontalAlignment", "VerticalAlignment", "HorzAlign2", "VertAlign2"])
for row in cursor:
[INDENT]row[0]= row[2][/INDENT]
[INDENT]row[1] = row[3][/INDENT]
[INDENT]cursor.update(row)[/INDENT]
del row, cursor

The good news is that the data access cursor runs 3 times as fast. The bad news: though the values for each row are correct, they don't display correctly in ArcMap. For example, an annotation with HorizontalAlignment of LEFT will display with an alignment of CENTER, which is the default value. If I start an editing session and change the value from LEFT to CENTER, and then back to LEFT,, Then it displays correctly.

Any ideas?
Tags (2)
0 Kudos
8 Replies
XanderBakker
Esri Esteemed Contributor
Hi Adam,

Not sure why the update cursor doesn't change the values, but the 2nd sample you provide is not making use of the arcpy.da.UpdateCursor. Furthermore the update statement should be "cursor.updateRow(row)":

fields = ["HorizontalAlignment", "VerticalAlignment", "HorzAlign2", "VertAlign2"]
with arcpy.da.UpdateCursor(fc, fields) as cursor:
    for row in cursor:
        row[0]= row[2]
        row[1] = row[3]
        cursor.updateRow(row)
    del row


Kind regards,

Xander
0 Kudos
AdamCrateau
New Contributor III
Thank you Xander,

I apologize, I was away from my workstation and guessed wrong on the syntax for the UpdateRow() method.  Also, forgot to add the '.da.' to the second example, but it was in my script.

Basically my code is the same as yours except that I used
cursor = arcpy.da.UpdateCursor(fc, fields)

instead of
with arcpy.da.UpdateCursor(fc, fields) as cursor:.

Would that make a difference?  Also, I should point out that the field I am working with is a CVD.
0 Kudos
XanderBakker
Esri Esteemed Contributor
Basically my code is the same as yours except that I used
cursor = arcpy.da.UpdateCursor(fc, fields)

instead of
with arcpy.da.UpdateCursor(fc, fields) as cursor:

Would that make a difference?


Hi Adam,

In the Help is states:
Using a with statement will guarantee close and release of database locks and reset iteration.

It is better using the with statement when working with data access cursors. It is also not necessary to delete the cursor afterwards.

Also, I should point out that the field I am working with is a CVD.


Could you explain to me what you mean with "CVD"?

Xander
0 Kudos
AdamCrateau
New Contributor III
Xander, Thank you for the tip on the with statement. I'll use that from now on.



Could you explain to me what you mean with "CVD"?


The annotation properties HorizontalAlignment and VerticalAlignment behave at least like value domains.  For example, the field HorizontalAlignment uses the domain HorizontalAlignment, which has the following coded values:

0 - Left
1 - Center
2 - Right
3 - Full

When I copy these fields into place holder fields I use the following code:

arcpy.AddField_management(TaxMapAnno,"VertAlign2","SHORT","","","","","","","VerticalAlignment")
arcpy.AddField_management(TaxMapAnno,"HorzAlign2","SHORT","","","","","","","HorizontalAlignment")

rows = arcpy.UpdateCursor(TaxMapAnno)

for row in rows:
   row.VERTALIGN2 = row.VERTICALALIGNMENT
   row.HORZALIGN2 = row.HORIZONTALALIGNMENT
   rows.updateRow(row)

# Delete row and rows to remove lock on data
del row
del rows


Then, when I calculate back the values from the place holder fields, I use the code we discussed above.
0 Kudos
AdamCrateau
New Contributor III
Xander,

I also tried the same code on non-value domain fields such as FontSize, and it behaves the same.  From what I can tell, the arcpy.da.updatecursor does not work with standard annotation attributes.

If you want to test this on your own:
1. Create an Annotation FC in a geodatabase.
2. Edit and add a few anno features with Font Size = 12.  Stop/Save edits and quit ArcMap
3. In Catalog, run the following code on this feature class:
import arcpy

fc = arcpy.GetParameterAsText(0)
fields = ('FontSize')

with arcpy.da.UpdateCursor(fc, fields) as cursor:
  for row in cursor:
    row[0] = 24


Now open the feature class in ArcMap again.  If you select one of the annotations, the attribute list will say 'FontSize = 24', but it will still be displaying at 12, or whatever it was originally.
0 Kudos
XanderBakker
Esri Esteemed Contributor
Hi Adam,

You are right that strange things happen with annotations. If you use the Field Calculator in an ArcMap session and calculate a new fontsize, it will directly display the changed annotation. If you use a cursor in Python to change the value, the value is changed, but this is not reflected in the map. Even after refreshing or removing the annotation and adding it again to the TOC.

import arcpy
fc = r'C:\Project\_Forums\anno\anno.gdb\linesAnno'

fields = ('FontSize')
with arcpy.da.UpdateCursor(fc, fields) as cursor:
    for row in cursor:
        row[0] = 20
        cursor.updateRow(row)
del row


It will work in case you actually use the Field Calculator tool from python code:

import arcpy
fc = r'C:\Project\_Forums\anno\anno.gdb\linesAnno'
fldFontSize = 'FontSize'
arcpy.CalculateField_management(fc,fldFontSize,"30","PYTHON_9.3")


After refreshing the map, the annotation will be drawn correctly.

Kind regards,

Xander
0 Kudos
AdamCrateau
New Contributor III
Thank you Xander for taking the time to look at this issue. 

Just also want to clarify:  the original arcpy cursors, e.g. arcpy.UpdateCursor(), work just fine with annotation.  FYI, they are not as fast as the new Data Access cursors, but are quite a bit faster than using the tool arcpy.CalculateField_management().  I've had the pleasure of timing all the above :rolleyes:


Best regards,
Adam
0 Kudos
XanderBakker
Esri Esteemed Contributor
Thank you Xander for taking the time to look at this issue. 

Just also want to clarify:  the original arcpy cursors, e.g. arcpy.UpdateCursor(), work just fine with annotation.  FYI, they are not as fast as the new Data Access cursors, but are quite a bit faster than using the tool arcpy.CalculateField_management().  I've had the pleasure of timing all the above :rolleyes:

Best regards,
Adam


Hi Adam,

That's true. Since this (unwanted) behaviour only applies to the da cursor, I think it's best to report it to Esri support.

Kind regards,

Xander
0 Kudos