root/MGET/Branches/Jason/PythonPackage/src/GeoEco/Datasets/Collections/HYCOM.py @ 533

Revision 533, 49.3 KB (checked in by jjr8, 3 years ago)

Continued work on the Datasets infrastructure.

Line 
1# Datasets/HYCOM.py - Grids representing HYCOM datasets.
2#
3# Copyright (C) 2010 Jason J. Roberts
4#
5# This program is free software; you can redistribute it and/or
6# modify it under the terms of the GNU General Public License
7# as published by the Free Software Foundation; either version 2
8# of the License, or (at your option) any later version.
9#
10# This program is distributed in the hope that it will be useful,
11# but WITHOUT ANY WARRANTY; without even the implied warranty of
12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13# GNU General Public License (available in the file LICENSE.TXT)
14# for more details.
15#
16# You should have received a copy of the GNU General Public License
17# along with this program; if not, write to the Free Software
18# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
19
20import datetime
21
22from GeoEco.Datasets import Dataset, QueryableAttribute, Grid
23from GeoEco.Datasets.OPeNDAP import THREDDSCatalog, OPeNDAPURL, OPeNDAPGrid
24from GeoEco.Datasets.Virtual import TimeSeriesGridStack, GridSliceCollection, MaskedGrid, ClippedGrid, RotatedGlobalGrid
25from GeoEco.DynamicDocString import DynamicDocString
26from GeoEco.Internationalization import _
27from GeoEco.Types import *
28
29
30class _HYCOMGridGOMl0043D(OPeNDAPGrid):
31    __doc__ = DynamicDocString()
32
33    def __init__(self, url, variableName, timeout, cacheDirectory):
34        self._CachedTCenterCoords = None
35        super(_HYCOMGridGOMl0043D, self).__init__(OPeNDAPURL(url, timeout=timeout, cacheDirectory=cacheDirectory),
36                                                    variableName,
37                                                    'Grid',
38                                                    lazyPropertyValues={'SpatialReference': Dataset.ConvertSpatialReference('proj4', '+proj=merc +ellps=sphere +a=6371001 +b=6371001', 'obj'),
39                                                                        'Dimensions': 'tyx',
40                                                                        'CoordDependencies': (None, None, None),
41                                                                        'CoordIncrements': (None, 4447.7949713872476, 4447.7949713872476),      # t increment is None because, sadly, HYCOM omits slices when their system occasionally fails to generate data for a day
42                                                                        'TCornerCoordType': 'center',
43                                                                        'PhysicalDimensions': 'tyx',
44                                                                        'PhysicalDimensionsFlipped': (False, False, False),
45                                                                        'UnscaledDataType': 'float32',
46                                                                        'UnscaledNoDataValue': 1.2676506002282294e+030,
47                                                                        'ScalingFunction': None})
48       
49    def _GetLazyPropertyPhysicalValue(self, name):
50        if name == 'CornerCoords':
51            return (self._GetCoords('t', 0, [0], [0], -0.5), 2045985.6431758059, -10897097.679898757)       # Center of lower-left cell, in degrees: 98.0 W, 18.091648101806641 N
52        return super(_HYCOMGridGOMl0043D, self)._GetLazyPropertyPhysicalValue(name)
53
54    def _GetCoords(self, coord, coordNum, slices, sliceDims, fixedIncrementOffset):
55        if coord != 't':
56            raise RuntimeError(_('_HYCOMGridGOMl0043D._GetCoords() called with coord == \'%(coord)s\'. This should never happen. Please contact the author of this tool for assistance.') % {u'coord': coord})
57        if self._CachedTCenterCoords is None:
58            import numpy
59            self._CachedTCenterCoords = numpy.array(map(lambda days: datetime.timedelta(days) + datetime.datetime(1900, 12, 31), list(self._GetOPeNDAPVariable()['MT'][:])), dtype='object')
60        if slices is None:
61            result = self._CachedTCenterCoords.copy()
62        else:
63            result = self._CachedTCenterCoords.__getitem__(*slices)
64        if fixedIncrementOffset != 0:
65            result += datetime.timedelta(fixedIncrementOffset)
66        return result
67
68
69class HYCOMGOMl0043D(Grid):
70    __doc__ = DynamicDocString()
71
72    def _GetVariableName(self):
73        return self._VariableName
74
75    VariableName = property(_GetVariableName, doc=DynamicDocString())
76
77    def _GetStartYear(self):
78        return self._StartYear
79
80    StartYear = property(_GetStartYear, doc=DynamicDocString())
81
82    def _GetEndYear(self):
83        return self._EndYear
84
85    EndYear = property(_GetEndYear, doc=DynamicDocString())
86
87    def __init__(self, variableName, startYear=None, endYear=None, timeout=600, cacheDirectory=None):
88        self.__doc__.Obj.ValidateMethodInvocation()
89
90        # Perform additional validation
91
92        if startYear is None:
93            startYear = 2003
94        elif startYear > (datetime.datetime.now() + datetime.timedelta(5)).year:
95            raise ValueError(_(u'The start year must be less than or equal to %(max)i.') % {u'max': (datetime.datetime.now() + datetime.timedelta(5)).year})
96
97        if endYear is not None and endYear < startYear:
98            raise ValueError(_(u'The end year must be greater than or equal to the start year. If the start year is not specified, the end year must be greater than or equal to 2003.'))
99
100        # Initialize our properties.
101
102        self._VariableName = variableName
103        self._StartYear = startYear
104        self._EndYear = endYear
105        self._Timeout = timeout
106        self._CacheDirectory = cacheDirectory
107        self._DisplayName = _(u'%(name)s grid of the HYCOM + NCODA Gulf of Mexico 1/25 degree Analysis (GOMl0.04) aggregated OPeNDAP datasets') % {u'name': variableName}
108        self._OpenURL = None
109        self._OpenGrid = None
110
111        # Initialize the base class.
112
113        super(HYCOMGOMl0043D, self).__init__(queryableAttributes=(QueryableAttribute(u'VariableName', _(u'Dataset variable'), UnicodeStringTypeMetadata(allowedValues=[u'emp', u'mld', u'mlp', u'qtot', u'ssh', u'surface_salinity_trend', u'surface_temperature_trend'], makeLowercase=True)),),
114                                             queryableAttributeValues={u'VariableName': variableName},
115                                             lazyPropertyValues={'SpatialReference': Dataset.ConvertSpatialReference('proj4', '+proj=merc +ellps=sphere +a=6371001 +b=6371001', 'obj'),
116                                                                 'Dimensions': u'tyx',
117                                                                 'CoordDependencies': (None, None, None),
118                                                                 'CoordIncrements': (1.0, 4447.7949713872476, 4447.7949713872476),
119                                                                 'TIncrementUnit': u'day',
120                                                                 'TSemiRegularity': None,
121                                                                 'TCountPerSemiRegularPeriod': None,
122                                                                 'TCornerCoordType': u'center',
123                                                                 'CornerCoords': (datetime.datetime(startYear, 1, 1), 2045985.6431758059, -10897097.679898757),       # Center of lower-left cell, in degrees: 98.0 W, 18.091648101806641 N
124                                                                 'PhysicalDimensions': u'tyx',
125                                                                 'PhysicalDimensionsFlipped': (False, False, False),
126                                                                 'UnscaledDataType': u'float32',
127                                                                 'UnscaledNoDataValue': 1.2676506002282294e+030,
128                                                                 'ScalingFunction': None})
129
130    def _GetDisplayName(self):
131        return self._DisplayName
132       
133    def _GetLazyPropertyPhysicalValue(self, name):
134
135        # The only property that we can retrieve here is the shape.
136        # For the t axis, add the number of days in the years leading
137        # up to the final year to the number of days available from
138        # HYCOM in the final year. For the x and y axes, just use
139        # hardcoded values.
140
141        if name == 'Shape':
142            if self._EndYear is not None and self._EndYear < datetime.datetime.now().year:
143                return ((datetime.datetime(self._EndYear + 1, 1, 1) - datetime.datetime(self._StartYear, 1, 1)).days, 385, 541)
144
145            endYearGrid = _HYCOMGridGOMl0043D('http://tds.hycom.org/thredds/dodsC/GOMl0.04/expt_30.1/%i' % datetime.datetime.now().year, self._VariableName, self._Timeout, self._CacheDirectory)
146            endDay = endYearGrid.CenterCoords['t', -1]
147           
148            if endDay.month == 12 and endDay.day == 31:
149                endYearGrid = _HYCOMGridGOMl0043D('http://tds.hycom.org/thredds/dodsC/GOMl0.04/expt_30.1/%i' % datetime.datetime.now().year + 1, self._VariableName, self._Timeout, self._CacheDirectory)
150                endDay = endYearGrid.CenterCoords['t', -1]
151
152            return ((endDay - datetime.datetime(self._StartYear, 1, 1)).days + 1, 385, 541)
153
154        raise AttributeError(_(u'\'%(class)s\' object has no lazy property named \'%(name)s\'') % {u'class': self.__class__.__name__, u'name': name})
155
156    def _ReadNumpyArray(self, sliceList):
157
158        # For many OPeNDAP datasets, we would be able to request the
159        # entire 3D slab directly. This won't work for the HYCOM
160        # GOMl0.04 dataset, for two reasons: 1) The dataset is split
161        # OPeNDAP URLs for each year, and 2) HYCOM omits slices when
162        # their system occasionally fails to generate data for a day,
163        # so most years do not have a full 365 (or 366) slices. To
164        # deal with this, we have to loop over the requested range of
165        # time indices and issue OPeNDAP requests to the proper URLs
166        # and per-URL time indices.
167        #
168        # First, allocate the array we will return. We'll populate
169        # this as we go along. (I prefer this approach rather than
170        # growing an array through concatenation because it avoids
171        # repeatedly allocating and copying memory.)
172
173        import numpy
174        result = numpy.zeros((sliceList[0].stop - sliceList[0].start, sliceList[1].stop - sliceList[1].start, sliceList[2].stop - sliceList[2].start), dtype=str(self.UnscaledDataType))
175
176        # Loop over the requested t indices, populating the result
177        # array.
178
179        i = 0
180        tCoords = self.CenterCoords['t', sliceList[0]]
181       
182        while i < len(tCoords):
183
184            # Open the _HYCOMGridGOMl0043D for the next block of t
185            # coordinates. These grids are 1 year long, except in 2010
186            # when HYCOM switched to an improved configuration after
187            # five months.
188
189            if tCoords[i] < datetime.datetime(2010, 6, 1):
190                url = 'http://tds.hycom.org/thredds/dodsC/GOMl0.04/expt_20.1/%i' % tCoords[i].year
191            else:
192                url = 'http://tds.hycom.org/thredds/dodsC/GOMl0.04/expt_30.1/%i' % tCoords[i].year
193
194            if self._OpenURL != url:
195                self._OpenGrid = _HYCOMGridGOMl0043D(url, self._VariableName, self._Timeout, self._CacheDirectory)
196                self._OpenURL = url
197
198            if tCoords[i] >= datetime.datetime(2010, 1, 1) and tCoords[i] <= datetime.datetime(2010, 5, 31):
199                lastDayOfDataset = datetime.datetime(2010, 5, 31)
200            else:
201                lastDayOfDataset = datetime.datetime(tCoords[i].year, 12, 31)
202
203            # Read the necessary data from this grid as one 3D slab.
204
205            import bisect
206
207            gridTStart = bisect.bisect_left(self._OpenGrid.CenterCoords['t'].tolist(), tCoords[i])
208            gridTStop = bisect.bisect_right(self._OpenGrid.CenterCoords['t'].tolist(), tCoords[-1])
209            gridTCoords = self._OpenGrid.CenterCoords['t', gridTStart:gridTStop]
210            data = self._OpenGrid.UnscaledData.__getitem__((slice(gridTStart, gridTStop), sliceList[1], sliceList[2]))
211
212            # Iterate through the t indices, copying out time slices
213            # when they are available, otherwise setting slices to the
214            # UnscaledNoDataValue.
215
216            j = 0
217
218            while i < len(tCoords) and tCoords[i] <= lastDayOfDataset:
219                if j < len(gridTCoords) and gridTCoords[j] == tCoords[i]:
220                    result[i] = data[j]
221                    j += 1
222                else:
223                    result[i] = self.UnscaledNoDataValue
224                i += 1
225
226        # Return successfully.
227
228        return result, self.UnscaledNoDataValue
229
230    @classmethod
231    def CreateArcGISRasters(cls, variableName,
232                            outputWorkspace, mode=u'add', rasterNameExpressions=['%(VariableName)s', '%%Y', '%(VariableName)s_%%Y%%j.img'],
233                            spatialExtent=None, linearUnit=u'Degrees', startDate=None, endDate=None,
234                            timeout=600, cacheDirectory=None,
235                            calculateStatistics=True, buildPyramids=False):
236        cls.__doc__.Obj.ValidateMethodInvocation()
237
238        # Construct a HYCOMGOMl0043D and clip it if requested.
239
240        if startDate is not None:
241            startYear = startDate.year
242        else:
243            startYear = None
244
245        if endDate is not None:
246            endYear = endDate.year
247        else:
248            endYear = None
249
250        grid = HYCOMGOMl0043D(variableName, startYear=startYear, endYear=endYear, timeout=timeout, cacheDirectory=cacheDirectory)
251
252        xMin, yMin, xMax, yMax = None, None, None, None
253        if spatialExtent is not None:
254            from GeoEco.Types import EnvelopeTypeMetadata
255            xMin, yMin, xMax, yMax = EnvelopeTypeMetadata.ParseFromArcGISString(spatialExtent)
256
257        # TODO: Project the spatialExtent, if necessary.
258
259        cls._LogWarning(_(u'The HYCOM OPeNDAP server often requires five to ten minutes to return the first time slice. Please be patient. This tool cannot be cancelled until the first one is returned. After the first one is returned, the rest will go much faster and you will be able to cancel the tool, if desired. If this tool fails with to a timeout error, increase the timeout value and try again.'))
260
261        if spatialExtent is not None or startDate is not None or endDate is not None:
262            grid = ClippedGrid(grid, u'Map coordinates', xMin=xMin, xMax=xMax, yMin=yMin, yMax=yMax, tMin=startDate, tMax=endDate)
263
264        # Construct an ArcGISWorkspace instance and import time slices
265        # from the HYCOMGOMl0043D instance.
266
267        from GeoEco.Datasets.ArcGIS import ArcGISWorkspace, ArcGISRaster
268
269        workspace = ArcGISWorkspace(outputWorkspace,
270                                    ArcGISRaster,
271                                    pathCreationExpressions=rasterNameExpressions,
272                                    cacheTree=True,
273                                    queryableAttributes=(QueryableAttribute(u'VariableName', _(u'Variable'), UnicodeStringTypeMetadata(allowedValues=[u'emp', u'mld', u'mlp', u'qtot', u'ssh', u'surface_salinity_trend', u'surface_temperature_trend'], makeLowercase=True)),
274                                                         QueryableAttribute(u'DateTime', _(u'Date'), DateTimeTypeMetadata())))
275
276        workspace.ImportDatasets(GridSliceCollection(grid, tQACoordType=u'center').QueryDatasets(), mode, calculateStatistics=calculateStatistics, buildPyramids=buildPyramids)
277
278        # Return successfully.
279
280        return outputWorkspace
281
282
283class _HYCOMGridGOMl0044D(OPeNDAPGrid):
284    __doc__ = DynamicDocString()
285
286    def __init__(self, url, variableName, timeout, cacheDirectory):
287        self._CachedTCenterCoords = None
288        super(_HYCOMGridGOMl0044D, self).__init__(OPeNDAPURL(url, timeout=timeout, cacheDirectory=cacheDirectory),
289                                                    variableName,
290                                                    'Grid',
291                                                    lazyPropertyValues={'SpatialReference': Dataset.ConvertSpatialReference('proj4', '+proj=merc +ellps=sphere +a=6371001 +b=6371001', 'obj'),
292                                                                        'Dimensions': 'tzyx',
293                                                                        'CoordDependencies': (None, None, None, None),
294                                                                        'CoordIncrements': (None, None, 4447.7949713872476, 4447.7949713872476),        # t increment is None because, sadly, HYCOM omits slices when their system occasionally fails to generate data for a day
295                                                                        'TCornerCoordType': 'center',
296                                                                        'PhysicalDimensions': 'tzyx',
297                                                                        'PhysicalDimensionsFlipped': (False, False, False, False),
298                                                                        'UnscaledDataType': 'float32',
299                                                                        'UnscaledNoDataValue': 1.2676506002282294e+030,
300                                                                        'ScalingFunction': None})
301       
302    def _GetLazyPropertyPhysicalValue(self, name):
303        if name == 'CornerCoords':
304            return (self._GetCoords('t', 0, [0], [0], -0.5), 0.0, 2045985.6431758059, -10897097.679898757)       # Center of lower-left cell, in degrees: 98.0 W, 18.091648101806641 N
305        return super(_HYCOMGridGOMl0044D, self)._GetLazyPropertyPhysicalValue(name)
306
307    def _GetCoords(self, coord, coordNum, slices, sliceDims, fixedIncrementOffset):
308        if coord not in ['t', 'z']:
309            raise RuntimeError(_('_HYCOMGridGOMl0044D._GetCoords() called with coord == \'%(coord)s\'. This should never happen. Please contact the author of this tool for assistance.') % {u'coord': coord})
310
311        if coord == 't':
312            if self._CachedTCenterCoords is None:
313                import numpy
314                self._CachedTCenterCoords = numpy.array(map(lambda days: datetime.timedelta(days) + datetime.datetime(1900, 12, 31), list(self._GetOPeNDAPVariable()['MT'][:])), dtype='object')
315            if slices is None:
316                result = self._CachedTCenterCoords.copy()
317            else:
318                result = self._CachedTCenterCoords.__getitem__(*slices)
319            if fixedIncrementOffset != 0:
320                result += datetime.timedelta(fixedIncrementOffset)
321            return result
322
323        zCoords = [0.0, 5.0, 10.0, 15.0, 20.0, 25.0, 30.0, 40.0, 50.0, 60.0, 70.0, 80.0, 90.0, 100.0, 125.0, 150.0, 200.0, 250.0, 300.0, 400.0, 500.0, 600.0, 700.0, 800.0, 900.0, 1000.0, 1100.0, 1200.0, 1300.0, 1400.0, 1500.0, 1750.0, 2000.0, 2500.0, 3000.0, 3500.0, 4000.0, 4500.0, 5000.0, 5500.0]
324        if fixedIncrementOffset == -0.5:
325            zCoords = [0.0] + map(lambda a, b: (a+b)/2., zCoords[:-1], zCoords[1:])
326        elif fixedIncrementOffset == 0.5:
327            zCoords = map(lambda a, b: (a+b)/2., zCoords[:-1], zCoords[1:]) + [11000.0]
328        return numpy.array(zCoords)
329
330
331class HYCOMGOMl0044D(Grid):
332    __doc__ = DynamicDocString()
333
334    def _GetVariableName(self):
335        return self._VariableName
336
337    VariableName = property(_GetVariableName, doc=DynamicDocString())
338
339    def _GetStartYear(self):
340        return self._StartYear
341
342    StartYear = property(_GetStartYear, doc=DynamicDocString())
343
344    def _GetEndYear(self):
345        return self._EndYear
346
347    EndYear = property(_GetEndYear, doc=DynamicDocString())
348
349    def __init__(self, variableName, startYear=None, endYear=None, timeout=600, cacheDirectory=None):
350        self.__doc__.Obj.ValidateMethodInvocation()
351
352        # Perform additional validation
353
354        if startYear is None:
355            startYear = 2003
356        elif startYear > (datetime.datetime.now() + datetime.timedelta(5)).year:
357            raise ValueError(_(u'The start year must be less than or equal to %(max)i.') % {u'max': (datetime.datetime.now() + datetime.timedelta(5)).year})
358
359        if endYear is not None and endYear < startYear:
360            raise ValueError(_(u'The end year must be greater than or equal to the start year. If the start year is not specified, the end year must be greater than or equal to 2003.'))
361
362        # Initialize our properties.
363
364        self._VariableName = variableName
365        self._StartYear = startYear
366        self._EndYear = endYear
367        self._Timeout = timeout
368        self._CacheDirectory = cacheDirectory
369        self._DisplayName = _(u'%(name)s grid of the HYCOM + NCODA Gulf of Mexico 1/25 degree Analysis (GOMl0.04) aggregated OPeNDAP datasets') % {u'name': variableName}
370        self._OpenURL = None
371        self._OpenGrid = None
372
373        # Initialize the base class.
374
375        super(HYCOMGOMl0044D, self).__init__(queryableAttributes=(QueryableAttribute(u'VariableName', _(u'Dataset variable'), UnicodeStringTypeMetadata(allowedValues=[u'salinity', u'temperature', u'u', u'v', u'w'], makeLowercase=True)),),
376                                             queryableAttributeValues={u'VariableName': variableName},
377                                             lazyPropertyValues={'SpatialReference': Dataset.ConvertSpatialReference('proj4', '+proj=merc +ellps=sphere +a=6371001 +b=6371001', 'obj'),
378                                                                 'Dimensions': u'tzyx',
379                                                                 'CoordDependencies': (None, None, None, None),
380                                                                 'CoordIncrements': (1.0, None, 4447.7949713872476, 4447.7949713872476),
381                                                                 'TIncrementUnit': u'day',
382                                                                 'TSemiRegularity': None,
383                                                                 'TCountPerSemiRegularPeriod': None,
384                                                                 'TCornerCoordType': u'center',
385                                                                 'CornerCoords': (datetime.datetime(startYear, 1, 1), 0.0, 2045985.6431758059, -10897097.679898757),       # Center of lower-left cell, in degrees: 98.0 W, 18.091648101806641 N
386                                                                 'PhysicalDimensions': u'txyx',
387                                                                 'PhysicalDimensionsFlipped': (False, False, False, False),
388                                                                 'UnscaledDataType': u'float32',
389                                                                 'UnscaledNoDataValue': 1.2676506002282294e+030,
390                                                                 'ScalingFunction': None})
391
392    def _GetDisplayName(self):
393        return self._DisplayName
394       
395    def _GetLazyPropertyPhysicalValue(self, name):
396
397        # The only property that we can retrieve here is the shape.
398        # For the t axis, add the number of days in the years leading
399        # up to the final year to the number of days available from
400        # HYCOM in the final year. For the x and y axes, just use
401        # hardcoded values.
402
403        if name == 'Shape':
404            if self._EndYear is not None and self._EndYear < datetime.datetime.now().year:
405                return ((datetime.datetime(self._EndYear + 1, 1, 1) - datetime.datetime(self._StartYear, 1, 1)).days, 40, 385, 541)
406
407            endYearGrid = _HYCOMGridGOMl0044D('http://tds.hycom.org/thredds/dodsC/GOMl0.04/expt_30.1/%i' % datetime.datetime.now().year, self._VariableName, self._Timeout, self._CacheDirectory)
408            endDay = endYearGrid.CenterCoords['t', -1]
409           
410            if endDay.month == 12 and endDay.day == 31:
411                endYearGrid = _HYCOMGridGOMl0044D('http://tds.hycom.org/thredds/dodsC/GOMl0.04/expt_30.1/%i' % datetime.datetime.now().year + 1, self._VariableName, self._Timeout, self._CacheDirectory)
412                endDay = endYearGrid.CenterCoords['t', -1]
413
414            return ((endDay - datetime.datetime(self._StartYear, 1, 1)).days + 1, 40, 385, 541)
415
416        raise AttributeError(_(u'\'%(class)s\' object has no lazy property named \'%(name)s\'') % {u'class': self.__class__.__name__, u'name': name})
417
418    def _GetCoords(self, coord, coordNum, slices, sliceDims, fixedIncrementOffset):
419        if coord == 'z':
420            raise RuntimeError(_('HYCOMGOMl0044D._GetCoords() called with coord == \'%(coord)s\'. This should never happen. Please contact the author of this tool for assistance.') % {u'coord': coord})
421        zCoords = [0.0, 5.0, 10.0, 15.0, 20.0, 25.0, 30.0, 40.0, 50.0, 60.0, 70.0, 80.0, 90.0, 100.0, 125.0, 150.0, 200.0, 250.0, 300.0, 400.0, 500.0, 600.0, 700.0, 800.0, 900.0, 1000.0, 1100.0, 1200.0, 1300.0, 1400.0, 1500.0, 1750.0, 2000.0, 2500.0, 3000.0, 3500.0, 4000.0, 4500.0, 5000.0, 5500.0]
422        if fixedIncrementOffset == -0.5:
423            zCoords = [0.0] + map(lambda a, b: (a+b)/2., zCoords[:-1], zCoords[1:])
424        elif fixedIncrementOffset == 0.5:
425            zCoords = map(lambda a, b: (a+b)/2., zCoords[:-1], zCoords[1:]) + [11000.0]
426        return numpy.array(zCoords)
427
428    def _ReadNumpyArray(self, sliceList):
429
430        # For many OPeNDAP datasets, we would be able to request the
431        # entire 4D slab directly. This won't work for the HYCOM
432        # GOMl0.04 dataset, for two reasons: 1) The dataset is split
433        # OPeNDAP URLs for each year, and 2) HYCOM omits slices when
434        # their system occasionally fails to generate data for a day,
435        # so most years do not have a full 365 (or 366) slices. To
436        # deal with this, we have to loop over the requested range of
437        # time indices and issue OPeNDAP requests to the proper URLs
438        # and per-URL time indices.
439        #
440        # First, allocate the array we will return. We'll populate
441        # this as we go along. (I prefer this approach rather than
442        # growing an array through concatenation because it avoids
443        # repeatedly allocating and copying memory.)
444
445        import numpy
446        result = numpy.zeros((sliceList[0].stop - sliceList[0].start, sliceList[1].stop - sliceList[1].start, sliceList[2].stop - sliceList[2].start, sliceList[3].stop - sliceList[3].start), dtype=str(self.UnscaledDataType))
447
448        # Loop over the requested t indices, populating the result
449        # array.
450
451        i = 0
452        tCoords = self.CenterCoords['t', sliceList[0]]
453       
454        while i < len(tCoords):
455
456            # Open the _HYCOMGridGOMl0044D for the next block of t
457            # coordinates. These grids are 1 year long, except in 2010
458            # when HYCOM switched to an improved configuration after
459            # five months.
460
461            if tCoords[i] < datetime.datetime(2010, 6, 1):
462                url = 'http://tds.hycom.org/thredds/dodsC/GOMl0.04/expt_20.1/%i' % tCoords[i].year
463            else:
464                url = 'http://tds.hycom.org/thredds/dodsC/GOMl0.04/expt_30.1/%i' % tCoords[i].year
465
466            if self._OpenURL != url:
467                self._OpenGrid = _HYCOMGridGOMl0044D(url, self._VariableName, self._Timeout, self._CacheDirectory)
468                self._OpenURL = url
469
470            if tCoords[i] >= datetime.datetime(2010, 1, 1) and tCoords[i] <= datetime.datetime(2010, 5, 31):
471                lastDayOfDataset = datetime.datetime(2010, 5, 31)
472            else:
473                lastDayOfDataset = datetime.datetime(tCoords[i].year, 12, 31)
474
475            # Read the necessary data from this grid as one 4D slab.
476
477            import bisect
478
479            gridTStart = bisect.bisect_left(self._OpenGrid.CenterCoords['t'].tolist(), tCoords[i])
480            gridTStop = bisect.bisect_right(self._OpenGrid.CenterCoords['t'].tolist(), tCoords[-1])
481            gridTCoords = self._OpenGrid.CenterCoords['t', gridTStart:gridTStop]
482            data = self._OpenGrid.UnscaledData.__getitem__((slice(gridTStart, gridTStop), sliceList[1], sliceList[2], sliceList[3]))
483
484            # Iterate through the t indices, copying out time slices
485            # when they are available, otherwise setting slices to the
486            # UnscaledNoDataValue.
487
488            j = 0
489
490            while i < len(tCoords) and tCoords[i] <= lastDayOfDataset:
491                if j < len(gridTCoords) and gridTCoords[j] == tCoords[i]:
492                    result[i] = data[j]
493                    j += 1
494                else:
495                    result[i] = self.UnscaledNoDataValue
496                i += 1
497
498        # Return successfully.
499
500        return result, self.UnscaledNoDataValue
501
502    @classmethod
503    def CreateArcGISRasters(cls, variableName,
504                            outputWorkspace, mode=u'add', rasterNameExpressions=['%(VariableName)s', '%%Y', 'Depth_%(Depth)04.0fm', '%(VariableName)s_%%Y%%j_%(Depth)04.0fm.img'],
505                            spatialExtent=None, linearUnit=u'Degrees', minDepth=None, maxDepth=None, startDate=None, endDate=None,
506                            timeout=600, cacheDirectory=None,
507                            calculateStatistics=True, buildPyramids=False):
508        cls.__doc__.Obj.ValidateMethodInvocation()
509
510        # Construct a HYCOMGOMl0044D and clip it if requested.
511
512        if startDate is not None:
513            startYear = startDate.year
514        else:
515            startYear = None
516
517        if endDate is not None:
518            endYear = endDate.year
519        else:
520            endYear = None
521
522        grid = HYCOMGOMl0044D(variableName, startYear=startYear, endYear=endYear, timeout=timeout, cacheDirectory=cacheDirectory)
523
524        xMin, yMin, xMax, yMax = None, None, None, None
525        if spatialExtent is not None:
526            from GeoEco.Types import EnvelopeTypeMetadata
527            xMin, yMin, xMax, yMax = EnvelopeTypeMetadata.ParseFromArcGISString(spatialExtent)
528
529        # TODO: Project the spatialExtent, if necessary.
530
531        cls._LogWarning(_(u'The HYCOM OPeNDAP server often requires five to ten minutes to return the first time slice. Please be patient. This tool cannot be cancelled until the first one is returned. After the first one is returned, the rest will go much faster and you will be able to cancel the tool, if desired. If this tool fails with to a timeout error, increase the timeout value and try again.'))
532
533        if spatialExtent is not None or minDepth is not None or maxDepth is not None or startDate is not None or endDate is not None:
534            grid = ClippedGrid(grid, u'Map coordinates', xMin=xMin, xMax=xMax, yMin=yMin, yMax=yMax, zMin=minDepth, zMax=maxDepth, tMin=startDate, tMax=endDate)
535
536        # Construct an ArcGISWorkspace instance and import time slices
537        # from the HYCOMGOMl0044D instance.
538
539        from GeoEco.Datasets.ArcGIS import ArcGISWorkspace, ArcGISRaster
540
541        workspace = ArcGISWorkspace(outputWorkspace,
542                                    ArcGISRaster,
543                                    pathCreationExpressions=rasterNameExpressions,
544                                    cacheTree=True,
545                                    queryableAttributes=(QueryableAttribute(u'VariableName', _(u'Variable'), UnicodeStringTypeMetadata(allowedValues=[u'salinity', u'temperature', u'u', u'v', u'w'], makeLowercase=True)),
546                                                         QueryableAttribute(u'DateTime', _(u'Date'), DateTimeTypeMetadata()),
547                                                         QueryableAttribute(u'Depth', _(u'Depth'), FloatTypeMetadata())))
548
549        workspace.ImportDatasets(GridSliceCollection(grid, tQACoordType=u'center').QueryDatasets(), mode, calculateStatistics=calculateStatistics, buildPyramids=buildPyramids)
550
551        # Return successfully.
552
553        return outputWorkspace
554
555
556###############################################################################
557# Metadata: module
558###############################################################################
559
560from GeoEco.ArcGIS import ArcGISDependency
561from GeoEco.Dependencies import PythonAggregatedModuleDependency
562from GeoEco.Datasets.ArcGIS import _UseUnscaledDataDescription, _CalculateStatisticsDescription, _BuildRATDescription, _BuildPyramidsDescription
563from GeoEco.Metadata import *
564from GeoEco.Types import *
565
566AddModuleMetadata(shortDescription=_(u'Grids representing HYCOM datasets.'))    # TODO: Better description
567
568###############################################################################
569# Metadata: _HYCOMGridGOMl0043D class
570###############################################################################
571
572AddClassMetadata(_HYCOMGridGOMl0043D,
573    shortDescription=_(u'TODO: Description.'))
574
575# TODO: Add metadata
576
577###############################################################################
578# Metadata: HYCOMGOMl0043D class
579###############################################################################
580
581AddClassMetadata(HYCOMGOMl0043D,
582    shortDescription=_(u'TODO: Description.'))
583
584# Constructor
585
586AddMethodMetadata(HYCOMGOMl0043D.__init__,
587    shortDescription=_(u'Constructs a new HYCOMGOMl0043D instance.'),
588    isExposedToPythonCallers=True,
589    dependencies=[PythonAggregatedModuleDependency('numpy')])
590
591AddArgumentMetadata(HYCOMGOMl0043D.__init__, u'self',
592    typeMetadata=ClassInstanceTypeMetadata(cls=HYCOMGOMl0043D),
593    description=_(u'HYCOMGOMl0043D instance.'))
594
595AddArgumentMetadata(HYCOMGOMl0043D.__init__, u'variableName',
596    typeMetadata=UnicodeStringTypeMetadata(allowedValues=[u'emp', u'mld', u'mlp', u'qtot', u'ssh', u'surface_salinity_trend', u'surface_temperature_trend'], makeLowercase=True),
597    description=_(u"""TODO: Description."""),
598    arcGISDisplayName=_(u'Dataset variable'))
599
600AddArgumentMetadata(HYCOMGOMl0043D.__init__, u'startYear',
601    typeMetadata=IntegerTypeMetadata(canBeNone=True, minValue=2003),
602    description=_(u"""TODO: Description."""))
603
604AddArgumentMetadata(HYCOMGOMl0043D.__init__, u'endYear',
605    typeMetadata=IntegerTypeMetadata(canBeNone=True),
606    description=_(u"""TODO: Description."""))
607
608CopyArgumentMetadata(THREDDSCatalog.__init__, u'timeout', HYCOMGOMl0043D.__init__, u'timeout')
609CopyArgumentMetadata(THREDDSCatalog.__init__, u'cacheDirectory', HYCOMGOMl0043D.__init__, u'cacheDirectory')
610
611AddResultMetadata(HYCOMGOMl0043D.__init__, u'grid',
612    typeMetadata=ClassInstanceTypeMetadata(cls=HYCOMGOMl0043D),
613    description=_(u'HYCOMGOMl0043D instance.'))
614
615# Public method: HYCOMGOMl0043D.CreateArcGISRasters
616
617AddMethodMetadata(HYCOMGOMl0043D.CreateArcGISRasters,
618    shortDescription=_(u'Downloads a HYCOM GOMl0.04 surface variable and creates ArcGIS rasters.'),
619    isExposedByCOM=True,
620    isExposedAsArcGISTool=True,
621    arcGISDisplayName=_(u'Download HYCOM GOMl0.04 Surface Variable to ArcGIS Rasters'),
622    arcGISToolCategory=_(u'Data Products\\HYCOM Consortium\\HYCOM + NCODA Gulf of Mexico 1/25 Degree Analysis (GLMl0.04)'),
623    dependencies=[ArcGISDependency(9, 1), PythonAggregatedModuleDependency('numpy')])
624
625AddArgumentMetadata(HYCOMGOMl0043D.CreateArcGISRasters, u'cls',
626    typeMetadata=ClassOrClassInstanceTypeMetadata(cls=HYCOMGOMl0043D),
627    description=_(u'HYCOMGOMl0043D class or instance.'))
628
629CopyArgumentMetadata(HYCOMGOMl0043D.__init__, u'variableName', HYCOMGOMl0043D.CreateArcGISRasters, u'variableName')
630
631AddArgumentMetadata(HYCOMGOMl0043D.CreateArcGISRasters, u'outputWorkspace',       # TODO: Centralize descriptiont text
632    typeMetadata=ArcGISWorkspaceTypeMetadata(createParentDirectories=True),
633    description=_(
634u"""Directory or geodatabase to receive the rasters.
635
636Unless you have a specific reason to store the rasters in a
637geodatabase, we recommend you store them in a directory because it
638will be much faster and allows the rasters to be organized in a tree.
639If you do store the rasters in a geodatabase, you must change the
640Raster Name Expressions parameter; see below for more
641information."""),
642    arcGISDisplayName=_(u'Output workspace'))
643
644AddArgumentMetadata(HYCOMGOMl0043D.CreateArcGISRasters, u'mode',
645    typeMetadata=UnicodeStringTypeMetadata(allowedValues=[u'Add', u'Replace'], makeLowercase=True),
646    description=_(
647u"""Overwrite mode, one of:
648
649* Add - create rasters that do not exist and skip those that already
650  exist. This is the default.
651
652* Replace - create rasters that do not exist and overwrite those that
653  already exist.
654
655'Add' is appropriate when working with HYCOM data older than five days
656from the current date. When working with newer data, consider using
657'Replace'. Each day, HYCOM provides a five day forecast and five day
658hindcast from the current date. Every day, all of the data between
659five days into the past and five days into the future are revised by
660HYCOM using the latest readings assimilated from buoys, satellites,
661and other sensors. By using 'Replace', you will be sure to overwrite
662obsolete data with the latest estimates.
663
664The ArcGIS Overwrite Outputs geoprocessing setting has no effect on
665this tool. If 'Replace' is selected the rasters will be overwritten,
666regardless of the ArcGIS Overwrite Outputs setting."""),
667    arcGISDisplayName=_(u'Overwrite mode'))
668
669AddArgumentMetadata(HYCOMGOMl0043D.CreateArcGISRasters, u'rasterNameExpressions',         # TODO: Centralize descriptiont text
670    typeMetadata=ListTypeMetadata(elementType=UnicodeStringTypeMetadata(), minLength=1),
671    description=_(
672u"""List of expressions specifying how the output rasters should be
673named.
674
675The default expression assumes you are storing rasters in a file
676system directory and creates them in a tree structure with names that
677imitate those used by the original data provider. When storing rasters
678in a directory, the final expression specifies the file name of the
679raster and any preceding expressions specify subdirectories. The
680extension of the final expression determines the output raster format:
681.asc for ArcInfo ASCII Grid, .bmp for BMP, .gif for GIF, .img for an
682ERDAS IMAGINE file, .jpg for JPEG, .jp2 for JPEG 2000, .png for PNG,
683.tif for GeoTIFF, or no extension for ArcInfo Binary Grid. The default
684expression uses .img.
685
686When storing rasters in a geodatabase, you should provide only one
687expression. That expression specifies the raster's name.
688
689Each expression may contain any sequence of characters permitted by
690the output workspace. Each expression may optionally contain one or
691more of the following case-sensitive codes. The tool replaces the
692codes with appropriate values when creating each raster:
693
694* %(VariableName)s - dataset variable represented in the output
695  raster.
696
697* %%Y - four-digit year of the raster.
698
699* %%m - two-digit month of the first day of the raster.
700
701* %%d - two-digit day of the month of the first day of the raster.
702
703* %%j - three-digit day of the year of the first day of the raster.
704"""),
705    arcGISDisplayName=_(u'Raster name expressions'))
706
707AddArgumentMetadata(HYCOMGOMl0043D.CreateArcGISRasters, u'spatialExtent',
708    typeMetadata=EnvelopeTypeMetadata(canBeNone=True),
709    description=_(
710u"""Spatial extent of the output rasters, in the units specified by
711the Linear Units parameter.
712
713If you do not specify a spatial extent, it will default to
714approximately 98 to 76 W, 18 to 32 N. The rasters can only be clipped
715in whole grid cells. The values you provide will be rounded off to the
716closest cell."""),
717    arcGISDisplayName=_(u'Spatial extent'),
718    arcGISCategory=_(u'Spatiotemporal extent'))
719
720AddArgumentMetadata(HYCOMGOMl0043D.CreateArcGISRasters, u'linearUnit',
721    typeMetadata=UnicodeStringTypeMetadata(allowedValues=[u'Degrees', u'Meters'], makeLowercase=True),
722    description=_(
723u"""Specifies the unit of the Spatial Extent parameter, one of:
724
725* Degrees - Decimal degrees.
726
727* Meters - Meters, in the coordinate system of the output rasters.
728"""),
729    arcGISDisplayName=_(u'Linear unit'),
730    arcGISCategory=_(u'Spatiotemporal extent'))
731
732AddArgumentMetadata(HYCOMGOMl0043D.CreateArcGISRasters, u'startDate',
733    typeMetadata=DateTimeTypeMetadata(canBeNone=True),
734    description=_(
735u"""Start date for the rasters to create.
736
737Rasters will be created for images that occur on or after the start
738date and on or before the end date. The HYCOM GOMl0.04 dataset
739provides a five-day forecast; its temporal extent ranges from 1
740January 2003 to today's date plus five days. If you do not specify a
741start date, 1 January 2003 will be used."""),
742    arcGISDisplayName=_(u'Start date'),
743    arcGISCategory=_(u'Spatiotemporal extent'))
744
745AddArgumentMetadata(HYCOMGOMl0043D.CreateArcGISRasters, u'endDate',
746    typeMetadata=DateTimeTypeMetadata(canBeNone=True),
747    description=_(
748u"""End date for the rasters to create.
749
750Rasters will be created for images that occur on or after the start
751date and on or before the end date. The HYCOM GOMl0.04 dataset
752provides a five-day forecast; its temporal extent ranges from 1
753January 2003 to today's date plus five days. If you do not specify an
754end date, the most recent day available will be used (typically
755today's date plus five days)."""),
756    arcGISDisplayName=_(u'End date'),
757    arcGISCategory=_(u'Spatiotemporal extent'))
758
759CopyArgumentMetadata(THREDDSCatalog.__init__, u'timeout', HYCOMGOMl0043D.CreateArcGISRasters, u'timeout')
760CopyArgumentMetadata(THREDDSCatalog.__init__, u'cacheDirectory', HYCOMGOMl0043D.CreateArcGISRasters, u'cacheDirectory')
761
762AddArgumentMetadata(HYCOMGOMl0043D.CreateArcGISRasters, u'calculateStatistics',
763    typeMetadata=BooleanTypeMetadata(),
764    description=_CalculateStatisticsDescription,
765    arcGISDisplayName=_(u'Calculate statistics'),
766    arcGISCategory=_(u'Additional raster processing options'))
767
768AddArgumentMetadata(HYCOMGOMl0043D.CreateArcGISRasters, u'buildPyramids',
769    typeMetadata=BooleanTypeMetadata(),
770    description=_BuildPyramidsDescription,
771    arcGISDisplayName=_(u'Build pyramids'),
772    arcGISCategory=_(u'Additional raster processing options'))
773
774AddResultMetadata(HYCOMGOMl0043D.CreateArcGISRasters, u'updatedOutputWorkspace',
775    typeMetadata=ArcGISWorkspaceTypeMetadata(),
776    description=_(u'Updated output workspace.'),
777    arcGISDisplayName=_(u'Updated output workspace'),
778    arcGISParameterDependencies=[u'outputWorkspace'])
779
780###############################################################################
781# Metadata: _HYCOMGridGOMl0044D class
782###############################################################################
783
784AddClassMetadata(_HYCOMGridGOMl0044D,
785    shortDescription=_(u'TODO: Description.'))
786
787# TODO: Add metadata
788
789###############################################################################
790# Metadata: HYCOMGOMl0044D class
791###############################################################################
792
793AddClassMetadata(HYCOMGOMl0044D,
794    shortDescription=_(u'TODO: Description.'))
795
796# Constructor
797
798AddMethodMetadata(HYCOMGOMl0044D.__init__,
799    shortDescription=_(u'Constructs a new HYCOMGOMl0044D instance.'),
800    isExposedToPythonCallers=True,
801    dependencies=[PythonAggregatedModuleDependency('numpy')])
802
803AddArgumentMetadata(HYCOMGOMl0044D.__init__, u'self',
804    typeMetadata=ClassInstanceTypeMetadata(cls=HYCOMGOMl0044D),
805    description=_(u'HYCOMGOMl0044D instance.'))
806
807AddArgumentMetadata(HYCOMGOMl0044D.__init__, u'variableName',
808    typeMetadata=UnicodeStringTypeMetadata(allowedValues=[u'salinity', u'temperature', u'u', u'v', u'w'], makeLowercase=True),
809    description=_(u"""TODO: Description."""),
810    arcGISDisplayName=_(u'Dataset variable'))
811
812CopyArgumentMetadata(HYCOMGOMl0043D.__init__, u'startYear', HYCOMGOMl0044D.__init__, u'startYear')
813CopyArgumentMetadata(HYCOMGOMl0043D.__init__, u'endYear', HYCOMGOMl0044D.__init__, u'endYear')
814CopyArgumentMetadata(HYCOMGOMl0043D.__init__, u'timeout', HYCOMGOMl0044D.__init__, u'timeout')
815CopyArgumentMetadata(HYCOMGOMl0043D.__init__, u'cacheDirectory', HYCOMGOMl0044D.__init__, u'cacheDirectory')
816
817CopyResultMetadata(HYCOMGOMl0043D.__init__, u'grid', HYCOMGOMl0044D.__init__, u'grid')
818
819# Public method: HYCOMGOMl0044D.CreateArcGISRasters
820
821AddMethodMetadata(HYCOMGOMl0044D.CreateArcGISRasters,
822    shortDescription=_(u'Downloads a HYCOM GOMl0.04 4D variable and creates ArcGIS rasters.'),
823    isExposedByCOM=True,
824    isExposedAsArcGISTool=True,
825    arcGISDisplayName=_(u'Download HYCOM GOMl0.04 4D Variable to ArcGIS Rasters'),
826    arcGISToolCategory=_(u'Data Products\\HYCOM Consortium\\HYCOM + NCODA Gulf of Mexico 1/25 Degree Analysis (GLMl0.04)'),
827    dependencies=[ArcGISDependency(9, 1), PythonAggregatedModuleDependency('numpy')])
828
829AddArgumentMetadata(HYCOMGOMl0044D.CreateArcGISRasters, u'cls',
830    typeMetadata=ClassOrClassInstanceTypeMetadata(cls=HYCOMGOMl0044D),
831    description=_(u'HYCOMGOMl0044D class or instance.'))
832
833CopyArgumentMetadata(HYCOMGOMl0044D.__init__, u'variableName', HYCOMGOMl0044D.CreateArcGISRasters, u'variableName')
834CopyArgumentMetadata(HYCOMGOMl0043D.CreateArcGISRasters, u'outputWorkspace', HYCOMGOMl0044D.CreateArcGISRasters, u'outputWorkspace')
835CopyArgumentMetadata(HYCOMGOMl0043D.CreateArcGISRasters, u'mode', HYCOMGOMl0044D.CreateArcGISRasters, u'mode')
836
837AddArgumentMetadata(HYCOMGOMl0044D.CreateArcGISRasters, u'rasterNameExpressions',
838    typeMetadata=ListTypeMetadata(elementType=UnicodeStringTypeMetadata(), minLength=1),
839    description=_(
840u"""List of expressions specifying how the output rasters should be
841named.
842
843The default expression assumes you are storing rasters in a file
844system directory and creates them in a tree structure with names that
845imitate those used by the original data provider. When storing rasters
846in a directory, the final expression specifies the file name of the
847raster and any preceding expressions specify subdirectories. The
848extension of the final expression determines the output raster format:
849.asc for ArcInfo ASCII Grid, .bmp for BMP, .gif for GIF, .img for an
850ERDAS IMAGINE file, .jpg for JPEG, .jp2 for JPEG 2000, .png for PNG,
851.tif for GeoTIFF, or no extension for ArcInfo Binary Grid. The default
852expression uses .img.
853
854When storing rasters in a geodatabase, you should provide only one
855expression. That expression specifies the raster's name.
856
857Each expression may contain any sequence of characters permitted by
858the output workspace. Each expression may optionally contain one or
859more of the following case-sensitive codes. The tool replaces the
860codes with appropriate values when creating each raster:
861
862* %(VariableName)s - dataset variable represented in the output
863  raster.
864
865* %(Depth)f - depth of the output raster. The f may be preceded by
866  Python's string formatting codes. Please see the Python
867  documentation for more information.
868
869* %%Y - four-digit year of the raster.
870
871* %%m - two-digit month of the first day of the raster.
872
873* %%d - two-digit day of the month of the first day of the raster.
874
875* %%j - three-digit day of the year of the first day of the raster.
876"""),
877    arcGISDisplayName=_(u'Raster name expressions'))
878
879CopyArgumentMetadata(HYCOMGOMl0043D.CreateArcGISRasters, u'spatialExtent', HYCOMGOMl0044D.CreateArcGISRasters, u'spatialExtent')
880CopyArgumentMetadata(HYCOMGOMl0043D.CreateArcGISRasters, u'linearUnit', HYCOMGOMl0044D.CreateArcGISRasters, u'linearUnit')
881
882AddArgumentMetadata(HYCOMGOMl0044D.CreateArcGISRasters, u'minDepth',
883    typeMetadata=FloatTypeMetadata(minValue=0.0, maxValue=5500.0, canBeNone=True),
884    description=_(
885u"""Minimum depth, in meters, for the rasters to create.
886
887The value must be between 0 and 5500, inclusive. Rasters will be
888created for images with depths that are greater than or equal to the
889minimum depth and less than or equal to the maximum depth. If you do
890not specify a minimum depth, 0 will be used."""),
891    arcGISDisplayName=_(u'Minimum depth'),
892    arcGISCategory=_(u'Spatiotemporal extent'))
893
894AddArgumentMetadata(HYCOMGOMl0044D.CreateArcGISRasters, u'maxDepth',
895    typeMetadata=FloatTypeMetadata(minValue=0.0, maxValue=5500.0, canBeNone=True),
896    description=_(
897u"""Maximum depth, in meters, for the rasters to create.
898
899The value must be between 0 and 5500, inclusive. Rasters will be
900created for images with depths that are greater than or equal to the
901minimum depth and less than or equal to the maximum depth. If you do
902not specify a maximum depth, 5500 will be used. This depth encompasses
903the deepest HYCOM layer."""),
904    arcGISDisplayName=_(u'Maximum depth'),
905    arcGISCategory=_(u'Spatiotemporal extent'))
906
907CopyArgumentMetadata(HYCOMGOMl0043D.CreateArcGISRasters, u'startDate', HYCOMGOMl0044D.CreateArcGISRasters, u'startDate')
908CopyArgumentMetadata(HYCOMGOMl0043D.CreateArcGISRasters, u'endDate', HYCOMGOMl0044D.CreateArcGISRasters, u'endDate')
909CopyArgumentMetadata(HYCOMGOMl0043D.CreateArcGISRasters, u'timeout', HYCOMGOMl0044D.CreateArcGISRasters, u'timeout')
910CopyArgumentMetadata(HYCOMGOMl0043D.CreateArcGISRasters, u'cacheDirectory', HYCOMGOMl0044D.CreateArcGISRasters, u'cacheDirectory')
911CopyArgumentMetadata(HYCOMGOMl0043D.CreateArcGISRasters, u'calculateStatistics', HYCOMGOMl0044D.CreateArcGISRasters, u'calculateStatistics')
912CopyArgumentMetadata(HYCOMGOMl0043D.CreateArcGISRasters, u'buildPyramids', HYCOMGOMl0044D.CreateArcGISRasters, u'buildPyramids')
913
914CopyResultMetadata(HYCOMGOMl0043D.CreateArcGISRasters, u'updatedOutputWorkspace', HYCOMGOMl0044D.CreateArcGISRasters, u'updatedOutputWorkspace')
915
916###############################################################################
917# Names exported by this module
918###############################################################################
919
920__all__ = ['HYCOMGOMl0043D', 'HYCOMGOMl0044D']
Note: See TracBrowser for help on using the browser.