Cannot reclassify raster with python

1704
9
08-06-2018 09:15 PM
TheWorm
New Contributor

I have a raster which originates from a large tiff file being clipped and resampled. The resulting raster resampled_raster retains the same projection and opens up just fine in arcmap.

I would like to reclassify resampled_raster using arcpy and assign the result to a variable named reclassed_raster. Both resampled_raster and reclassed_raster are not string variables but rather variables of type <class 'arcpy.arcobjects.arcobjects.Result'> which should be fine for my purposes. I have been flinging these objects around in my script as geoprocessing inputs and outputs without any problems thus far.

The following command, when executed from cmd:

reclassed_raster = arcpy.gp.Reclassify_sa(resampled_raster, "Value", "1 1;2 1;3 1;4 1;5 1;NODATA 0", "reclass", "DATA")

throws an error:

return lambda *args: val(*gp_fixargs(args, True))
arcgisscripting.ExecuteError: ERROR 999999: Error executing function.
General function failure This spatial reference object cannot be
defined from the available information. Failed to execute
(Reclassify).

Strangely, when I try to reclass my raster (the same exact one) through an arcmap session I don't have any problems, it reclasses just fine.

I also googled the error to see if any potential solutions or workarounds exist and I came across this link, which claims the following:

Cause This is expected behavior, as there are certain naming
restrictions set for the grid raster format. The naming restrictions
include special characters, which are not supported by the grid raster
format. Special characters may include accents and umlauts as well as
non-alphanumeric characters.

Solution or Workaround Rename the folder to ensure the path name of
the raster dataset does not contain special characters, or move the
raster file to a directory containing no special characters.

But in my case my directory contains no special characters. I tried different possibilities such as adding the name of the output raster in my function call, not assigning the result to a `reclassed_raster` variable and other obvious variations, but to no avail.

I need to be able to reclass this raster through cmd so I don't have to babysit my script. What could be the problem here? Why does it run OK in arcmap but not in my script through cmd?

0 Kudos
9 Replies
DanPatterson_Retired
MVP Emeritus

when you are running outside of arcmap or pro, you need to be particular about specifying your environment or using full path names to your data.  Are you wanting to run a script as a scheduled task?  I would not be surprised that you didn't get other error messages given the information that you have provided.  What information preceeded the line you posted?  If you are running a script, can you provide it in full using code syntax highlighting.  

0 Kudos
TheWorm
New Contributor

Hi Dan, thanks for your response. I have attached the full scripts to my original question. The problematic line is line 100. test.py is the main script. force_zonal.py is called by test.py at line 123 but I really don't think it will have an impact on the reclassify problem. I've just included here for completeness. If you cannot find the scripts, please let me know and I'll provide another link for you to download them.

0 Kudos
DanPatterson_Retired
MVP Emeritus

resampled_raster… is that on disk? or in memory? it is hard to tell since you are switching around it appears.

You can reclass the raster within arcmap/pro since all the information to do so can be found.  It appears that when the script is run outside, something is indeed missing in order to complete the reclassification

0 Kudos
TheWorm
New Contributor

resampled_raster is on disk. I want for reclassed_raster to get dumped to disk also. Stepping out of the script to run an entire arcmap session for a simple reclass is definitely something I'd like to avoid. I'd like to try to resolve the source of this problem. Line 76 takes hours to run, and once its done I expect line 123 also to take hours. Furthermore I will have to make sure this script can run for several input datasets. I have to start the script and let it run overnight. Interrupting the whole process by reclassifying in ArcMap is not an option I'm afraid. 

0 Kudos
DuncanHornby
MVP Notable Contributor

I followed the link from GIS Stack exchange to review your scripts and I have a few comments:

  1. You are saying you have some long run times and I note your inputs are shapefiles, make sure your have built spatial indices for all input shapefiles, this will speed up certain types of operations.
  2. Geoprocessing tools return RESULT objects, which you can query for the output and a bunch of other properties such as did it actually succeed. In your Test.py code line 47, you do not provide the correct parameters for the buffer tool, the second parameter is the output featureclass, so where has it gone? I guess ArcMap has defaulted to some other location and you assign the result of the buffer tool to "extraction_buffer". I personally think this is bad coding as "extraction_buffer" is really a result object which you would then query for output/success.
  3. I feel you make the same confusing mistakes on lines 23, 35 &  57, you are passing result objects around and treating them as datasets which makes reading the code very confusing and may possibly be the source of your problem? For example does the result object expose the spatial reference of the output, may be the tool is trying to extract that unsuccessfully?
  4. For track-ability you are writing some of your datasets to the workspace as defined by the python command os.getcwd(), so where is that? Some sub-folder in your user profile I suspect? Better off defining it precisely such as r"C:\Temp".

Some ideas to follow.

DanPatterson_Retired
MVP Emeritus

would have been nice to know that there was a parallel thread going.

you can take over Duncan

0 Kudos
DuncanHornby
MVP Notable Contributor

I would never step on your toes!

0 Kudos
TheWorm
New Contributor

Thanks for taking a look. I will address items 2 and 3 from your post. 1 and 4 are important and relevant, however I don't believe they are causing the issue at hand. My responses are as follows:

2. I am doing this because, in my humble opinion, the following is quite redundant (alternate to line 35):

extraction_buffer = arcpy.Buffer_analysis(in_features=input_shapefile, out_feature_class = 'extraction_buffer', buffer_distance_or_field=mask_extraction_buffer_size_as_string, line_side="FULL", line_end_type="FLAT", dissolve_option="ALL", dissolve_field="", method="PLANAR")

I don't like the idea of having to specify both the out_feature_class as 'extraction_buffer' while instantiating the variable in my script. This result being intermediate, it's name should be completely irrelevant. I am intentionally omitting the output file name and letting arcpy choose an arbitrary name for it. I only want to keep a reference to it such that I can use it in a subsequent geoprocessing operation.

Of course I could do this instead:

arcpy.Buffer_analysis(in_features=input_shapefile, out_feature_class = 'extraction_buffer', buffer_distance_or_field=mask_extraction_buffer_size_as_string, line_side="FULL", line_end_type="FLAT", dissolve_option="ALL", dissolve_field="", method="PLANAR")

But then I would not be able to place it as part of some internal pythonic data structure if I wanted to (such as a list or dict). I'd always have to refer to it by 'extraction_buffer' as a string which is somehow annoying to me.I want the thing as an object. I'm sure arcpy has a way to do this? Aren't arcpy.FeatureSet and arcpy.Raster class types which represent feature classes or rasters? I used those in lines 20 and 21...

3. It's quite likely that the resultobject has no spatial reference. If so then I would ask the following: how can I set the results of geoprocessing operations such that I don't have to worry about their file name and extension, and such that they retain all their geospatial properties including projection/spatial reference?

Sorry for the long-winded response, but I hope it clarifies things. Thanks!

0 Kudos
DuncanHornby
MVP Notable Contributor

I would code some thing like this, as you can see I call my result object something sensible like res for result! Interrogate it to see if the buffer tool actual ran and as the output of a buffer tool is a FeatureClass I convert that into a layer object which I'm referencing by name with the string extraction_buffer_layer . You could argue that your approach uses less code but I think my approach is more transparent which should help you track down the source of the error.

import os
import arcpy

#check out extension in arcpy
arcpy.CheckOutExtension("Spatial")

input_raster_path = r"D:\GIS\GIS Data\nm50_dem"
input_raster = arcpy.Raster(input_raster_path)

# Layer names
extraction_buffer_layer = "extraction_buffer_layer"

#Set environment
arcpy.env.overwriteOutput = True
arcpy.env.workspace= r"C:\scratch"

res = arcpy.Buffer_analysis("test.shp","buffered.shp",100)
if res.status == 4:
    # Success OK to continue

    arcpy.MakeFeatureLayer_management("buffered.shp",extraction_buffer_layer)
    extracted_raster = arcpy.gp.ExtractByMask_sa(input_raster, extraction_buffer_layer)
else:
    print("Someting went wrong!")‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍
0 Kudos