4

I am clipping a raster image to each polygon row in a shapefile in ArcMap 9.3 using the Clip tool (Data Management) in Python with Clipping Geometry set. While the clipped raster successfully depicts the intersection of the raster and the polygon, the extent of the clipped raster is still that of the original raster. Here is my code:

# Import system modules 
import sys
import string
import os
import arcgisscripting  
# Create the Geoprocessor object
gp = arcgisscripting.create(9.3)
# Load required toolboxes...
gp.AddToolbox("C:/Program Files (x86)/ArcGIS/ArcToolbox/Toolboxes/Data Management Tools.tbx")
# Designate a workspace
gp.workspace = "L:\Clip"  # Assign variables... 
clipto = "test.shp"  # shapefile to clip to 
clipit = "vfcm.tif" # features to be clipped  

# Cursor time
rows = gp.SearchCursor(clipto)
row = rows.Next()

# clip management
while row:
    n = str(row.VAHU6) # assign a variable for the processing message based on a field
    clipgeo = row.Shape
    print "clipping to: " +n # tells what row was clipped
    # Clip_management <in_raster> <rectangle> <out_raster> {in_template_dataset}   {nodata_value} {NONE | ClippingGeometry} 
    outputname = str(row.VAHU6) + "_c" 
    extent=str(clipgeo.extent)
    gp.Clip_management(clipit, extent, outputname, clipgeo, "", ClippingGeometry) 
    #update str if necessary
    print str(row.VAHU6)
    row=rows.next()

# reset the array...
del rows
del gp

Do you know why I am having this problem? When I run the tool in Model Builder, it works correctly. This problem is evident both in the file size (which is 10x greater than when correctly clipped) and when I "zoom to layer" in ArcMap. If you know how to adjust the code to work, I'd be very appreciative!

UPDATE: Even if I export one polygon from the shapefile manually, look up the extent in the source tab, and then type those coordinates directly into the extent in my code, it still doesn't clip properly.

4 Answers 4

4

cross-posting this solution to this thread AND user3397's other thread

@lpinner was on the right track, by stating that the extent being used is the entire extent of the 'clipto' shapefile. This is an underlying attribute of that shapefile, and doesn't change according to the current feature being processed by a cursor. So, every time you're feeding the extent object into the Clip tool, you're giving it this same overall extent, over and over.

You can manipulate the output by changing the Extent environment setting - this is done by setting the gp.Extent property. In my experience, there are two different ways of doing this:

  1. the legacy method involved getting and setting the extent as a space-delimited string,
  2. the newer (9.3+ I think) method involves instantiating an 'Extent' object, and getting and setting its Xmax, YMax, etc properties

Option 1: legacy method

# Set extent property with a space-delimited string
# extents should be in this order: XMin YMin XMax YMax 
gp.Extent = "-180 -90 180 90"

Option 2: modern method

# Create Extent object, and set its attributes
ext = gp.CreateObject('Extent')
ext.XMin, ext.YMin, ext.XMax, ext.YMax = -180, -90, 180, 90
gp.Extent = ext

I'm not sure which ArcGIS versions restrict you to which method (off the top of my head, I think you can do both in 9.3+, but you can't do Option 2 in 9.2-).

So, to solve your problem, you need to extract the XMin, YMin, XMax and YMax lat/longs from each polygon, and change gp.Extent every time. I.e.:

while row:
    # do your other processing and extract extent co-ords from current polygon        
    ext = gp.CreateObject('Extent')
    ext.XMin, ext.YMin, ext.XMax, ext.YMax = currentXMin, currentYMin, currentXMax, currentYMax
    gp.Extent = ext
    gp.Clip_management #...continue with Clip operation

A third option, I guess, would be to write each polygon to a new temporary feature class. This temporary FC's Extent property would then be the same as the individual polygon's extent. This would be a slow operation if you wrote these temp files to disk, but you can write them to ArcGIS's 'in_memory' workspace to keep it nippy. I.e.:

# Get the primary key field name for the polygon shapefile
oidField = gp.Describe(clipit).OIDFieldName

while row: # Iterate through each polygon
    oid = row.GetValue(oidField) # get the unique id for this polygon

    # Use Select tool to extract individual polygon to temporary in_memory file
    # use the unique ID as the SQL query to extract this record
    gp.Select_management(clipit, 'in_memory/temp', '"%s" = %s' % (oidField, oid))  

    # get the polygon's extent
    ext = gp.Describe('in_memory/temp').Extent

From here, you can either use this in_memory/temp polygon as ClippingGeometry for the raster Clip tool, or you can extract the Extent object's values and feed them into the Clip tool's 'extent' parameters as text.

I'll cut my answer off here, and wait and see if it helps. I can clarify any points some more my referring to my scripts at work - I'm writing this off the top off my head at the moment.

1
  • I copied and pasted the code you wrote into my script, but the current extents (ie "= currentxmin") didn't work. Also, I've extracted each of the polygons into individual shapefiles, and when I use your script to get their extent and then copy and paste that extent into my clipping code, I have the same problem.
    – user3397
    Commented Jun 22, 2011 at 21:41
3

You are setting the extent to the entire featureclass "clipto". Instead, set the extent to that of the "clipgeo" geometry - i.e. extent=str(row.getvalue(shape).extent) or extent=str(clipgeo.extent)

You could also try ensuring the extent environment variable is set:

gp.extent=extent
gp.Clip_management(clipit, extent, outputname, clipgeo, "", ClippingGeometry) 
4
  • Unfortunately, that doesn't work either. It still keeps the same file size and extent. I read somewhere that python doesn't even use the extent specified if ClippingGeometry is activated. I don't know whether that's true or not, but I'm still not sure how to resolve this issue...
    – user3397
    Commented Jun 20, 2011 at 10:50
  • 1
    @user3397 Please update your code in the opening post so we can see what you have tried.
    – Nathanus
    Commented Jun 20, 2011 at 12:22
  • @Nathanus Just did, and I added an update at the bottom. Thanks for trying to figure this out.
    – user3397
    Commented Jun 20, 2011 at 23:35
  • @user3397 - I've updated my answer.
    – user2856
    Commented Jun 21, 2011 at 6:09
2

If you want to select a particular region on a raster data set, use masking in the raster analysis environment.[for arcgis 9.3]

For arcgis 10. I would recommend you to use Extract by mask tool in the spatial analyst toolbox. And ofcourse in arcgis 10, you can use python script.

1

Have you tried quoting the last argument?

gp.Clip_management(clipit, extent, outputname, clipgeo, "", ClippingGeometry)

gp.Clip_management(clipit, extent, outputname, clipgeo, "", "ClippingGeometry")

1
  • Thanks for the suggestion. I tried that and it's still not working.
    – user3397
    Commented Jun 20, 2011 at 23:24

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.