Wednesday, July 27, 2011

Select the correct geographic (datum) transformation when projecting between datums

I recently had to change lots of data from one datum to another, and I found this help article from Esri very useful:  http://support.esri.com/en/knowledgebase/techarticles/detail/21327

Happy Projecting!

Monday, July 25, 2011

Printing Using Arcpy.mapping

The ArcGIS Server Blog has a great article covering gp printing from server.  I highly recommend that anyone who wants to export maps to PDFs or automate printing go to this site: http://blogs.esri.com/Dev/blogs/arcgisserver/archive/2011/04/12/An-introduction-to-arcpy.mapping-for-ArcGIS-Server-developers.aspx

Enjoy

Thursday, July 21, 2011

Wednesday, July 20, 2011

Extract Package

Extracts the contents of a layer or map package to a specified folder. The contents of the output folder is updated with the contents of the input package.


Example: Extract a Layer Package

import arcpy
import os
package = arcpy.GetParameterAsText(0)
destinationFolder = arcpy.GetParameterAsText(1)

extracted = destinationFolder + os.sep + 'unpackedLayers'

arcpy.ExtractPackage_management(package, extracted)

arcpy.SetParameterAsText(2,extracted)

Tuesday, July 19, 2011

Create a Layer Package

The layer package allows users to consolidate all your data resources into a single folder or compressed file.  The tools help users organize data that can be spread across the network.  The layer package also allows users to Share data by making it easy to publish the package to ArcGIS.com. 


Some interesting notes:

  • Layer packages are backwards compatible with ArcGIS 9.3.1.

  • A warning is issued when this tool encounters an unsupported layer type (a schematics or tool layer).

  • For layers that contain a join or participate in a relationship class, all joined or related data sources will be consolidated into the output folder.
  • The Schema Only parameter, if checked, will only consolidate the schema of the input data source(s).



Example of Consolidating all Layers:

import arcpy
import os

env.workspace = r"c:\temp"
listLayers = arcpy.ListFiles("*.lyr")
arcpy.PackageLayer_management(listLayers, 'packagelayers.lpk', "PRESERVE", "CONVERT_ARCSDE", "#", "ALL", "ALL", "CURRENT")

Monday, July 18, 2011

Testing for Schema Locks

TestingSchemaLock tests if a feature class or table has a schema lock.  Any tool that alters schema will require a schema lock to be placed on the input data.  If a tool requires a schema lock and is unable to acquire one an error message is provided.


import arcpy
data = arcpy.GetParameterAsText(0)
isLocked = arcpy.TextSchemaLock(data)
if lockTest:
   arcpy.AddField_management(data,"Flag","long")
else:
   print "Unable to acquire the necessary schema lock to add the new field"

Thursday, July 14, 2011

Removing Illegal Characters and Preventing Unicode Errors

I hate unicode errors like the one below, and I kept getting them intermediately on a table I was writing some scripts against.  Here is an example of an error I received:
UnicodeEncodeError: 'ascii' codec can't encode characters in position 1-4:
ordinal not in range(128)


After much internal debate, I decided to just remove the illegal characters when exporting or reading values in that table.  First I check to see if the value returned is a unicode type, then I apply my operation.

userValue = row.getValue(field)
if type(userValue) is unicode:
   val = ''.join([x for x in userValue if ord(x) < 128]) 

   # do something with val #
Now, the illegal characters are gone!

Here is a simpler example using IDLE:

>>> userValue = "abcdéf"
>>> val = ''.join([x for x in userValue if ord(x) < 128])
>>> print val
abcdf

Notice that the function just removed the é value and produced 'abcdf'.

Hope this helps!

Wednesday, July 13, 2011

Creating Extent Polygons Using ArcPy

Awhile ago I wrote an article about creating extent polygons using the old arcgisscripting geoprocessing framework at version 931.  I've decided to update the posting because ArcPy makes it easy because you can easily get the extent object of a geometry and directly grab the extent point objects from the extent object.

To create an extent of the whole dataset use the describe method:

import arcpy
from arcpy import env
import os

inFC = r"c:\temp\USA.gdb\States"
extentPoly = str(env.scratchWorkspace) + os.sep + "extent.shp"
# Feature extent
#
extent = arcpy.Describe(inFC).extent
# Array to hold points
#
array = arcpy.Array()
# Create the bounding box
array.add(extent.lowerLeft)
array.add(extent.lowerRight)
array.add(extent.upperRight)
array.add(extent.upperLeft)
# ensure the polygon is closed
array.add(extent.lowerLeft)
# Create the polygon object
polygon = arcpy.Polygon(array)
array.removeAll()
# save to disk
arcpy.CopyFeatures_management(polygon, extentPoly)
del polygon

That should create a box around all your data in a feature class. Very simple!

Next, let's say you need the bounding box for each feature. In the example, I will continue with using a states polygon:

import arcpy
from arcpy import env
import os


env.overwriteOutput = True

inFC = r"c:\temp\USA.gdb\States"
extentPoly = str(env.scratchWorkspace) + os.sep + "extent.shp"
ptList = []
rows = arcpy.SearchCursor(inFC)

for row in rows:
   extent = row.Shape.extent
   array.add(extent.lowerLeft)
   array.add(extent.lowerRight)
   array.add(extent.upperRight)
   array.add(extent.upperLeft)
   array.add(extent.lowerLeft)
   polygon = arcpy.Polygon(array)
   ptList.append(polygon)
   array.removeAll()
del rows
arcpy.CopyFeatures_management(ptList, extentPoly)

In this code sample, it loops through the feature class and write the bounding box geometry to a python list. That list is then given as an input to CopyFeatures() and it writes it to disk. Notice that you can get the extent right from the Shape value from the row object. This makes life easy.

Here is a image of what the lower 48 would look like as extents:
The white lines are the extents.

Enjoy

Tuesday, July 12, 2011

Scripting Cache Clearing for ArcGIS Server

If you work with ArcGIS Server and publish geoprocessing task, you know that you need to clear the cache quite a bit at times.  Here is a script to help automate that process:
*** NOTE: THIS SHOULD NEVER BE PUBLISHED TO SERVER OR PUT IN A PRODUCTION ENVIRONMENT, USE AT YOUR OWN RISK ***



import urllib
import urllib2
import os
import json

import arcpy

username = str(arcpy.GetParameterAsText(0))
password = str(arcpy.GetParameterAsText(1))
baseAdminLoginURL = str(arcpy.GetParameterAsText(2))#example: "http://server/ArcGIS/rest/admin" #
baseTokenURL = baseAdminLoginURL + r"/generatetoken"
baseAdminURL = baseAdminLoginURL + r"/cache/clear"

#
# Get the TOKEN from the SERVER
#
try:
   tokenurl = baseTokenURL + r"?" + urllib.urlencode({"username":username}) + \
   "&" + urllib.urlencode({"password":password}) + \
   "&ip=&referer=&client=requestip&expiration=525600&f=json"
   token_request = urllib2.Request(tokenurl)
   response = urllib2.urlopen(token_request)
   json_raw = response.read()
   json_object = json.loads(json_raw)
   response.close()
   token = json_object['token']
   #
   # Clear the Cache from the Server
   #
   cache_url = baseAdminURL + "?token=" + token + "&f=json"
   cache_request = urllib2.Request(cache_url)
   response = urllib2.urlopen(cache_request)
   json_raw = response.read()
   json_object = json.loads(json_raw)
   response.close()
   arcpy.AddMessage(json_raw)
   print json_raw
   arcpy.SetParameterAsText(3, json_raw)
except:
   print 'could not clear cache'
   arcpy.AddError("COULD NOT CLEAR THE CACHE")


All you need to do after you get this script working is to create a toolbox and a tool reference and have the 3 text inputs of type string and 1 derived output of type text.

And just in case you missed this:
*** NOTE: THIS SHOULD NEVER BE PUBLISHED TO SERVER OR PUT IN A PRODUCTION ENVIRONMENT, USE AT YOUR OWN RISK ***

Monday, July 11, 2011

Moving Layer Position in Table of Contents

In the arcpy.mapping module there is a function called MoveLayer() which allows developers to move a layer to a specific location within a data frame or group layer in a map document.  It does not give you the ability to move layers between data frames and the moved layer and reference layer must reside in the same data frame as well.

To move layers between data frames, use the Add Layer, Insert Layer and Remove Layer functions.

Example: Move Layer Position

import arcpy
from arcpy import mapping
for lyr in mapping.ListLayers(mxd,"",df):
   if lyr.name == "layer1":
      moveLayer = lyr
   if lyr.name == "layer2":
      refLayer = lyr
mapping.MoveLayer(df,refLayer,moveLayer,"AFTER")
mxd.save()
del mxd

The final result will be that layer1 is below layer2:






Enjoy

Wednesday, July 6, 2011

Kicking off Idle Users from Windows Server

When working with servers that you remote into, sometimes people forget to log off, so you need to boot them. 

To query who is logged into a machine, do the following from the command prompt:

query session /server:SERVERNAME


You will be given the user's ID number to boot. Take that number, and boot the person:

rwinsta /server:SERVERNAME 1


Now you can log in.

Tuesday, July 5, 2011

Resetting Scripting Environmental Variables

To reset an environmental variable in ArcPy, use the ClearEnvironment().  This function will reset the environmental variable to it's default value.

Example: Setting then Clearing the Scratch Workspace

>>> import arcpy
>>> from arcpy import env
>>> env.scratchWorkspace = r"c:\temp"
>>> print env.scratchWorkspace
c:\temp
>>> arcpy.ClearEnvironment("scratchWorkspace")
>>> print env.scratchWorkspace
None


To learn more, check out the webhelp link.

Enjoy

Friday, July 1, 2011

ArcPy - Looking inside Group Layers

A group layer contains other layers. Group layers help organize related kinds of layers in a map and can be used to define advanced drawing options. For example, suppose you have two layers on a map representing railroads and highways. You could group these layers together and name the resulting layer Transportation Networks. If you need to, you can even create nested group layers (groups of group layers). (source: esri)

Now, let's say you have to do some analysis on layers inside the group layers, you can loop the layers as follows:


import arcpy
mxdPath = r"c:\temp\mapDoc.mxd"
mxd = arcpy.mapping.MapDocument(mxdPath)
layers = arcpy.mapping.ListLayers()
for layer in layers:
if layer.isGroupLayer:
for subLayer in layer:
print "This layer is in a group layer: " + str(subLayer.name)



This will print a list of layer contained in a groupLayer.