root/MGET/Branches/Jason/PythonPackage/src/GeoEco/DataManagement/ArcGISRasters.py @ 877

Revision 877, 211.8 KB (checked in by jjr8, 17 months ago)

Added Project Raster To Template tool.

Line 
1# ArcGISRasters.py - Provides methods for performing common data management
2# operations on ArcGIS rasters.
3#
4# Copyright (C) 2007 Jason J. Roberts
5#
6# This program is free software; you can redistribute it and/or
7# modify it under the terms of the GNU General Public License
8# as published by the Free Software Foundation; either version 2
9# of the License, or (at your option) any later version.
10#
11# This program is distributed in the hope that it will be useful,
12# but WITHOUT ANY WARRANTY; without even the implied warranty of
13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14# GNU General Public License (available in the file LICENSE.TXT)
15# for more details.
16#
17# You should have received a copy of the GNU General Public License
18# along with this program; if not, write to the Free Software
19# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
20
21import glob
22import locale
23import math
24import os
25import random
26import re
27import sys
28
29from GeoEco.ArcGIS import GeoprocessorManager, ArcGISDependency, ArcGISExtensionDependency
30from GeoEco.DatabaseAccess import DatabaseConnection, InsertCursor
31from GeoEco.DatabaseAccess.ArcGIS import ArcGIS91DatabaseConnection
32from GeoEco.Dependencies import ImportGDALModule, SetGDALDataEnvVar, ResetGDALDataEnvVar
33from GeoEco.DynamicDocString import DynamicDocString
34from GeoEco.GeoArray import GeoArray, GDALDataset
35from GeoEco.Internationalization import _
36from GeoEco.Logging import Logger
37from GeoEco.Types import EnvelopeTypeMetadata
38
39
40class GeoArrayArcGISRasterLayer(GeoArray):
41    __doc__ = DynamicDocString()
42
43    # Constructor and destructor.
44
45    def __init__(self, raster):
46        # TODO: cls.__doc__.Obj.ValidateMethodInvocation()
47        super(GeoArrayArcGISRasterLayer, self).__init__()
48       
49        self._Raster = raster
50        self._TempDir = None
51        self._TempRaster = None
52        self._GDALDataset = None
53
54        self._PropertiesRetrieved = False
55        self._Width = None
56        self._Height = None
57        self._Bands = None
58        self._CellSize = None
59        self._XUpperLeftCorner = None
60        self._YUpperLeftCorner = None
61        self._XMinCoords = None
62        self._YMaxCoords = None
63
64        if GeoprocessorManager.GetArcGISMajorVersion() > 9 or GeoprocessorManager.GetArcGISMajorVersion() == 9 and GeoprocessorManager.GetArcGISMinorVersion() >= 2:
65            self._DataTypeForBand = None
66            self._NoDataValueForBand = None
67            self._MinValueForBand = None
68            self._MaxValueForBand = None
69
70    def __del__(self):
71        self._Close()
72
73    def _Close(self):
74        self._GDALDataset = None
75        self._TempDir = None
76
77    # Overridden properties of GeoArray.
78
79    def _GetSpatialReference(self):
80        if not self._PropertiesRetrieved:
81            self._RetrieveProperties()
82        return super(GeoArrayArcGISRasterLayer, self)._GetSpatialReference()
83
84    def _GetSpatialReferenceESRI(self):
85        if not self._PropertiesRetrieved:
86            self._RetrieveProperties()
87        return super(GeoArrayArcGISRasterLayer, self)._GetSpatialReferenceESRI()
88
89    def _GetWidth(self):
90        if not self._PropertiesRetrieved:
91            self._RetrieveProperties()
92        return self._Width
93
94    def _GetHeight(self):
95        if not self._PropertiesRetrieved:
96            self._RetrieveProperties()
97        return self._Height
98
99    def _GetXMinCoords(self):
100        if self._XMinCoords is None:
101            if not self._PropertiesRetrieved:
102                self._RetrieveProperties()
103            self._XMinCoords = map(lambda x: self._XUpperLeftCorner + x*self._CellWidth, range(self._Width))
104        return self._XMinCoords
105
106    def _GetYMaxCoords(self):
107        if self._YMaxCoords is None:
108            if not self._PropertiesRetrieved:
109                self._RetrieveProperties()
110            self._YMaxCoords = map(lambda x: self._YUpperLeftCorner - x*self._CellHeight, range(self._Height))
111        return self._YMaxCoords
112
113    def _GetCellWidth(self):
114        if not self._PropertiesRetrieved:
115            self._RetrieveProperties()
116        return self._CellWidth
117
118    def _GetCellHeight(self):
119        if not self._PropertiesRetrieved:
120            self._RetrieveProperties()
121        return self._CellHeight
122
123    def _GetBands(self):
124        if not self._PropertiesRetrieved:
125            self._RetrieveProperties()
126        return self._Bands
127
128    SpatialReference = property(_GetSpatialReference, doc=DynamicDocString())
129    SpatialReferenceESRI = property(_GetSpatialReferenceESRI, doc=DynamicDocString())
130
131    Width = property(_GetWidth, doc=DynamicDocString())
132    Height = property(_GetHeight, doc=DynamicDocString())
133
134    XMinCoords = property(_GetXMinCoords, doc=DynamicDocString())
135    YMaxCoords = property(_GetYMaxCoords, doc=DynamicDocString())
136
137    CellWidth = property(_GetCellWidth, doc=DynamicDocString())
138    CellHeight = property(_GetCellHeight, doc=DynamicDocString())
139
140    Bands = property(_GetBands, doc=DynamicDocString())
141
142    # Overridden methods of GeoArray.
143
144    def _GetDataType(self, band):
145        if hasattr(self, '_DataTypeForBand'):
146            if band is None:
147                band = u'Band_1'
148            return self._DataTypeForBand[band]
149        if self._GDALDataset is None:
150            self._InstantiateGDALDataset()
151        return self._GDALDataset.GetDataType(band)
152
153    def _GetNoDataValue(self, band):
154        if hasattr(self, '_NoDataValueForBand'):
155            if band is None:
156                band = u'Band_1'
157            return self._NoDataValueForBand[band]
158        if self._GDALDataset is None:
159            self._InstantiateGDALDataset()
160        return self._GDALDataset.GetNoDataValue(band)
161
162    def _GetMinValue(self, band):
163        if hasattr(self, '_MinValueForBand'):
164            if band is None:
165                band = u'Band_1'
166            return self._MinValueForBand[band]
167        if self._GDALDataset is None:
168            self._InstantiateGDALDataset()
169        return self._GDALDataset.GetMinValue(band)
170
171    def _GetMaxValue(self, band):
172        if hasattr(self, '_MaxValueForBand'):
173            if band is None:
174                band = u'Band_1'
175            return self._MaxValueForBand[band]
176        if self._GDALDataset is None:
177            self._InstantiateGDALDataset()
178        return self._GDALDataset.GetMaxValue(band)
179
180    def _GetNumpyArray(self, band, sliceList, keepDatasetOpen):
181        if self._GDALDataset is None:
182            self._InstantiateGDALDataset()
183        return self._GDALDataset._GetNumpyArray(band, sliceList, keepDatasetOpen)
184
185    # Additional public methods.
186
187    @classmethod
188    def From2DGeoArray(cls, geoArray, raster, bands=None, projectedCoordinateSystem=None, geographicTransformation=None, resamplingTechnique=None, projectedCellSize=None, registrationPoint=None, clippingRectangle=None, mapAlgebraExpression=None, buildPyramids=False, overwriteExisting=False):
189        #self.__doc__.Obj.ValidateMethodInvocation() # TODO
190
191        # Perform additional parameter validation.
192
193        if geoArray.Depth is not None or geoArray.TimeSlices is not None:
194            Logger.RaiseException(ValueError(_(u'The input array has more than two dimensions. To be written to an ArcGIS raster, it must have exactly two dimensions.')))
195
196        if geoArray.CellWidth is None or geoArray.CellHeight is None:
197            Logger.RaiseException(ValueError(_(u'The input array does not have a constant cell width and/or cell height. To be written to an ArcGIS raster, it must have a constant cell width and cell height, and the two must be the same.')))
198
199        if geoArray.CellWidth != geoArray.CellHeight:
200            Logger.RaiseException(ValueError(_(u'The input array\'s cell width does not equal its height. To be written to an ArcGIS raster, the cell height and cell width must be the same.')))
201
202        # TODO: If multiband, validate that name is short enough
203
204        # Verify that the bands exist and that they all have supported
205        # data types. Note: if geoArray is a
206        # GeoArrayArcGISRasterLayer, assume that it is a supported
207        # data type.
208
209        if bands is None:
210            bands = geoArray.Bands
211
212        if bands is None:
213            if not isinstance(geoArray, GeoArrayArcGISRasterLayer) and geoArray.GetDataType() not in ['int8', 'uint8', 'int16', 'uint16', 'int32', 'uint32', 'float32']:
214                Logger.RaiseException(TypeError(_(u'The input array has the data type %(dt)s, which is not supported by this tool and/or ArcGIS. Please convert the array to one of the following data types and try again: int8, uint8, int16, uint16, int32, uint32, or float32.') % {u'dt': geoArray.GetDataType()}))
215        else:
216            for band in bands:
217                if band not in geoArray.Bands or not isinstance(geoArray, GeoArrayArcGISRasterLayer) and (geoArray.GetDataType(band) not in ['int8', 'uint8', 'int16', 'uint16', 'int32', 'uint32', 'float32']):
218                    Logger.RaiseException(TypeError(_(u'The band "%(band)s" of the input array has the data type %(dt)s, which is not supported by this tool and/or ArcGIS. Please convert the array to one of the following data types and try again: int8, uint8, int16, uint16, int32, uint32, or float32.') % {u'band': band, u'dt': geoArray.GetDataType(band)}))
219
220        # If geoArray is not a GeoArrayArcGISRasterLayer and the
221        # caller requested that we clip but did not request that we
222        # project, then use GeoArray to perform the clip in the
223        # coordinate system of the input array.
224
225        if not isinstance(geoArray, GeoArrayArcGISRasterLayer) and clippingRectangle is not None:
226            left, bottom, right, top = EnvelopeTypeMetadata.ParseFromArcGISString(clippingRectangle)
227            if projectedCoordinateSystem is None:
228                geoArray = geoArray.ClipToExtent(left, right, bottom, top)
229                clippingRectangle = None
230
231        # In order to choose the optimal processing steps, we need to
232        # know if the raster is multiband and if the destination is a
233        # geodatabase.
234
235        gp = GeoprocessorManager.GetWrappedGeoprocessor()
236
237        isMultiband = (bands is not None and len(bands) > 1)
238        rasterExt = os.path.splitext(raster)[1].lower()
239        parent = os.path.dirname(raster)
240        parentExt = os.path.splitext(parent)[1].lower()
241        grandparent = os.path.dirname(parent)
242        grandparentExt = os.path.splitext(grandparent)[1].lower()
243        destIsGeoDB = (re.match('[A-Za-z]:\\\\.+', raster) is None and re.match('\\\\\\\\[A-Za-z0-9_\\-]+\\\\.+\\\\.+', raster) is None) or \
244                      (parentExt == '.mdb' and os.path.isfile(parent) or parentExt == '.gdb' and os.path.isdir(parent)) or \
245                      (grandparentExt == '.mdb' and os.path.isfile(grandparent) or grandparentExt == '.gdb' and os.path.isdir(grandparent))
246
247        # If the final destination is an ArcInfo binary grid and
248        # copying the raster to that directory will cause ArcGIS
249        # to crash due to a bug, create temporary ArcInfo binary
250        # grids that will prevent the crash.
251
252        if not destIsGeoDB and len(rasterExt) <= 0:
253            tempRasters = ArcGISRaster.CreateTemporaryRastersToPreventArcGISCrash(parent, 1)
254        try:
255
256            # If the raster is not multiband, the processing is simpler.
257
258            if not isMultiband:
259
260                # If the geoArray is a GeoArrayArcGISRasterLayer, we
261                # can operate on it directly using ArcGIS
262                # geoprocessing tools. If the caller requested that we
263                # project, clip, or execute map algebra, create a
264                # temporary directory to the temporary rasters we'll
265                # need to create. (Otherwise we don't need to do this,
266                # because we will just be making a copy of the
267                # geoArray's raster.)
268
269                from GeoEco.DataManagement.Directories import TemporaryDirectory
270                tempDir = None
271               
272                if isinstance(geoArray, GeoArrayArcGISRasterLayer):
273                    tempRaster = geoArray._Raster
274                    if projectedCoordinateSystem is not None or clippingRectangle is not None or mapAlgebraExpression is not None:
275                        tempDir = TemporaryDirectory()
276
277                # But if the geoArray is not a
278                # GeoArrayArcGISRasterLayer, we must use GDAL to
279                # create a raster in the file system before calling
280                # any geoprocessing tools.
281
282                else:
283
284                    # If the destination is a .img or .tif file and
285                    # the caller did not request that we project,
286                    # clip, or execute map algebra, create the raster
287                    # directly at the final output location using
288                    # GDALDataset.From2DGeoArray. I do not yet know
289                    # how to get GDAL to build a raster attribute
290                    # table, so call ArcGIS's Calculate Statistics
291                    # tool to do this. Finally, build pyramids if
292                    # requested, and return.
293
294                    if not destIsGeoDB and rasterExt in ['.img', '.tif'] and projectedCoordinateSystem is None and clippingRectangle is None and mapAlgebraExpression is None:
295                        GDALDataset.From2DGeoArray(geoArray, raster, bands, calculateStatistics=False, overwriteExisting=overwriteExisting)
296                        gp.RefreshCatalog(os.path.dirname(raster))
297                        gp.CalculateStatistics_Management(raster)
298                        if buildPyramids:
299                            gp.BuildPyramids_Management(raster)
300                        return
301
302                    # Otherwise we must create one or more temporary
303                    # rasters as part of the processing. Create a
304                    # temporary directory and write a .img file to it.
305                    # It is not necessary to call ArcGIS's Calculate
306                    # Statistics on this raster because statistics
307                    # will be automatically calculated by the
308                    # subsequent operations.
309
310                    tempDir = TemporaryDirectory()
311                    tempRaster = os.path.join(tempDir.Path, u'raster.img')
312                    GDALDataset.From2DGeoArray(geoArray, tempRaster, bands, calculateStatistics=True)
313                    gp.RefreshCatalog(tempDir.Path)
314
315                # Do requested post processing operations, create the
316                # destination raster, and return.
317
318                cls._DoRasterPostProcessing(tempRaster, raster, tempDir, projectedCoordinateSystem, geographicTransformation, resamplingTechnique, projectedCellSize, registrationPoint, clippingRectangle, mapAlgebraExpression, buildPyramids)
319                return
320
321            # If the raster is multiband, we must perform the processing
322            # for each individual band in a temporary directory and then
323            # build a final multiband raster.
324
325            Logger.RaiseException(NotImplementedError(_(u'Multiband rasters are not supported yet. Please contact the author of this tool for assistance.')))
326               
327        # If we created temporary rasters to prevent an ArcGIS
328        # crash, delete them now.
329
330        finally:
331            if not destIsGeoDB and len(rasterExt) <= 0:
332                ArcGISRaster.DeleteTemporaryRastersThatPreventedArcGISCrash(tempRasters)
333
334    # Private methods.
335
336    @classmethod
337    def _DoRasterPostProcessing(cls, tempRaster, finalRaster, tempDir, projectedCoordinateSystem, geographicTransformation, resamplingTechnique, projectedCellSize, registrationPoint, clippingRectangle, mapAlgebraExpression, buildPyramids):
338
339        # If the caller did not request that we project, clip, or
340        # execute map algebra, just copy the existing temporary raster
341        # to the final destination. Due to the problems described in
342        # tickets #310 and #311, call Copy_mangement on ArcGIS 9.1,
343        # and CopyRaster_management on later versions.
344
345        gp = GeoprocessorManager.GetWrappedGeoprocessor()
346
347        if projectedCoordinateSystem is None and clippingRectangle is None and mapAlgebraExpression is None:
348            Logger.Debug(_(u'Copying %(in)s to %(out)s.') % {u'in' : tempRaster, u'out' : finalRaster})
349            if GeoprocessorManager.GetArcGISMajorVersion() <= 9 and GeoprocessorManager.GetArcGISMinorVersion() <= 1:
350                gp.Copy_Management(tempRaster, finalRaster)
351            else:
352                gp.CopyRaster_Management(tempRaster, finalRaster)
353
354        # Otherwise do the requested operations.
355
356        else:
357           
358            # Project the raster, if requested.
359           
360            if projectedCoordinateSystem is not None:
361                if clippingRectangle is None and mapAlgebraExpression is None:
362                    tempRaster2 = finalRaster
363                else:
364                    tempRaster2 = os.path.join(tempDir.Path, os.path.splitext(os.path.basename(tempRaster))[0].split('_')[0] + '_projected.img')
365
366                Logger.Debug(_(u'Projecting %(in)s to %(out)s.') % {u'in' : tempRaster, u'out' : tempRaster2})
367                if geographicTransformation is not None or registrationPoint is not None:
368                    gp.ProjectRaster_Management(tempRaster, tempRaster2, projectedCoordinateSystem, resamplingTechnique, projectedCellSize, geographicTransformation, registrationPoint)
369                else:
370                    gp.ProjectRaster_Management(tempRaster, tempRaster2, projectedCoordinateSystem, resamplingTechnique, projectedCellSize)
371
372                tempRaster = tempRaster2
373
374            # Clip the raster, if requested.
375
376            if clippingDataset is not None or clippingRectangle is not None:
377                if mapAlgebraExpression is None:
378                    tempRaster2 = finalRaster
379                else:
380                    tempRaster2 = os.path.join(tempDir.Path, os.path.splitext(os.path.basename(tempRaster))[0].split('_')[0] + '_clipped.img')
381
382                # If this is ArcGIS 9.2, pass tempRaster for the
383                # in_template_dataset parameter, to work around the
384                # 9.2 bug described in
385                # http://forums.esri.com/Thread.asp?c=93&f=1729&t=230897&mc=11.
386
387                Logger.Debug(_(u'Clipping %(in)s to %(out)s.') % {u'in' : tempRaster, u'out' : tempRaster2})
388                if GeoprocessorManager.GetArcGISMajorVersion() == 9 and GeoprocessorManager.GetArcGISMinorVersion() == 2:
389                    gp.Clip_Management(tempRaster, clippingRectangle, tempRaster2, tempRaster)
390                else:
391                    gp.Clip_Management(tempRaster, clippingRectangle, tempRaster2)
392
393                tempRaster = tempRaster2
394
395            # Execute map algebra, if requested.
396
397            if mapAlgebraExpression is not None:
398
399                # Replace all occurences of the string "inputRaster"
400                # in the mapAlgebraExpression with the value of the
401                # tempRaster variable.
402
403                if GeoprocessorManager.GetArcGISMajorVersion() >= 10:
404                    (mapAlgebraExpressionToExecute, numberOfReplacements) = re.subn(u'(?<!\w)(inputRaster)(?=$|\W)', lambda s: u' [' + tempRaster + u'] ', mapAlgebraExpression)
405                else:
406                    (mapAlgebraExpressionToExecute, numberOfReplacements) = re.subn(u'(?<!\w)(inputRaster)(?=$|\W)', lambda s: u' ' + tempRaster + u' ', mapAlgebraExpression)
407                if numberOfReplacements <= 0:
408                    Logger.RaiseException(ValueError(_(u'The map algebra expression must include the case-sensitive string "inputRaster".')))
409                if len(mapAlgebraExpressionToExecute) > 4000:
410                    Logger.RaiseException(ValueError(_(u'The map algebra expression is too long for the Spatial Analyst Single Output Map Algebra tool to execute. It must be no longer than 4000 characters.')))
411
412                # Execute the map algebra expression.
413               
414                Logger.Debug(_(u'Executing map algebra expression "%(expr)s", outputting to %(out)s.') % {u'expr' : mapAlgebraExpressionToExecute, u'out' : finalRaster})
415                gp.SingleOutputMapAlgebra_sa(mapAlgebraExpressionToExecute, finalRaster)
416                gp.RefreshCatalog(os.path.dirname(finalRaster))
417
418                # Sometimes the Single Output Map Algebra tool in
419                # ArcGIS 9.1 strips the projection information,
420                # causing the spatial reference to be displayed as
421                # "<Undefined>" in ArcCatalog. Handle this ArcGIS bug
422                # by defining the projection again. See MGET ticket
423                # #156 for more information.
424
425                if GeoprocessorManager.GetArcGISMajorVersion() == 9 and GeoprocessorManager.GetArcGISMinorVersion() == 1:
426                    Logger.Debug(_(u'Defining the projection again, to work around the ArcGIS 9.1 bug described in MGET ticket #156.'))
427                    if projectedCoordinateSystem is not None:
428                        gp.DefineProjection_Management(finalRaster, projectedCoordinateSystem)     # When we already know what the coordinate system should be, don't look it up
429                    else:
430                        gp.DefineProjection_Management(finalRaster, gp.Describe(tempRaster).SpatialReference)
431
432        # Build pyramids, if requested by the caller.
433
434        if buildPyramids:
435            Logger.Debug(_(u'Building pyramids for %(raster)s.') % {u'raster' : finalRaster})
436            gp.BuildPyramids_Management(finalRaster)
437
438        # Return successfully.
439       
440        return tempRaster
441
442    def _RetrieveProperties(self):
443        if self._PropertiesRetrieved:
444            return
445
446        # Use the ArcGIS geoprocessor to retrieve the raster's
447        # properties. If the geoprocessor has not been initialized
448        # yet, raise an exception. This should only occur when we're
449        # called by someone's program, rather than an MGET ArcGIS
450        # tool. It is therefore fine to raise an exception saying they
451        # need to initialize the geoprocessor first.
452
453        # TODO: Replace this with call to validation infrastructure
454
455        gp = GeoprocessorManager.GetWrappedGeoprocessor()
456        if gp is None:
457            Logger.RaiseException(RuntimeError(_(u'The ArcGIS raster %(raster)s is in a format that can only be read by ArcGIS (it cannot be read by GDAL). Please initialize the ArcGIS geoprocessor (call GeoprocessorManager.InitializeGeoprocessor() from the GeoEco.ArcGIS module) and try again.') % {u'raster': self._Raster}))
458
459        # Retrieve the Describe object and band count for the raster.
460        # In ArcGIS 9.3.1 and possibly other versions, there is a bug
461        # in the BandCount attribute of the Describe object. When
462        # Describe object is for a RasterLayer of a single band,
463        # BandCount is not 1; it is the number of bands in the entire
464        # multiband raster:
465        #
466        # >>> import arcgisscripting; gp = arcgisscripting.create()
467        # >>> dDatasetNoBands = gp.Describe(r'C:\Temp\qual')
468        # >>> dDatasetWithBands = gp.Describe(r'C:\Temp\ccomp2')
469        # >>> dBand = gp.Describe(r'C:\Temp\ccomp2\Band_5')
470        # >>> datasetNoBandsLayer = gp.MakeRasterLayer(r'C:\Temp\qual', 'datasetNoBandsLayer')
471        # >>> dDatasetNoBandsLayer = gp.Describe('datasetNoBandsLayer')
472        # >>> datasetWithBandsLayer = gp.MakeRasterLayer(r'C:\Temp\ccomp2', 'datasetWithBandsLayer')
473        # >>> dDatasetWithBandsLayer = gp.Describe('datasetWithBandsLayer')
474        # >>> bandLayer = gp.MakeRasterLayer(r'C:\Temp\ccomp2\Band_5', 'bandLayer')
475        # >>> dBandLayer = gp.Describe('bandLayer')
476        # >>> print '%s, %s, %s, %s, %s, %s' % (dDatasetNoBands.DataType, dDatasetWithBands.DataType, dBand.DataType, dDatasetNoBandsLayer.DataType, dDatasetWithBandsLayer.DataType, dBandLayer.DataType)
477        # RasterDataset, RasterDataset, RasterBand, RasterLayer, RasterLayer, RasterLayer
478        # >>> print '%s, %s, %s, %s, %s, %s' % (str(hasattr(dDatasetNoBands, 'BandCount')), str(hasattr(dDatasetWithBands, 'BandCount')), str(hasattr(dBand, 'BandCount')), str(hasattr(dDatasetNoBandsLayer, 'BandCount')), str(hasattr(dDatasetWithBandsLayer, 'BandCount')), str(hasattr(dBandLayer, 'BandCount')))
479        # True, True, False, True, True, True
480        # >>> print '%i, %i, None, %i, %i, %i' % (dDatasetNoBands.BandCount, dDatasetWithBands.BandCount, dDatasetNoBandsLayer.BandCount, dDatasetWithBandsLayer.BandCount, dBandLayer.BandCount)
481        # 1, 5, None, 1, 5, 5
482        #
483        # In the example above, the problem is that both
484        # dDatasetWithBandsLayer.BandCount and dBandLayer.BandCount
485        # are 5. We expected that dBandLayer.BandCount would be 1.
486        #
487        # To work around this, on ArcGIS 9.2. or later, call
488        # GetRasterProperties_management to retrieve the band count.
489        # That tool appears to work properly. ArcGIS 9.1 does not have
490        # that tool. But the CopyRaster_management tool knows whether
491        # a RasterLayer represents a single band or a multiband
492        # raster. On 9.1, make a copy of the raster and then retrieve
493        # the Describe object from it instead.
494
495        d = gp.Describe(self._Raster)
496        if hasattr(d, 'BandCount'):
497            bandCount = d.BandCount
498        else:
499            bandCount = 1
500           
501        if d.DataType.lower() == 'rasterlayer' and bandCount is not None and bandCount > 1:
502            if GeoprocessorManager.GetArcGISMajorVersion() > 9 or GeoprocessorManager.GetArcGISMajorVersion() == 9 and GeoprocessorManager.GetArcGISMinorVersion() >= 2:
503                bandCount = int(gp.GetRasterProperties_management(self._Raster, 'BANDCOUNT'))
504                if bandCount <= 0:
505                    bandCount = 1
506            else:
507                self._MakeTempCopy()
508                d = gp.Describe(self._TempRaster)
509                bandCount = d.BandCount
510
511        # If this is ArcGIS 9.2 or later, the GetRasterProperties tool
512        # also allows us to retrieve min and max values of the raster.
513        # From these, we can calculate the most compact data type and
514        # NoData value for this raster.
515        #
516        # For ArcGIS 9.1, we do not do this. Thus, when the caller
517        # attempts to retrieve these properties, we will make a
518        # temporary copy of the raster and use GDAL to read them. (We
519        # do not do that now because it is expensive.)
520
521        if GeoprocessorManager.GetArcGISMajorVersion() > 9 or GeoprocessorManager.GetArcGISMajorVersion() == 9 and GeoprocessorManager.GetArcGISMinorVersion() >= 2:
522            self._DataTypeForBand = {}
523            self._NoDataValueForBand = {}
524            self._MinValueForBand = {}
525            self._MaxValueForBand = {}
526
527        # If the raster has a band count of 1, retrieve the width,
528        # height, and cell dimensions from it and leave our Bands
529        # property set to None.
530       
531        if bandCount == 1:
532            self._Width = d.Width
533            self._Height = d.Height
534            self._CellWidth = float(d.MeanCellWidth)
535            self._CellHeight = float(d.MeanCellHeight)
536
537            # If this is ArcGIS 9.2 or later, get the data type,
538            # NoData value, and min and max values as described above.
539
540            if GeoprocessorManager.GetArcGISMajorVersion() > 9 or GeoprocessorManager.GetArcGISMajorVersion() == 9 and GeoprocessorManager.GetArcGISMinorVersion() >= 2:
541                if self._TempRaster is None:
542                    rasterPath = self._Raster
543                else:
544                    rasterPath = self._TempRaster
545                dataType, noDataValue, minValue, maxValue = self._RetrieveBandProperties(rasterPath, d)
546                self._DataTypeForBand[u'Band_1'] = dataType
547                self._NoDataValueForBand[u'Band_1'] = noDataValue
548                self._MinValueForBand[u'Band_1'] = minValue
549                self._MaxValueForBand[u'Band_1'] = maxValue
550
551        # Otherwise, generate a list of band names using the standard
552        # ArcGIS convention (Band_1, Band_2, ...). Use the width and
553        # height from the first band and verify that the other bands
554        # have the same raster and cell dimensions. If they don't,
555        # report an error; we don't support multi-band rasters that
556        # have different raster or cell dimensions. (For the types of
557        # data the GeoArray infrastructure is designed to process, I
558        # have never seen multi-band rasters where different bands
559        # have different dimensions.)
560
561        else:
562            self._Bands = []
563            for i in range(1, bandCount + 1):
564                self._Bands.append(u'Band_%i' % i)
565                if self._TempRaster is None:
566                    rasterPath = self._Raster + '/Band_%i' % i
567                else:
568                    rasterPath = self._TempRaster + '/Band_%i' % i
569                dBand = gp.Describe(rasterPath)
570                if i == 1:
571                    self._Width = dBand.Width
572                    self._Height = dBand.Height
573                    self._CellWidth = float(dBand.MeanCellWidth)
574                    self._CellHeight = float(dBand.MeanCellHeight)
575                elif dBand.Width != self._Width or dBand.Height != self._Height:
576                    Logger.RaiseException(ValueError(_(u'ArcGIS raster %(raster)s cannot be processed by this tool. The raster contains multiple bands but band %(band)i does not have the same dimensions as band 1. This tool requires that all bands have the same dimensions.') % {u'raster': self._Raster, u'band': i}))
577                elif float(dBand.MeanCellWidth) != self._CellWidth or float(dBand.MeanCellHeight) != self._CellHeight:
578                    Logger.RaiseException(ValueError(_(u'ArcGIS raster %(raster)s cannot be processed by this tool. The raster contains multiple bands but band %(band)i has a different cell size than band 1. This tool requires that all bands have the same cell size.') % {u'raster': self._Raster, u'band': i}))
579
580                # If this is ArcGIS 9.2 or later, get the data type,
581                # NoData value, and min and max values as described
582                # above, for each band.
583
584                if GeoprocessorManager.GetArcGISMajorVersion() > 9 or GeoprocessorManager.GetArcGISMajorVersion() == 9 and GeoprocessorManager.GetArcGISMinorVersion() >= 2:
585                    dataType, noDataValue, minValue, maxValue = self._RetrieveBandProperties(rasterPath, dBand)
586                    self._DataTypeForBand[u'Band_%i' % i] = dataType
587                    self._NoDataValueForBand[u'Band_%i' % i] = noDataValue
588                    self._MinValueForBand[u'Band_%i' % i] = minValue
589                    self._MaxValueForBand[u'Band_%i' % i] = maxValue
590
591        # Retrieve the corner coordinates.
592
593        extent = d.Extent.split()
594        self._XUpperLeftCorner = float(extent[0])
595        self._YUpperLeftCorner = float(extent[3])
596
597        # Retrieve the spatial reference.
598
599        super(GeoArrayArcGISRasterLayer, self)._SetSpatialReference(u'{B286C06B-0879-11D2-AACA-00C04FA33C20}')      # This is ESRI's GUID for the "Unknown" coordinate system
600        srObj = d.SpatialReference
601        if srObj is not None:
602            esriWKT = gp.CreateSpatialReference_management(srObj).split(';')[0]
603            if len(esriWKT) > 0:
604                super(GeoArrayArcGISRasterLayer, self)._SetSpatialReference(esriWKT)
605
606        # Return successfully
607       
608        self._PropertiesRetrieved = True
609
610    def _RetrieveBandProperties(self, rasterPath, d):
611        gp = GeoprocessorManager.GetWrappedGeoprocessor()
612       
613        pixelType = d.PixelType.upper()
614        minValue = gp.GetRasterProperties_management(rasterPath, 'MINIMUM')
615        maxValue = gp.GetRasterProperties_management(rasterPath, 'MAXIMUM')
616        try:
617            noDataValue = d.NoDataValue
618        except:
619            Logger.Debug('ArcGIS reports that this band does not have a NoData value.')
620            noDataValue = None
621           
622        if pixelType in ['F32', 'FLOAT', 'F64', 'DOUBLE']:
623            if pixelType in ['F32', 'FLOAT']:
624                dataType = u'float32'
625            else:
626                dataType = u'float64'
627            return dataType, noDataValue, minValue, maxValue
628
629        elif pixelType in ['U1', 'U2', 'U4', 'U8', 'UCHAR', 'S8', 'CHAR', 'U16', 'USHORT', 'S16', 'SHORT', 'U32', 'ULONG', 'S32', 'LONG']:
630            minValue = int(minValue)
631            maxValue = int(maxValue)
632            if noDataValue is not None:
633                noDataValue = int(noDataValue)
634                if noDataValue == minValue:
635                    Logger.RaiseException(RuntimeError(_(u'Unexpected error in this tool: For raster %(raster)s, ArcGIS reported that the minimum value and the NoData value are the same (%(val)i). This should not be possible. Please contact the author of this tool for assistance.') % {u'raster': rasterPath, u'val': noDataValue}))
636                if noDataValue == maxValue:
637                    Logger.RaiseException(RuntimeError(_(u'Unexpected error in this tool: For raster %(raster)s, ArcGIS reported that the maximum value and the NoData value are the same (%(val)i). This should not be possible. Please contact the author of this tool for assistance.') % {u'raster': rasterPath, u'val': noDataValue}))
638                   
639            if noDataValue is None or noDataValue > minValue and noDataValue < maxValue:
640                if minValue >= -128 and maxValue <= 127:
641                    dataType = 'int8'
642                elif minValue >= 0 and maxValue <= 255:
643                    dataType = 'uint8'
644                elif minValue >= -32768 and maxValue <= 32767:
645                    dataType = 'int16'
646                elif minValue >= 0 and maxValue <= 65535:
647                    dataType = 'uint16'
648                elif minValue >= -2147483648 and maxValue <= 2147483647:
649                    dataType = 'int32'
650                else:
651                    dataType = 'uint32'
652            elif minValue > -128 and maxValue <= 127:
653                dataType = 'int8'
654                if noDataValue < -128 or noDataValue > 127:
655                    noDataValue = -128
656            elif minValue >= -128 and maxValue < 127:
657                dataType = 'int8'
658                if noDataValue < -128 or noDataValue > 127:
659                    noDataValue = 127
660            elif minValue > 0 and maxValue <= 255:
661                dataType = 'uint8'
662                if noDataValue < 0 or noDataValue > 255:
663                    noDataValue = 0
664            elif minValue >= 0 and maxValue < 255:
665                dataType = 'uint8'
666                if noDataValue < 0 or noDataValue > 255:
667                    noDataValue = 255
668            elif minValue > -32768 and maxValue <= 32767:
669                dataType = 'int16'
670                if noDataValue < -32768 or noDataValue > 32767:
671                    noDataValue = -32768
672            elif minValue >= -32768 and maxValue < 32767:
673                dataType = 'int16'
674                if noDataValue < -32768 or noDataValue > 32767:
675                    noDataValue = 32767
676            elif minValue > 0 and maxValue <= 65535:
677                dataType = 'uint16'
678                if noDataValue < 0 or noDataValue > 65535:
679                    noDataValue = 0
680            elif minValue >= 0 and maxValue < 65535:
681                dataType = 'uint16'
682                if noDataValue < 0 or noDataValue > 65535:
683                    noDataValue = 65535
684            elif minValue > -2147483648 and maxValue <= 2147483647:
685                dataType = 'int32'
686                if noDataValue < -2147483648 or noDataValue > 2147483647:
687                    noDataValue = -2147483648
688            elif minValue >= -2147483648 and maxValue < 2147483647:
689                dataType = 'int32'
690                if noDataValue < -2147483648 or noDataValue > 2147483647:
691                    noDataValue = 2147483647
692            else:
693                dataType = 'uint32'   
694
695            return dataType, noDataValue, minValue, maxValue
696
697        Logger.RaiseException(ValueError(_(u'Raster %(raster)s cannot be processed by this tool because it has unknown pixel type %(pt)s. Please contact the author of this tool for assistance.') % {u'raster': rasterPath, u'pt': pixelType}))
698
699    def _MakeTempCopy(self):
700        if self._TempRaster is not None:
701            return
702        from GeoEco.DataManagement.Directories import TemporaryDirectory
703        self._TempDir = TemporaryDirectory()
704        self._TempRaster = os.path.join(self._TempDir.Path, u'raster')
705        try:
706            ArcGISRaster.CopySilent(self._Raster, self._TempRaster)
707        except:
708            self._TempRaster = None
709            self._TempDir = None
710            raise
711
712    def _InstantiateGDALDataset(self):
713        if self._GDALDataset is not None:
714            return
715
716        # If we already made a temporary copy of the raster,
717        # instantiate the GDALDataset from it.
718       
719        if self._TempRaster is not None:
720            self._GDALDataset = GDALDataset(self._TempRaster)
721       
722        # Otherwise, instantiate the GDALDataset from the raster's
723        # path and try to retrieve a property. This will cause GDAL to
724        # try to read the path. If GDAL has a driver that can read the
725        # path, we do not need to make a temporary copy of the raster.
726        #
727        # If we fail to retrieve the property, create a temporary copy
728        # and try again.
729
730        else:
731            gdalDataset = GDALDataset(self._Raster)
732            try:
733                width = gdalDataset.Width       # TODO: Improve this. It results in error messages that we don't want to see.
734            except:
735                self._MakeTempCopy()
736                gdalDataset = GDALDataset(self._TempRaster)
737            self._GDALDataset = gdalDataset   
738
739
740
741
742
743class ArcGISRaster(object):
744    __doc__ = DynamicDocString()
745
746    @classmethod
747    def Copy(cls, sourceRaster, destinationRaster, overwriteExisting=False):
748        cls.__doc__.Obj.ValidateMethodInvocation()
749        oldLogInfoAsDebug = Logger.LogInfoAndSetInfoToDebug(_(u'Copying ArcGIS raster %(in)s to %(out)s...') % {u'in' : sourceRaster, u'out' : destinationRaster})
750        try:
751            try:
752                cls._Copy(sourceRaster, destinationRaster)
753            except:
754                Logger.LogExceptionAsError(_(u'Could not copy ArcGIS raster %(source)s to %(dest)s') % {u'source' :  sourceRaster, u'dest' : destinationRaster})
755                raise
756        finally:
757            Logger.SetLogInfoAsDebug(oldLogInfoAsDebug)
758
759    @classmethod
760    def _Copy(cls, sourceRaster, destinationRaster):
761
762        # If the copy operation will cause ArcGIS to crash due to a
763        # bug, create temporary rasters that will prevent the crash.
764       
765        tempRasters = cls.CreateTemporaryRastersToPreventArcGISCrash(os.path.dirname(destinationRaster), 1)
766
767        # Copy the raster. Due to the problems described in tickets
768        # #310 and #311, call Copy_mangement on ArcGIS 9.1, and
769        # CopyRaster_management on later versions.
770
771        gp = GeoprocessorManager.GetWrappedGeoprocessor()
772        try:
773            if GeoprocessorManager.GetArcGISMajorVersion() <= 9 and GeoprocessorManager.GetArcGISMinorVersion() <= 1:
774                gp.Copy_Management(sourceRaster, destinationRaster)
775            else:
776                gp.CopyRaster_Management(sourceRaster, destinationRaster)
777
778        # If we created temporary rasters, delete them now.
779       
780        finally:
781            cls.DeleteTemporaryRastersThatPreventedArcGISCrash(tempRasters)
782
783    @classmethod
784    def CopySilent(cls, sourceRaster, destinationRaster, overwriteExisting=False):
785        oldLogInfoAsDebug = Logger.GetLogInfoAsDebug()
786        Logger.SetLogInfoAsDebug(True)
787        try:
788            cls.Copy(sourceRaster, destinationRaster, overwriteExisting)
789        finally:
790            Logger.SetLogInfoAsDebug(oldLogInfoAsDebug)
791
792    @classmethod
793    def CreateTemporaryRastersToPreventArcGISCrash(cls, directory, rastersToAdd):
794        cls.__doc__.Obj.ValidateMethodInvocation()
795
796        # See http://forums.esri.com/Thread.asp?c=93&f=1729&t=196716&mc=0 for a
797        # complete description of the problem that this function is designed to
798        # work around.
799
800        # First determine the maximum entry in the arc.dir file.
801
802        if not os.path.isdir(directory) or not os.path.isdir(os.path.join(directory, "info")):
803            return []
804       
805        infoEntries = glob.glob(os.path.join(directory, "info", "arc[0-9][0-9][0-9][0-9].*"))
806        if len(infoEntries) <= 0:
807            return []
808       
809        infoEntries.sort()
810        maxInfoEntry = int(os.path.basename(infoEntries[len(infoEntries)-1])[3:7])
811
812        # If adding rastersToAdd integer rasters to the directory would not
813        # cause the maximum entry to cross a multiple of 1024, then it would not
814        # cause Arc to crash, and we can just return.
815       
816        maxInfoEntry = divmod(maxInfoEntry, 1024)[1]
817        if maxInfoEntry + rastersToAdd * 3 < 1023:          # Each integer raster requires 3 entries in arc.dir (floating point rasters only require 2)
818            return []
819
820        # If the current entry is only 1 less than the 1024 boundary (actually
821        # 1 less than 1023 since the entries are 0-based), we can just return
822        # because all rasters require at least two entries, so it is guaranteed
823        # that we would not hit the magic crashing number (which is a multiple
824        # of 1024 - 1, again since the entries are 0-based).
825
826        if maxInfoEntry == 1023 - 1:
827            return []
828
829        # We're going to cross a multiple of 1024 and there could be a crash.
830        # Create enough temporary rasters to safely take us just over the
831        # boundary.
832
833        Logger.Debug(_(u'Creating temporary rasters in %(dir)s to prevent ArcGIS from crashing when %(rasters)i rasters are added to that directory. The temporary rasters begin with \"tmp\" and should be deleted automatically after the real rasters are added. If they are not, you can delete them manually.') % {u'dir' : directory, u'rasters' : rastersToAdd})
834
835        entriesNeeded = 1024 - maxInfoEntry
836        rastersCreated = []
837        gp = GeoprocessorManager.GetWrappedGeoprocessor()
838
839        while entriesNeeded > 0:
840            raster = None
841            while raster is None or os.path.exists(raster):
842                raster = os.path.join(directory, "tmp%08X" % random.randint(0, sys.maxint))
843
844            # If creating an integer raster would not crash Arc, do
845            # it. Otherwise create a floating-point raster. Due to the
846            # problems described in tickets #310 and #311, call
847            # Copy_mangement on ArcGIS 9.1 and 9.2, and
848            # CopyRaster_management on ArcGIS 9.3.
849
850            if entriesNeeded != 4:
851                dummyRaster = os.path.join(os.path.dirname(sys.modules[u'GeoEco.ArcGIS'].__file__), u'ArcGISToolbox', u'Rasters', u'dummyint')
852                entriesNeeded -= 3
853            else:
854                dummyRaster = os.path.join(os.path.dirname(sys.modules[u'GeoEco.ArcGIS'].__file__), u'ArcGISToolbox', u'Rasters', u'dummyfloat')
855                entriesNeeded -= 2
856
857            if GeoprocessorManager.GetArcGISMajorVersion() <= 9 and GeoprocessorManager.GetArcGISMinorVersion() <= 2:
858                gp.Copy_Management(dummyRaster, raster)
859            else:
860                gp.CopyRaster_Management(dummyRaster, raster)
861
862            rastersCreated.append(raster)
863
864        Logger.Debug(_(u'%i temporary rasters created.') % len(rastersCreated))
865
866        # Return the list of rasters we created.
867
868        return rastersCreated
869
870    @classmethod
871    def CreateXRaster(cls, raster, extent, cellSize, cellValue=u'Center', coordinateSystem=None, buildPyramids=False, overwriteExisting=False):
872        cls.__doc__.Obj.ValidateMethodInvocation()
873
874        # Perform additional validation.
875
876        left, bottom, right, top = EnvelopeTypeMetadata.ParseFromArcGISString(extent)
877
878        if right - left <= 0:
879            Logger.RaiseException(ValueError(_(u'The horizontal extent must be greater than zero.')))
880
881        if top - bottom <= 0:
882            Logger.RaiseException(ValueError(_(u'The vertical extent must be greater than zero.')))
883
884        if cellSize <= 0.0:
885            Logger.RaiseException(ValueError(_(u'The cell size must be greater than zero.')))
886
887        # Determine the number of rows and columns of the raster.
888
889        rows = int(math.ceil((top - bottom) / cellSize))
890        cols = int(math.ceil((right - left) / cellSize))
891
892        # Create a numpy array that contains the raster values.
893
894        if cellValue == u'center':
895            increment = cellSize / 2
896        elif cellValue == u'right':
897            increment = cellSize
898        else:
899            increment = 0
900
901        import numpy
902        values = numpy.arange(left + increment, right + increment, cellSize) * numpy.ones((rows, cols))
903
904        # Create the raster.
905
906        oldLogInfoAsDebug = Logger.LogInfoAndSetInfoToDebug(_(u'Creating X coordinate raster %(out)s...') % {u'out' : raster})
907        try:
908            try:
909                from GeoEco.DataManagement.Directories import TemporaryDirectory
910                tempDir = TemporaryDirectory()
911               
912                from GeoEco.DataManagement.ArcInfoASCIIGrids import ArcInfoASCIIGrid
913                ArcInfoASCIIGrid.FromNumpyArray(values, os.path.join(tempDir.Path, 'temp.txt'), left, bottom, cellSize)
914                ArcInfoASCIIGrid.ToArcGISRaster(os.path.join(tempDir.Path, 'temp.txt'), raster, coordinateSystem=coordinateSystem, buildPyramids=buildPyramids, overwriteExisting=overwriteExisting)
915            except:
916                Logger.LogExceptionAsError()
917                raise
918        finally:
919            Logger.SetLogInfoAsDebug(oldLogInfoAsDebug)
920
921    @classmethod
922    def CreateYRaster(cls, raster, extent, cellSize, cellValue=u'Center', coordinateSystem=None, buildPyramids=False, overwriteExisting=False):
923        cls.__doc__.Obj.ValidateMethodInvocation()
924
925        # Perform additional validation.
926
927        left, bottom, right, top = EnvelopeTypeMetadata.ParseFromArcGISString(extent)
928
929        if right - left <= 0:
930            Logger.RaiseException(ValueError(_(u'The horizontal extent must be greater than zero.')))
931
932        if top - bottom <= 0:
933            Logger.RaiseException(ValueError(_(u'The vertical extent must be greater than zero.')))
934
935        if cellSize <= 0.0:
936            Logger.RaiseException(ValueError(_(u'The cell size must be greater than zero.')))
937
938        # Determine the number of rows and columns of the raster.
939
940        rows = int(math.ceil((top - bottom) / cellSize))
941        cols = int(math.ceil((right - left) / cellSize))
942
943        # Create a numpy array that contains the raster values.
944
945        if cellValue == u'center':
946            increment = cellSize / 2
947        elif cellValue == u'bottom':
948            increment = cellSize
949        else:
950            increment = 0
951
952        import numpy
953        values = numpy.arange(top - increment, bottom - increment, 0 - cellSize).reshape(rows,1) * numpy.ones((rows, cols))
954
955        # Create the raster.
956
957        oldLogInfoAsDebug = Logger.LogInfoAndSetInfoToDebug(_(u'Creating Y coordinate raster %(out)s...') % {u'out' : raster})
958        try:
959            try:
960                from GeoEco.DataManagement.Directories import TemporaryDirectory
961                tempDir = TemporaryDirectory()
962               
963                from GeoEco.DataManagement.ArcInfoASCIIGrids import ArcInfoASCIIGrid
964                ArcInfoASCIIGrid.FromNumpyArray(values, os.path.join(tempDir.Path, 'temp.txt'), left, bottom, cellSize)
965                ArcInfoASCIIGrid.ToArcGISRaster(os.path.join(tempDir.Path, 'temp.txt'), raster, coordinateSystem=coordinateSystem, buildPyramids=buildPyramids, overwriteExisting=overwriteExisting)
966            except:
967                Logger.LogExceptionAsError()
968                raise
969        finally:
970            Logger.SetLogInfoAsDebug(oldLogInfoAsDebug)
971
972    @classmethod
973    def Delete(cls, raster):
974        cls.__doc__.Obj.ValidateMethodInvocation()
975        GeoprocessorManager.DeleteArcGISObject(raster, [u'rasterdataset'], _(u'ArcGIS raster'))
976
977    @classmethod
978    def DeleteTemporaryRastersThatPreventedArcGISCrash(cls, rasters):
979        cls.__doc__.Obj.ValidateMethodInvocation()
980        if len(rasters) > 0:
981            oldLogInfoAsDebug = Logger.GetLogInfoAsDebug()
982            Logger.SetLogInfoAsDebug(True)
983            try:
984                for raster in rasters:
985                    cls.Delete(raster)
986            finally:
987                Logger.SetLogInfoAsDebug(oldLogInfoAsDebug)
988
989    @classmethod
990    def Exists(cls, path):
991        cls.__doc__.Obj.ValidateMethodInvocation()
992        return GeoprocessorManager.ArcGISObjectExists(path, [u'rasterdataset'], u'ArcGIS raster')
993
994    @classmethod
995    def Find(cls, workspace, wildcard=u'*', searchTree=False, rasterType=None, basePath=None, getExtent=False, dateParsingExpression=None):
996        cls.__doc__.Obj.ValidateMethodInvocation()
997        Logger.Info(_(u'Finding ArcGIS rasters: workspace="%(workspace)s", wildcard="%(wildcard)s", searchTree=%(tree)s, rasterType="%(type)s"') % {u'workspace': workspace, u'wildcard': wildcard, u'tree': unicode(searchTree), u'type': rasterType})
998        return cls._Find(workspace,
999                         wildcard,
1000                         searchTree,
1001                         rasterType,
1002                         basePath,
1003                         getExtent,
1004                         dateParsingExpression)
1005
1006    @classmethod
1007    def _Find(cls, workspace, wildcard, searchTree, rasterType, basePath, getExtent, dateParsingExpression, searchPattern=None, strptimePattern=None):
1008
1009        # If the caller provided a dateParsingExpression, parse it into a
1010        # pattern we can pass the re.search() and a corresponding pattern we can
1011        # subsequently pass to time.strptime().
1012
1013        from GeoEco.DataManagement.Files import File       
1014
1015        if dateParsingExpression is not None and searchPattern is None:
1016            searchPattern, strptimePattern = File.ValidateDateParsingExpression(dateParsingExpression)
1017
1018        # Change the current workspace to that specified by the caller. If the
1019        # workspace hasn't been set, ArcGIS 9.2 will return None for the
1020        # workspace property, but will raise an exception if we set it to None.
1021        # To work around this screwy design, we convert None to u'', which is
1022        # what ArcGIS 9.1 returns when the workspace hasn't been set.
1023
1024        gp = GeoprocessorManager.GetWrappedGeoprocessor()
1025        oldWorkspace = gp.Workspace
1026        if oldWorkspace is None:
1027            oldWorkspace = u''
1028        gp.Workspace = workspace
1029
1030        # Find matching rasters in the specified workspace.
1031
1032        results = []
1033
1034        if basePath is not None:
1035            os.path.normpath(basePath)
1036            baseParts = basePath.split(os.sep)
1037
1038        try:
1039            if rasterType is not None:
1040                enum = gp.ListRasters(wildcard, rasterType)
1041            else:
1042                enum = gp.ListRasters(wildcard)
1043
1044            try:
1045                raster = enum.Next()
1046                while isinstance(raster, basestring) and len(raster) > 0:
1047                    raster = os.path.join(workspace, raster)
1048
1049                    # Append the absolute path to the result row.
1050                   
1051                    Logger.Debug(_(u'Found raster %s'), raster)
1052
1053                    result = [raster]
1054
1055                    # If requested, append the relative path to the result row.
1056
1057                    if basePath is not None:
1058                        rasterParts = raster.split(os.sep)
1059                        i = 0
1060                        while i < len(baseParts) and i < len(rasterParts) and os.path.normcase(baseParts[i]) == os.path.normcase(rasterParts[i]):
1061                            i += 1
1062                        if i == 0:
1063                            result.append(raster)
1064                        else:
1065                            result.append(os.path.join(('..' + os.sep) * (len(baseParts) - i), os.sep.join(rasterParts[i:])))
1066
1067                    # If requested, append the other optional fields to the result row.
1068                       
1069                    if getExtent:
1070                        (xMin, yMin, xMax, yMax) = EnvelopeTypeMetadata.ParseFromArcGISString(gp.Describe(raster).Extent)
1071                        result.append(xMin)
1072                        result.append(yMin)
1073                        result.append(xMax)
1074                        result.append(yMax)
1075
1076                    # If requested, parse a date from the absolute path and append it
1077                    # to the result row, in both datetime and UNIX time formats.
1078
1079                    if dateParsingExpression is not None:
1080                        dateTime, unixTime = File.ParseDateFromPath(raster, dateParsingExpression, searchPattern, strptimePattern)
1081                        result.append(dateTime)
1082                        result.append(unixTime)
1083
1084                    # Append this result row to the list of results to return.
1085
1086                    results.append(result)
1087                    raster = enum.Next()
1088
1089            finally:
1090                del enum
1091
1092            # Search child workspaces, if requested.
1093            #
1094            # NOTE: The ArcGIS 9.1 geoprocessor's ListWorkspaces method does not
1095            # seem to always work for workspaces that are operating system
1096            # directories. Sometimes it seems to claim that a given directory is
1097            # empty, even though it contains subdirectories. I do not know why.
1098            # For this reason, if the current workspace is a directory, use
1099            # Python's functions instead of ListWorkspaces.
1100           
1101            if searchTree:
1102                if os.path.isdir(workspace):
1103                    for childWorkspace in os.listdir(workspace):
1104                        dataType = gp.Describe(os.path.join(workspace, childWorkspace)).DataType.lower()
1105                        if childWorkspace.lower() != u'info' and (dataType == u'workspace' or dataType == u'folder'):
1106                            results.extend(cls._Find(os.path.join(workspace, childWorkspace),
1107                                                     wildcard,
1108                                                     searchTree,
1109                                                     rasterType,
1110                                                     basePath,
1111                                                     getExtent,
1112                                                     dateParsingExpression,
1113                                                     searchPattern,
1114                                                     strptimePattern))
1115                else:
1116                    enum = gp.ListWorkspaces(u'*')
1117                    try:
1118                        childWorkspace = enum.Next()
1119                        while isinstance(childWorkspace, basestring) and len(childWorkspace) > 0:
1120                            results.extend(cls._Find(os.path.join(workspace, childWorkspace),
1121                                                     wildcard,
1122                                                     searchTree,
1123                                                     rasterType,
1124                                                     basePath,
1125                                                     getExtent,
1126                                                     dateParsingExpression,
1127                                                     searchPattern,
1128                                                     strptimePattern))
1129                            childWorkspace = enum.Next()
1130                    finally:
1131                        del enum
1132
1133        # Change the current workspace back to what it was.                   
1134
1135        finally:
1136            gp.Workspace = oldWorkspace
1137
1138        # Return successfully.
1139
1140        return results       
1141
1142    @classmethod
1143    def FindAndFillTable(cls, workspace, insertCursor, rasterField, wildcard=u'*', searchTree=False, rasterType=None, relativePathField=None, basePath=None, populateExtentFields=False, parsedDateField=None, dateParsingExpression=None, unixTimeField=None):
1144        cls.__doc__.Obj.ValidateMethodInvocation()
1145
1146        # Perform additional validation.
1147
1148        fields = [rasterField, relativePathField, parsedDateField, unixTimeField]
1149        fieldsDict = {}
1150        for f in fields:
1151            if f is not None:
1152                if fieldsDict.has_key(f.lower()):
1153                    Logger.RaiseException(ValueError(_(u'The same field "%(field)s" is specified for two different parameters. Please specify a unique field name for each parameter.') % {u'field': f}))
1154                fieldsDict[f] = True
1155
1156        if populateExtentFields:
1157            for f in fields:
1158                if f is not None:
1159                    if f.lower() in [u'xmin', u'xmax', u'ymin', u'ymax']:
1160                        Logger.RaiseException(ValueError(_(u'The field "%(field)s" is reserved for storing the raster extent. Please specify a different field name') % {u'field': f}))
1161
1162        if parsedDateField is not None and dateParsingExpression is None:
1163            Logger.RaiseException(ValueError(_(u'If you specify a field to receive parsed dates, you must also specify a date parsing expression.')))
1164
1165        if unixTimeField is not None and dateParsingExpression is None:
1166            Logger.RaiseException(ValueError(_(u'If you specify a field to receive UNIX times, you must also specify a date parsing expression.')))
1167
1168        if relativePathField is None:
1169            basePath = None
1170
1171        # Find the rasters.
1172
1173        Logger.Info(_(u'Finding ArcGIS rasters and inserting rows into table "%(table)s": workspace="%(workspace)s", wildcard="%(wildcard)s", searchTree=%(tree)s, rasterType="%(type)s"') % {u'table': insertCursor.Table, u'workspace': workspace, u'wildcard': wildcard, u'tree': unicode(searchTree), u'type': rasterType})
1174        results = cls._Find(workspace,
1175                            wildcard,
1176                            searchTree,
1177                            rasterType,
1178                            basePath,
1179                            populateExtentFields,
1180                            dateParsingExpression)
1181
1182        # Insert the rows.
1183
1184        if len(results) > 0:
1185            insertCursor.SetRowCount(len(results))
1186
1187            for result in results:
1188                value = result.pop(0)
1189                insertCursor.SetValue(rasterField, value)
1190
1191                if relativePathField is not None:
1192                    value = result.pop(0)
1193                    insertCursor.SetValue(relativePathField, value)
1194
1195                if populateExtentFields:
1196                    value = result.pop(0)
1197                    insertCursor.SetValue(u'XMin', value)
1198                    value = result.pop(0)
1199                    insertCursor.SetValue(u'YMin', value)
1200                    value = result.pop(0)
1201                    insertCursor.SetValue(u'XMax', value)
1202                    value = result.pop(0)
1203                    insertCursor.SetValue(u'YMax', value)
1204
1205                if parsedDateField is not None or unixTimeField is not None:
1206                    value = result.pop(0)
1207                    if parsedDateField is not None:
1208                        insertCursor.SetValue(parsedDateField, value)
1209
1210                    value = result.pop(0)
1211                    if unixTimeField is not None:
1212                        insertCursor.SetValue(unixTimeField, value)
1213
1214                insertCursor.InsertRow()
1215
1216    @classmethod
1217    def FindAndCreateTable(cls, workspace, connection, table, rasterField, wildcard=u'*', searchTree=False, rasterType=None, relativePathField=None, basePath=None, populateExtentFields=False, parsedDateField=None, dateParsingExpression=None, unixTimeField=None, pathFieldsDataType=u'TEXT', extentFieldsDataType=u'DOUBLE', dateFieldsDataType=u'DATE', unixTimeFieldDataType=u'INT', maxPathLength=255, overwriteExisting=False):
1218        cls.__doc__.Obj.ValidateMethodInvocation()
1219
1220        # Perform additional validation.
1221
1222        fields = [rasterField, relativePathField, parsedDateField, unixTimeField]
1223        fieldsDict = {}
1224        for f in fields:
1225            if f is not None:
1226                if fieldsDict.has_key(f.lower()):
1227                    Logger.RaiseException(ValueError(_(u'The same field "%(field)s" is specified for two different parameters. Please specify a unique field name for each parameter.') % {u'field': f}))
1228                fieldsDict[f] = True
1229
1230        if populateExtentFields:
1231            for f in fields:
1232                if f is not None:
1233                    if f.lower() in [u'xmin', u'xmax', u'ymin', u'ymax']:
1234                        Logger.RaiseException(ValueError(_(u'The field "%(field)s" is reserved for storing the raster extent. Please specify a different field name') % {u'field': f}))
1235
1236        if parsedDateField is not None and dateParsingExpression is None:
1237            Logger.RaiseException(ValueError(_(u'If you specify a field to receive parsed dates, you must also specify a date parsing expression.')))
1238
1239        if unixTimeField is not None and dateParsingExpression is None:
1240            Logger.RaiseException(ValueError(_(u'If you specify a field to receive UNIX times, you must also specify a date parsing expression.')))
1241
1242        if relativePathField is None:
1243            basePath = None
1244
1245        # If requested, delete the table if it already exists.
1246       
1247        if connection.TableExists(table):
1248            if overwriteExisting:
1249                connection.DeleteTable(table)
1250            else:
1251                Logger.RaiseException(ValueError(_(u'Cannot create table %s because it already exists.') % table))
1252
1253        # Create the table and add the fields.
1254
1255        table = connection.CreateTable(table)
1256       
1257        try:
1258            if not connection.FieldLengthSupported:
1259                maxPathLength = None
1260            rasterField = connection.AddField(table, rasterField, pathFieldsDataType, length=maxPathLength)
1261
1262            if relativePathField is not None:
1263                relativePathFIeld = connection.AddField(table, relativePathField, pathFieldsDataType, length=maxPathLength)
1264
1265            if populateExtentFields:
1266                connection.AddField(table, u'XMin', extentFieldsDataType)
1267                connection.AddField(table, u'YMin', extentFieldsDataType)
1268                connection.AddField(table, u'XMax', extentFieldsDataType)
1269                connection.AddField(table, u'YMax', extentFieldsDataType)
1270
1271            if parsedDateField is not None:
1272                parsedDateField = connection.AddField(table, parsedDateField, dateFieldsDataType)
1273
1274            if unixTimeField is not None:
1275                unixTimeField = connection.AddField(table, unixTimeField, unixTimeFieldDataType)
1276
1277            # Create an insert cursor and fill the table.
1278
1279            cursor = connection.OpenInsertCursor(table)
1280            try:
1281                cls.FindAndFillTable(workspace,
1282                                     cursor,
1283                                     rasterField,
1284                                     wildcard,
1285                                     searchTree,
1286                                     rasterType,
1287                                     relativePathField,
1288                                     basePath,
1289                                     populateExtentFields,
1290                                     parsedDateField,
1291                                     dateParsingExpression,
1292                                     unixTimeField)
1293            finally:
1294                del cursor
1295
1296        # If an exception was raised, delete the table.
1297       
1298        except:
1299            try:
1300                connection.DeleteTable(table)
1301            except:
1302                pass
1303            raise
1304
1305        # Return successfully.
1306
1307        return table       
1308
1309    @classmethod
1310    def FindAndCreateArcGISTable(cls, inputWorkspace, outputWorkspace, table, rasterField=u'Image', wildcard=u'*', searchTree=False, rasterType=None, relativePathField=None, populateExtentFields=True, parsedDateField=None, dateParsingExpression=None, unixTimeField=None, maxPathLength=255, overwriteExisting=False):
1311        cls.__doc__.Obj.ValidateMethodInvocation()
1312
1313        # If the caller's output workspace is a directory (rather than a database),
1314        # the geoprocessor's CreateTable tool will create a DBF table,
1315        # regardless of what file extension the caller placed on the table. Even
1316        # if the caller's extension is .csv or .txt, the geoprocessor will
1317        # replace it with .dbf. If the caller does not provide an extension, the
1318        # geoprocessor will tack on .dbf.
1319        #
1320        # Because we know the geoprocessor will do this, we do it here
1321        # preemptively, so we can check for and delete the existing table, if
1322        # desired by the caller.
1323
1324        if os.path.isdir(outputWorkspace) and not table.lower().endswith(u'.dbf'):
1325            if table.find(u'.') >= 0:
1326                newTable = table[:table.find(u'.')] + u'.dbf'
1327                Logger.Warning(u'When creating tables in the file system, the ArcGIS CreateTable tool ignores the extension you specify and always creates a dBASE table with the extension .dbf. It will create the table %(new)s even though you asked for %(old)s.' % {u'new': newTable, u'old': table})
1328            else:
1329                newTable = table + u'.dbf'
1330                Logger.Warning(u'The ArcGIS CreateTable tool always creates dBASE tables in the file system. Even though you did not specify a file extension for your table, .dbf will be used.')
1331            table = newTable
1332
1333        # Create the table.
1334       
1335        connection = ArcGIS91DatabaseConnection()
1336        table = cls.FindAndCreateTable(inputWorkspace,
1337                                       connection,
1338                                       os.path.normpath(os.path.join(outputWorkspace, table)),
1339                                       rasterField,
1340                                       wildcard,
1341                                       searchTree,
1342                                       rasterType,
1343                                       relativePathField,
1344                                       outputWorkspace,
1345                                       populateExtentFields,
1346                                       parsedDateField,
1347                                       dateParsingExpression,
1348                                       unixTimeField,
1349                                       u'TEXT',
1350                                       u'DOUBLE',
1351                                       u'DATE',
1352                                       u'LONG',
1353                                       maxPathLength,
1354                                       overwriteExisting)
1355
1356        # If it is a DBF table, delete the Field1 field. ArcGIS always creates
1357        # this field because, according to the documentation, DBF files must
1358        # always have at least one field, and it is not possible to give a field
1359        # to the geoprocessor's CreateTable tool. Also delete the M_S_O_F_T
1360        # field if it exists; this is created by the Microsoft ODBC dBASE
1361        # driver, which ArcGIS could conceivably use in the future.
1362       
1363        if table.lower().endswith(u'.dbf'):
1364            if connection.FieldExists(table, u'Field1'):
1365                connection.DeleteField(table, u'Field1')
1366            if connection.FieldExists(table, u'M_S_O_F_T'):
1367                connection.DeleteField(table, u'M_S_O_F_T')
1368
1369        # Return successfully.
1370       
1371        return table
1372
1373    @classmethod
1374    def Move(cls, sourceRaster, destinationRaster, overwriteExisting=False):
1375        cls.__doc__.Obj.ValidateMethodInvocation()
1376        oldLogInfoAsDebug = Logger.LogInfoAndSetInfoToDebug(_(u'Moving ArcGIS raster %(in)s to %(out)s...') % {u'in' : sourceRaster, u'out' : destinationRaster})
1377        try:
1378            try:
1379                cls._Copy(sourceRaster, destinationRaster)
1380                GeoprocessorManager.DeleteArcGISObject(sourceRaster, [u'rasterdataset'], _(u'ArcGIS raster'))
1381            except:
1382                Logger.LogExceptionAsError(_(u'Could not move ArcGIS raster %(source)s to %(dest)s') % {u'source' :  sourceRaster, u'dest' : destinationRaster})
1383                raise
1384        finally:
1385            Logger.SetLogInfoAsDebug(oldLogInfoAsDebug)
1386
1387    @classmethod
1388    def MoveSilent(cls, sourceRaster, destinationRaster, overwriteExisting=False):
1389        oldLogInfoAsDebug = Logger.GetLogInfoAsDebug()
1390        Logger.SetLogInfoAsDebug(True)
1391        try:
1392            cls.Move(sourceRaster, destinationRaster, overwriteExisting)
1393        finally:
1394            Logger.SetLogInfoAsDebug(oldLogInfoAsDebug)
1395
1396    @classmethod
1397    def FromNumpyArray(cls, numpyArray, raster, xLowerLeftCorner, yLowerLeftCorner, cellSize, nodataValue=None, coordinateSystem=None, projectedCoordinateSystem=None, geographicTransformation=None, resamplingTechnique=None, projectedCellSize=None, registrationPoint=None, clippingRectangle=None, mapAlgebraExpression=None, buildPyramids=False, overwriteExisting=False):
1398        #cls.__doc__.Obj.ValidateMethodInvocation()
1399        oldLogInfoAsDebug = Logger.LogInfoAndSetInfoToDebug(_(u'Creating ArcGIS raster %(out)s...') % {u'out' : raster})
1400        try:
1401            try:
1402                from GeoEco.DataManagement.Directories import TemporaryDirectory
1403                tempDir = TemporaryDirectory()
1404
1405                asciiFile = os.path.join(tempDir.Path, 'temp.txt')
1406                Logger.Debug(_(u'Writing ArcInfo ASCII Grid file %(out)s') % {u'out' : asciiFile})
1407
1408                from GeoEco.Dependencies import ImportNumpyDependentExtensionModule
1409
1410                ArcInfoASCIIGridUtils = ImportNumpyDependentExtensionModule('GeoEco.DataManagement.ArcInfoASCIIGridUtils')
1411                if nodataValue is not None:
1412                    ArcInfoASCIIGridUtils.NumpyArrayToArcInfoASCIIGrid(numpyArray, str(asciiFile), numpyArray.shape[1], numpyArray.shape[0], xLowerLeftCorner, yLowerLeftCorner, cellSize, 1, nodataValue)
1413                else:
1414                    ArcInfoASCIIGridUtils.NumpyArrayToArcInfoASCIIGrid(numpyArray, str(asciiFile), numpyArray.shape[1], numpyArray.shape[0], xLowerLeftCorner, yLowerLeftCorner, cellSize)
1415               
1416                from GeoEco.DataManagement.ArcInfoASCIIGrids import ArcInfoASCIIGrid
1417                ArcInfoASCIIGrid.ToArcGISRaster(asciiFile, raster, isInteger=numpyArray.dtype.kind=='i', coordinateSystem=coordinateSystem, projectedCoordinateSystem=projectedCoordinateSystem, geographicTransformation=geographicTransformation, resamplingTechnique=resamplingTechnique, projectedCellSize=projectedCellSize, registrationPoint=registrationPoint, clippingRectangle=clippingRectangle, mapAlgebraExpression=mapAlgebraExpression, buildPyramids=buildPyramids, overwriteExisting=overwriteExisting)
1418            except:
1419                Logger.LogExceptionAsError()
1420                raise
1421        finally:
1422            Logger.SetLogInfoAsDebug(oldLogInfoAsDebug)
1423
1424    @classmethod
1425    def ToNumpyArray(cls, raster, band=1, tempRasterPath=None):
1426        cls.__doc__.Obj.ValidateMethodInvocation()
1427        oldLogInfoAsDebug = Logger.GetLogInfoAsDebug()
1428        Logger.SetLogInfoAsDebug(True)
1429        try:
1430            try:
1431                gp = GeoprocessorManager.GetWrappedGeoprocessor()
1432
1433                # If the raster does not exist on disk (e.g. it is in a
1434                # geodatabase), copy it to a temporary location.
1435               
1436                if os.path.exists(raster):
1437                    tempRasterPath = raster
1438                else:
1439
1440                    # If the caller did not provide a temp raster
1441                    # path, create a temp directory.
1442                   
1443                    if tempRasterPath is None:
1444                        from GeoEco.DataManagement.Directories import TemporaryDirectory
1445                        tempDir = TemporaryDirectory()
1446                        tempRasterPath = os.path.join(tempDir.Path, u'raster')
1447
1448                    # Copy the raster to the temp path.
1449
1450                    Logger.Debug(_(u'Copying ArcGIS raster %(in)s to %(out)s...') % {u'in' : raster, u'out' : tempRasterPath})
1451                    cls._Copy(raster, tempRasterPath)
1452
1453                # Use GDAL to read the raster into a numpy array.
1454
1455                from GeoEco.Dependencies import ImportGDALModule, SetGDALDataEnvVar, ResetGDALDataEnvVar
1456
1457                gdal = ImportGDALModule('osgeo.gdal')
1458                gdalconst = ImportGDALModule('osgeo.gdalconst')
1459
1460                SetGDALDataEnvVar()
1461                try:
1462                    Logger.Debug(_(u'Reading raster %(raster)s into memory...') % {u'raster': tempRasterPath})
1463                    ds = gdal.Open(str(tempRasterPath), gdalconst.GA_ReadOnly)
1464                    b = ds.GetRasterBand(1)
1465                    a = b.ReadAsArray()
1466                finally:
1467                    ResetGDALDataEnvVar()
1468
1469                # For integer rasters, sometimes GDAL appears to read
1470                # the raster as a data type that does not match the
1471                # raster's data type. For example, I have seen it read
1472                # a uint16 raster as int32. Other times, ArcGIS does
1473                # not seem to use the most compact pixel data type.
1474                # For example, a raster that contains values from 0 to
1475                # 65535 with no NODATA value will be stored as int32
1476                # rather than uint16. Both of these situations cause
1477                # problems for callers that expect the data to be in
1478                # the most compact type. To avoid these problems,
1479                # explicitly cast the numpy array to the most compact
1480                # type. This may cause us to change the NODATA value
1481                # from what ArcGIS is using, but it should not affect
1482                # our callers.
1483
1484                noDataValue = b.GetNoDataValue()       # On ArcGIS 9.1 sp2, gp.Describe(tempRasterPath).NoDataValue crashes Python, so we use this instead
1485               
1486                if gp.Describe(tempRasterPath).IsInteger:
1487                    if noDataValue is not None:
1488                        noDataValue = int(noDataValue)
1489                       
1490                    minValue = int(b.GetMinimum())
1491                    maxValue = int(b.GetMaximum())
1492                    valueRange = maxValue - minValue + 1
1493
1494                    import numpy                   
1495                   
1496                    if minValue >= -128 and maxValue <= 127:
1497                        if a.dtype.name != 'int8':
1498                            if valueRange < 256:
1499                                if minValue > -128:
1500                                    a[a == noDataValue] = -128
1501                                    a = numpy.cast['int8'](a)
1502                                    noDataValue = -128
1503                                else:
1504                                    a[a == noDataValue] = 127
1505                                    a = numpy.cast['int8'](a)
1506                                    noDataValue = 127
1507                            elif not numpy.sometrue(a == noDataValue):
1508                                a = numpy.cast['int8'](a)
1509                                noDataValue = None
1510                   
1511                    elif minValue >= 0 and maxValue <= 255:
1512                        if a.dtype.name != 'uint8':
1513                            if valueRange < 256:
1514                                if minValue > 0:
1515                                    a[a == noDataValue] = 0
1516                                    a = numpy.cast['uint8'](a)
1517                                    noDataValue = 0
1518                                else:
1519                                    a[a == noDataValue] = 255
1520                                    a = numpy.cast['uint8'](a)
1521                                    noDataValue = 255
1522                            elif not numpy.sometrue(a == noDataValue):
1523                                a = numpy.cast['uint8'](a)
1524                                noDataValue = None
1525                   
1526                    elif minValue >= -32768 and maxValue <= 32767:
1527                        if a.dtype.name != 'int16':
1528                            if valueRange < 65536:
1529                                if minValue > -32768:
1530                                    a[a == noDataValue] = -32768
1531                                    a = numpy.cast['int16'](a)
1532                                    noDataValue = -32768
1533                                else:
1534                                    a[a == noDataValue] = 32767
1535                                    a = numpy.cast['int16'](a)
1536                                    noDataValue = 32767
1537                            elif not numpy.sometrue(a == noDataValue):
1538                                a = numpy.cast['int16'](a)
1539                                noDataValue = None
1540                   
1541                    elif minValue >= 0 and maxValue <= 65535:
1542                        if a.dtype.name != 'uint16':
1543                            if valueRange < 65536:
1544                                if minValue > 0:
1545                                    a[a == noDataValue] = 0
1546                                    a = numpy.cast['uint16'](a)
1547                                    noDataValue = 0
1548                                else:
1549                                    a[a == noDataValue] = 65535
1550                                    a = numpy.cast['uint16'](a)
1551                                    noDataValue = 65535
1552                            elif not numpy.sometrue(a == noDataValue):
1553                                a = numpy.cast['uint16'](a)
1554                                noDataValue = None
1555
1556                # Return successfully.
1557
1558                return a, noDataValue
1559               
1560            except:
1561                Logger.LogExceptionAsError()
1562                raise
1563        finally:
1564            Logger.SetLogInfoAsDebug(oldLogInfoAsDebug)
1565
1566    @classmethod
1567    def ExtractByMask(cls, inputRaster, mask, outputRaster, overwriteExisting=False):
1568        cls.__doc__.Obj.ValidateMethodInvocation()
1569        try:
1570            gp = GeoprocessorManager.GetWrappedGeoprocessor()
1571            gp.ExtractByMask_sa(inputRaster, mask, outputRaster)
1572        except:
1573            Logger.LogExceptionAsError()
1574            raise
1575
1576    @classmethod
1577    def ProjectClipAndOrExecuteMapAlgebra(cls, inputRaster, outputRaster, projectedCoordinateSystem=None, geographicTransformation=None, resamplingTechnique=None, projectedCellSize=None, registrationPoint=None, clippingDataset=None, clippingRectangle=None, mapAlgebraExpression=None, buildPyramids=False, overwriteExisting=False):
1578        cls.__doc__.Obj.ValidateMethodInvocation()
1579        cls._ValidateProjectClipAndOrExecuteMapAlgebraParameters(projectedCoordinateSystem, geographicTransformation, resamplingTechnique, projectedCellSize, registrationPoint, clippingDataset, clippingRectangle, mapAlgebraExpression)
1580        Logger.Info(_(u'Processing ArcGIS raster %(in)s into raster %(out)s...') % {u'in' : inputRaster, u'out' : outputRaster})
1581        try:
1582            from GeoEco.DataManagement.Directories import TemporaryDirectory
1583            tempDir = TemporaryDirectory()
1584           
1585            outputRasterTemp = cls._ProjectClipAndOrExecuteMapAlgebraInTempDir(inputRaster, tempDir.Path,
1586                                                                               projectedCoordinateSystem=projectedCoordinateSystem,
1587                                                                               geographicTransformation=geographicTransformation,
1588                                                                               resamplingTechnique=resamplingTechnique,
1589                                                                               projectedCellSize=projectedCellSize,
1590                                                                               registrationPoint=registrationPoint,
1591                                                                               clippingDataset=clippingDataset,
1592                                                                               clippingRectangle=clippingRectangle,
1593                                                                               mapAlgebraExpression=mapAlgebraExpression,
1594                                                                               buildPyramids=buildPyramids)
1595           
1596            cls.MoveSilent(outputRasterTemp, outputRaster, overwriteExisting=overwriteExisting)
1597        except:
1598            Logger.LogExceptionAsError()
1599            raise
1600
1601    @classmethod
1602    def _ValidateProjectClipAndOrExecuteMapAlgebraParameters(cls, projectedCoordinateSystem=None, geographicTransformation=None, resamplingTechnique=None, projectedCellSize=None, registrationPoint=None, clippingDataset=None, clippingRectangle=None, mapAlgebraExpression=None):
1603        if projectedCoordinateSystem is None and clippingDataset is None and clippingRectangle is None and mapAlgebraExpression is None:
1604            Logger.RaiseException(ValueError(_(u'You did not specify a projected coordinate system, clipping dataset/rectangle, or map algebra expression. To use this tool, you must specify at least one of these three parameters.')))
1605        if projectedCoordinateSystem is not None and resamplingTechnique is None:
1606            Logger.RaiseException(ValueError(_(u'To project the converted raster to a new coordinate system, you must specify the resampling technique.')))
1607        if clippingDataset is not None and clippingRectangle is not None:
1608            Logger.RaiseException(ValueError(_(u'You cannot specify both a dataset for clipping and a rectangle for clipping. Please specify just one of these parameters.')))
1609        if projectedCoordinateSystem is None and geographicTransformation is not None:
1610            Logger.Warning(_(u'The geographic transformation will be ignored because no projected coordinate system was specified.'))
1611        if projectedCoordinateSystem is None and resamplingTechnique is not None:
1612            Logger.Warning(_(u'The resampling technique will be ignored because no projected coordinate system was specified.'))
1613        if projectedCoordinateSystem is None and projectedCellSize is not None:
1614            Logger.Warning(_(u'The projected cell size will be ignored because no projected coordinate system was specified.'))
1615        if projectedCoordinateSystem is None and registrationPoint is not None:
1616            Logger.Warning(_(u'The registration point will be ignored because no projected coordinate system was specified.'))
1617
1618    @classmethod
1619    def _ProjectClipAndOrExecuteMapAlgebraInTempDir(cls, inputRaster, tempDir, projectedCoordinateSystem=None, geographicTransformation=None, resamplingTechnique=None, projectedCellSize=None, registrationPoint=None, clippingDataset=None, clippingRectangle=None, mapAlgebraExpression=None, buildPyramids=False, overwriteExisting=False):
1620        import tempfile
1621       
1622        gp = GeoprocessorManager.GetWrappedGeoprocessor()
1623        outputRaster = inputRaster
1624
1625        # Project the raster, if requested.
1626       
1627        if projectedCoordinateSystem is not None:
1628            outputRaster = None
1629            while outputRaster is None or '-' in outputRaster:      # Python mktemp can generate a name that includes a - character, which is illegal in ArcInfo Binary Grid names.
1630                outputRaster = tempfile.mktemp(dir=tempDir)
1631               
1632            Logger.Debug(_(u'Projecting...'))
1633            if geographicTransformation is not None or registrationPoint is not None:
1634                gp.ProjectRaster_Management(inputRaster, outputRaster, projectedCoordinateSystem, resamplingTechnique, projectedCellSize, geographicTransformation, registrationPoint)
1635            else:
1636                gp.ProjectRaster_Management(inputRaster, outputRaster, projectedCoordinateSystem, resamplingTechnique, projectedCellSize)
1637
1638            inputRaster = outputRaster
1639
1640        # Clip the raster, if requested.
1641
1642        if clippingDataset is not None or clippingRectangle is not None:
1643            outputRaster = None
1644            while outputRaster is None or '-' in outputRaster:      # Python mktemp can generate a name that includes a - character, which is illegal in ArcInfo Binary Grid names.
1645                outputRaster = tempfile.mktemp(dir=tempDir)
1646
1647            Logger.Debug(_(u'Clipping...'))
1648
1649            # If the caller provided a clipping dataset, get its
1650            # extent and use that as the clipping rectangle.
1651
1652            if clippingDataset is not None:
1653                clippingRectangle = gp.Describe(clippingDataset).Extent
1654                if not isinstance(clippingRectangle, basestring) or len(clippingRectangle) <= 0:
1655                    Logger.RaiseException(ValueError(_(u'Cannot clip to the extent of dataset %(ds)s because ArcGIS cannot determine the extent of this dataset. Please select a different dataset or use the clipping rectangle parameter instead. Error details: gp.Describe(%(reprds)s).Extent returned None or an empty string.') % {'ds': clippingDataset, 'reprds': repr(clippingDataset)}))
1656
1657            # If this is ArcGIS 9.2, pass inputRaster for the
1658            # in_template_dataset parameter, to work around the 9.2
1659            # bug described in
1660            # http://forums.esri.com/Thread.asp?c=93&f=1729&t=230897&mc=11.
1661
1662            if GeoprocessorManager.GetArcGISMajorVersion() == 9 and GeoprocessorManager.GetArcGISMinorVersion() == 2:
1663                gp.Clip_Management(inputRaster, clippingRectangle, outputRaster, inputRaster)
1664            else:
1665                gp.Clip_Management(inputRaster, clippingRectangle, outputRaster)
1666            inputRaster = outputRaster
1667
1668        # Execute map algebra, if requested.
1669
1670        if mapAlgebraExpression is not None:
1671
1672            # Replace all occurences of the string "inputRaster" in
1673            # the mapAlgebraExpression with the value of the
1674            # inputRaster variable.
1675
1676            if GeoprocessorManager.GetArcGISMajorVersion() >= 10:
1677                (mapAlgebraExpressionToExecute, numberOfReplacements) = re.subn(u'(?<!\w)(inputRaster)(?=$|\W)', lambda s: u' [' + inputRaster + u'] ', mapAlgebraExpression)
1678            else:
1679                (mapAlgebraExpressionToExecute, numberOfReplacements) = re.subn(u'(?<!\w)(inputRaster)(?=$|\W)', lambda s: u' ' + inputRaster + u' ', mapAlgebraExpression)
1680            if numberOfReplacements <= 0:
1681                Logger.RaiseException(ValueError(_(u'The map algebra expression must include the case-sensitive string "inputRaster".')))
1682            if len(mapAlgebraExpressionToExecute) > 4000:
1683                Logger.RaiseException(ValueError(_(u'The map algebra expression is too long for the Spatial Analyst Single Output Map Algebra tool to execute. It must be no longer than 4000 characters.')))
1684
1685            # Execute the map algebra expression.
1686           
1687            Logger.Debug(_(u'Executing map algebra...'))
1688
1689            outputRaster = None
1690            while outputRaster is None or '-' in outputRaster:      # Python mktemp can generate a name that includes a - character, which is illegal in ArcInfo Binary Grid names.
1691                outputRaster = tempfile.mktemp(dir=tempDir)
1692
1693            gp.SingleOutputMapAlgebra_sa(mapAlgebraExpressionToExecute, outputRaster)
1694            gp.RefreshCatalog(tempDir)
1695
1696            # Sometimes the Single Output Map Algebra tool in
1697            # ArcGIS 9.1 strips the projection information,
1698            # causing the spatial reference to be displayed as
1699            # "<Undefined>" in ArcCatalog. Handle this ArcGIS
1700            # bug by defining the projection again. See MGET
1701            # ticket #156 for more information.
1702
1703            if GeoprocessorManager.GetArcGISMajorVersion() == 9 and GeoprocessorManager.GetArcGISMinorVersion() == 1:
1704                Logger.Debug(_(u'Defining the projection again, to work around the ArcGIS 9.1 bug described in MGET ticket #156...'))
1705                if projectedCoordinateSystem is not None:
1706                    gp.DefineProjection_Management(outputRaster, projectedCoordinateSystem)     # When we already know what the coordinate system should be, don't look it up
1707                else:
1708                    gp.DefineProjection_Management(outputRaster, gp.Describe(inputRaster).SpatialReference)
1709
1710        # Build pyramids, if requested.
1711
1712        if buildPyramids:
1713            Logger.Debug(_(u'Building pyramids...'))
1714            gp.BuildPyramids_Management(outputRaster)
1715
1716        # Return the path to the last raster we created in the temp
1717        # directory.
1718
1719        return outputRaster
1720
1721    @classmethod
1722    def ProjectToTemplate(cls, inputRaster, templateRaster, outputRaster, resamplingTechnique, interpolationMethod=None, maxHoleSize=None, mask=False, overwriteExisting=False):
1723        try:
1724            # Perform additional validation.
1725
1726            if interpolationMethod is not None and resamplingTechnique.lower() not in [u'bilinear', u'cubic']:
1727                raise ValueError(_(u'Values cannot be interpolated for No Data cells if the NEAREST or MAJORITY resampling technique is used. Please select the BILINEAR or CUBIC resampling technique instead.'))
1728
1729            # Look up the coordinate system, extent, and cell size of
1730            # the template raster.
1731
1732            gp = GeoprocessorManager.GetWrappedGeoprocessor()
1733            d = gp.Describe(templateRaster)
1734            coordinateSystem = gp.CreateSpatialReference(d.SpatialReference).split(';')[0]
1735            extent = d.Extent
1736            cellSize = d.MeanCellWidth
1737           
1738            # Below, we will set the Extent environment variable and
1739            # then call ArcGIS's ProjectRaster_management to
1740            # simultaneously project and clip the input raster to the
1741            # coordinate system, extent, and cell size of the template
1742            # raster. Unfortunately ProjectRaster_management will not
1743            # necessarily create a raster that has exactly the desired
1744            # extent. It may be one cell larger or smaller in any of
1745            # the four directions. Different versions of ArcGIS seem
1746            # to work differently in this respect.
1747            #
1748            # To deal with this annoyance, we will expand the extent
1749            # in all four directions by 10 cells--guaranteeing that we
1750            # have a raster that is larger than the desired
1751            # extent--and then use ExtractByMask_sa to obtain a raster
1752            # of the desired extent.
1753            #
1754            # We use 10 cells rather than 1 cell because of a
1755            # different problem: if the caller requested that we
1756            # interpolate values for No Data cells, the most accurate
1757            # values can be obtained if each No Data region is
1758            # completely surrounded by cells with data. In the event
1759            # that the template raster extent bisects a No Data
1760            # region, the 10 cell buffer increases the chance that we
1761            # will interpolate that region using cells from both sides
1762            # of the extent line: the side that is within the template
1763            # extent and also the side that is outside the extent but
1764            # within the buffer.
1765
1766            from GeoEco.DataManagement.Directories import TemporaryDirectory
1767            tempDir = TemporaryDirectory()
1768
1769            [left, bottom, right, top] = EnvelopeTypeMetadata.ParseFromArcGISString(extent)
1770            oldExtent = gp.Extent
1771            gp.Extent = '%r %r %r %r' % (left - cellSize*10, bottom - cellSize*10, right + cellSize*10, top + cellSize*10)
1772
1773            try:
1774                # If this is ArcGIS 9.3, set the SnapRaster
1775                # environment variable to the template raster.
1776               
1777                if GeoprocessorManager.GetArcGISMajorVersion() > 9 or GeoprocessorManager.GetArcGISMajorVersion() == 9 and GeoprocessorManager.GetArcGISMinorVersion() >= 3:
1778                    oldSnapRaster = gp.SnapRaster
1779                    gp.SnapRaster = templateRaster
1780
1781                # Project the raster. If this is ArcGIS 9.3 or later,
1782                # the SnapRaster and Extent environment variables will
1783                # ensure the projected cells are snapped and clipped
1784                # as requested by the caller. If it is 9.2, use the
1785                # Registration_Point parameter instead of SnapRaster,
1786                # which did not exist in 9.2 (there was something like
1787                # it, but it did not work correctly).
1788
1789                try:
1790                    projectedRaster = os.path.join(tempDir.Path, u'projected.img')
1791                    if GeoprocessorManager.GetArcGISMajorVersion() > 9 or GeoprocessorManager.GetArcGISMajorVersion() == 9 and GeoprocessorManager.GetArcGISMinorVersion() >= 3:
1792                        gp.ProjectRaster_management(inputRaster, projectedRaster, coordinateSystem, resamplingTechnique, cellSize)
1793                    else:
1794                        gp.ProjectRaster_management(inputRaster, projectedRaster, coordinateSystem, resamplingTechnique, cellSize, None, extent.rsplit(' ', 2)[0])
1795
1796                # If this is ArcGIS 9.3, reset the SnapRaster
1797                # environment variable to what it was before.
1798               
1799                finally:
1800                    if GeoprocessorManager.GetArcGISMajorVersion() > 9 or GeoprocessorManager.GetArcGISMajorVersion() == 9 and GeoprocessorManager.GetArcGISMinorVersion() >= 3:
1801                        gp.SnapRaster = oldSnapRaster
1802
1803            # Reset the Extent ArcGIS environment variable to what it
1804            # was before.
1805           
1806            finally:
1807                gp.Extent = oldExtent
1808
1809            # If the caller requested that we interpolate values for
1810            # No Data regions, do it now.
1811
1812            if interpolationMethod is not None:
1813                from GeoEco.SpatialAnalysis.Interpolation import Interpolator
1814                infilledRaster = os.path.join(tempDir.Path, u'infilled.img')
1815                Interpolator.InpaintArcGISRaster(projectedRaster, infilledRaster, interpolationMethod, maxHoleSize)
1816                projectedRaster = infilledRaster
1817
1818            # We are about to use ExtractByMask_sa to extract a raster
1819            # of the desired extent from the projected raster in the
1820            # temp directory. But ExtractByMask_sa also has a side
1821            # effect that we might not want: it sets cells that are No
1822            # Data in the mask to No Data in the output raster. If the
1823            # caller did not request that to happen (using the
1824            # template raster as the mask), create a constant raster
1825            # that has the same coordinate system, extent, and cell
1826            # size as the template raster. We'll use it instead.
1827
1828            if not mask:
1829                oldOutputCoordinateSystem = gp.OutputCoordinateSystem
1830                gp.OutputCoordinateSystem = coordinateSystem
1831                try:
1832                    maskRaster = os.path.join(tempDir.Path, u'constant.img')
1833                    gp.CreateConstantRaster_sa(maskRaster, 0, 'INTEGER', cellSize, extent)
1834                finally:
1835                    gp.OutputCoordinateSystem = oldOutputCoordinateSystem
1836
1837                # For safety, verify that the output raster has the
1838                # expected number of columns and rows.
1839               
1840                d2 = gp.Describe(maskRaster)
1841                if d2.Width != d.Width or d2.Height != d.Height:
1842                    raise RuntimeError(_(u'Programming error in this tool: the constant raster does not have the same number of rows or columns as the template raster. Please contact the author of this tool for assistance.'))
1843
1844            else:
1845                maskRaster = templateRaster
1846
1847            # Extract the raster.
1848
1849            gp.ExtractByMask_sa(projectedRaster, maskRaster, outputRaster)
1850
1851        except:
1852            Logger.LogExceptionAsError()
1853            raise
1854
1855    @classmethod
1856    def ToPolygons(cls, inputRaster, outputFeatureClass, simplify=True, field=None, projectedCoordinateSystem=None, geographicTransformation=None, resamplingTechnique=None, projectedCellSize=None, registrationPoint=None, clippingDataset=None, clippingRectangle=None, mapAlgebraExpression=None, overwriteExisting=False):
1857        cls.__doc__.Obj.ValidateMethodInvocation()
1858       
1859        # Perform additional validation.
1860
1861        gp = GeoprocessorManager.GetWrappedGeoprocessor()
1862        if mapAlgebraExpression is None and gp.Describe(inputRaster).PixelType.upper() not in ['U1', 'U2', 'U4', 'S8', 'U8', 'S16', 'U16', 'S32', 'U32', 'S64', 'U64']:
1863            Logger.RaiseException(RuntimeError(_(u'The input raster %(in)s is a floating-point raster. Only integer rasters can be converted to polygons. Please specify an integer raster or provide a map algebra expression that converts this one to an integer raster.') % {u'in': inputRaster}))
1864       
1865        Logger.Info(_(u'Converting ArcGIS raster %(in)s to polygon feature class %(out)s...') % {u'in' : inputRaster, u'out' : outputFeatureClass})
1866        try:
1867            # Perform requested pre-conversion processing in a temp
1868            # directory.
1869           
1870            if projectedCoordinateSystem is not None or clippingRectangle is not None or mapAlgebraExpression is not None:
1871                cls._ValidateProjectClipAndOrExecuteMapAlgebraParameters(projectedCoordinateSystem, geographicTransformation, resamplingTechnique, projectedCellSize, registrationPoint, clippingDataset, clippingRectangle, mapAlgebraExpression)
1872                from GeoEco.DataManagement.Directories import TemporaryDirectory
1873                tempDir = TemporaryDirectory()
1874                inputRaster = cls._ProjectClipAndOrExecuteMapAlgebraInTempDir(inputRaster, tempDir.Path,
1875                                                                              projectedCoordinateSystem=projectedCoordinateSystem,
1876                                                                              geographicTransformation=geographicTransformation,
1877                                                                              resamplingTechnique=resamplingTechnique,
1878                                                                              projectedCellSize=projectedCellSize,
1879                                                                              registrationPoint=registrationPoint,
1880                                                                              clippingDataset=clippingDataset,
1881                                                                              clippingRectangle=clippingRectangle,
1882                                                                              mapAlgebraExpression=mapAlgebraExpression)
1883
1884                if mapAlgebraExpression is not None and gp.Describe(inputRaster).PixelType.upper() not in ['U1', 'U2', 'U4', 'S8', 'U8', 'S16', 'U16', 'S32', 'U32', 'S64', 'U64']:
1885                    Logger.RaiseException(RuntimeError(_(u'The map algebra expression yielded a floating-point raster. Only integer rasters can be converted to polygons. Please provide a map algebra expression that yields an integer raster.')))
1886
1887            # Convert the raster to a polygon feature class.
1888           
1889            if simplify:
1890                gp.RasterToPolygon_conversion(inputRaster, outputFeatureClass, 'SIMPLIFY', field)
1891            else:
1892                gp.RasterToPolygon_conversion(inputRaster, outputFeatureClass, 'NO_SIMPLIFY', field)
1893
1894        except:
1895            Logger.LogExceptionAsError()
1896            raise
1897
1898    @classmethod
1899    def ToPolygonOutlines(cls, inputRaster, outputFeatureClass, simplify=True, field=None, projectedCoordinateSystem=None, geographicTransformation=None, resamplingTechnique=None, projectedCellSize=None, registrationPoint=None, clippingDataset=None, clippingRectangle=None, mapAlgebraExpression=None, overwriteExisting=False):
1900        cls.__doc__.Obj.ValidateMethodInvocation()
1901        oldLogInfoAsDebug = Logger.LogInfoAndSetInfoToDebug(_(u'Converting ArcGIS raster %(in)s to outlines in line feature class %(out)s...') % {u'in' : inputRaster, u'out' : outputFeatureClass})
1902        try:
1903            try:
1904                # Convert the raster to a polygon feature class in a
1905                # temporary directory.
1906               
1907                from GeoEco.DataManagement.Directories import TemporaryDirectory
1908                tempDir = TemporaryDirectory()
1909                tempFeatureClass = os.path.join(tempDir.Path, u'polygons.shp')
1910                cls.ToPolygons(inputRaster,
1911                               tempFeatureClass,
1912                               simplify=simplify,
1913                               field=field,
1914                               projectedCoordinateSystem=projectedCoordinateSystem,
1915                               geographicTransformation=geographicTransformation,
1916                               resamplingTechnique=resamplingTechnique,
1917                               projectedCellSize=projectedCellSize,
1918                               registrationPoint=registrationPoint,
1919                               clippingDataset=clippingDataset,
1920                               clippingRectangle=clippingRectangle,
1921                               mapAlgebraExpression=mapAlgebraExpression,
1922                               overwriteExisting=overwriteExisting)
1923
1924                # Convert the polygon feature class to a line
1925                # feature class.
1926
1927                gp = GeoprocessorManager.GetWrappedGeoprocessor()
1928                gp.FeatureToLine_management(tempFeatureClass, outputFeatureClass)
1929
1930            except:
1931                Logger.LogExceptionAsError()
1932                raise
1933        finally:
1934            Logger.SetLogInfoAsDebug(oldLogInfoAsDebug)
1935
1936    @classmethod
1937    def ToLines(cls, inputRaster, outputFeatureClass, backgroundValue=u'ZERO', minDangleLength=0.0, simplify=True, field=None, projectedCoordinateSystem=None, geographicTransformation=None, resamplingTechnique=None, projectedCellSize=None, registrationPoint=None, clippingDataset=None, clippingRectangle=None, mapAlgebraExpression=None, overwriteExisting=False):
1938        cls.__doc__.Obj.ValidateMethodInvocation()
1939        gp = GeoprocessorManager.GetWrappedGeoprocessor()
1940        Logger.Info(_(u'Converting ArcGIS raster %(in)s to line feature class %(out)s...') % {u'in' : inputRaster, u'out' : outputFeatureClass})
1941        try:
1942            # Perform requested pre-conversion processing in a temp
1943            # directory.
1944           
1945            if projectedCoordinateSystem is not None or clippingRectangle is not None or mapAlgebraExpression is not None:
1946                cls._ValidateProjectClipAndOrExecuteMapAlgebraParameters(projectedCoordinateSystem, geographicTransformation, resamplingTechnique, projectedCellSize, registrationPoint, clippingDataset, clippingRectangle, mapAlgebraExpression)
1947                from GeoEco.DataManagement.Directories import TemporaryDirectory
1948                tempDir = TemporaryDirectory()
1949                inputRaster = cls._ProjectClipAndOrExecuteMapAlgebraInTempDir(inputRaster, tempDir.Path,
1950                                                                              projectedCoordinateSystem=projectedCoordinateSystem,
1951                                                                              geographicTransformation=geographicTransformation,
1952                                                                              resamplingTechnique=resamplingTechnique,
1953                                                                              projectedCellSize=projectedCellSize,
1954                                                                              registrationPoint=registrationPoint,
1955                                                                              clippingDataset=clippingDataset,
1956                                                                              clippingRectangle=clippingRectangle,
1957                                                                              mapAlgebraExpression=mapAlgebraExpression)
1958
1959            # Convert the raster to a line feature class.
1960
1961            try:
1962                if simplify:
1963                    gp.RasterToPolyline_conversion(inputRaster, outputFeatureClass, backgroundValue, minDangleLength, 'SIMPLIFY', field)
1964                else:
1965                    gp.RasterToPolyline_conversion(inputRaster, outputFeatureClass, backgroundValue, minDangleLength, 'NO_SIMPLIFY', field)
1966            except Exception, e:
1967                if str(e).lower().find('empty feature class') >= 0:
1968                    Logger.Warning(_(u'The raster %(raster)s is empty, so no lines can be created from it. Line feature class %(fc)s will be empty.') % {u'raster': inputRaster, u'fc': outputFeatureClass})
1969                else:
1970                    raise
1971
1972        except:
1973            Logger.LogExceptionAsError()
1974            raise
1975
1976    @classmethod
1977    def ToPoints(cls, inputRaster, outputFeatureClass, field=None, projectedCoordinateSystem=None, geographicTransformation=None, resamplingTechnique=None, projectedCellSize=None, registrationPoint=None, clippingDataset=None, clippingRectangle=None, mapAlgebraExpression=None, overwriteExisting=False):
1978        cls.__doc__.Obj.ValidateMethodInvocation()
1979        gp = GeoprocessorManager.GetWrappedGeoprocessor()
1980        Logger.Info(_(u'Converting ArcGIS raster %(in)s to point feature class %(out)s...') % {u'in' : inputRaster, u'out' : outputFeatureClass})
1981        try:
1982            # Perform requested pre-conversion processing in a temp
1983            # directory.
1984           
1985            if projectedCoordinateSystem is not None or clippingRectangle is not None or mapAlgebraExpression is not None:
1986                cls._ValidateProjectClipAndOrExecuteMapAlgebraParameters(projectedCoordinateSystem, geographicTransformation, resamplingTechnique, projectedCellSize, registrationPoint, clippingDataset, clippingRectangle, mapAlgebraExpression)
1987                from GeoEco.DataManagement.Directories import TemporaryDirectory
1988                tempDir = TemporaryDirectory()
1989                inputRaster = cls._ProjectClipAndOrExecuteMapAlgebraInTempDir(inputRaster, tempDir.Path,
1990                                                                              projectedCoordinateSystem=projectedCoordinateSystem,
1991                                                                              geographicTransformation=geographicTransformation,
1992                                                                              resamplingTechnique=resamplingTechnique,
1993                                                                              projectedCellSize=projectedCellSize,
1994                                                                              registrationPoint=registrationPoint,
1995                                                                              clippingDataset=clippingDataset,
1996                                                                              clippingRectangle=clippingRectangle,
1997                                                                              mapAlgebraExpression=mapAlgebraExpression)
1998
1999            # Convert the raster to a point feature class.
2000           
2001            gp.RasterToPoint_conversion(inputRaster, outputFeatureClass, field)
2002
2003        except:
2004            Logger.LogExceptionAsError()
2005            raise
2006           
2007
2008###############################################################################
2009# Metadata: module
2010###############################################################################
2011
2012from GeoEco.DataManagement.BinaryRasters import BinaryRaster
2013from GeoEco.Dependencies import PythonAggregatedModuleDependency
2014from GeoEco.Metadata import *
2015from GeoEco.Types import *
2016
2017AddModuleMetadata(shortDescription=_(u'Provides methods for performing common data management operations on ArcGIS rasters.'))
2018
2019###############################################################################
2020# Metadata: ArcGISRaster class
2021###############################################################################
2022
2023AddClassMetadata(ArcGISRaster,
2024    shortDescription=_(u'Provides methods for performing common data management operations on ArcGIS rasters.'),
2025    longDescription=_(
2026u"""This class provides a significant advantage over the ArcGIS geoprocessing
2027tools for managing rasters: it can work around a bug in ArcGIS that causes it to
2028crash when a large number of rasters are stored in a single directory."""),
2029    isExposedAsCOMServer=True,
2030    comIID=u'{82BD49EF-6F06-4AC0-8E91-4E6B2FB84EB1}',
2031    comCLSID=u'{22C205A0-BE4C-4ECA-AF7C-BE496196C75F}')
2032
2033# Public method: ArcGISRaster.Copy
2034
2035AddMethodMetadata(ArcGISRaster.Copy,
2036    shortDescription=_(u'Copies an ArcGIS raster.'),
2037    longDescription=_(
2038u"""Unlike the ArcGIS geoprocessor\'s CopyRaster tool, this tool does
2039not crash ArcGIS when copying rasters to a destination directory that
2040already contains several hundred rasters. For more information on this
2041ArcGIS bug, see
2042http://forums.esri.com/Thread.asp?c=93&f=1729&t=196716&mc=0."""),
2043    isExposedToPythonCallers=True,
2044    isExposedByCOM=True,
2045    isExposedAsArcGISTool=True,
2046    arcGISDisplayName=_(u'Copy Raster'),
2047    arcGISToolCategory=_(u'Data Management\\ArcGIS Rasters\\Copy'),
2048    dependencies=[ArcGISDependency(9, 1)])
2049
2050AddArgumentMetadata(ArcGISRaster.Copy, u'cls',
2051    typeMetadata=ClassOrClassInstanceTypeMetadata(cls=ArcGISRaster),
2052    description=_(u'%s class or an instance of it.') % ArcGISRaster.__name__)
2053
2054AddArgumentMetadata(ArcGISRaster.Copy, u'sourceRaster',
2055    typeMetadata=ArcGISRasterLayerTypeMetadata(mustExist=True),
2056    description=_(u'Raster to copy.'),
2057    arcGISDisplayName=_(u'Source raster'))
2058
2059AddArgumentMetadata(ArcGISRaster.Copy, u'destinationRaster',
2060    typeMetadata=ArcGISRasterTypeMetadata(mustBeDifferentThanArguments=[u'sourceRaster'], deleteIfParameterIsTrue=u'overwriteExisting', createParentDirectories=True),
2061    description=_(
2062u"""Copy to create.
2063
2064If this is a file system path, missing directories in the path will be created
2065if they do not exist."""),
2066    direction=u'Output',
2067    arcGISDisplayName=_(u'Destination raster'))
2068
2069AddArgumentMetadata(ArcGISRaster.Copy, u'overwriteExisting',
2070    typeMetadata=BooleanTypeMetadata(),
2071    description=_(
2072u"""If True, the destination raster will be overwritten, if it exists.
2073If False, a ValueError will be raised if the destination raster
2074exists."""),
2075    initializeToArcGISGeoprocessorVariable=u'OverwriteOutput')
2076
2077# Public method: ArcGISRaster.CopySilent
2078
2079AddMethodMetadata(ArcGISRaster.CopySilent,
2080    shortDescription=_(u'Copies an ArcGIS raster and logs a debug message rather than an informational message.'),
2081    longDescription=_(
2082u"""This method does the same thing as the Copy method, except it logs
2083a debug message rather than an informational message. It is intended
2084for use when the raster-copy operation is not imporant enough to
2085warrent notifying the user (for example, when an output raster is
2086extracted from a temporary directory to the final location)."""),
2087    isExposedToPythonCallers=True,
2088    isExposedByCOM=True,
2089    dependencies=[ArcGISDependency(9, 1)])
2090
2091CopyArgumentMetadata(ArcGISRaster.Copy, u'cls', ArcGISRaster.CopySilent, u'cls')
2092CopyArgumentMetadata(ArcGISRaster.Copy, u'sourceRaster', ArcGISRaster.CopySilent, u'sourceRaster')
2093CopyArgumentMetadata(ArcGISRaster.Copy, u'destinationRaster', ArcGISRaster.CopySilent, u'destinationRaster')
2094CopyArgumentMetadata(ArcGISRaster.Copy, u'overwriteExisting', ArcGISRaster.CopySilent, u'overwriteExisting')
2095
2096# Public method: ArcGISRaster.CreateTemporaryRastersToPreventArcGISCrash
2097
2098AddMethodMetadata(ArcGISRaster.CreateTemporaryRastersToPreventArcGISCrash,
2099    shortDescription=_(u'Creates enough temporary ArcGIS rasters in a directory to prevent ArcGIS from crashing when a specified number of rasters are added to the directory.'),
2100    longDescription=_(
2101u"""A bug in ArcGIS 9.x causes it to crash if several hundred rasters are added
2102to a directory. Whether the crash occurs depends on the number and data types of
2103the rasters. See http://forums.esri.com/Thread.asp?c=93&f=1729&t=196716&mc=0 for
2104a complete description of the problem. At the time this documentation was
2105written, the problem was still present in ArcGIS 9.1 SP2 and 9.2 SP1.
2106
2107This function is designed to work around the problem. You call this function
2108prior to adding rasters to a directory and specify the number of of rasters
2109you're going to add. This function analyzes the current contents of the
2110directory. If there is any possibility that adding your rasters would hit the
2111combination needed to cause the crash, this function creates enough temporary
2112rasters to prevent the problem.
2113
2114If this function creates any temporary rasters, it returns a list of their full
2115paths to you. You should delete them after you've added your own rasters. The
2116DeleteTemporaryRastersThatPreventedArcGISCrash function is provided for this
2117purpose.
2118"""),
2119    isExposedToPythonCallers=True,
2120    isExposedByCOM=True,
2121    dependencies=[ArcGISDependency(9, 1)])
2122
2123AddArgumentMetadata(ArcGISRaster.CreateTemporaryRastersToPreventArcGISCrash, u'cls',
2124    typeMetadata=ClassOrClassInstanceTypeMetadata(cls=ArcGISRaster),
2125    description=_(u'%s class or an instance of it.') % ArcGISRaster.__name__)
2126
2127AddArgumentMetadata(ArcGISRaster.CreateTemporaryRastersToPreventArcGISCrash, u'directory',
2128    typeMetadata=DirectoryTypeMetadata(),
2129    description=_(
2130u"""Directory in which temporary rasters should be created, in anticipation of
2131additional rasters being added by the caller after this method returns."""))
2132
2133AddArgumentMetadata(ArcGISRaster.CreateTemporaryRastersToPreventArcGISCrash, u'rastersToAdd',
2134    typeMetadata=IntegerTypeMetadata(minValue=1, maxValue=511),
2135    description=_(
2136u"""Number of rasters that the caller will add to the directory after this
2137method returns."""))
2138
2139AddResultMetadata(ArcGISRaster.CreateTemporaryRastersToPreventArcGISCrash, u'temporaryRasters',
2140    typeMetadata=ListTypeMetadata(elementType=ArcGISRasterTypeMetadata()),
2141    description=_(u"""List of temporary rasters that were created."""))
2142
2143# Public method: ArcGISRaster.CreateXRaster
2144
2145AddMethodMetadata(ArcGISRaster.CreateXRaster,
2146    shortDescription=_(u'Creates an ArcGIS raster where the value of each cell is the X coordinate of the cell.'),
2147    isExposedToPythonCallers=True,
2148    isExposedByCOM=True,
2149    isExposedAsArcGISTool=True,
2150    arcGISDisplayName=_(u'Create X Coordinate Raster'),
2151    arcGISToolCategory=_(u'Spatial Analysis\\Create Rasters'),
2152    dependencies=[ArcGISDependency(9, 1), PythonAggregatedModuleDependency('numpy')])
2153
2154CopyArgumentMetadata(ArcGISRaster.Copy, u'cls', ArcGISRaster.CreateXRaster, u'cls')
2155
2156AddArgumentMetadata(ArcGISRaster.CreateXRaster, u'raster',
2157    typeMetadata=ArcGISRasterTypeMetadata(deleteIfParameterIsTrue=u'overwriteExisting', createParentDirectories=True),
2158    description=_(
2159u"""Raster to create.
2160
2161If this is a file system path, missing directories in the path will be created
2162if they do not exist."""),
2163    direction=u'Output',
2164    arcGISDisplayName=_(u'Output raster'))
2165
2166AddArgumentMetadata(ArcGISRaster.CreateXRaster, u'extent',
2167    typeMetadata=EnvelopeTypeMetadata(),
2168    description=_(u"""Extent of the output raster."""),
2169    arcGISDisplayName=_(u'Extent'))
2170
2171AddArgumentMetadata(ArcGISRaster.CreateXRaster, u'cellSize',
2172    typeMetadata=FloatTypeMetadata(minValue=0.0),
2173    description=_(
2174u"""Cell size of the output raster.
2175
2176If the horizontal or vertical extents of the raster are not evenly
2177divisble by the cell size, the extents will be increased right or up
2178by the smallest amount needed to make them evenly divisible. For
2179example, if the horizontal extent runs from 0 to 25 and the cell size
2180is 2, the right extent will be increased to 26."""),
2181    arcGISDisplayName=_(u'Cell size'))
2182
2183AddArgumentMetadata(ArcGISRaster.CreateXRaster, u'cellValue',
2184    typeMetadata=UnicodeStringTypeMetadata(allowedValues=[u'Center', u'Left', u'Right'], makeLowercase=True),
2185    description=_(
2186u"""Value of the raster cells, either:
2187
2188* Center - the X coordinate of the center of the cell.
2189
2190* Left - the X coordinate of the left edge of the cell.
2191
2192* Right - the X coordinate of the right edge of the cell.
2193"""),
2194    arcGISDisplayName=_(u'Cell value'))
2195
2196AddArgumentMetadata(ArcGISRaster.CreateXRaster, u'coordinateSystem',
2197    typeMetadata=CoordinateSystemTypeMetadata(canBeNone=True),
2198    description=_(
2199u"""Coordinate system to define for the raster. If not specified, a
2200coordinate system will not be defined."""),
2201    arcGISDisplayName=_(u'Coordinate system'))
2202
2203AddArgumentMetadata(ArcGISRaster.CreateXRaster, u'buildPyramids',
2204    typeMetadata=BooleanTypeMetadata(),
2205    description=_(
2206u"""If True, pyramids will be built for the raster, which will
2207improve its display speed in the ArcGIS user interface."""),
2208    arcGISDisplayName=_(u'Build pyramids'))
2209
2210AddArgumentMetadata(ArcGISRaster.CreateXRaster, u'overwriteExisting',
2211    typeMetadata=BooleanTypeMetadata(),
2212    description=_(
2213u"""If True, the raster will be overwritten, if it exists. If False, a
2214ValueError will be raised if the raster exists."""),
2215    initializeToArcGISGeoprocessorVariable=u'OverwriteOutput')
2216
2217# Public method: ArcGISRaster.CreateYRaster
2218
2219AddMethodMetadata(ArcGISRaster.CreateYRaster,
2220    shortDescription=_(u'Creates an ArcGIS raster where the value of each cell is the Y coordinate of the cell.'),
2221    isExposedToPythonCallers=True,
2222    isExposedByCOM=True,
2223    isExposedAsArcGISTool=True,
2224    arcGISDisplayName=_(u'Create Y Coordinate Raster'),
2225    arcGISToolCategory=_(u'Spatial Analysis\\Create Rasters'),
2226    dependencies=[ArcGISDependency(9, 1), PythonAggregatedModuleDependency('numpy')])
2227
2228CopyArgumentMetadata(ArcGISRaster.CreateXRaster, u'cls', ArcGISRaster.CreateYRaster, u'cls')
2229CopyArgumentMetadata(ArcGISRaster.CreateXRaster, u'raster', ArcGISRaster.CreateYRaster, u'raster')
2230CopyArgumentMetadata(ArcGISRaster.CreateXRaster, u'extent', ArcGISRaster.CreateYRaster, u'extent')
2231CopyArgumentMetadata(ArcGISRaster.CreateXRaster, u'cellSize', ArcGISRaster.CreateYRaster, u'cellSize')
2232
2233AddArgumentMetadata(ArcGISRaster.CreateYRaster, u'cellValue',
2234    typeMetadata=UnicodeStringTypeMetadata(allowedValues=[u'Center', u'Bottom', u'Top'], makeLowercase=True),
2235    description=_(
2236u"""Value of the raster cells, either:
2237
2238* Center - the X coordinate of the center of the cell.
2239
2240* Bottom - the Y coordinate of the bottom edge of the cell.
2241
2242* Top - the X coordinate of the top edge of the cell.
2243"""),
2244    arcGISDisplayName=_(u'Cell value'))
2245
2246CopyArgumentMetadata(ArcGISRaster.CreateXRaster, u'coordinateSystem', ArcGISRaster.CreateYRaster, u'coordinateSystem')
2247CopyArgumentMetadata(ArcGISRaster.CreateXRaster, u'buildPyramids', ArcGISRaster.CreateYRaster, u'buildPyramids')
2248CopyArgumentMetadata(ArcGISRaster.CreateXRaster, u'overwriteExisting', ArcGISRaster.CreateYRaster, u'overwriteExisting')
2249
2250# Public method: ArcGISRaster.Delete
2251
2252AddMethodMetadata(ArcGISRaster.Delete,
2253    shortDescription=_(u'Deletes an ArcGIS raster.'),
2254    isExposedToPythonCallers=True,
2255    isExposedByCOM=True,
2256    isExposedAsArcGISTool=True,
2257    arcGISDisplayName=_(u'Delete Raster'),
2258    arcGISToolCategory=_(u'Data Management\\ArcGIS Rasters\\Delete'),
2259    dependencies=[ArcGISDependency(9, 1)])
2260
2261AddArgumentMetadata(ArcGISRaster.Delete, u'cls',
2262    typeMetadata=ClassOrClassInstanceTypeMetadata(cls=ArcGISRaster),
2263    description=_(u'%s class or an instance of it.') % ArcGISRaster.__name__)
2264
2265AddArgumentMetadata(ArcGISRaster.Delete, u'raster',
2266    typeMetadata=ArcGISRasterTypeMetadata(),
2267    description=_(u"""Raster to delete."""),
2268    arcGISDisplayName=_(u'Raster'))
2269
2270# Public method: ArcGISRaster.DeleteTemporaryRastersThatPreventedArcGISCrash
2271
2272AddMethodMetadata(ArcGISRaster.DeleteTemporaryRastersThatPreventedArcGISCrash,
2273    shortDescription=_(u'Deletes the temporary ArcGIS rasters created by the CreateTemporaryRastersToPreventArcGISCrash function.'),
2274    isExposedToPythonCallers=True,
2275    isExposedByCOM=True,
2276    dependencies=[ArcGISDependency(9, 1)])
2277
2278AddArgumentMetadata(ArcGISRaster.DeleteTemporaryRastersThatPreventedArcGISCrash, u'cls',
2279    typeMetadata=ClassOrClassInstanceTypeMetadata(cls=ArcGISRaster),
2280    description=_(u'%s class or an instance of it.') % ArcGISRaster.__name__)
2281
2282AddArgumentMetadata(ArcGISRaster.DeleteTemporaryRastersThatPreventedArcGISCrash, u'rasters',
2283    typeMetadata=ListTypeMetadata(elementType=ArcGISRasterTypeMetadata()),
2284    description=_(
2285u"""List of temporary rasters to delete, returned by the
2286CreateTemporaryRastersToPreventArcGISCrash function."""))
2287
2288# Public method: ArcGISRaster.Exists
2289
2290AddMethodMetadata(ArcGISRaster.Exists,
2291    shortDescription=_(u'Tests that a specified path exists and is an ArcGIS raster.'),
2292    isExposedToPythonCallers=True,
2293    isExposedByCOM=True)
2294
2295CopyArgumentMetadata(ArcGISRaster.Copy, u'cls', ArcGISRaster.Exists, u'cls')
2296
2297AddArgumentMetadata(ArcGISRaster.Exists, u'path',
2298    typeMetadata=ArcGISRasterTypeMetadata(),
2299    description=_(u'Path to test.'))
2300
2301AddResultMetadata(ArcGISRaster.Exists, u'exists',
2302    typeMetadata=BooleanTypeMetadata(),
2303    description=_(u'True if the specified path exists.'))
2304
2305AddResultMetadata(ArcGISRaster.Exists, u'isRaster',
2306    typeMetadata=BooleanTypeMetadata(),
2307    description=_(u'True if the specified path exists and is an ArcGIS raster.'))
2308
2309# Public method: ArcGISRaster.Find
2310
2311AddMethodMetadata(ArcGISRaster.Find,
2312    shortDescription=_(u'Finds rasters in an ArcGIS workspace.'),
2313    longDescription=_(
2314u"""Rasters are returned in an arbitrary order determined by the
2315ArcGIS geoprocessor and the search algorithm."""),
2316    isExposedToPythonCallers=True,
2317    isExposedByCOM=True,
2318    dependencies=[ArcGISDependency(9, 1)])
2319
2320CopyArgumentMetadata(ArcGISRaster.Copy, u'cls', ArcGISRaster.Find, u'cls')
2321
2322AddArgumentMetadata(ArcGISRaster.Find, u'workspace',
2323    typeMetadata=ArcGISWorkspaceTypeMetadata(mustExist=True),
2324    description=_(u'Workspace to search.'),
2325    arcGISDisplayName=_(u'Workspace to search'))
2326
2327AddArgumentMetadata(ArcGISRaster.Find, u'wildcard',
2328    typeMetadata=UnicodeStringTypeMetadata(),
2329    description=_(
2330u"""Wildcard expression specifying the rasters to find. Please see the
2331documentation for the ArcGIS geoprocessor's ListRasters function for
2332more information about the syntax. At the time of this writing, only
2333the * wildcard character was supported, which would match zero or more
2334of any character."""),
2335    arcGISDisplayName=_(u'Wildcard expression'),
2336    arcGISCategory=_(u'Search options'))
2337
2338AddArgumentMetadata(ArcGISRaster.Find, u'searchTree',
2339    typeMetadata=BooleanTypeMetadata(),
2340    description=_(u'If True, child workspaces will be searched.'),
2341    arcGISDisplayName=_(u'Search workspace tree'),
2342    arcGISCategory=_(u'Search options'))
2343
2344AddArgumentMetadata(ArcGISRaster.Find, u'rasterType',
2345    typeMetadata=UnicodeStringTypeMetadata(canBeNone=True),
2346    description=_(
2347u"""Type of rasters to find. If provided, only rasters of this type
2348will be found. At the time of this writing, the ArcGIS 9.3
2349documentation specified that any of the following strings would be
2350accepted: ALL, BMP, GIF, GRID, IMG, JP2, JPG, PNG, TIFF.
2351
2352This parameter requires ArcGIS 9.3 or later."""),
2353    arcGISDisplayName=_(u'Raster type'),
2354    arcGISCategory=_(u'Search options'),
2355    dependencies=[ArcGISDependency(9, 3)])
2356
2357AddArgumentMetadata(ArcGISRaster.Find, u'basePath',
2358    typeMetadata=UnicodeStringTypeMetadata(canBeNone=True),
2359    description=_(
2360u"""Absolute path from which relative paths to the rasters will be
2361calculated. If provided, relative paths will be calculated and
2362included as part of the two dimensional array returned by this
2363function.
2364
2365For example, if the base path was::
2366
2367    C:\\Data\\Rasters
2368
2369the relative paths for the rasters::
2370
2371    C:\\Data\\Rasters\\Group1\\r1
2372    C:\\Data\\Rasters\\r1
2373    C:\\Data\\r1
2374    C:\\r1
2375    D:\\r1
2376    \\\\MyServer\\Data\\r1
2377
2378would be::   
2379
2380    Group1\\r1
2381    r1
2382    ..\\r1
2383    ..\\..\\r1
2384    D:\\r1
2385    \\\\MyServer\\Data\\r1
2386"""))
2387
2388AddArgumentMetadata(ArcGISRaster.Find, u'getExtent',
2389    typeMetadata=BooleanTypeMetadata(),
2390    description=_(
2391u"""'If True, the extent of each raster will be included as part of
2392the two-dimensional array returned by this function. The extent is
2393represented by four floating point numbers: XMin, YMin, XMax, and
2394YMax."""))
2395
2396_DateParsingExpressionSyntaxDocumentation = _(
2397u"""The expression is a standard `Python regular expression
2398<http://docs.python.org/lib/re-syntax.html>`_ with additional codes
2399for matching fragments of dates::
2400
2401    %d - Day of the month as a decimal number (range: 01 to 31)
2402    %H - Hour (24-hour clock) as a decimal number (range: 00 to 23)
2403    %j - Day of the year as a decimal number (range: 001 to 366)
2404    %m - Month as a decimal number (range: 01 to 12)
2405    %M - Minute as a decimal number (range: 00 to 59)
2406    %S - Second as a decimal number (range: 00 to 61)
2407    %y - Year without century as a decimal number (range: 00 to 99)
2408    %Y - Year with century as a decimal number (range: 0001 to 9999)
2409    %% - A literal "%" character
2410
2411A date is parsed from a path as follows:
2412
24131. The date fragment codes in your expression are replaced by regular
2414   expression groups to produce a true regular expression. For
2415   example, if your expression is "%Y_%m_%d", it is converted to the
2416   regular expression
2417   "(\\\\d\\\\d\\\\d\\\\d)_(\\\\d\\\\d)_(\\\\d\\\\d)".
2418
24192. The Python re.search function is invoked to find the
2420   first occurrence of the regular expression in the path. The
2421   search proceeds from left to right.
2422
24233. If an occurrence is found, the regular expression groups are
2424   extracted and the Python time.strptime function is invoked to parse
2425   a date from the groups.
2426
2427Notes:
2428
2429* Your expression must include at least one date fragment code, but it
2430  need not include all of them. If a particular code is missing, the
2431  following default values will be used: year 1900, month 01, day 01,
2432  hour 00, minute 00, second 00.
2433
2434* You cannot specify a given date fragment code more than once.
2435
2436* You cannot specify date fragment codes that might conflict. For
2437  example, you cannot specify both %j and %d because this could result
2438  in conflicting values for the day.
2439
2440* For %y, values 00 to 68 are interpreted as years 2000 through 2068,
2441  while 69 through 99 are interpreted as years 1969 through 1999.
2442
2443* Remember that the entire path is searched for your expression, from
2444  left to right. The first occurrence of it may be in the parent
2445  directories.
2446
2447* The date fragment codes are case-sensitive.
2448
2449* If the underlying database table can hold the time as well as the
2450  date in a single field, the time will be stored along with the date.
2451  These databases include Microsoft Access, Microsoft SQL Server, and
2452  Oracle, among others. If the table cannot hold the time and date in
2453  a single field, then only the date will be stored. This is the case,
2454  for example, with dBASE III and IV tables (.dbf files), often used
2455  by ArcGIS.
2456
2457* The timezone of the parsed date is assumed to be UTC.
2458
2459Examples:
2460
2461The expression::
2462
2463    %Y%j
2464
2465will parse dates from rasters namd with the year and day of year::
2466
2467    C:\\SST\\Rasters\\2006\\sst2006001
2468    C:\\SST\\Rasters\\2006\\sst2006002
2469    C:\\SST\\Rasters\\2006\\sst2006003
2470
2471Note that, in this example, the 2006 is parsed from the raster name,
2472not the 2006 directory, because the directory is not followed by a day
2473of year, it is followed by a backslash. The date parsing expression
2474will only match a year followed by a day of year.""")
2475
2476AddArgumentMetadata(ArcGISRaster.Find, u'dateParsingExpression',
2477    typeMetadata=UnicodeStringTypeMetadata(canBeNone=True),
2478    description=_(
2479u"""'Expression for parsing dates from the paths of each raster. If
2480provided, dates will be parsed from the paths of each raster using
2481this expression and included as part of the two dimensional array
2482returned by this function.
2483
2484""") +
2485_DateParsingExpressionSyntaxDocumentation)
2486
2487AddResultMetadata(ArcGISRaster.Find, u'rasters',
2488    typeMetadata=ListTypeMetadata(ListTypeMetadata(elementType=AnyObjectTypeMetadata())),
2489    description=_(
2490u"""Two-dimensional array listing the rasters that were found and the
2491requested metadata about them. The array is organized as a table with
2492the following columns in the order shown:
2493
2494* Path - Unicode string; this column always exists.
2495
2496* Relative path - Unicode string; this column will only exist if
2497  basePath is provided.
2498
2499* XMin, YMin, XMax, YMax - float; these columns will only exist if
2500  getExtent is true.
2501
2502* Parsed date - datetime; this column will only exist if
2503  dateParsingExpression is provided.
2504
2505* Parsed UNIX time - integer; this column will only exist if
2506  dateParsingExpression is provided. It is the same value as the
2507  previous column, but in UNIX time format. UNIX times are 32-bit
2508  signed integers that are the number of seconds since 1970-01-01
2509  00:00:00 UTC. This tool assumes the date that was parsed is in the
2510  UTC timezone. The UNIX time values produced by this tool do not
2511  include leap seconds; this tool assumes that a regular year is
2512  31536000 seconds and a leap year is 31622400 seconds.
2513"""))
2514
2515# Public method: ArcGISRaster.FindAndFillTable
2516
2517AddMethodMetadata(ArcGISRaster.FindAndFillTable,
2518    shortDescription=_(u'Finds rasters within an ArcGIS workspace and inserts a row for each one into an existing table.'),
2519    longDescription=ArcGISRaster.Find.__doc__.Obj.LongDescription,
2520    isExposedToPythonCallers=True,
2521    dependencies=[ArcGISDependency(9, 1)])
2522
2523CopyArgumentMetadata(ArcGISRaster.Copy, u'cls', ArcGISRaster.FindAndFillTable, u'cls')
2524CopyArgumentMetadata(ArcGISRaster.Find, u'workspace', ArcGISRaster.FindAndFillTable, u'workspace')
2525
2526AddArgumentMetadata(ArcGISRaster.FindAndFillTable, u'insertCursor',
2527    typeMetadata=ClassInstanceTypeMetadata(cls=InsertCursor),
2528    description=_(
2529u"""Insert cursor opened to the table that will receive the rows. The
2530cursor will still be open when this function returns."""))
2531
2532AddArgumentMetadata(ArcGISRaster.FindAndFillTable, u'rasterField',
2533    typeMetadata=UnicodeStringTypeMetadata(),
2534    description=_(
2535u"""Name of the field to receive absolute paths to the rasters that
2536were found."""),
2537    arcGISDisplayName=_(u'File path field'))
2538
2539CopyArgumentMetadata(ArcGISRaster.Find, u'wildcard', ArcGISRaster.FindAndFillTable, u'wildcard')
2540CopyArgumentMetadata(ArcGISRaster.Find, u'searchTree', ArcGISRaster.FindAndFillTable, u'searchTree')
2541CopyArgumentMetadata(ArcGISRaster.Find, u'rasterType', ArcGISRaster.FindAndFillTable, u'rasterType')
2542
2543AddArgumentMetadata(ArcGISRaster.FindAndFillTable, u'relativePathField',
2544    typeMetadata=UnicodeStringTypeMetadata(canBeNone=True),
2545    description=_(
2546u"""Name of the field to receive paths of the rasters that were found,
2547relative to the path you specify for the base path parameter. For
2548example, if the base path was::
2549
2550    C:\\Data\\Rasters
2551
2552the relative paths for the rasters::
2553
2554    C:\\Data\\Rasters\\Group1\\r1
2555    C:\\Data\\Rasters\\r1
2556    C:\\Data\\r1
2557    C:\\r1
2558    D:\\r1
2559    \\\\MyServer\\Data\\r1
2560
2561would be::   
2562
2563    Group1\\r1
2564    r1
2565    ..\\r1
2566    ..\\..\\r1
2567    D:\\r1
2568    \\\\MyServer\\Data\\r1
2569"""))
2570
2571AddArgumentMetadata(ArcGISRaster.FindAndFillTable, u'basePath',
2572    typeMetadata=UnicodeStringTypeMetadata(canBeNone=True),
2573    description=_(
2574u"""Absolute path from which relative paths will be calculated and
2575stored in the field specified by the relative path field parameter.
2576Please see the documentation for that field for more information."""))
2577
2578AddArgumentMetadata(ArcGISRaster.FindAndFillTable, u'populateExtentFields',
2579    typeMetadata=BooleanTypeMetadata(),
2580    description=_(
2581u"""If True, the fields named XMin, YMin, XMax, and YMax will be
2582populated with the rasters' extents. If you populate these fields and
2583store the rasters' paths in a field named Image, ArcGIS will treat
2584your table as an unmanaged raster catalog and enable additional
2585functionality from the ArcGIS user interface, such as time series
2586animations."""),
2587    arcGISDisplayName=_(u'Populate XMin, YMin, XMax, and YMax fields'),
2588    arcGISCategory=_(u'Output table options'))
2589
2590AddArgumentMetadata(ArcGISRaster.FindAndFillTable, u'parsedDateField',
2591    typeMetadata=UnicodeStringTypeMetadata(canBeNone=True),
2592    description=_(
2593u"""Name of the field to receive dates parsed from the paths of the
2594rasters that were found. You must also specify a date parsing
2595expression."""),
2596    arcGISDisplayName=_(u'Parsed date field'),
2597    arcGISCategory=_(u'Output table options'))
2598
2599AddArgumentMetadata(ArcGISRaster.FindAndFillTable, u'dateParsingExpression',
2600    typeMetadata=UnicodeStringTypeMetadata(canBeNone=True),
2601    description=_(
2602u"""Expression for parsing dates from the paths of the rasters that
2603were found. The expression will be ignored if you do not also specify
2604a field to receive the dates or the equivalent UNIX time.
2605
2606""") + _DateParsingExpressionSyntaxDocumentation,
2607    arcGISDisplayName=_(u'Date parsing expression'),
2608    arcGISCategory=_(u'Output table options'))
2609
2610AddArgumentMetadata(ArcGISRaster.FindAndFillTable, u'unixTimeField',
2611    typeMetadata=UnicodeStringTypeMetadata(canBeNone=True),
2612    description=_(
2613u"""Name of the field to receive dates, in "UNIX time" format, parsed
2614from the paths of the rasters that were found. You must also specify a
2615date parsing expression.
2616
2617UNIX times are 32-bit signed integers that are the number of seconds
2618since 1970-01-01 00:00:00 UTC. This tool assumes the date that was
2619parsed is in the UTC timezone. The UNIX time values produced by this
2620tool do not include leap seconds; this tool assumes that a regular
2621year is 31536000 seconds and a leap year is 31622400 seconds."""),
2622    arcGISDisplayName=_(u'UNIX time field'),
2623    arcGISCategory=_(u'Output table options'))
2624
2625# Public method: ArcGISRaster.FindAndCreateTable
2626
2627AddMethodMetadata(ArcGISRaster.FindAndCreateTable,
2628    shortDescription=_(u'Finds rasters within an ArcGIS workspace and creates a table that lists them.'),
2629    longDescription=ArcGISRaster.Find.__doc__.Obj.LongDescription,
2630    isExposedToPythonCallers=True,
2631    dependencies=[ArcGISDependency(9, 1)])
2632
2633CopyArgumentMetadata(ArcGISRaster.Copy, u'cls', ArcGISRaster.FindAndCreateTable, u'cls')
2634CopyArgumentMetadata(ArcGISRaster.Find, u'workspace', ArcGISRaster.FindAndCreateTable, u'workspace')
2635
2636AddArgumentMetadata(ArcGISRaster.FindAndCreateTable, u'connection',
2637    typeMetadata=ClassInstanceTypeMetadata(cls=DatabaseConnection),
2638    description=_(u'Connection opened to the database that will receive the new table.'))
2639
2640AddArgumentMetadata(ArcGISRaster.FindAndCreateTable, u'table',
2641    typeMetadata=UnicodeStringTypeMetadata(),
2642    description=_(u'Name of the table to create. The table must not exist.'),
2643    arcGISDisplayName=_(u'Output table name'))
2644
2645CopyArgumentMetadata(ArcGISRaster.FindAndFillTable, u'rasterField', ArcGISRaster.FindAndCreateTable, u'rasterField')
2646CopyArgumentMetadata(ArcGISRaster.FindAndFillTable, u'wildcard', ArcGISRaster.FindAndCreateTable, u'wildcard')
2647CopyArgumentMetadata(ArcGISRaster.FindAndFillTable, u'searchTree', ArcGISRaster.FindAndCreateTable, u'searchTree')
2648CopyArgumentMetadata(ArcGISRaster.FindAndFillTable, u'rasterType', ArcGISRaster.FindAndCreateTable, u'rasterType')
2649CopyArgumentMetadata(ArcGISRaster.FindAndFillTable, u'relativePathField', ArcGISRaster.FindAndCreateTable, u'relativePathField')
2650CopyArgumentMetadata(ArcGISRaster.FindAndFillTable, u'basePath', ArcGISRaster.FindAndCreateTable, u'basePath')
2651CopyArgumentMetadata(ArcGISRaster.FindAndFillTable, u'populateExtentFields', ArcGISRaster.FindAndCreateTable, u'populateExtentFields')
2652CopyArgumentMetadata(ArcGISRaster.FindAndFillTable, u'parsedDateField', ArcGISRaster.FindAndCreateTable, u'parsedDateField')
2653CopyArgumentMetadata(ArcGISRaster.FindAndFillTable, u'dateParsingExpression', ArcGISRaster.FindAndCreateTable, u'dateParsingExpression')
2654CopyArgumentMetadata(ArcGISRaster.FindAndFillTable, u'unixTimeField', ArcGISRaster.FindAndCreateTable, u'unixTimeField')
2655
2656AddArgumentMetadata(ArcGISRaster.FindAndCreateTable, u'pathFieldsDataType',
2657    typeMetadata=UnicodeStringTypeMetadata(),
2658    description=_(
2659u"""Database data type to use when creating the raster path fields.
2660Because the fields will contain paths, they must have a string data
2661type such as TEXT or VARCHAR. The appropriate data type depends on the
2662underlying database and the API used to access it."""))
2663
2664AddArgumentMetadata(ArcGISRaster.FindAndCreateTable, u'extentFieldsDataType',
2665    typeMetadata=UnicodeStringTypeMetadata(),
2666    description=_(
2667u"""Database data type to use when creating the raster extent fields
2668(XMin, YMin, XMax, and YMax). The fields will contain floating point
2669numbers. The appropriate data type depends on the underlying database
2670and the API used to access it. For many databases, the DOUBLE or FLOAT
2671data type are appropriate."""))
2672
2673AddArgumentMetadata(ArcGISRaster.FindAndCreateTable, u'dateFieldsDataType',
2674    typeMetadata=UnicodeStringTypeMetadata(),
2675    description=_(
2676u"""Database data type to use when creating the parsed date field. The
2677appropriate data type depends on the underlying database and the API
2678used to access it. For many databases, the DATE or DATETIME data type
2679are appropriate."""))
2680
2681AddArgumentMetadata(ArcGISRaster.FindAndCreateTable, u'unixTimeFieldDataType',
2682    typeMetadata=UnicodeStringTypeMetadata(),
2683    description=_(
2684u"""Database data type to use when creating the UNIX date field. The
2685appropriate data type depends on the underlying database and the API
2686used to access it. Because UNIX dates are 32-bit signed integers, the
2687INT or LONG data type is usually appropriate for most databases."""))
2688
2689AddArgumentMetadata(ArcGISRaster.FindAndCreateTable, u'maxPathLength',
2690    typeMetadata=IntegerTypeMetadata(canBeNone=True, minValue=1),
2691    description=_(
2692u"""Maximum length of a path for this operating system. This value is
2693used to specify the width of the field that is created. You should
2694provide a value only if the underlying database requires that you
2695specify a width for string fields. If you provide a value that is too
2696small to hold one of the paths that is found, this function will fail
2697when it finds that path."""))
2698
2699AddArgumentMetadata(ArcGISRaster.FindAndCreateTable, u'overwriteExisting',
2700    typeMetadata=BooleanTypeMetadata(),
2701    description=_(
2702u"""If True, the output table will be overwritten, if it exists.
2703
2704If False, a ValueError will be raised if the output table exists."""),
2705    initializeToArcGISGeoprocessorVariable=u'OverwriteOutput')
2706
2707CopyResultMetadata(DatabaseConnection.CreateTable, u'createdTable', ArcGISRaster.FindAndCreateTable, u'createdTable')
2708
2709# Public method: ArcGISRaster.FindAndCreateArcGISTable
2710
2711AddMethodMetadata(ArcGISRaster.FindAndCreateArcGISTable,
2712    shortDescription=_(u'Finds rasters within an ArcGIS workspace and creates a table that lists them.'),
2713    longDescription=ArcGISRaster.FindAndCreateTable.__doc__.Obj.LongDescription,
2714    isExposedToPythonCallers=True,
2715    isExposedByCOM=True,
2716    isExposedAsArcGISTool=True,
2717    arcGISDisplayName=_(u'Find Rasters'),
2718    arcGISToolCategory=_(u'Data Management\\ArcGIS Rasters'),
2719    dependencies=[ArcGISDependency(9, 1)])
2720
2721CopyArgumentMetadata(ArcGISRaster.Copy, u'cls', ArcGISRaster.FindAndCreateArcGISTable, u'cls')
2722CopyArgumentMetadata(ArcGISRaster.FindAndCreateTable, u'workspace', ArcGISRaster.FindAndCreateArcGISTable, u'inputWorkspace')
2723
2724AddArgumentMetadata(ArcGISRaster.FindAndCreateArcGISTable, u'outputWorkspace',
2725    typeMetadata=ArcGISWorkspaceTypeMetadata(mustExist=True),
2726    description=_(u'Workspace in which the table should be created.'),
2727    arcGISDisplayName=_(u'Output workspace'))
2728
2729AddArgumentMetadata(ArcGISRaster.FindAndCreateArcGISTable, u'table',
2730    typeMetadata=UnicodeStringTypeMetadata(),
2731    description=_(
2732u"""Name of the table to create.
2733
2734If the output workspace is a directory (rather than a database) a
2735dBASE table will be created. It is not possible to create other types
2736of tables in the file system (e.g. comma or space-delimited text
2737files). This restriction is imposed by the ArcGIS CreateTable tool,
2738which is used to create the table. If you omit an extension from the
2739table name, .dbf will be added automatically. If you specify another
2740extension, such as .csv or .txt, it will be replaced with .dbf."""),
2741    arcGISDisplayName=_(u'Output table name'))
2742
2743CopyArgumentMetadata(ArcGISRaster.FindAndCreateTable, u'rasterField', ArcGISRaster.FindAndCreateArcGISTable, u'rasterField')
2744CopyArgumentMetadata(ArcGISRaster.FindAndCreateTable, u'wildcard', ArcGISRaster.FindAndCreateArcGISTable, u'wildcard')
2745CopyArgumentMetadata(ArcGISRaster.FindAndCreateTable, u'searchTree', ArcGISRaster.FindAndCreateArcGISTable, u'searchTree')
2746CopyArgumentMetadata(ArcGISRaster.FindAndCreateTable, u'rasterType', ArcGISRaster.FindAndCreateArcGISTable, u'rasterType')
2747
2748AddArgumentMetadata(ArcGISRaster.FindAndCreateArcGISTable, u'relativePathField',
2749    typeMetadata=UnicodeStringTypeMetadata(canBeNone=True),
2750    description=_(
2751u"""Name of the field to receive paths of the rasters that were found,
2752relative to the output table. For example, if the path to the table is::
2753
2754    C:\\Data\\Rasters\\FoundRasters.dbf
2755
2756the relative paths for the rasters::
2757
2758    C:\\Data\\Rasters\\Group1\\r1
2759    C:\\Data\\Rasters\\r1
2760    C:\\Data\\r1
2761    C:\\r1
2762    D:\\r1
2763    \\\\MyServer\\Data\\r1
2764
2765would be::   
2766
2767    Group1\\r1
2768    r1
2769    ..\\r1
2770    ..\\..\\r1
2771    D:\\r1
2772    \\\\MyServer\\Data\\r1
2773
2774If the table is in a personal geodatabase::
2775
2776    C:\\Data\\Rasters\\RasterInfo.mdb\\FoundRasters
2777
2778the relative paths would be::   
2779
2780    ..\\Group1\\r1
2781    ..\\r1
2782    ..\\..\\r1
2783    ..\\..\\..\\r1
2784    D:\\r1
2785    \\\\MyServer\\Data\\r1
2786"""),
2787    arcGISDisplayName=_(u'Relative path field'),
2788    arcGISCategory=_(u'Output table options'))
2789
2790CopyArgumentMetadata(ArcGISRaster.FindAndCreateTable, u'populateExtentFields', ArcGISRaster.FindAndCreateArcGISTable, u'populateExtentFields')
2791CopyArgumentMetadata(ArcGISRaster.FindAndCreateTable, u'parsedDateField', ArcGISRaster.FindAndCreateArcGISTable, u'parsedDateField')
2792CopyArgumentMetadata(ArcGISRaster.FindAndCreateTable, u'dateParsingExpression', ArcGISRaster.FindAndCreateArcGISTable, u'dateParsingExpression')
2793CopyArgumentMetadata(ArcGISRaster.FindAndCreateTable, u'unixTimeField', ArcGISRaster.FindAndCreateArcGISTable, u'unixTimeField')
2794CopyArgumentMetadata(ArcGISRaster.FindAndCreateTable, u'maxPathLength', ArcGISRaster.FindAndCreateArcGISTable, u'maxPathLength')
2795CopyArgumentMetadata(ArcGISRaster.FindAndCreateTable, u'overwriteExisting', ArcGISRaster.FindAndCreateArcGISTable, u'overwriteExisting')
2796
2797AddResultMetadata(ArcGISRaster.FindAndCreateArcGISTable, u'createdTable',
2798    typeMetadata=ArcGISTableTypeMetadata(),
2799    description=DatabaseConnection.CreateTable.__doc__.Obj.GetResultByName(u'createdTable').Description,
2800    arcGISDisplayName=_(u'Output table'))
2801
2802# Public method: ArcGISRaster.Move
2803
2804AddMethodMetadata(ArcGISRaster.Move,
2805    shortDescription=_(u'Moves an ArcGIS raster.'),
2806    longDescription=ArcGISRaster.Copy.__doc__.Obj.LongDescription,
2807    isExposedToPythonCallers=True,
2808    isExposedByCOM=True,
2809    isExposedAsArcGISTool=True,
2810    arcGISDisplayName=_(u'Move Raster'),
2811    arcGISToolCategory=_(u'Data Management\\ArcGIS Rasters\\Move'),
2812    dependencies=[ArcGISDependency(9, 1)])
2813
2814AddArgumentMetadata(ArcGISRaster.Move, u'cls',
2815    typeMetadata=ClassOrClassInstanceTypeMetadata(cls=ArcGISRaster),
2816    description=ArcGISRaster.Copy.__doc__.Obj.Arguments[0].Description)
2817
2818AddArgumentMetadata(ArcGISRaster.Move, u'sourceRaster',
2819    typeMetadata=ArcGISRasterTypeMetadata(mustExist=True),
2820    description=_(u'Raster to move.'),
2821    arcGISDisplayName=_(u'Source raster'))
2822
2823AddArgumentMetadata(ArcGISRaster.Move, u'destinationRaster',
2824    typeMetadata=ArcGISRasterTypeMetadata(mustBeDifferentThanArguments=[u'sourceRaster'], deleteIfParameterIsTrue=u'overwriteExisting', createParentDirectories=True),
2825    description=_(
2826u"""New path for the raster.
2827
2828If this is a file system path, missing directories in the path will be created
2829if they do not exist."""),
2830    direction=u'Output',
2831    arcGISDisplayName=_(u'Destination raster'))
2832
2833AddArgumentMetadata(ArcGISRaster.Move, u'overwriteExisting',
2834    typeMetadata=BooleanTypeMetadata(),
2835    description=ArcGISRaster.Copy.__doc__.Obj.Arguments[3].Description,
2836    initializeToArcGISGeoprocessorVariable=u'OverwriteOutput')
2837
2838# Public method: ArcGISRaster.MoveSilent
2839
2840AddMethodMetadata(ArcGISRaster.MoveSilent,
2841    shortDescription=_(u'Moves an ArcGIS raster and logs a debug message rather than an informational message.'),
2842    longDescription=_(
2843u"""This method does the same thing as the Move method, except it logs
2844a debug message rather than an informational message. It is intended
2845for use when the raster-move operation is not imporant enough to
2846warrent notifying the user (for example, when an output raster is
2847extracted from a temporary directory to the final location)."""),
2848    isExposedToPythonCallers=True,
2849    isExposedByCOM=True,
2850    dependencies=[ArcGISDependency(9, 1)])
2851
2852CopyArgumentMetadata(ArcGISRaster.Move, u'cls', ArcGISRaster.MoveSilent, u'cls')
2853CopyArgumentMetadata(ArcGISRaster.Move, u'sourceRaster', ArcGISRaster.MoveSilent, u'sourceRaster')
2854CopyArgumentMetadata(ArcGISRaster.Move, u'destinationRaster', ArcGISRaster.MoveSilent, u'destinationRaster')
2855CopyArgumentMetadata(ArcGISRaster.Move, u'overwriteExisting', ArcGISRaster.MoveSilent, u'overwriteExisting')
2856
2857# Public method: ArcGISRaster.FromNumpyArray
2858
2859AddMethodMetadata(ArcGISRaster.FromNumpyArray,
2860    shortDescription=_(u'Creates an ArcGIS raster from a numpy array.'),
2861    isExposedToPythonCallers=True,
2862    dependencies=[ArcGISDependency(9, 1), PythonAggregatedModuleDependency('numpy')])
2863
2864CopyArgumentMetadata(ArcGISRaster.Copy, u'cls', ArcGISRaster.FromNumpyArray, u'cls')
2865
2866AddArgumentMetadata(ArcGISRaster.FromNumpyArray, u'numpyArray',
2867    typeMetadata=NumPyArrayTypeMetadata(dimensions=2, minShape=[1,1], allowedDTypes=[u'int8', u'uint8', u'int16', u'uint16', u'int32', u'uint32', u'float32']),
2868    description=_(u'Numpy array to write out as an ArcGIS raster.'))
2869
2870AddArgumentMetadata(ArcGISRaster.FromNumpyArray, u'raster',
2871    typeMetadata=ArcGISRasterTypeMetadata(deleteIfParameterIsTrue=u'overwriteExisting', createParentDirectories=True),
2872    description=_(u'Output raster to create.'))
2873
2874CopyArgumentMetadata(BinaryRaster.ToArcGISRaster, u'xLowerLeftCorner', ArcGISRaster.FromNumpyArray, u'xLowerLeftCorner')
2875CopyArgumentMetadata(BinaryRaster.ToArcGISRaster, u'yLowerLeftCorner', ArcGISRaster.FromNumpyArray, u'yLowerLeftCorner')
2876CopyArgumentMetadata(BinaryRaster.ToArcGISRaster, u'cellSize', ArcGISRaster.FromNumpyArray, u'cellSize')
2877CopyArgumentMetadata(BinaryRaster.ToArcGISRaster, u'nodataValue', ArcGISRaster.FromNumpyArray, u'nodataValue')
2878CopyArgumentMetadata(BinaryRaster.ToArcGISRaster, u'coordinateSystem', ArcGISRaster.FromNumpyArray, u'coordinateSystem')
2879CopyArgumentMetadata(BinaryRaster.ToArcGISRaster, u'projectedCoordinateSystem', ArcGISRaster.FromNumpyArray, u'projectedCoordinateSystem')
2880CopyArgumentMetadata(BinaryRaster.ToArcGISRaster, u'geographicTransformation', ArcGISRaster.FromNumpyArray, u'geographicTransformation')
2881CopyArgumentMetadata(BinaryRaster.ToArcGISRaster, u'resamplingTechnique', ArcGISRaster.FromNumpyArray, u'resamplingTechnique')
2882CopyArgumentMetadata(BinaryRaster.ToArcGISRaster, u'projectedCellSize', ArcGISRaster.FromNumpyArray, u'projectedCellSize')
2883CopyArgumentMetadata(BinaryRaster.ToArcGISRaster, u'registrationPoint', ArcGISRaster.FromNumpyArray, u'registrationPoint')
2884CopyArgumentMetadata(BinaryRaster.ToArcGISRaster, u'clippingRectangle', ArcGISRaster.FromNumpyArray, u'clippingRectangle')
2885CopyArgumentMetadata(BinaryRaster.ToArcGISRaster, u'mapAlgebraExpression', ArcGISRaster.FromNumpyArray, u'mapAlgebraExpression')
2886CopyArgumentMetadata(BinaryRaster.ToArcGISRaster, u'buildPyramids', ArcGISRaster.FromNumpyArray, u'buildPyramids')
2887CopyArgumentMetadata(BinaryRaster.ToArcGISRaster, u'overwriteExisting', ArcGISRaster.FromNumpyArray, u'overwriteExisting')
2888
2889# Public method: ArcGISRaster.ToNumpyArray
2890
2891AddMethodMetadata(ArcGISRaster.ToNumpyArray,
2892    shortDescription=_(u'Reads an ArcGIS raster or raster layer into a numpy array.'),
2893    isExposedToPythonCallers=True,
2894    dependencies=[ArcGISDependency(9, 1), PythonAggregatedModuleDependency('numpy')])
2895
2896CopyArgumentMetadata(ArcGISRaster.Copy, u'cls', ArcGISRaster.ToNumpyArray, u'cls')
2897
2898AddArgumentMetadata(ArcGISRaster.ToNumpyArray, u'raster',
2899    typeMetadata=ArcGISRasterLayerTypeMetadata(mustExist=True),
2900    description=_(u'Raster to read.'))
2901
2902AddArgumentMetadata(ArcGISRaster.ToNumpyArray, u'band',
2903    typeMetadata=IntegerTypeMetadata(minValue=1),
2904    description=_(u'Band number to read, starting with 1.'))
2905
2906AddArgumentMetadata(ArcGISRaster.ToNumpyArray, u'tempRasterPath',
2907    typeMetadata=ArcGISRasterTypeMetadata(canBeNone=True, mustNotExist=True),
2908    description=_(
2909u"""Path to use if it is necessary to create a temporary copy of the
2910raster. The caller can provide this as an optimization. If provided,
2911the caller is responsible for deleting the temporary raster, if it
2912happened to be created (the caller should check for this after this
2913function returns).
2914
2915If you do not provide a path, this function will create a temporary
2916directory to hold the temporary raster, and delete it before
2917returning.
2918
2919The temporary raster is only created when the input raster does not
2920exist on disk (i.e. it exists in a geodatabase). This function uses
2921GDAL to read the raster, and GDAL can only read rasters that are on
2922disk. Thus if the raster is not on disk, a temporary copy is needed so
2923it can be read by GDAL."""))
2924
2925AddResultMetadata(ArcGISRaster.ToNumpyArray, u'numpyArray',
2926    typeMetadata=NumPyArrayTypeMetadata(dimensions=2),
2927    description=_(
2928u"""Numpy array read from the raster.
2929
2930Note that, for integer rasters, the array will use the most compact
2931data type that can represent all of the values in the raster.
2932Normally, ArcGIS automatically selects the most compact data type, but
2933this does not always happen. For example, I have seen ArcGIS store
2934data ranging from 0 to 65535 (with no NODATA value) as an int32 raster
2935even though a uint16 is the most compact data type for that
2936range."""))
2937
2938AddResultMetadata(ArcGISRaster.ToNumpyArray, u'noDataValue',
2939    typeMetadata=FloatTypeMetadata(canBeNone=True),
2940    description=_(
2941u"""Value in the returned numpy array that represents NODATA. Note
2942that, if the numpy array is compacted (as described above), this value
2943may be different than what ArcGIS used when it created the
2944raster."""))
2945
2946# Public method: ArcGISRaster.ExtractByMask
2947
2948AddMethodMetadata(ArcGISRaster.ExtractByMask,
2949    shortDescription=_(u'Extracts the cells of a raster that correspond to the areas defined by a mask.'),
2950    longDescription=_(
2951u"""This tool just calls the ArcGIS Spatial Analyst's Extract By Mask
2952tool. It only exists so that we can easily create a batched version of
2953that tool."""),
2954    isExposedToPythonCallers=True,
2955    isExposedByCOM=True,
2956    isExposedAsArcGISTool=False,
2957    arcGISToolCategory=_(u'Spatial Analysis\\Project, Clip and/or Execute Map Algebra'),
2958    dependencies=[ArcGISDependency(9, 1), ArcGISExtensionDependency(u'spatial')])
2959
2960CopyArgumentMetadata(ArcGISRaster.Copy, u'cls', ArcGISRaster.ExtractByMask, u'cls')
2961
2962AddArgumentMetadata(ArcGISRaster.ExtractByMask, u'inputRaster',
2963    typeMetadata=ArcGISRasterLayerTypeMetadata(mustExist=True),
2964    description=_(u'The input raster from which cells will be extracted.'),
2965    arcGISDisplayName=_(u'Input raster'))
2966
2967AddArgumentMetadata(ArcGISRaster.ExtractByMask, u'mask',
2968    typeMetadata=ArcGISGeoDatasetTypeMetadata(mustExist=True),
2969    description=_(
2970u"""Input mask data defining areas to extract.
2971
2972This is a raster or feature dataset.
2973
2974When the input mask data is a raster, NoData cells on the mask will be
2975assigned NoData values on the output raster."""),
2976    arcGISDisplayName=_(u'Input raster or feature mask data'))
2977
2978AddArgumentMetadata(ArcGISRaster.ExtractByMask, u'outputRaster',
2979    typeMetadata=ArcGISRasterTypeMetadata(mustBeDifferentThanArguments=[u'inputRaster', u'mask'], deleteIfParameterIsTrue=u'overwriteExisting', createParentDirectories=True),
2980    description=_(
2981u"""The output raster containing the cell values extracted from the
2982input raster.
2983
2984If this path refers to the file system, missing directories in the
2985path will be created if they do not exist."""),
2986    direction=u'Output',
2987    arcGISDisplayName=_(u'Output raster'))
2988
2989CopyArgumentMetadata(ArcGISRaster.CreateXRaster, u'overwriteExisting', ArcGISRaster.ExtractByMask, u'overwriteExisting')
2990
2991# Public method: ArcGISRaster.ProjectClipAndOrExecuteMapAlgebra
2992
2993AddMethodMetadata(ArcGISRaster.ProjectClipAndOrExecuteMapAlgebra,
2994    shortDescription=_(u'Projects, clips, and/or perfoms map algebra on an ArcGIS raster. You must request at least one of these three operations. If you request multiple operations, the tool performs them in the order they are listed.'),
2995    isExposedToPythonCallers=True,
2996    isExposedByCOM=True,
2997    isExposedAsArcGISTool=True,
2998    arcGISDisplayName=_(u'Project, Clip, and/or Execute Map Algebra'),
2999    arcGISToolCategory=_(u'Spatial Analysis\\Project, Clip and/or Execute Map Algebra'),
3000    dependencies=[ArcGISDependency(9, 1)])
3001
3002CopyArgumentMetadata(ArcGISRaster.Copy, u'cls', ArcGISRaster.ProjectClipAndOrExecuteMapAlgebra, u'cls')
3003
3004AddArgumentMetadata(ArcGISRaster.ProjectClipAndOrExecuteMapAlgebra, u'inputRaster',
3005    typeMetadata=ArcGISRasterLayerTypeMetadata(mustExist=True),
3006    description=_(u'Input raster.'),
3007    arcGISDisplayName=_(u'Input raster'))
3008
3009AddArgumentMetadata(ArcGISRaster.ProjectClipAndOrExecuteMapAlgebra, u'outputRaster',
3010    typeMetadata=ArcGISRasterTypeMetadata(mustBeDifferentThanArguments=[u'inputRaster'], deleteIfParameterIsTrue=u'overwriteExisting', createParentDirectories=True),
3011    description=_(
3012u"""Output raster.
3013
3014If this path refers to the file system, missing directories in the
3015path will be created if they do not exist."""),
3016    direction=u'Output',
3017    arcGISDisplayName=_(u'Output raster'))
3018
3019CopyArgumentMetadata(BinaryRaster.ToArcGISRaster, u'projectedCoordinateSystem', ArcGISRaster.ProjectClipAndOrExecuteMapAlgebra, u'projectedCoordinateSystem')
3020ArcGISRaster.ProjectClipAndOrExecuteMapAlgebra.__doc__.Obj.GetArgumentByName(u'projectedCoordinateSystem').ArcGISCategory = None
3021
3022CopyArgumentMetadata(BinaryRaster.ToArcGISRaster, u'geographicTransformation', ArcGISRaster.ProjectClipAndOrExecuteMapAlgebra, u'geographicTransformation')
3023ArcGISRaster.ProjectClipAndOrExecuteMapAlgebra.__doc__.Obj.GetArgumentByName(u'geographicTransformation').ArcGISCategory = None
3024
3025CopyArgumentMetadata(BinaryRaster.ToArcGISRaster, u'resamplingTechnique', ArcGISRaster.ProjectClipAndOrExecuteMapAlgebra, u'resamplingTechnique')
3026ArcGISRaster.ProjectClipAndOrExecuteMapAlgebra.__doc__.Obj.GetArgumentByName(u'resamplingTechnique').ArcGISCategory = None
3027
3028CopyArgumentMetadata(BinaryRaster.ToArcGISRaster, u'projectedCellSize', ArcGISRaster.ProjectClipAndOrExecuteMapAlgebra, u'projectedCellSize')
3029ArcGISRaster.ProjectClipAndOrExecuteMapAlgebra.__doc__.Obj.GetArgumentByName(u'projectedCellSize').ArcGISCategory = None
3030
3031CopyArgumentMetadata(BinaryRaster.ToArcGISRaster, u'registrationPoint', ArcGISRaster.ProjectClipAndOrExecuteMapAlgebra, u'registrationPoint')
3032ArcGISRaster.ProjectClipAndOrExecuteMapAlgebra.__doc__.Obj.GetArgumentByName(u'registrationPoint').ArcGISCategory = None
3033
3034AddArgumentMetadata(ArcGISRaster.ProjectClipAndOrExecuteMapAlgebra, u'clippingDataset',
3035    typeMetadata=ArcGISGeoDatasetTypeMetadata(mustExist=True, canBeNone=True),
3036    description=_(
3037u"""Existing feature class, raster, or other geographic dataset having
3038the extent to which the raster should be clipped.
3039
3040WARNING: If you use this tool from in an ArcGIS geoprocessing model
3041and you select a dataset by clicking the folder icon and browsing to
3042the dataset, your selection may mysteriously disappear from this text
3043box after you close the tool. This is a bug in ArcGIS. To work around
3044it, drag and drop the desired dataset into the model. This will create
3045a layer in the model for that dataset. Then select that layer in this
3046tool by clicking the drop-down box rather than clicking the folder
3047icon. The selected layer should not disappear when you close the
3048tool."""),
3049    arcGISDisplayName=_(u'Clip to extent of geographic dataset'))
3050
3051CopyArgumentMetadata(BinaryRaster.ToArcGISRaster, u'clippingRectangle', ArcGISRaster.ProjectClipAndOrExecuteMapAlgebra, u'clippingRectangle')
3052ArcGISRaster.ProjectClipAndOrExecuteMapAlgebra.__doc__.Obj.GetArgumentByName(u'clippingRectangle').ArcGISCategory = None
3053
3054CopyArgumentMetadata(BinaryRaster.ToArcGISRaster, u'mapAlgebraExpression', ArcGISRaster.ProjectClipAndOrExecuteMapAlgebra, u'mapAlgebraExpression')
3055ArcGISRaster.ProjectClipAndOrExecuteMapAlgebra.__doc__.Obj.GetArgumentByName(u'mapAlgebraExpression').ArcGISCategory = None
3056
3057CopyArgumentMetadata(BinaryRaster.ToArcGISRaster, u'buildPyramids', ArcGISRaster.ProjectClipAndOrExecuteMapAlgebra, u'buildPyramids')
3058ArcGISRaster.ProjectClipAndOrExecuteMapAlgebra.__doc__.Obj.GetArgumentByName(u'buildPyramids').ArcGISCategory = None
3059
3060CopyArgumentMetadata(BinaryRaster.ToArcGISRaster, u'overwriteExisting', ArcGISRaster.ProjectClipAndOrExecuteMapAlgebra, u'overwriteExisting')
3061ArcGISRaster.ProjectClipAndOrExecuteMapAlgebra.__doc__.Obj.GetArgumentByName(u'overwriteExisting').ArcGISCategory = None
3062
3063# Public method: ArcGISRaster.ProjectToTemplate
3064
3065AddMethodMetadata(ArcGISRaster.ProjectToTemplate,
3066    shortDescription=_(u'Projects a raster to the coordinate system, cell size, and extent of a template raster.'),
3067    isExposedToPythonCallers=True,
3068    isExposedByCOM=True,
3069    isExposedAsArcGISTool=True,
3070    arcGISDisplayName=_(u'Project Raster to Template'),
3071    arcGISToolCategory=_(u'Spatial Analysis\\Project Raster to Template'),
3072    dependencies=[ArcGISDependency(9, 1)])
3073
3074CopyArgumentMetadata(ArcGISRaster.Copy, u'cls', ArcGISRaster.ProjectToTemplate, u'cls')
3075
3076AddArgumentMetadata(ArcGISRaster.ProjectToTemplate, u'inputRaster',
3077    typeMetadata=ArcGISRasterLayerTypeMetadata(mustExist=True),
3078    description=_(
3079u"""Raster to project to the template raster's coordinate system, cell
3080size, and extent."""),
3081    arcGISDisplayName=_(u'Raster to project'))
3082
3083AddArgumentMetadata(ArcGISRaster.ProjectToTemplate, u'templateRaster',
3084    typeMetadata=ArcGISRasterLayerTypeMetadata(mustExist=True, mustBeDifferentThanArguments=[u'inputRaster']),
3085    description=_(
3086u"""Raster defining the coordinate system, cell size, and extent of
3087the output raster."""),
3088    arcGISDisplayName=_(u'Template raster'))
3089
3090AddArgumentMetadata(ArcGISRaster.ProjectToTemplate, u'outputRaster',
3091    typeMetadata=ArcGISRasterTypeMetadata(mustBeDifferentThanArguments=[u'inputRaster', u'templateRaster'], deleteIfParameterIsTrue=u'overwriteExisting', createParentDirectories=True),
3092    description=_(
3093u"""Output raster.
3094
3095If this path refers to the file system, missing directories in the
3096path will be created if they do not exist."""),
3097    direction=u'Output',
3098    arcGISDisplayName=_(u'Output raster'))
3099
3100AddArgumentMetadata(ArcGISRaster.ProjectToTemplate, u'resamplingTechnique',
3101    typeMetadata=UnicodeStringTypeMetadata(makeLowercase=True, allowedValues=[u'BILINEAR', u'CUBIC']),
3102    description=_(
3103u"""Resampling algorithm to be used to project the input raster to the
3104template raster's coordinate system. One of:
3105
3106* NEAREST - `Nearest neighbor assignment
3107  <http://en.wikipedia.org/wiki/Nearest-neighbor_interpolation>`_.
3108
3109* BILINEAR - `Bilinear interpolation
3110  <http://en.wikipedia.org/wiki/Bilinear_interpolation>`_.
3111
3112* CUBIC - Cubic convolution, also known as `bicubic interpolation
3113  <http://en.wikipedia.org/wiki/Bicubic_interpolation>`_.
3114
3115* MAJORITY - Majority resampling. This method requires ArcGIS 9.3 or
3116  later.
3117
3118The NEAREST and MAJORITY algorithms should be used for categorical
3119data, such as a land use classification. It is not recommended that
3120NEAREST or MAJORITY be used for continuous data, such as elevation
3121surfaces.
3122
3123The BILINEAR and CUBIC options are most appropriate for continuous
3124data. Do not use BILINEAR or CUBIC with categorical data.
3125
3126The projection is accomplished with the ArcGIS Project Raster tool.
3127Please see the documentation for that tool for more information."""),
3128    arcGISDisplayName=_(u'Resampling technique'))
3129
3130AddArgumentMetadata(ArcGISRaster.ProjectToTemplate, u'interpolationMethod',
3131    typeMetadata=UnicodeStringTypeMetadata(makeLowercase=True, allowedValues=[u'Del2a', u'Del2b', u'Del2c', u'Del4', u'Spring'], canBeNone=True),
3132    description=_(
3133u"""Method to use to guess values for No Data cells.
3134
3135Use this option to "fill in" clusters of No Data cells with values
3136obtained by interpolation and extrapolation. This option is
3137appropriate for rasters representing continuous surfaces, e.g. images
3138of sea surface temperature in which cloudy pixels contain No Data. It
3139uses algorithms based on differential calculus that may provide more
3140accurate guesses than traditional ArcGIS approaches, such as computing
3141the focal mean of a 3x3 neighborhood.
3142
3143This option is not appropriate for rasters representing categorical
3144data, such as land cover classifications. Therefore, in order to use
3145this option, you must select BILINEAR or CUBIC for the Resampling
3146Technique parameter.
3147
3148The available algorithms are:
3149
3150* Del2a - Laplacian interpolation and linear extrapolation.
3151
3152* Del2b - Same as Del2a but does not build as large a linear system of
3153  equations. May be faster than Del2a at the cost of some accuracy.
3154
3155* Del2c - Same as Del2a but solves a direct linear system of equations
3156  for the No Data values. Faster than both Del2a and Del2b but is the
3157  least robust to noise on the boundaries of No Data cells and least
3158  able to interpolate accurately for smooth surfaces.
3159
3160* Del4 - Same as Del2a but instead of the Laplace operator (also
3161  called the del^2 operator) it uses the biharmonic operator (also
3162  called the del^4 operator). May result in more accurate
3163  interpolations, at some cost in speed.
3164
3165* Spring - Uses a spring metaphor. Assumes springs (with a nominal
3166  length of zero) connect each cell with every neighbor (horizontally,
3167  vertically and diagonally). Since each cell tries to be like its
3168  neighbors, extrapolation is as a constant function where this is
3169  consistent with the neighboring nodes.
3170
3171This option is applied after the input raster has been projected to
3172the coordinate system and cell size of the template raster.
3173
3174Although this tool can fill No Data clusters of any size, you should
3175apply common sense when using it. The larger the cluster, the less
3176accurate the guessed values will be, especially for rasters that
3177represent a noisy surface.
3178
3179Thanks to John D'Errico for providing the code that implements the
3180mathematical algorithms described here (click `here
3181<http://www.mathworks.com/matlabcentral/fileexchange/4551>`_ for more
3182information)."""),
3183    arcGISDisplayName=_(u'Method for interpolating No Data cells'),
3184    arcGISCategory=_(u'Interpolation and masking options'))
3185
3186AddArgumentMetadata(ArcGISRaster.ProjectToTemplate, u'maxHoleSize',
3187    typeMetadata=IntegerTypeMetadata(mustBeGreaterThan=0, canBeNone=True),
3188    description=_(
3189u"""Maximum size, in cells of the template raster, that a region of
31904-connected No Data cells may be for it to be filled in.
3191
3192Use this option to prevent the filling of large No Data regions (e.g.
3193large clouds in remote sensing images) when you are concerned that
3194values cannot be accurately guessed for those regions. If this option
3195is omitted, all regions will be filled, regardless of size."""),
3196    arcGISDisplayName=_(u'Maximum size of No Data regions to interpolate'),
3197    arcGISCategory=_(u'Interpolation and masking options'))
3198
3199AddArgumentMetadata(ArcGISRaster.ProjectToTemplate, u'mask',
3200    typeMetadata=BooleanTypeMetadata(),
3201    description=_(
3202u"""If True, the template raster will be used to mask the input raster
3203after it has been projected to the template raster's coordinate system
3204and values have been interpolated for No Data cells (if your requested
3205that). Cells of the template raster that are No Data will be set to No
3206Data in the output raster, even if you requested that values be
3207interpolated for No Data cells. This is appropriate in situations
3208where the template defines the areas for which you want to retain
3209data; for example, when you are analyzing the ocean and you have a
3210mask in which ocean cells have data and land cells are set to No Data.
3211
3212If False, the template raster will only be used to define the
3213coordinate system, cell size, and rectangular extent of the output
3214raster, and no masking will be done."""),
3215    arcGISDisplayName=_(u'Use template raster as mask'),
3216    arcGISCategory=_(u'Interpolation and masking options'))
3217
3218# Public method: ArcGISRaster.ToPolygons
3219
3220AddMethodMetadata(ArcGISRaster.ToPolygons,
3221    shortDescription=_(u'Converts an ArcGIS raster to polygons that encompass groups of adjacent raster cells having the same value.'),
3222    isExposedToPythonCallers=True,
3223    isExposedByCOM=True,
3224    isExposedAsArcGISTool=True,
3225    arcGISDisplayName=_(u'Convert ArcGIS Raster to Polygons'),
3226    arcGISToolCategory=_(u'Conversion\\To Polygons\\From ArcGIS Raster'),
3227    dependencies=[ArcGISDependency(9, 1)])
3228
3229CopyArgumentMetadata(ArcGISRaster.Copy, u'cls', ArcGISRaster.ToPolygons, u'cls')
3230
3231AddArgumentMetadata(ArcGISRaster.ToPolygons, u'inputRaster',
3232    typeMetadata=ArcGISRasterLayerTypeMetadata(mustExist=True),
3233    description=_(
3234u"""Raster to convert.
3235
3236The raster will be converted to a polygon feature class using the
3237ArcGIS Raster to Polygon tool. That tool can only convert integer
3238rasters to polygons. If the input raster is a floating-point raster,
3239you must use the Map Algebra Expression parameter to convert it to an
3240integer raster."""),
3241    arcGISDisplayName=_(u'Input raster'))
3242
3243AddArgumentMetadata(ArcGISRaster.ToPolygons, u'outputFeatureClass',
3244    typeMetadata=ArcGISFeatureClassTypeMetadata(allowedShapeTypes=[u'polygon'], mustBeDifferentThanArguments=[u'inputRaster'], deleteIfParameterIsTrue=u'overwriteExisting', createParentDirectories=True),
3245    description=_(
3246u"""Output polygon feature class that will contain the converted
3247polygons.
3248
3249Missing directories in this path will be created if they do not
3250exist."""),
3251    direction=u'Output',
3252    arcGISDisplayName=_(u'Output polygon feature class'))
3253
3254AddArgumentMetadata(ArcGISRaster.ToPolygons, u'simplify',
3255    typeMetadata=BooleanTypeMetadata(),
3256    description=_(
3257u"""Determines if the output polygons will be smoothed into simpler
3258shapes or conform to the input raster's cell edges.
3259
3260* True - The polygons will be smoothed into simpler shapes. This is
3261  the default.
3262
3263* False - The polygons will conform to the input raster's cell edges.
3264"""),
3265    arcGISDisplayName=_(u'Simplify polygons'))
3266
3267AddArgumentMetadata(ArcGISRaster.ToPolygons, u'field',
3268    typeMetadata=ArcGISFieldTypeMetadata(mustExist=True, allowedFieldTypes=[u'SHORT', u'LONG', u'TEXT'], canBeNone=True),
3269    description=_(
3270u"""The field used to assign values from the cells in the input raster
3271to the polygons in the output dataset. It can be an integer or a
3272string field."""),
3273    arcGISParameterDependencies=[u'inputRaster'],
3274    arcGISDisplayName=_(u'Field'))
3275
3276CopyArgumentMetadata(ArcGISRaster.ProjectClipAndOrExecuteMapAlgebra, u'projectedCoordinateSystem', ArcGISRaster.ToPolygons, u'projectedCoordinateSystem')
3277ArcGISRaster.ToPolygons.__doc__.Obj.GetArgumentByName(u'projectedCoordinateSystem').ArcGISCategory = _(u'Pre-conversion processing')
3278
3279CopyArgumentMetadata(ArcGISRaster.ProjectClipAndOrExecuteMapAlgebra, u'geographicTransformation', ArcGISRaster.ToPolygons, u'geographicTransformation')
3280ArcGISRaster.ToPolygons.__doc__.Obj.GetArgumentByName(u'geographicTransformation').ArcGISCategory = _(u'Pre-conversion processing')
3281
3282CopyArgumentMetadata(ArcGISRaster.ProjectClipAndOrExecuteMapAlgebra, u'resamplingTechnique', ArcGISRaster.ToPolygons, u'resamplingTechnique')
3283ArcGISRaster.ToPolygons.__doc__.Obj.GetArgumentByName(u'resamplingTechnique').ArcGISCategory = _(u'Pre-conversion processing')
3284
3285CopyArgumentMetadata(ArcGISRaster.ProjectClipAndOrExecuteMapAlgebra, u'projectedCellSize', ArcGISRaster.ToPolygons, u'projectedCellSize')
3286ArcGISRaster.ToPolygons.__doc__.Obj.GetArgumentByName(u'projectedCellSize').ArcGISCategory = _(u'Pre-conversion processing')
3287
3288CopyArgumentMetadata(ArcGISRaster.ProjectClipAndOrExecuteMapAlgebra, u'registrationPoint', ArcGISRaster.ToPolygons, u'registrationPoint')
3289ArcGISRaster.ToPolygons.__doc__.Obj.GetArgumentByName(u'registrationPoint').ArcGISCategory = _(u'Pre-conversion processing')
3290
3291CopyArgumentMetadata(ArcGISRaster.ProjectClipAndOrExecuteMapAlgebra, u'clippingDataset', ArcGISRaster.ToPolygons, u'clippingDataset')
3292ArcGISRaster.ToPolygons.__doc__.Obj.GetArgumentByName(u'clippingDataset').ArcGISCategory = _(u'Pre-conversion processing')
3293
3294CopyArgumentMetadata(ArcGISRaster.ProjectClipAndOrExecuteMapAlgebra, u'clippingRectangle', ArcGISRaster.ToPolygons, u'clippingRectangle')
3295ArcGISRaster.ToPolygons.__doc__.Obj.GetArgumentByName(u'clippingRectangle').ArcGISCategory = _(u'Pre-conversion processing')
3296
3297CopyArgumentMetadata(ArcGISRaster.ProjectClipAndOrExecuteMapAlgebra, u'mapAlgebraExpression', ArcGISRaster.ToPolygons, u'mapAlgebraExpression')
3298ArcGISRaster.ToPolygons.__doc__.Obj.GetArgumentByName(u'mapAlgebraExpression').ArcGISCategory = _(u'Pre-conversion processing')
3299
3300AddArgumentMetadata(ArcGISRaster.ToPolygons, u'overwriteExisting',
3301    typeMetadata=BooleanTypeMetadata(),
3302    description=_(
3303u"""If True, the output feature class will be overwritten, if it
3304exists. If False, a ValueError will be raised if the output feature
3305class exists."""),
3306    initializeToArcGISGeoprocessorVariable=u'OverwriteOutput')
3307
3308# Public method: ArcGISRaster.ToPolygonOutlines
3309
3310AddMethodMetadata(ArcGISRaster.ToPolygonOutlines,
3311    shortDescription=_(u'Converts an ArcGIS raster to lines that outline groups of adjacent raster cells having the same value.'),
3312    isExposedToPythonCallers=True,
3313    isExposedByCOM=True,
3314    isExposedAsArcGISTool=True,
3315    arcGISDisplayName=_(u'Convert ArcGIS Raster to Polygon Outlines'),
3316    arcGISToolCategory=_(u'Conversion\\To Polygon Outlines\\From ArcGIS Raster'),
3317    dependencies=[ArcGISDependency(9, 1)])
3318
3319CopyArgumentMetadata(ArcGISRaster.Copy, u'cls', ArcGISRaster.ToPolygonOutlines, u'cls')
3320
3321AddArgumentMetadata(ArcGISRaster.ToPolygonOutlines, u'inputRaster',
3322    typeMetadata=ArcGISRasterLayerTypeMetadata(mustExist=True),
3323    description=_(
3324u"""Raster to convert.
3325
3326The raster will be converted to a polygon feature class using the
3327ArcGIS Raster to Polygon tool, and then to line features using the
3328Feature to Line tool. The Raster to Polygon tool can only convert
3329integer rasters to polygons. If the input raster is a floating-point
3330raster, you must use the Map Algebra Expression parameter to convert
3331it to an integer raster."""),
3332    arcGISDisplayName=_(u'Input raster'))
3333
3334AddArgumentMetadata(ArcGISRaster.ToPolygonOutlines, u'outputFeatureClass',
3335    typeMetadata=ArcGISFeatureClassTypeMetadata(allowedShapeTypes=[u'polyline'], mustBeDifferentThanArguments=[u'inputRaster'], deleteIfParameterIsTrue=u'overwriteExisting', createParentDirectories=True),
3336    description=_(
3337u"""Output line feature class.
3338
3339Missing directories in this path will be created if they do not
3340exist."""),
3341    direction=u'Output',
3342    arcGISDisplayName=_(u'Output line feature class'))
3343
3344CopyArgumentMetadata(ArcGISRaster.ToPolygons, u'simplify', ArcGISRaster.ToPolygonOutlines, u'simplify')
3345
3346AddArgumentMetadata(ArcGISRaster.ToPolygonOutlines, u'field',
3347    typeMetadata=ArcGISFieldTypeMetadata(mustExist=True, allowedFieldTypes=[u'SHORT', u'LONG', u'TEXT'], canBeNone=True),
3348    description=_(
3349u"""The field used to assign values from the cells in the input raster
3350to the lines in the output dataset. It can be an integer or a
3351string field."""),
3352    arcGISParameterDependencies=[u'inputRaster'],
3353    arcGISDisplayName=_(u'Field'))
3354
3355CopyArgumentMetadata(ArcGISRaster.ToPolygons, u'projectedCoordinateSystem', ArcGISRaster.ToPolygonOutlines, u'projectedCoordinateSystem')
3356CopyArgumentMetadata(ArcGISRaster.ToPolygons, u'geographicTransformation', ArcGISRaster.ToPolygonOutlines, u'geographicTransformation')
3357CopyArgumentMetadata(ArcGISRaster.ToPolygons, u'resamplingTechnique', ArcGISRaster.ToPolygonOutlines, u'resamplingTechnique')
3358CopyArgumentMetadata(ArcGISRaster.ToPolygons, u'projectedCellSize', ArcGISRaster.ToPolygonOutlines, u'projectedCellSize')
3359CopyArgumentMetadata(ArcGISRaster.ToPolygons, u'registrationPoint', ArcGISRaster.ToPolygonOutlines, u'registrationPoint')
3360CopyArgumentMetadata(ArcGISRaster.ToPolygons, u'clippingDataset', ArcGISRaster.ToPolygonOutlines, u'clippingDataset')
3361CopyArgumentMetadata(ArcGISRaster.ToPolygons, u'clippingRectangle', ArcGISRaster.ToPolygonOutlines, u'clippingRectangle')
3362CopyArgumentMetadata(ArcGISRaster.ToPolygons, u'mapAlgebraExpression', ArcGISRaster.ToPolygonOutlines, u'mapAlgebraExpression')
3363CopyArgumentMetadata(ArcGISRaster.ToPolygons, u'overwriteExisting', ArcGISRaster.ToPolygonOutlines, u'overwriteExisting')
3364
3365# Public method: ArcGISRaster.ToLines
3366
3367AddMethodMetadata(ArcGISRaster.ToLines,
3368    shortDescription=_(u'Converts an ArcGIS raster to a feature class of lines that connect adjacent foreground raster cells.'),
3369    isExposedToPythonCallers=True,
3370    isExposedByCOM=True,
3371    isExposedAsArcGISTool=True,
3372    arcGISDisplayName=_(u'Convert ArcGIS Raster to Lines'),
3373    arcGISToolCategory=_(u'Conversion\\To Lines\\From ArcGIS Raster'),
3374    dependencies=[ArcGISDependency(9, 1)])
3375
3376CopyArgumentMetadata(ArcGISRaster.Copy, u'cls', ArcGISRaster.ToLines, u'cls')
3377
3378AddArgumentMetadata(ArcGISRaster.ToLines, u'inputRaster',
3379    typeMetadata=ArcGISRasterLayerTypeMetadata(mustExist=True),
3380    description=_(
3381u"""Raster to convert.
3382
3383The raster will be converted to a line feature class using the
3384ArcGIS Raster to Polyline tool. For each pair of adjacent foreground
3385raster cells, the tool draws a line connecting their centers. This
3386algorithm is appropriate for converting line-like raster features,
3387such as sea surface temperature fronts or other boundary data, into
3388vector features."""),
3389    arcGISDisplayName=_(u'Input raster'))
3390
3391AddArgumentMetadata(ArcGISRaster.ToLines, u'outputFeatureClass',
3392    typeMetadata=ArcGISFeatureClassTypeMetadata(allowedShapeTypes=[u'polyline'], mustBeDifferentThanArguments=[u'inputRaster'], deleteIfParameterIsTrue=u'overwriteExisting', createParentDirectories=True),
3393    description=_(
3394u"""Output polygon feature class that will contain the converted
3395lines.
3396
3397Missing directories in this path will be created if they do not
3398exist."""),
3399    direction=u'Output',
3400    arcGISDisplayName=_(u'Output line feature class'))
3401
3402AddArgumentMetadata(ArcGISRaster.ToLines, u'backgroundValue',
3403    typeMetadata=UnicodeStringTypeMetadata(allowedValues=[u'ZERO', u'NODATA'], makeLowercase=True),
3404    description=_(
3405u"""Specifies the cell value that will identify the background cells.
3406The raster dataset is viewed as a set of foreground cells and
3407background cells. The linear features are formed from the foreground
3408cells.
3409
3410* ZERO - The background is composed of cells of zero or less or
3411  NoData. All cells with a value greater than zero are considered a
3412  foreground value.
3413
3414* NODATA - The background is composed of NoData cells. All cells with
3415  valid values belong to the foreground.
3416"""),
3417    arcGISDisplayName=_(u'Background value'))
3418
3419AddArgumentMetadata(ArcGISRaster.ToLines, u'minDangleLength',
3420    typeMetadata=FloatTypeMetadata(minValue=0.0),
3421    description=_(
3422u"""Minimum length of dangling lines that will be retained. The
3423default is zero."""),
3424    arcGISDisplayName=_(u'Minimum dangle length'))
3425
3426AddArgumentMetadata(ArcGISRaster.ToLines, u'simplify',
3427    typeMetadata=BooleanTypeMetadata(),
3428    description=_(
3429u"""If True (the default) the output lines will be smoothed
3430according to an undocumented algorithm implemented by the ArcGIS
3431Raster to Polyline tool."""),
3432    arcGISDisplayName=_(u'Simplify lines'))
3433
3434AddArgumentMetadata(ArcGISRaster.ToLines, u'field',
3435    typeMetadata=ArcGISFieldTypeMetadata(mustExist=True, allowedFieldTypes=[u'SHORT', u'LONG', u'TEXT'], canBeNone=True),
3436    description=_(
3437u"""The field used to assign values from the cells in the input raster
3438to the lines in the output dataset. It can be an integer or a
3439string field."""),
3440    arcGISParameterDependencies=[u'inputRaster'],
3441    arcGISDisplayName=_(u'Field'))
3442
3443CopyArgumentMetadata(ArcGISRaster.ToPolygons, u'projectedCoordinateSystem', ArcGISRaster.ToLines, u'projectedCoordinateSystem')
3444CopyArgumentMetadata(ArcGISRaster.ToPolygons, u'geographicTransformation', ArcGISRaster.ToLines, u'geographicTransformation')
3445CopyArgumentMetadata(ArcGISRaster.ToPolygons, u'resamplingTechnique', ArcGISRaster.ToLines, u'resamplingTechnique')
3446CopyArgumentMetadata(ArcGISRaster.ToPolygons, u'projectedCellSize', ArcGISRaster.ToLines, u'projectedCellSize')
3447CopyArgumentMetadata(ArcGISRaster.ToPolygons, u'registrationPoint', ArcGISRaster.ToLines, u'registrationPoint')
3448CopyArgumentMetadata(ArcGISRaster.ToPolygons, u'clippingDataset', ArcGISRaster.ToLines, u'clippingDataset')
3449CopyArgumentMetadata(ArcGISRaster.ToPolygons, u'clippingRectangle', ArcGISRaster.ToLines, u'clippingRectangle')
3450CopyArgumentMetadata(ArcGISRaster.ToPolygons, u'mapAlgebraExpression', ArcGISRaster.ToLines, u'mapAlgebraExpression')
3451CopyArgumentMetadata(ArcGISRaster.ToPolygons, u'overwriteExisting', ArcGISRaster.ToLines, u'overwriteExisting')
3452
3453# Public method: ArcGISRaster.ToPoints
3454
3455AddMethodMetadata(ArcGISRaster.ToPoints,
3456    shortDescription=_(u'Converts an ArcGIS raster to a feature class of points that occur at the centers of the raster cells.'),
3457    isExposedToPythonCallers=True,
3458    isExposedByCOM=True,
3459    isExposedAsArcGISTool=True,
3460    arcGISDisplayName=_(u'Convert ArcGIS Raster to Points'),
3461    arcGISToolCategory=_(u'Conversion\\To Points\\From ArcGIS Raster'),
3462    dependencies=[ArcGISDependency(9, 1)])
3463
3464CopyArgumentMetadata(ArcGISRaster.Copy, u'cls', ArcGISRaster.ToPoints, u'cls')
3465
3466AddArgumentMetadata(ArcGISRaster.ToPoints, u'inputRaster',
3467    typeMetadata=ArcGISRasterLayerTypeMetadata(mustExist=True),
3468    description=_(
3469u"""Raster to convert.
3470
3471The raster will be converted to a point feature class using the ArcGIS
3472Raster to Point tool. This tool creates a point at the center of each
3473raster cell, except noData cells."""),
3474    arcGISDisplayName=_(u'Input raster'))
3475
3476AddArgumentMetadata(ArcGISRaster.ToPoints, u'outputFeatureClass',
3477    typeMetadata=ArcGISFeatureClassTypeMetadata(allowedShapeTypes=[u'point'], mustBeDifferentThanArguments=[u'inputRaster'], deleteIfParameterIsTrue=u'overwriteExisting', createParentDirectories=True),
3478    description=_(
3479u"""Output point feature class.
3480
3481Missing directories in this path will be created if they do not
3482exist."""),
3483    direction=u'Output',
3484    arcGISDisplayName=_(u'Output point feature class'))
3485
3486AddArgumentMetadata(ArcGISRaster.ToPoints, u'field',
3487    typeMetadata=ArcGISFieldTypeMetadata(mustExist=True, allowedFieldTypes=[u'SHORT', u'LONG', u'TEXT'], canBeNone=True),
3488    description=_(
3489u"""The field used to assign values from the cells in the input raster
3490to the points in the output dataset. It can be an integer,
3491floating-point, or string field."""),
3492    arcGISParameterDependencies=[u'inputRaster'],
3493    arcGISDisplayName=_(u'Field'))
3494
3495CopyArgumentMetadata(ArcGISRaster.ToPolygons, u'projectedCoordinateSystem', ArcGISRaster.ToPoints, u'projectedCoordinateSystem')
3496CopyArgumentMetadata(ArcGISRaster.ToPolygons, u'geographicTransformation', ArcGISRaster.ToPoints, u'geographicTransformation')
3497CopyArgumentMetadata(ArcGISRaster.ToPolygons, u'resamplingTechnique', ArcGISRaster.ToPoints, u'resamplingTechnique')
3498CopyArgumentMetadata(ArcGISRaster.ToPolygons, u'projectedCellSize', ArcGISRaster.ToPoints, u'projectedCellSize')
3499CopyArgumentMetadata(ArcGISRaster.ToPolygons, u'registrationPoint', ArcGISRaster.ToPoints, u'registrationPoint')
3500CopyArgumentMetadata(ArcGISRaster.ToPolygons, u'clippingDataset', ArcGISRaster.ToPoints, u'clippingDataset')
3501CopyArgumentMetadata(ArcGISRaster.ToPolygons, u'clippingRectangle', ArcGISRaster.ToPoints, u'clippingRectangle')
3502CopyArgumentMetadata(ArcGISRaster.ToPolygons, u'mapAlgebraExpression', ArcGISRaster.ToPoints, u'mapAlgebraExpression')
3503CopyArgumentMetadata(ArcGISRaster.ToPolygons, u'overwriteExisting', ArcGISRaster.ToPoints, u'overwriteExisting')
3504
3505###############################################################################
3506# Batch processing versions of methods
3507###############################################################################
3508
3509from GeoEco.BatchProcessing import BatchProcessing
3510from GeoEco.DataManagement.Fields import Field
3511
3512BatchProcessing.GenerateForMethod(ArcGISRaster.Copy,
3513    inputParamNames=[u'sourceRaster'],
3514    inputParamFieldArcGISDisplayNames=[_(u'Source raster field')],
3515    inputParamDescriptions=[_(u'%s rasters to copy.')],
3516    outputParamNames=[u'destinationRaster'],
3517    outputParamFieldArcGISDisplayNames=[_(u'Destination raster field')],
3518    outputParamExpressionArcGISDisplayNames=[_(u'Destination raster Python expression')],
3519    outputParamDescriptions=[_(u'%s destination rasters.')],
3520    outputParamExpressionDescriptions=[
3521u"""Python expression used to calculate the absolute path of a
3522destination raster. The expression may be any Python statement
3523appropriate for passing to the eval function and must return a Unicode
3524string. The expression may reference the following variables:
3525
3526* workspaceToSearch - the value provided for the workspace to search
3527  parameter
3528
3529* destinationWorkspace - the value provided for the destination
3530  workspace parameter
3531
3532* sourceRaster - the absolute path to the source raster
3533
3534The default expression::
3535
3536    os.path.join(destinationWorkspace, sourceRaster[len(workspaceToSearch)+1:])
3537
3538stores the raster in the destination workspace at the same relative
3539location it appears in the workspace to search. The destination path
3540is calculated by stripping the workspace to search from the source
3541path and replacing it with the destination workspace.
3542
3543For more information on Python syntax, please see the `Python
3544documentation <http://www.python.org/doc/>`_."""],
3545    outputParamDefaultExpressions=[u'os.path.join(destinationWorkspace, sourceRaster[len(workspaceToSearch)+1:])'],
3546    processListMethodName=u'CopyList',
3547    processListMethodShortDescription=_(u'Copies a list of ArcGIS rasters.'),
3548    processTableMethodName=u'CopyTable',
3549    processTableMethodShortDescription=_(u'Copies the ArcGIS rasters listed in a table.'),
3550    processArcGISTableMethodName=u'CopyArcGISTable',
3551    processArcGISTableMethodArcGISDisplayName=_(u'Copy Rasters Listed in Table'),
3552    findAndProcessMethodName=u'FindAndCopy',
3553    findAndProcessMethodArcGISDisplayName=u'Find and Copy Rasters',
3554    findAndProcessMethodShortDescription=_(u'Finds and copies rasters in an ArcGIS workspace.'),
3555    findMethod=ArcGISRaster.FindAndCreateTable,
3556    findOutputFieldParams=[u'rasterField'],
3557    findAdditionalParams=[u'wildcard', u'searchTree', u'rasterType'],
3558    outputLocationTypeMetadata=ArcGISWorkspaceTypeMetadata(createParentDirectories=True),
3559    outputLocationParamDescription=_(u'Workspace to receive copies of the rasters.'),
3560    outputLocationParamArcGISDisplayName=_(u'Destination workspace'),
3561    calculateFieldMethod=Field.CalculateField,
3562    calculateFieldExpressionParam=u'pythonExpression',
3563    calculateFieldAdditionalParams=[u'modulesToImport'],
3564    calculateFieldAdditionalParamsDefaults=[[u'os.path']],
3565    calculateFieldHiddenParams=[u'statementsToExecFirst', u'statementsToExecPerRow'],
3566    calculateFieldHiddenParamValues=[[u'import inspect\nf = inspect.currentframe()\ntry:\n    workspaceToSearch = f.f_back.f_back.f_back.f_back.f_back.f_locals[\'inputWorkspace\']\n    destinationWorkspace = f.f_back.f_back.f_back.f_back.f_back.f_locals[\'outputWorkspace\']\nfinally:\n    del f\n'], [u'sourceRaster = row.sourceRaster']],
3567    calculatedOutputsArcGISCategory=_(u'Destination raster name options'),
3568    skipExistingDescription=_(u'If True, copying will be skipped for destination rasters that already exist.'),
3569    overwriteExistingDescription=_(u'If True and skipExisting is False, existing destination rasters will be overwritten.'))
3570
3571BatchProcessing.GenerateForMethod(ArcGISRaster.Delete,
3572    inputParamNames=[u'raster'],
3573    inputParamFieldArcGISDisplayNames=[_(u'Raster field')],
3574    inputParamDescriptions=[_(u'%s rasters to delete.')],
3575    processListMethodName=u'DeleteList',
3576    processListMethodShortDescription=_(u'Deletes a list of ArcGIS rasters.'),
3577    processTableMethodName=u'DeleteTable',
3578    processTableMethodShortDescription=_(u'Deletes the ArcGIS rasters listed in a table.'),
3579    processArcGISTableMethodName=u'DeleteArcGISTable',
3580    processArcGISTableMethodArcGISDisplayName=_(u'Delete Rasters Listed in Table'),
3581    findAndProcessMethodName=u'FindAndDelete',
3582    findAndProcessMethodArcGISDisplayName=u'Find and Delete Rasters',
3583    findAndProcessMethodShortDescription=_(u'Finds and deletes rasters in an ArcGIS workspace.'),
3584    findMethod=ArcGISRaster.FindAndCreateTable,
3585    findOutputFieldParams=[u'rasterField'],
3586    findAdditionalParams=[u'wildcard', u'searchTree', u'rasterType'])
3587
3588BatchProcessing.GenerateForMethod(ArcGISRaster.Move,
3589    inputParamNames=[u'sourceRaster'],
3590    inputParamFieldArcGISDisplayNames=[_(u'Source raster field')],
3591    inputParamDescriptions=[_(u'%s rasters to move.')],
3592    outputParamNames=[u'destinationRaster'],
3593    outputParamFieldArcGISDisplayNames=[_(u'Destination raster field')],
3594    outputParamExpressionArcGISDisplayNames=[_(u'Destination raster Python expression')],
3595    outputParamDescriptions=[_(u'%s destination rasters.')],
3596    outputParamExpressionDescriptions=[ArcGISRaster.FindAndCopy.__doc__.Obj.GetArgumentByName(u'destinationRasterPythonExpression').Description],
3597    outputParamDefaultExpressions=[ArcGISRaster.FindAndCopy.__doc__.Obj.GetArgumentByName(u'destinationRasterPythonExpression').Default],
3598    processListMethodName=u'MoveList',
3599    processListMethodShortDescription=_(u'Moves a list of ArcGIS rasters.'),
3600    processTableMethodName=u'MoveTable',
3601    processTableMethodShortDescription=_(u'Moves the ArcGIS rasters listed in a table.'),
3602    processArcGISTableMethodName=u'MoveArcGISTable',
3603    processArcGISTableMethodArcGISDisplayName=_(u'Move Rasters Listed in Table'),
3604    findAndProcessMethodName=u'FindAndMove',
3605    findAndProcessMethodArcGISDisplayName=u'Find and Move Rasters',
3606    findAndProcessMethodShortDescription=_(u'Finds and moves rasters in an ArcGIS workspace.'),
3607    findMethod=ArcGISRaster.FindAndCreateTable,
3608    findOutputFieldParams=[u'rasterField'],
3609    findAdditionalParams=[u'wildcard', u'searchTree', u'rasterType'],
3610    outputLocationTypeMetadata=ArcGISWorkspaceTypeMetadata(createParentDirectories=True),
3611    outputLocationParamDescription=_(u'Workspace to receive the rasters.'),
3612    outputLocationParamArcGISDisplayName=_(u'Destination workspace'),
3613    calculateFieldMethod=Field.CalculateField,
3614    calculateFieldExpressionParam=u'pythonExpression',
3615    calculateFieldAdditionalParams=[u'modulesToImport'],
3616    calculateFieldAdditionalParamsDefaults=[[u'os.path']],
3617    calculateFieldHiddenParams=[u'statementsToExecFirst', u'statementsToExecPerRow'],
3618    calculateFieldHiddenParamValues=[[u'import inspect\nf = inspect.currentframe()\ntry:\n    workspaceToSearch = f.f_back.f_back.f_back.f_back.f_back.f_locals[\'inputWorkspace\']\n    destinationWorkspace = f.f_back.f_back.f_back.f_back.f_back.f_locals[\'outputWorkspace\']\nfinally:\n    del f\n'], [u'sourceRaster = row.sourceRaster']],
3619    calculatedOutputsArcGISCategory=_(u'Destination raster name options'),
3620    skipExistingDescription=_(u'If True, moving will be skipped for destination rasters that already exist.'),
3621    overwriteExistingDescription=_(u'If True and skipExisting is False, existing destination rasters will be overwritten.'))
3622
3623BatchProcessing.GenerateForMethod(ArcGISRaster.ExtractByMask,
3624    inputParamNames=[u'inputRaster'],
3625    inputParamFieldArcGISDisplayNames=[_(u'Input raster field')],
3626    inputParamDescriptions=[_(u'%s input rasters.')],
3627    outputParamNames=[u'outputRaster'],
3628    outputParamFieldArcGISDisplayNames=[_(u'Output raster field')],
3629    outputParamExpressionArcGISDisplayNames=[_(u'Output raster Python expression')],
3630    outputParamDescriptions=[_(
3631u"""%s output rasters to receive the cell values extracted from the
3632input rasters.
3633
3634If these paths refers to the file system, missing directories in the
3635paths will be created if they do not exist.""")],
3636    outputParamExpressionDescriptions=[
3637u"""Python expression used to calculate the absolute path of an output
3638raster. The expression may be any Python statement appropriate
3639for passing to the eval function and must return a Unicode string. The
3640expression may reference the following variables:
3641
3642* workspaceToSearch - the value provided for the workspace to search
3643  parameter
3644
3645* outputWorkspace - the value provided for the output workspace
3646  parameter
3647
3648* inputRaster - the absolute path to the input raster
3649
3650The default expression::
3651
3652    os.path.join(outputWorkspace, inputRaster[len(workspaceToSearch)+1:])
3653
3654stores the output rasters in the output workspace at the same relative
3655location as the input rasteres appear in the workspace to search. The
3656output raster path is calculated by stripping the workspace to search
3657from the input raster path and replacing it with the output workspace.
3658
3659For more information on Python syntax, please see the `Python
3660documentation <http://www.python.org/doc/>`_."""],
3661    outputParamDefaultExpressions=[u'os.path.join(outputWorkspace, inputRaster[len(workspaceToSearch)+1:])'],
3662    constantParamNames=[u'mask'],
3663    processListMethodName=u'ExtractByMaskList',
3664    processListMethodShortDescription=_(u'For each ArcGIS raster in a list, extracts the cells that correspond to the areas defined by a mask.'),
3665    processTableMethodName=u'ExtractByMaskTable',
3666    processTableMethodShortDescription=_(u'For each ArcGIS raster in a table, extracts the cells that correspond to the areas defined by a mask.'),
3667    processArcGISTableMethodName=u'ExtractByMaskArcGISTable',
3668    processArcGISTableMethodArcGISDisplayName=_(u'Extract By Mask for ArcGIS Rasters Listed in Table'),
3669    findAndProcessMethodName=u'FindAndExtractByMask',
3670    findAndProcessMethodArcGISDisplayName=u'Find ArcGIS Rasters and Extract By Mask',
3671    findAndProcessMethodShortDescription=_(u'Finds rasters in an ArcGIS workspace and extracts the cells that correspond to the areas defined by a mask.'),
3672    findMethod=ArcGISRaster.FindAndCreateTable,
3673    findOutputFieldParams=[u'rasterField'],
3674    findAdditionalParams=[u'wildcard', u'searchTree', u'rasterType'],
3675    outputLocationTypeMetadata=ArcGISWorkspaceTypeMetadata(createParentDirectories=True),
3676    outputLocationParamDescription=_(u'Workspace to receive the output rasters.'),
3677    outputLocationParamArcGISDisplayName=_(u'Output workspace'),
3678    calculateFieldMethod=Field.CalculateField,
3679    calculateFieldExpressionParam=u'pythonExpression',
3680    calculateFieldAdditionalParams=[u'modulesToImport'],
3681    calculateFieldAdditionalParamsDefaults=[[u'os.path']],
3682    calculateFieldHiddenParams=[u'statementsToExecFirst', u'statementsToExecPerRow'],
3683    calculateFieldHiddenParamValues=[[u'import inspect\nf = inspect.currentframe()\ntry:\n    workspaceToSearch = f.f_back.f_back.f_back.f_back.f_back.f_locals[\'inputWorkspace\']\n    outputWorkspace = f.f_back.f_back.f_back.f_back.f_back.f_locals[\'outputWorkspace\']\nfinally:\n    del f\n'], [u'inputRaster = row.inputRaster']],
3684    calculatedOutputsArcGISCategory=_(u'Output raster name options'),
3685    skipExistingDescription=_(u'If True, processing will be skipped for output rasters that already exist.'),
3686    overwriteExistingDescription=_(u'If True and skipExisting is False, existing output rasters will be overwritten.'))
3687
3688BatchProcessing.GenerateForMethod(ArcGISRaster.ProjectClipAndOrExecuteMapAlgebra,
3689    inputParamNames=[u'inputRaster'],
3690    inputParamFieldArcGISDisplayNames=[_(u'Input raster field')],
3691    inputParamDescriptions=[_(u'%s input rasters.')],
3692    outputParamNames=[u'outputRaster'],
3693    outputParamFieldArcGISDisplayNames=[_(u'Output raster field')],
3694    outputParamExpressionArcGISDisplayNames=[_(u'Output raster Python expression')],
3695    outputParamDescriptions=[_(
3696u"""%s output rasters.
3697
3698If these paths refers to the file system, missing directories in the
3699paths will be created if they do not exist.""")],
3700    outputParamExpressionDescriptions=[
3701u"""Python expression used to calculate the absolute path of an output
3702raster. The expression may be any Python statement appropriate
3703for passing to the eval function and must return a Unicode string. The
3704expression may reference the following variables:
3705
3706* workspaceToSearch - the value provided for the workspace to search
3707  parameter
3708
3709* outputWorkspace - the value provided for the output workspace
3710  parameter
3711
3712* inputRaster - the absolute path to the input raster
3713
3714The default expression::
3715
3716    os.path.join(outputWorkspace, inputRaster[len(workspaceToSearch)+1:])
3717
3718stores the output rasters in the output workspace at the same relative
3719location as the input rasteres appear in the workspace to search. The
3720output raster path is calculated by stripping the workspace to search
3721from the input raster path and replacing it with the output workspace.
3722
3723For more information on Python syntax, please see the `Python
3724documentation <http://www.python.org/doc/>`_."""],
3725    outputParamDefaultExpressions=[u'os.path.join(outputWorkspace, inputRaster[len(workspaceToSearch)+1:])'],
3726    constantParamNames=[u'projectedCoordinateSystem', u'geographicTransformation', u'resamplingTechnique', u'projectedCellSize', u'registrationPoint', u'clippingDataset', u'clippingRectangle', u'mapAlgebraExpression', u'buildPyramids'],
3727    processListMethodName=u'ProjectClipAndOrExecuteMapAlgebraList',
3728    processListMethodShortDescription=_(u'Projects, clips, and/or perfoms map algebra on the ArcGIS rasters in a list. You must request at least one of these three operations. If you request multiple operations, the tool performs them in the order they are listed.'),
3729    processTableMethodName=u'ProjectClipAndOrExecuteMapAlgebraTable',
3730    processTableMethodShortDescription=_(u'Projects, clips, and/or perfoms map algebra on the ArcGIS rasters listed in a table. You must request at least one of these three operations. If you request multiple operations, the tool performs them in the order they are listed.'),
3731    processArcGISTableMethodName=u'ProjectClipAndOrExecuteMapAlgebraArcGISTable',
3732    processArcGISTableMethodArcGISDisplayName=_(u'Project, Clip, and/or Execute Map Algebra on ArcGIS Rasters Listed in Table'),
3733    findAndProcessMethodName=u'FindAndProjectClipAndOrExecuteMapAlgebra',
3734    findAndProcessMethodArcGISDisplayName=u'Find ArcGIS Rasters and Project, Clip, and/or Execute Map Algebra',
3735    findAndProcessMethodShortDescription=_(u'Finds rasters in an ArcGIS workspace and projects, clips, and/or perfoms map algebra on them. You must request at least one of these three operations. If you request multiple operations, the tool performs them in the order they are listed.'),
3736    findMethod=ArcGISRaster.FindAndCreateTable,
3737    findOutputFieldParams=[u'rasterField'],
3738    findAdditionalParams=[u'wildcard', u'searchTree', u'rasterType'],
3739    outputLocationTypeMetadata=ArcGISWorkspaceTypeMetadata(createParentDirectories=True),
3740    outputLocationParamDescription=_(u'Workspace to receive the output rasters.'),
3741    outputLocationParamArcGISDisplayName=_(u'Output workspace'),
3742    calculateFieldMethod=Field.CalculateField,
3743    calculateFieldExpressionParam=u'pythonExpression',
3744    calculateFieldAdditionalParams=[u'modulesToImport'],
3745    calculateFieldAdditionalParamsDefaults=[[u'os.path']],
3746    calculateFieldHiddenParams=[u'statementsToExecFirst', u'statementsToExecPerRow'],
3747    calculateFieldHiddenParamValues=[[u'import inspect\nf = inspect.currentframe()\ntry:\n    workspaceToSearch = f.f_back.f_back.f_back.f_back.f_back.f_locals[\'inputWorkspace\']\n    outputWorkspace = f.f_back.f_back.f_back.f_back.f_back.f_locals[\'outputWorkspace\']\nfinally:\n    del f\n'], [u'inputRaster = row.inputRaster']],
3748    calculatedOutputsArcGISCategory=_(u'Output raster name options'),
3749    skipExistingDescription=_(u'If True, processing will be skipped for output rasters that already exist.'),
3750    overwriteExistingDescription=_(u'If True and skipExisting is False, existing output rasters will be overwritten.'))
3751
3752_OutputFeatureClassParamExpressionDescription = _(u"""Python expression used to calculate the absolute path of an output
3753feature class. The expression may be any Python statement appropriate
3754for passing to the eval function and must return a Unicode string. The
3755expression may reference the following variables:
3756
3757* workspaceToSearch - the value provided for the workspace to search
3758  parameter
3759
3760* outputWorkspace - the value provided for the output workspace
3761  parameter
3762
3763* inputRaster - the absolute path to the input raster
3764
3765The default expression::
3766
3767    os.path.join(outputWorkspace, inputRaster[len(workspaceToSearch)+1:])
3768
3769stores the feature classes in the output workspace at the same
3770relative location as the input rasteres in the workspace to search.
3771The feature class path is calculated by stripping the workspace to
3772search from the input raster path and replacing it with the output
3773workspace.
3774
3775For more information on Python syntax, please see the `Python
3776documentation <http://www.python.org/doc/>`_.""")
3777
3778BatchProcessing.GenerateForMethod(ArcGISRaster.ToPolygons,
3779    inputParamNames=[u'inputRaster'],
3780    inputParamFieldArcGISDisplayNames=[_(u'Input raster field')],
3781    inputParamDescriptions=[_(
3782u"""%s rasters to convert.
3783
3784The rasters will be converted to polygon feature classes using the
3785ArcGIS Raster to Polygon tool. That tool can only convert integer
3786rasters to polygons. If the input rasters are floating-point rasters,
3787you must use the Map Algebra Expression parameter to convert them to
3788integer rasters.""")],
3789    outputParamNames=[u'outputFeatureClass'],
3790    outputParamFieldArcGISDisplayNames=[_(u'Output polygon feature class field')],
3791    outputParamExpressionArcGISDisplayNames=[_(u'Output polygon feature class Python expression')],
3792    outputParamDescriptions=[_(
3793u"""%s output polygon feature classes.
3794
3795One feature class will be created per raster. Missing directories the
3796output paths will be created if they do not exist.""")],
3797    outputParamExpressionDescriptions=[_OutputFeatureClassParamExpressionDescription],
3798    outputParamDefaultExpressions=[u'os.path.join(outputWorkspace, inputRaster[len(workspaceToSearch)+1:])'],
3799    constantParamNames=[u'simplify', u'field', u'projectedCoordinateSystem', u'geographicTransformation', u'resamplingTechnique', u'projectedCellSize', u'registrationPoint', u'clippingDataset', u'clippingRectangle', u'mapAlgebraExpression'],
3800    processListMethodName=u'ToPolygonsList',
3801    processListMethodShortDescription=_(u'Converts a list of ArcGIS rasters to polygons that encompass groups of adjacent raster cells having the same value.'),
3802    processTableMethodName=u'ToPolygonsTable',
3803    processTableMethodShortDescription=_(u'Converts the ArcGIS rasters listed in a table to polygons that encompass groups of adjacent raster cells having the same value.'),
3804    processArcGISTableMethodName=u'ToPolygonsArcGISTable',
3805    processArcGISTableMethodArcGISDisplayName=_(u'Convert ArcGIS Rasters Listed in Table to Polygons'),
3806    findAndProcessMethodName=u'FindAndConvertToPolygons',
3807    findAndProcessMethodArcGISDisplayName=u'Find and Convert ArcGIS Rasters to Polygons',
3808    findAndProcessMethodShortDescription=_(u'Finds rasters in an ArcGIS workspace and converts them to polygons that encompass groups of adjacent raster cells having the same value.'),
3809    findMethod=ArcGISRaster.FindAndCreateTable,
3810    findOutputFieldParams=[u'rasterField'],
3811    findAdditionalParams=[u'wildcard', u'searchTree', u'rasterType'],
3812    outputLocationTypeMetadata=ArcGISWorkspaceTypeMetadata(createParentDirectories=True),
3813    outputLocationParamDescription=_(u'Workspace to receive the polygon feature classes.'),
3814    outputLocationParamArcGISDisplayName=_(u'Output workspace'),
3815    calculateFieldMethod=Field.CalculateField,
3816    calculateFieldExpressionParam=u'pythonExpression',
3817    calculateFieldAdditionalParams=[u'modulesToImport'],
3818    calculateFieldAdditionalParamsDefaults=[[u'os.path']],
3819    calculateFieldHiddenParams=[u'statementsToExecFirst', u'statementsToExecPerRow'],
3820    calculateFieldHiddenParamValues=[[u'import inspect\nf = inspect.currentframe()\ntry:\n    workspaceToSearch = f.f_back.f_back.f_back.f_back.f_back.f_locals[\'inputWorkspace\']\n    outputWorkspace = f.f_back.f_back.f_back.f_back.f_back.f_locals[\'outputWorkspace\']\nfinally:\n    del f\n'], [u'inputRaster = row.inputRaster']],
3821    calculatedOutputsArcGISCategory=_(u'Output feature class name options'),
3822    skipExistingDescription=_(u'If True, conversion will be skipped for feature classes that already exist.'),
3823    overwriteExistingDescription=_(u'If True and skipExisting is False, existing feature classes will be overwritten.'))
3824
3825BatchProcessing.GenerateForMethod(ArcGISRaster.ToPolygonOutlines,
3826    inputParamNames=[u'inputRaster'],
3827    inputParamFieldArcGISDisplayNames=[_(u'Input raster field')],
3828    inputParamDescriptions=[_(
3829u"""%s rasters to convert.
3830
3831The rasters will be converted to polygon feature classes using the
3832ArcGIS Raster to Polygon tool, and then to line features using the
3833Feature to Line tool. The Raster to Polygon tool can only convert
3834integer rasters to polygons. If the input rasters are floating-point
3835rasters, you must use the Map Algebra Expression parameter to convert
3836them to integer rasters.""")],
3837    outputParamNames=[u'outputFeatureClass'],
3838    outputParamFieldArcGISDisplayNames=[_(u'Output line feature class field')],
3839    outputParamExpressionArcGISDisplayNames=[_(u'Output line feature class Python expression')],
3840    outputParamDescriptions=[_(
3841u"""%s output line feature classes.
3842
3843One feature class will be created per raster. Missing directories the
3844output paths will be created if they do not exist.""")],
3845    outputParamExpressionDescriptions=[_OutputFeatureClassParamExpressionDescription],
3846    outputParamDefaultExpressions=[u'os.path.join(outputWorkspace, inputRaster[len(workspaceToSearch)+1:])'],
3847    constantParamNames=[u'simplify', u'field', u'projectedCoordinateSystem', u'geographicTransformation', u'resamplingTechnique', u'projectedCellSize', u'registrationPoint', u'clippingDataset', u'clippingRectangle', u'mapAlgebraExpression'],
3848    processListMethodName=u'ToPolygonOutlinesList',
3849    processListMethodShortDescription=_(u'Converts a list of ArcGIS rasters to lines that outline groups of adjacent raster cells having the same value.'),
3850    processTableMethodName=u'ToPolygonOutlinesTable',
3851    processTableMethodShortDescription=_(u'Converts the ArcGIS rasters listed in a table to lines that outline groups of adjacent raster cells having the same value.'),
3852    processArcGISTableMethodName=u'ToPolygonOutlinesArcGISTable',
3853    processArcGISTableMethodArcGISDisplayName=_(u'Convert ArcGIS Rasters Listed in Table to Polygon Outlines'),
3854    findAndProcessMethodName=u'FindAndConvertToPolygonOutlines',
3855    findAndProcessMethodArcGISDisplayName=u'Find and Convert ArcGIS Rasters to Polygon Outlines',
3856    findAndProcessMethodShortDescription=_(u'Finds rasters in an ArcGIS workspace and converts them to lines that outline groups of adjacent raster cells having the same value.'),
3857    findMethod=ArcGISRaster.FindAndCreateTable,
3858    findOutputFieldParams=[u'rasterField'],
3859    findAdditionalParams=[u'wildcard', u'searchTree', u'rasterType'],
3860    outputLocationTypeMetadata=ArcGISWorkspaceTypeMetadata(createParentDirectories=True),
3861    outputLocationParamDescription=_(u'Workspace to receive the line feature classes.'),
3862    outputLocationParamArcGISDisplayName=_(u'Output workspace'),
3863    calculateFieldMethod=Field.CalculateField,
3864    calculateFieldExpressionParam=u'pythonExpression',
3865    calculateFieldAdditionalParams=[u'modulesToImport'],
3866    calculateFieldAdditionalParamsDefaults=[[u'os.path']],
3867    calculateFieldHiddenParams=[u'statementsToExecFirst', u'statementsToExecPerRow'],
3868    calculateFieldHiddenParamValues=[[u'import inspect\nf = inspect.currentframe()\ntry:\n    workspaceToSearch = f.f_back.f_back.f_back.f_back.f_back.f_locals[\'inputWorkspace\']\n    outputWorkspace = f.f_back.f_back.f_back.f_back.f_back.f_locals[\'outputWorkspace\']\nfinally:\n    del f\n'], [u'inputRaster = row.inputRaster']],
3869    calculatedOutputsArcGISCategory=_(u'Output feature class name options'),
3870    skipExistingDescription=_(u'If True, conversion will be skipped for feature classes that already exist.'),
3871    overwriteExistingDescription=_(u'If True and skipExisting is False, existing feature classes will be overwritten.'))
3872
3873BatchProcessing.GenerateForMethod(ArcGISRaster.ToLines,
3874    inputParamNames=[u'inputRaster'],
3875    inputParamFieldArcGISDisplayNames=[_(u'Input raster field')],
3876    inputParamDescriptions=[_(
3877u"""%s rasters to convert.
3878
3879The rasters will be converted to line feature classes using the
3880ArcGIS Raster to Polyline tool. For each pair of adjacent foreground
3881raster cells, the tool draws a line connecting their centers. This
3882algorithm is appropriate for converting line-like raster features,
3883such as sea surface temperature fronts or other boundary data, into
3884vector features.""")],
3885    outputParamNames=[u'outputFeatureClass'],
3886    outputParamFieldArcGISDisplayNames=[_(u'Output line feature class field')],
3887    outputParamExpressionArcGISDisplayNames=[_(u'Output line feature class Python expression')],
3888    outputParamDescriptions=[_(
3889u"""%s output line feature classes.
3890
3891One feature class will be created per raster. Missing directories the
3892output paths will be created if they do not exist.""")],
3893    outputParamExpressionDescriptions=[_OutputFeatureClassParamExpressionDescription],
3894    outputParamDefaultExpressions=[u'os.path.join(outputWorkspace, inputRaster[len(workspaceToSearch)+1:])'],
3895    constantParamNames=[u'backgroundValue', u'minDangleLength', u'simplify', u'field', u'projectedCoordinateSystem', u'geographicTransformation', u'resamplingTechnique', u'projectedCellSize', u'registrationPoint', u'clippingDataset', u'clippingRectangle', u'mapAlgebraExpression'],
3896    processListMethodName=u'ToLinesList',
3897    processListMethodShortDescription=_(u'Converts a list of ArcGIS rasters to lines that outline groups of adjacent raster cells having the same value.'),
3898    processTableMethodName=u'ToLinesTable',
3899    processTableMethodShortDescription=_(u'Converts the ArcGIS rasters listed in a table to lines that outline groups of adjacent raster cells having the same value.'),
3900    processArcGISTableMethodName=u'ToLinesArcGISTable',
3901    processArcGISTableMethodArcGISDisplayName=_(u'Convert ArcGIS Rasters Listed in Table to Lines'),
3902    findAndProcessMethodName=u'FindAndConvertToLines',
3903    findAndProcessMethodArcGISDisplayName=u'Find and Convert ArcGIS Rasters to Lines',
3904    findAndProcessMethodShortDescription=_(u'Finds rasters in an ArcGIS workspace and converts them to lines that outline groups of adjacent raster cells having the same value.'),
3905    findMethod=ArcGISRaster.FindAndCreateTable,
3906    findOutputFieldParams=[u'rasterField'],
3907    findAdditionalParams=[u'wildcard', u'searchTree', u'rasterType'],
3908    outputLocationTypeMetadata=ArcGISWorkspaceTypeMetadata(createParentDirectories=True),
3909    outputLocationParamDescription=_(u'Workspace to receive the line feature classes.'),
3910    outputLocationParamArcGISDisplayName=_(u'Output workspace'),
3911    calculateFieldMethod=Field.CalculateField,
3912    calculateFieldExpressionParam=u'pythonExpression',
3913    calculateFieldAdditionalParams=[u'modulesToImport'],
3914    calculateFieldAdditionalParamsDefaults=[[u'os.path']],
3915    calculateFieldHiddenParams=[u'statementsToExecFirst', u'statementsToExecPerRow'],
3916    calculateFieldHiddenParamValues=[[u'import inspect\nf = inspect.currentframe()\ntry:\n    workspaceToSearch = f.f_back.f_back.f_back.f_back.f_back.f_locals[\'inputWorkspace\']\n    outputWorkspace = f.f_back.f_back.f_back.f_back.f_back.f_locals[\'outputWorkspace\']\nfinally:\n    del f\n'], [u'inputRaster = row.inputRaster']],
3917    calculatedOutputsArcGISCategory=_(u'Output feature class name options'),
3918    skipExistingDescription=_(u'If True, conversion will be skipped for feature classes that already exist.'),
3919    overwriteExistingDescription=_(u'If True and skipExisting is False, existing feature classes will be overwritten.'))
3920
3921BatchProcessing.GenerateForMethod(ArcGISRaster.ToPoints,
3922    inputParamNames=[u'inputRaster'],
3923    inputParamFieldArcGISDisplayNames=[_(u'Input raster field')],
3924    inputParamDescriptions=[_(
3925u"""%s rasters to convert.
3926
3927The rasters will be converted to point feature classes using the
3928ArcGIS Raster to Point tool. This tool creates a point at the center
3929of each raster cell, except NoData cells.""")],
3930    outputParamNames=[u'outputFeatureClass'],
3931    outputParamFieldArcGISDisplayNames=[_(u'Output point feature class field')],
3932    outputParamExpressionArcGISDisplayNames=[_(u'Output point feature class Python expression')],
3933    outputParamDescriptions=[_(
3934u"""%s output point feature classes.
3935
3936One feature class will be created per raster. Missing directories the
3937output paths will be created if they do not exist.""")],
3938    outputParamExpressionDescriptions=[_OutputFeatureClassParamExpressionDescription],
3939    outputParamDefaultExpressions=[u'os.path.join(outputWorkspace, inputRaster[len(workspaceToSearch)+1:])'],
3940    constantParamNames=[u'field', u'projectedCoordinateSystem', u'geographicTransformation', u'resamplingTechnique', u'projectedCellSize', u'registrationPoint', u'clippingDataset', u'clippingRectangle', u'mapAlgebraExpression'],
3941    processListMethodName=u'ToPointsList',
3942    processListMethodShortDescription=_(u'Converts a list of ArcGIS rasters to points that occur at the centers of the raster cells.'),
3943    processTableMethodName=u'ToPointsTable',
3944    processTableMethodShortDescription=_(u'Converts the ArcGIS rasters listed in a table to points that occur at the centers of the raster cells.'),
3945    processArcGISTableMethodName=u'ToPointsArcGISTable',
3946    processArcGISTableMethodArcGISDisplayName=_(u'Convert ArcGIS Rasters Listed in Table to Points'),
3947    findAndProcessMethodName=u'FindAndConvertToPoints',
3948    findAndProcessMethodArcGISDisplayName=u'Find and Convert ArcGIS Rasters to Points',
3949    findAndProcessMethodShortDescription=_(u'Finds rasters in an ArcGIS workspace and converts them to points that occur at the centers of the raster cells.'),
3950    findMethod=ArcGISRaster.FindAndCreateTable,
3951    findOutputFieldParams=[u'rasterField'],
3952    findAdditionalParams=[u'wildcard', u'searchTree', u'rasterType'],
3953    outputLocationTypeMetadata=ArcGISWorkspaceTypeMetadata(createParentDirectories=True),
3954    outputLocationParamDescription=_(u'Workspace to receive the point feature classes.'),
3955    outputLocationParamArcGISDisplayName=_(u'Output workspace'),
3956    calculateFieldMethod=Field.CalculateField,
3957    calculateFieldExpressionParam=u'pythonExpression',
3958    calculateFieldAdditionalParams=[u'modulesToImport'],
3959    calculateFieldAdditionalParamsDefaults=[[u'os.path']],
3960    calculateFieldHiddenParams=[u'statementsToExecFirst', u'statementsToExecPerRow'],
3961    calculateFieldHiddenParamValues=[[u'import inspect\nf = inspect.currentframe()\ntry:\n    workspaceToSearch = f.f_back.f_back.f_back.f_back.f_back.f_locals[\'inputWorkspace\']\n    outputWorkspace = f.f_back.f_back.f_back.f_back.f_back.f_locals[\'outputWorkspace\']\nfinally:\n    del f\n'], [u'inputRaster = row.inputRaster']],
3962    calculatedOutputsArcGISCategory=_(u'Output feature class name options'),
3963    skipExistingDescription=_(u'If True, conversion will be skipped for feature classes that already exist.'),
3964    overwriteExistingDescription=_(u'If True and skipExisting is False, existing feature classes will be overwritten.'))
3965
3966###############################################################################
3967# Names exported by this module
3968###############################################################################
3969
3970__all__ = ['ArcGISRaster']
Note: See TracBrowser for help on using the browser.