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

Revision 534, 57.9 KB (checked in by jjr8, 3 years ago)

Continuing 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.ParentCollection._Open()
60            self._CachedTCenterCoords = numpy.array(map(lambda days: datetime.timedelta(days) + datetime.datetime(1900, 12, 31), list(self.ParentCollection._PydapDataset['MT'][:])), dtype='object')
61        if slices is None:
62            result = self._CachedTCenterCoords.copy()
63        else:
64            result = self._CachedTCenterCoords.__getitem__(*slices)
65        if fixedIncrementOffset != 0:
66            result += datetime.timedelta(fixedIncrementOffset)
67        return result
68
69
70class HYCOMGOMl0043D(Grid):
71    __doc__ = DynamicDocString()
72
73    def _GetVariableName(self):
74        return self._VariableName
75
76    VariableName = property(_GetVariableName, doc=DynamicDocString())
77
78    def _GetStartYear(self):
79        return self._StartYear
80
81    StartYear = property(_GetStartYear, doc=DynamicDocString())
82
83    def _GetEndYear(self):
84        return self._EndYear
85
86    EndYear = property(_GetEndYear, doc=DynamicDocString())
87
88    def __init__(self, variableName, startYear=None, endYear=None, timeout=600, cacheDirectory=None):
89        self.__doc__.Obj.ValidateMethodInvocation()
90
91        # Perform additional validation
92
93        if startYear is None:
94            startYear = 2003
95        elif startYear > (datetime.datetime.now() + datetime.timedelta(5)).year:
96            raise ValueError(_(u'The start year must be less than or equal to %(max)i.') % {u'max': (datetime.datetime.now() + datetime.timedelta(5)).year})
97
98        if endYear is not None and endYear < startYear:
99            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.'))
100
101        # Initialize our properties.
102
103        self._VariableName = variableName
104        self._StartYear = startYear
105        self._EndYear = endYear
106        self._Timeout = timeout
107        self._CacheDirectory = cacheDirectory
108        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}
109        self._OpenURL = None
110        self._OpenGrid = None
111
112        # Initialize the base class.
113
114        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)),),
115                                             queryableAttributeValues={u'VariableName': variableName},
116                                             lazyPropertyValues={'SpatialReference': Dataset.ConvertSpatialReference('proj4', '+proj=merc +ellps=sphere +a=6371001 +b=6371001', 'obj'),
117                                                                 'Dimensions': u'tyx',
118                                                                 'CoordDependencies': (None, None, None),
119                                                                 'CoordIncrements': (1.0, 4447.7949713872476, 4447.7949713872476),
120                                                                 'TIncrementUnit': u'day',
121                                                                 'TSemiRegularity': None,
122                                                                 'TCountPerSemiRegularPeriod': None,
123                                                                 'TCornerCoordType': u'center',
124                                                                 'CornerCoords': (datetime.datetime(startYear, 1, 1), 2045985.6431758059, -10897097.679898757),       # Center of lower-left cell, in degrees: 98.0 W, 18.091648101806641 N
125                                                                 'PhysicalDimensions': u'tyx',
126                                                                 'PhysicalDimensionsFlipped': (False, False, False),
127                                                                 'UnscaledDataType': u'float32',
128                                                                 'UnscaledNoDataValue': 1.2676506002282294e+030,
129                                                                 'ScalingFunction': None})
130
131    def _GetDisplayName(self):
132        return self._DisplayName
133       
134    def _GetLazyPropertyPhysicalValue(self, name):
135
136        # The only property that we can retrieve here is the shape.
137        # For the t axis, add the number of days in the years leading
138        # up to the final year to the number of days available from
139        # HYCOM in the final year. For the x and y axes, just use
140        # hardcoded values.
141
142        if name == 'Shape':
143            if self._EndYear is not None and self._EndYear < datetime.datetime.now().year:
144                return ((datetime.datetime(self._EndYear + 1, 1, 1) - datetime.datetime(self._StartYear, 1, 1)).days, 385, 541)
145
146            endYearGrid = _HYCOMGridGOMl0043D('http://tds.hycom.org/thredds/dodsC/GOMl0.04/expt_30.1/%i' % datetime.datetime.now().year, self._VariableName, self._Timeout, self._CacheDirectory)
147            endDay = endYearGrid.CenterCoords['t', -1]
148           
149            if endDay.month == 12 and endDay.day == 31:
150                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)
151                endDay = endYearGrid.CenterCoords['t', -1]
152
153            return ((endDay - datetime.datetime(self._StartYear, 1, 1)).days + 1, 385, 541)
154
155        raise AttributeError(_(u'\'%(class)s\' object has no lazy property named \'%(name)s\'') % {u'class': self.__class__.__name__, u'name': name})
156
157    def _ReadNumpyArray(self, sliceList):
158
159        # For many OPeNDAP datasets, we would be able to request the
160        # entire 3D slab directly. This won't work for the HYCOM
161        # GOMl0.04 dataset, for two reasons: 1) The dataset is split
162        # OPeNDAP URLs for each year, and 2) HYCOM omits slices when
163        # their system occasionally fails to generate data for a day,
164        # so most years do not have a full 365 (or 366) slices. To
165        # deal with this, we have to loop over the requested range of
166        # time indices and issue OPeNDAP requests to the proper URLs
167        # and per-URL time indices.
168        #
169        # First, allocate the array we will return. We'll populate
170        # this as we go along. (I prefer this approach rather than
171        # growing an array through concatenation because it avoids
172        # repeatedly allocating and copying memory.)
173
174        import numpy
175        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))
176
177        # Loop over the requested t indices, populating the result
178        # array.
179
180        i = 0
181        tCoords = self.CenterCoords['t', sliceList[0]]
182       
183        while i < len(tCoords):
184
185            # Open the _HYCOMGridGOMl0043D for the next block of t
186            # coordinates. These grids are 1 year long, except in 2010
187            # when HYCOM switched to an improved configuration after
188            # six months.
189
190            if tCoords[i] < datetime.datetime(2010, 7, 1):
191                url = 'http://tds.hycom.org/thredds/dodsC/GOMl0.04/expt_20.1/%i' % tCoords[i].year
192            else:
193                url = 'http://tds.hycom.org/thredds/dodsC/GOMl0.04/expt_30.1/%i' % tCoords[i].year
194
195            if self._OpenURL != url:
196                self._OpenGrid = _HYCOMGridGOMl0043D(url, self._VariableName, self._Timeout, self._CacheDirectory)
197                self._OpenURL = url
198
199            if tCoords[i] >= datetime.datetime(2010, 1, 1) and tCoords[i] <= datetime.datetime(2010, 6, 30):
200                lastDayOfDataset = datetime.datetime(2010, 6, 30)
201            else:
202                lastDayOfDataset = datetime.datetime(tCoords[i].year, 12, 31)
203
204            # Read the necessary data from this grid as one 3D slab.
205
206            import bisect
207
208            gridTStart = bisect.bisect_left(self._OpenGrid.CenterCoords['t'].tolist(), tCoords[i])
209            gridTStop = bisect.bisect_right(self._OpenGrid.CenterCoords['t'].tolist(), tCoords[-1])
210            gridTCoords = self._OpenGrid.CenterCoords['t', gridTStart:gridTStop]
211            data = self._OpenGrid.UnscaledData.__getitem__((slice(gridTStart, gridTStop), sliceList[1], sliceList[2]))
212
213            # Iterate through the t indices, copying out time slices
214            # when they are available, otherwise setting slices to the
215            # UnscaledNoDataValue.
216
217            j = 0
218
219            while i < len(tCoords) and tCoords[i] <= lastDayOfDataset:
220                if j < len(gridTCoords) and gridTCoords[j] == tCoords[i]:
221                    result[i] = data[j]
222                    j += 1
223                else:
224                    result[i] = self.UnscaledNoDataValue
225                i += 1
226
227        # Return successfully.
228
229        return result, self.UnscaledNoDataValue
230
231    @classmethod
232    def CreateArcGISRasters(cls, variableName,
233                            outputWorkspace, mode=u'add', rasterNameExpressions=['%(VariableName)s', '%%Y', '%(VariableName)s_%%Y%%j.img'],
234                            spatialExtent=None, linearUnit=u'Degrees', startDate=None, endDate=None,
235                            timeout=600, cacheDirectory=None,
236                            calculateStatistics=True, buildPyramids=False):
237        cls.__doc__.Obj.ValidateMethodInvocation()
238
239        # Construct a HYCOMGOMl0043D and clip it if requested.
240
241        if startDate is not None:
242            startYear = startDate.year
243        else:
244            startYear = None
245
246        if endDate is not None:
247            endYear = endDate.year
248        else:
249            endYear = None
250
251        grid = HYCOMGOMl0043D(variableName, startYear=startYear, endYear=endYear, timeout=timeout, cacheDirectory=cacheDirectory)
252
253        xMin, yMin, xMax, yMax = None, None, None, None
254        if spatialExtent is not None:
255            from GeoEco.Types import EnvelopeTypeMetadata
256            xMin, yMin, xMax, yMax = EnvelopeTypeMetadata.ParseFromArcGISString(spatialExtent)
257
258            if linearUnit == u'Degrees':
259                osr = cls._osr()
260                transformer = osr.CoordinateTransformation(Dataset.ConvertSpatialReference('proj4', '+proj=latlong +ellps=sphere +a=6371001 +b=6371001', 'obj'), grid.GetSpatialReference('obj'))
261                xMin, yMin = transformer.TransformPoint(xMin, yMin)
262                xMax, yMax = transformer.TransformPoint(xMax, yMax)
263
264        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.'))
265
266        if spatialExtent is not None or startDate is not None or endDate is not None:
267            grid = ClippedGrid(grid, u'Map coordinates', xMin=xMin, xMax=xMax, yMin=yMin, yMax=yMax, tMin=startDate, tMax=endDate)
268
269        # Construct an ArcGISWorkspace instance and import time slices
270        # from the HYCOMGOMl0043D instance.
271
272        from GeoEco.Datasets.ArcGIS import ArcGISWorkspace, ArcGISRaster
273
274        workspace = ArcGISWorkspace(outputWorkspace,
275                                    ArcGISRaster,
276                                    pathCreationExpressions=rasterNameExpressions,
277                                    cacheTree=True,
278                                    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)),
279                                                         QueryableAttribute(u'DateTime', _(u'Date'), DateTimeTypeMetadata())))
280
281        workspace.ImportDatasets(GridSliceCollection(grid, tQACoordType=u'center').QueryDatasets(), mode, calculateStatistics=calculateStatistics, buildPyramids=buildPyramids)
282
283        # Return successfully.
284
285        return outputWorkspace
286
287
288class _HYCOMGridGOMl0044D(OPeNDAPGrid):
289    __doc__ = DynamicDocString()
290
291    def __init__(self, url, variableName, timeout, cacheDirectory):
292        self._CachedTCenterCoords = None
293        super(_HYCOMGridGOMl0044D, self).__init__(OPeNDAPURL(url, timeout=timeout, cacheDirectory=cacheDirectory),
294                                                    variableName,
295                                                    'Grid',
296                                                    lazyPropertyValues={'SpatialReference': Dataset.ConvertSpatialReference('proj4', '+proj=merc +ellps=sphere +a=6371001 +b=6371001', 'obj'),
297                                                                        'Dimensions': 'tzyx',
298                                                                        'CoordDependencies': (None, None, None, None),
299                                                                        '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
300                                                                        'TCornerCoordType': 'center',
301                                                                        'PhysicalDimensions': 'tzyx',
302                                                                        'PhysicalDimensionsFlipped': (False, False, False, False),
303                                                                        'UnscaledDataType': 'float32',
304                                                                        'UnscaledNoDataValue': 1.2676506002282294e+030,
305                                                                        'ScalingFunction': None})
306       
307    def _GetLazyPropertyPhysicalValue(self, name):
308        if name == 'CornerCoords':
309            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
310        return super(_HYCOMGridGOMl0044D, self)._GetLazyPropertyPhysicalValue(name)
311
312    def _GetCoords(self, coord, coordNum, slices, sliceDims, fixedIncrementOffset):
313        if coord not in ['t', 'z']:
314            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})
315
316        import numpy
317
318        if coord == 't':
319            if self._CachedTCenterCoords is None:
320                self.ParentCollection._Open()
321                self._CachedTCenterCoords = numpy.array(map(lambda days: datetime.timedelta(days) + datetime.datetime(1900, 12, 31), list(self.ParentCollection._PydapDataset['MT'][:])), dtype='object')
322            if slices is None:
323                result = self._CachedTCenterCoords.copy()
324            else:
325                result = self._CachedTCenterCoords.__getitem__(*slices)
326            if fixedIncrementOffset != 0:
327                result += datetime.timedelta(fixedIncrementOffset)
328            return result
329
330        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]
331        if fixedIncrementOffset == -0.5:
332            zCoords = [0.0] + map(lambda a, b: (a+b)/2., zCoords[:-1], zCoords[1:])
333        elif fixedIncrementOffset == 0.5:
334            zCoords = map(lambda a, b: (a+b)/2., zCoords[:-1], zCoords[1:]) + [11000.0]
335        if slices is None:
336            return numpy.array(zCoords)
337        return numpy.array(zCoords).__getitem__(*slices)
338
339
340class HYCOMGOMl0044D(Grid):
341    __doc__ = DynamicDocString()
342
343    def _GetVariableName(self):
344        return self._VariableName
345
346    VariableName = property(_GetVariableName, doc=DynamicDocString())
347
348    def _GetStartYear(self):
349        return self._StartYear
350
351    StartYear = property(_GetStartYear, doc=DynamicDocString())
352
353    def _GetEndYear(self):
354        return self._EndYear
355
356    EndYear = property(_GetEndYear, doc=DynamicDocString())
357
358    def __init__(self, variableName, startYear=None, endYear=None, timeout=600, cacheDirectory=None):
359        self.__doc__.Obj.ValidateMethodInvocation()
360
361        # Perform additional validation
362
363        if startYear is None:
364            startYear = 2003
365        elif startYear > (datetime.datetime.now() + datetime.timedelta(5)).year:
366            raise ValueError(_(u'The start year must be less than or equal to %(max)i.') % {u'max': (datetime.datetime.now() + datetime.timedelta(5)).year})
367
368        if endYear is not None and endYear < startYear:
369            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.'))
370
371        # Initialize our properties.
372
373        self._VariableName = variableName
374        self._StartYear = startYear
375        self._EndYear = endYear
376        self._Timeout = timeout
377        self._CacheDirectory = cacheDirectory
378        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}
379        self._OpenURL = None
380        self._OpenGrid = None
381
382        # Initialize the base class.
383
384        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)),),
385                                             queryableAttributeValues={u'VariableName': variableName},
386                                             lazyPropertyValues={'SpatialReference': Dataset.ConvertSpatialReference('proj4', '+proj=merc +ellps=sphere +a=6371001 +b=6371001', 'obj'),
387                                                                 'Dimensions': u'tzyx',
388                                                                 'CoordDependencies': (None, None, None, None),
389                                                                 'CoordIncrements': (1.0, None, 4447.7949713872476, 4447.7949713872476),
390                                                                 'TIncrementUnit': u'day',
391                                                                 'TSemiRegularity': None,
392                                                                 'TCountPerSemiRegularPeriod': None,
393                                                                 'TCornerCoordType': u'center',
394                                                                 '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
395                                                                 'PhysicalDimensions': u'tzyx',
396                                                                 'PhysicalDimensionsFlipped': (False, False, False, False),
397                                                                 'UnscaledDataType': u'float32',
398                                                                 'UnscaledNoDataValue': 1.2676506002282294e+030,
399                                                                 'ScalingFunction': None})
400
401    def _GetDisplayName(self):
402        return self._DisplayName
403       
404    def _GetLazyPropertyPhysicalValue(self, name):
405
406        # The only property that we can retrieve here is the shape.
407        # For the t axis, add the number of days in the years leading
408        # up to the final year to the number of days available from
409        # HYCOM in the final year. For the x and y axes, just use
410        # hardcoded values.
411
412        if name == 'Shape':
413            if self._EndYear is not None and self._EndYear < datetime.datetime.now().year:
414                return ((datetime.datetime(self._EndYear + 1, 1, 1) - datetime.datetime(self._StartYear, 1, 1)).days, 40, 385, 541)
415
416            endYearGrid = _HYCOMGridGOMl0044D('http://tds.hycom.org/thredds/dodsC/GOMl0.04/expt_30.1/%i' % datetime.datetime.now().year, self._VariableName, self._Timeout, self._CacheDirectory)
417            endDay = endYearGrid.CenterCoords['t', -1]
418           
419            if endDay.month == 12 and endDay.day == 31:
420                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)
421                endDay = endYearGrid.CenterCoords['t', -1]
422
423            return ((endDay - datetime.datetime(self._StartYear, 1, 1)).days + 1, 40, 385, 541)
424
425        raise AttributeError(_(u'\'%(class)s\' object has no lazy property named \'%(name)s\'') % {u'class': self.__class__.__name__, u'name': name})
426
427    def _GetCoords(self, coord, coordNum, slices, sliceDims, fixedIncrementOffset):
428        if coord != 'z':
429            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})
430        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]
431        if fixedIncrementOffset == -0.5:
432            zCoords = [0.0] + map(lambda a, b: (a+b)/2., zCoords[:-1], zCoords[1:])
433        elif fixedIncrementOffset == 0.5:
434            zCoords = map(lambda a, b: (a+b)/2., zCoords[:-1], zCoords[1:]) + [11000.0]
435        import numpy
436        if slices is None:
437            return numpy.array(zCoords)
438        return numpy.array(zCoords).__getitem__(*slices)
439
440    def _ReadNumpyArray(self, sliceList):
441
442        # For many OPeNDAP datasets, we would be able to request the
443        # entire 4D slab directly. This won't work for the HYCOM
444        # GOMl0.04 dataset, for two reasons: 1) The dataset is split
445        # OPeNDAP URLs for each year, and 2) HYCOM omits slices when
446        # their system occasionally fails to generate data for a day,
447        # so most years do not have a full 365 (or 366) slices. To
448        # deal with this, we have to loop over the requested range of
449        # time indices and issue OPeNDAP requests to the proper URLs
450        # and per-URL time indices.
451        #
452        # First, allocate the array we will return. We'll populate
453        # this as we go along. (I prefer this approach rather than
454        # growing an array through concatenation because it avoids
455        # repeatedly allocating and copying memory.)
456
457        import numpy
458        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))
459
460        # Loop over the requested t indices, populating the result
461        # array.
462
463        i = 0
464        tCoords = self.CenterCoords['t', sliceList[0]]
465       
466        while i < len(tCoords):
467
468            # Open the _HYCOMGridGOMl0044D for the next block of t
469            # coordinates. These grids are 1 year long, except in 2010
470            # when HYCOM switched to an improved configuration after
471            # five months.
472
473            if tCoords[i] < datetime.datetime(2010, 7, 1):
474                url = 'http://tds.hycom.org/thredds/dodsC/GOMl0.04/expt_20.1/%i' % tCoords[i].year
475            else:
476                url = 'http://tds.hycom.org/thredds/dodsC/GOMl0.04/expt_30.1/%i' % tCoords[i].year
477
478            if self._OpenURL != url:
479                self._OpenGrid = _HYCOMGridGOMl0044D(url, self._VariableName, self._Timeout, self._CacheDirectory)
480                self._OpenURL = url
481
482            if tCoords[i] >= datetime.datetime(2010, 1, 1) and tCoords[i] <= datetime.datetime(2010, 6, 30):
483                lastDayOfDataset = datetime.datetime(2010, 6, 30)
484            else:
485                lastDayOfDataset = datetime.datetime(tCoords[i].year, 12, 31)
486
487            # Read the necessary data from this grid as one 4D slab.
488
489            import bisect
490
491            gridTStart = bisect.bisect_left(self._OpenGrid.CenterCoords['t'].tolist(), tCoords[i])
492            gridTStop = bisect.bisect_right(self._OpenGrid.CenterCoords['t'].tolist(), tCoords[-1])
493            gridTCoords = self._OpenGrid.CenterCoords['t', gridTStart:gridTStop]
494            data = self._OpenGrid.UnscaledData.__getitem__((slice(gridTStart, gridTStop), sliceList[1], sliceList[2], sliceList[3]))
495
496            # Iterate through the t indices, copying out time slices
497            # when they are available, otherwise setting slices to the
498            # UnscaledNoDataValue.
499
500            j = 0
501
502            while i < len(tCoords) and tCoords[i] <= lastDayOfDataset:
503                if j < len(gridTCoords) and gridTCoords[j] == tCoords[i]:
504                    result[i] = data[j]
505                    j += 1
506                else:
507                    result[i] = self.UnscaledNoDataValue
508                i += 1
509
510        # Return successfully.
511
512        return result, self.UnscaledNoDataValue
513
514    @classmethod
515    def CreateArcGISRasters(cls, variableName,
516                            outputWorkspace, mode=u'add', rasterNameExpressions=['%(VariableName)s', '%%Y', 'Depth_%(Depth)04.0fm', '%(VariableName)s_%%Y%%j_%(Depth)04.0fm.img'],
517                            spatialExtent=None, linearUnit=u'Degrees', minDepth=None, maxDepth=None, startDate=None, endDate=None,
518                            timeout=600, cacheDirectory=None,
519                            calculateStatistics=True, buildPyramids=False):
520        cls.__doc__.Obj.ValidateMethodInvocation()
521
522        # Construct a HYCOMGOMl0044D and clip it if requested.
523
524        if startDate is not None:
525            startYear = startDate.year
526        else:
527            startYear = None
528
529        if endDate is not None:
530            endYear = endDate.year
531        else:
532            endYear = None
533
534        grid = HYCOMGOMl0044D(variableName, startYear=startYear, endYear=endYear, timeout=timeout, cacheDirectory=cacheDirectory)
535
536        xMin, yMin, xMax, yMax = None, None, None, None
537        if spatialExtent is not None:
538            from GeoEco.Types import EnvelopeTypeMetadata
539            xMin, yMin, xMax, yMax = EnvelopeTypeMetadata.ParseFromArcGISString(spatialExtent)
540
541            if linearUnit == u'Degrees':
542                osr = cls._osr()
543                transformer = osr.CoordinateTransformation(Dataset.ConvertSpatialReference('proj4', '+proj=latlong +ellps=sphere +a=6371001 +b=6371001', 'obj'), grid.GetSpatialReference('obj'))
544                xMin, yMin = transformer.TransformPoint(xMin, yMin)
545                xMax, yMax = transformer.TransformPoint(xMax, yMax)
546
547        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.'))
548
549        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:
550            grid = ClippedGrid(grid, u'Map coordinates', xMin=xMin, xMax=xMax, yMin=yMin, yMax=yMax, zMin=minDepth, zMax=maxDepth, tMin=startDate, tMax=endDate)
551
552        # Construct an ArcGISWorkspace instance and import time slices
553        # from the HYCOMGOMl0044D instance.
554
555        from GeoEco.Datasets.ArcGIS import ArcGISWorkspace, ArcGISRaster
556
557        workspace = ArcGISWorkspace(outputWorkspace,
558                                    ArcGISRaster,
559                                    pathCreationExpressions=rasterNameExpressions,
560                                    cacheTree=True,
561                                    queryableAttributes=(QueryableAttribute(u'VariableName', _(u'Variable'), UnicodeStringTypeMetadata(allowedValues=[u'salinity', u'temperature', u'u', u'v', u'w'], makeLowercase=True)),
562                                                         QueryableAttribute(u'DateTime', _(u'Date'), DateTimeTypeMetadata()),
563                                                         QueryableAttribute(u'Depth', _(u'Depth'), FloatTypeMetadata())))
564
565        workspace.ImportDatasets(GridSliceCollection(grid, tQACoordType=u'center', zQACoordType=u'center').QueryDatasets(), mode, calculateStatistics=calculateStatistics, buildPyramids=buildPyramids)
566
567        # Return successfully.
568
569        return outputWorkspace
570
571
572###############################################################################
573# Metadata: module
574###############################################################################
575
576from GeoEco.ArcGIS import ArcGISDependency
577from GeoEco.Dependencies import PythonAggregatedModuleDependency
578from GeoEco.Datasets.ArcGIS import _UseUnscaledDataDescription, _CalculateStatisticsDescription, _BuildRATDescription, _BuildPyramidsDescription
579from GeoEco.Metadata import *
580from GeoEco.Types import *
581
582AddModuleMetadata(shortDescription=_(u'Grids representing HYCOM datasets.'))
583
584###############################################################################
585# Metadata: _HYCOMGridGOMl0043D class
586###############################################################################
587
588AddClassMetadata(_HYCOMGridGOMl0043D,
589    shortDescription=_(u'An OPeNDAPGrid for a 3D variable of a HYCOM GOMl0.04 OPeNDAP URL.')
590    longDescription=_(
591u"""This class is intended for private use within GeoEco and is not
592intended for external callers."""))
593
594###############################################################################
595# Metadata: HYCOMGOMl0043D class
596###############################################################################
597
598_HYCOMGOMl004_LongDescription = _(
599u"""At the time this %(name)s was developed, the
600`HYCOM + NCODA Gulf of Mexico 1/25 Degree Analysis (GLMl0.04) <http://www.hycom.org/dataserver/goml0pt04/>`_
601consisted of two gridded datasets:
602
603* expt_20.1 - The 20.1 experiment running from 1 January 2003 through
604  30 June 2010.
605
606* expt_30.1 - The 30.1 experiment running from 1 July 2010 and running
607  to the present day plus five days.
608
609The datasets have identical spatiotemporal extents and resolutions and
610the same oceanographic variables. This %(name)s treats them as one
611continuous dataset and takes time slices prior to 1 July 2010 from
612expt_20.1 and on or after that date from expt_30.1. (On the HYCOM
613server, the datasets actually overlap slightly, with expt_20.1 ending
614slightly after 30 June 2010 and expt_30.1 starting slightly before 1
615July 2010. The %(name)s ignores the overlapping time slices and
616switches from expt_20.1 to expt_30.1 on 1 July.)
617
618The grids are in Mercator projection based on a sphere with radius
6196371001 m, with square cells approximately 4.5 km on a side. The
620geographic extent is approximately 98 to 76 W, 18 to 32 N. The time
621step is 1 day, with time slices representing the instantaneous
622condition of the ocean estimated at 00:00 UTC on each day.
623
624The HYCOM documentation states that HYCOM provides a five day forecast
625and five day hindcast from the current date, although we have
626regularly observed netCDF files on their servers that suggested this
627window actually extends seven days in both directions. HYCOM revises
628the data within this window daily, using the latest ocean observations
629assimilated from buoys, satellites, and other sensors. Use caution
630when working with time slices close to the current date, as it appears
631that time slices continue to be revised until they are 7 days older
632than the current date.
633
634Occasionally, HYCOM fails to generate data for a time slice,
635presumably due to an outage or other problem in their data processing
636infrastructure. For example, in 2004, HYCOM failed to generate data
637for three of the 366 time slices of that year. Although HYCOM omits
638these time slices from their server, this %(name)s represents them as
639grids filled with the No Data value.
640
641The datasets include both 3D variables (dimensions x, y, and time) and
6424D variables (dimensions x, y, depth, and time). The 4D variables are
643estimated at 40 depth levels: 0, 5, 10, 15, 20, 25, 30, 40, 50, 60,
64470, 80, 90, 100, 125, 150, 200, 250, 300, 400, 500, 600, 700, 800,
645900, 1000, 1100, 1200, 1300, 1400, 1500, 1750, 2000, 2500, 3000, 3500,
6464000, 4500, 5000, and 5500 m.
647
648This %(name)s accesses the HYCOM datasets using the
649`OPeNDAP <http://opendap.org/>`_ protocol, allowing slices of data to
650be retrieved very efficiently. However, during periods of high load,
651the HYCOM OPeNDAP server often requires five to ten minutes to return
652the first slice of data. Please be patient; after the first one is
653returned, the rest will go much faster. During periods of extreme
654load, the tool may fail with a timeout error. If this happens,
655increase the timeout value and try again, or wait until later when the
656server is less busy."""),
657
658AddClassMetadata(HYCOMGOMl0043D,
659    shortDescription=_(u'Represents a HYCOM GOMl0.04 3D variable as a Grid Dataset.'),
660    longDescription=_HYCOMGOMl004_LongDescription % {u'name': 'class'})
661
662# Constructor
663
664AddMethodMetadata(HYCOMGOMl0043D.__init__,
665    shortDescription=_(u'Constructs a new HYCOMGOMl0043D instance.'),
666    isExposedToPythonCallers=True,
667    dependencies=[PythonAggregatedModuleDependency('numpy')])
668
669AddArgumentMetadata(HYCOMGOMl0043D.__init__, u'self',
670    typeMetadata=ClassInstanceTypeMetadata(cls=HYCOMGOMl0043D),
671    description=_(u'HYCOMGOMl0043D instance.'))
672
673AddArgumentMetadata(HYCOMGOMl0043D.__init__, u'variableName',
674    typeMetadata=UnicodeStringTypeMetadata(allowedValues=[u'emp', u'mld', u'mlp', u'qtot', u'ssh', u'surface_salinity_trend', u'surface_temperature_trend'], makeLowercase=True),
675    description=_(
676u"""HYCOM GOMl0.04 3D variable (dimensions x, y, and time), one of:
677
678* emp - Water flux into the ocean, in kg/m2/s.
679
680* mld - Mixed layer thickness, in m, defined as the depth at which the
681  temperature change from the surface temperature is 0.02 degrees C.
682
683* mlp - Mixed layer thickness, in m, defined as the depth at which the
684  pressure change from the surface pressure is 0.03 kg/m3.
685
686* qtot - Surface downward heat flux, in w/m2.
687
688* ssh - Sea surface height, in m, above the HYCOM reference spheroid.
689
690* surface_salinity_trend - Surface salinity trend, in psu/day.
691
692* surface_temperature_trend - Surface temperature trend, in degrees
693  C/day.
694
695Please see the HYCOM documentation for more information about these
696variables."""),
697    arcGISDisplayName=_(u'Dataset variable'))
698
699AddArgumentMetadata(HYCOMGOMl0043D.__init__, u'startYear',
700    typeMetadata=IntegerTypeMetadata(canBeNone=True, minValue=2003),
701    description=_(
702u"""Starting year for this grid. This parameter is optional; if a
703value is not specified, 2003 will be used."""))
704
705AddArgumentMetadata(HYCOMGOMl0043D.__init__, u'endYear',
706    typeMetadata=IntegerTypeMetadata(canBeNone=True),
707u"""Ending year for this grid. This parameter is optional; if a value
708is not specified, the grid will extend to the maximum temporal extent
709of the HYCOM data. If you do not need data for the current year,
710specify an earlier year for this parameter. This will make it
711unnecessary to query the HYCOM server to determine the maximum
712temporal extent."""))
713
714CopyArgumentMetadata(THREDDSCatalog.__init__, u'timeout', HYCOMGOMl0043D.__init__, u'timeout')
715
716AddArgumentMetadata(HYCOMGOMl0043D.__init__, u'cacheDirectory',
717    typeMetadata=DirectoryTypeMetadata(canBeNone=True),
718    description=_(
719u"""Directory to cache OPeNDAP datasets.
720
721A cache directory can dramatically speed up scenarios that involve
722accessing the same subsets the HYCOM data over and over again. When
723OPeNDAP data is requested from the HYCOM server, the cache directory
724will be checked for data that was downloaded and cached during prior
725requests. If cached data exists that can fulfill part of the current
726request, the request will be serviced by reading from cache files
727rather than the OPeNDAP server. If the entire request can be serviced
728from the cache, the OPeNDAP server will not be accessed at all and the
729request will be completed extremely quickly. Any parts of the request
730that cannot be serviced from the cache will be downloaded from the
731OPeNDAP server and added to the cache, speeding up future requests for
732the same data.
733
734If you use a cache directory, be aware of these common pitfalls:
735
736* The HYCOM documentation states that HYCOM provides a five day forecast
737  and five day hindcast from the current date, although we have
738  regularly observed netCDF files on their servers that suggested this
739  window actually extends seven days in both directions. HYCOM revises
740  the data within this time window daily, using the latest ocean
741  observations assimilated from buoys, satellites, and other sensors.
742  We recommend you do not cache data in this time window. The caching
743  algorithm cannot detect whether cached data should be replaced with
744  revised versions available on the server.
745
746* The caching algorithm permits the cache to grow to infinite size and
747  never deletes any cached data. If you access a large amount of data
748  it will all be added to the cache. Be careful that you do not fill
749  up your hard disk. To mitigate this, manually delete the entire
750  cache or selected directories or files within it.
751
752* The caching algorithm stores data in uncompressed files, so that
753  subsets of those files may be quickly accessed. To save space on
754  your hard disk, you can enable compression of the cache directory
755  using the operating system. On Windows, right click on the directory
756  in Windows Explorer, select Properties, click Advanced, and enable
757  "Compress contents to save disk space".
758"""),
759    arcGISDisplayName=_(u'Cache directory'),
760    arcGISCategory=_(u'OPeNDAP options'))
761
762AddResultMetadata(HYCOMGOMl0043D.__init__, u'grid',
763    typeMetadata=ClassInstanceTypeMetadata(cls=HYCOMGOMl0043D),
764    description=_(u'HYCOMGOMl0043D instance.'))
765
766# Public method: HYCOMGOMl0043D.CreateArcGISRasters
767
768AddMethodMetadata(HYCOMGOMl0043D.CreateArcGISRasters,
769    shortDescription=_(u'Downloads a HYCOM GOMl0.04 3D variable and creates ArcGIS rasters.'),
770    longDescription=_HYCOMGOMl004_LongDescription % {u'name': 'tool'})
771    isExposedByCOM=True,
772    isExposedAsArcGISTool=True,
773    arcGISDisplayName=_(u'Download HYCOM GOMl0.04 3D Variable to ArcGIS Rasters'),
774    arcGISToolCategory=_(u'Data Products\\HYCOM Consortium\\HYCOM + NCODA Gulf of Mexico 1/25 Degree Analysis (GLMl0.04)'),
775    dependencies=[ArcGISDependency(9, 1), PythonAggregatedModuleDependency('numpy')])
776
777AddArgumentMetadata(HYCOMGOMl0043D.CreateArcGISRasters, u'cls',
778    typeMetadata=ClassOrClassInstanceTypeMetadata(cls=HYCOMGOMl0043D),
779    description=_(u'HYCOMGOMl0043D class or instance.'))
780
781CopyArgumentMetadata(HYCOMGOMl0043D.__init__, u'variableName', HYCOMGOMl0043D.CreateArcGISRasters, u'variableName')
782
783AddArgumentMetadata(HYCOMGOMl0043D.CreateArcGISRasters, u'outputWorkspace',
784    typeMetadata=ArcGISWorkspaceTypeMetadata(createParentDirectories=True),
785    description=_(
786u"""Directory or geodatabase to receive the rasters.
787
788Unless you have a specific reason to store the rasters in a
789geodatabase, we recommend you store them in a directory because it
790will be much faster and allows the rasters to be organized in a tree.
791If you do store the rasters in a geodatabase, you must change the
792Raster Name Expressions parameter; see below for more
793information."""),
794    arcGISDisplayName=_(u'Output workspace'))
795
796AddArgumentMetadata(HYCOMGOMl0043D.CreateArcGISRasters, u'mode',
797    typeMetadata=UnicodeStringTypeMetadata(allowedValues=[u'Add', u'Replace'], makeLowercase=True),
798    description=_(
799u"""Overwrite mode, one of:
800
801* Add - create rasters that do not exist and skip those that already
802  exist. This is the default.
803
804* Replace - create rasters that do not exist and overwrite those that
805  already exist.
806
807'Add' is appropriate when working with HYCOM data older than one week
808from the current date. When working with newer data, consider using
809'Replace'. The HYCOM documentation states that HYCOM provides a five
810day forecast and five day hindcast from the current date, although we
811have regularly observed netCDF files on their servers that suggested
812this window actually extends seven days in both directions. HYCOM
813revises the data within this window daily, using the latest ocean
814observations assimilated from buoys, satellites, and other sensors.
815Therefore, by using 'Replace' when working with data within this
816window, you will be sure to overwrite obsolete data with the latest
817estimates.
818
819The ArcGIS Overwrite Outputs geoprocessing setting has no effect on
820this tool. If 'Replace' is selected the rasters will be overwritten,
821regardless of the ArcGIS Overwrite Outputs setting."""),
822    arcGISDisplayName=_(u'Overwrite mode'))
823
824AddArgumentMetadata(HYCOMGOMl0043D.CreateArcGISRasters, u'rasterNameExpressions',
825    typeMetadata=ListTypeMetadata(elementType=UnicodeStringTypeMetadata(), minLength=1),
826    description=_(
827u"""List of expressions specifying how the output rasters should be
828named.
829
830The default expression assumes you are storing rasters in a file
831system directory and creates them in a tree structure with names that
832imitate those used by the original data provider. When storing rasters
833in a directory, the final expression specifies the file name of the
834raster and any preceding expressions specify subdirectories. The
835extension of the final expression determines the output raster format:
836.asc for ArcInfo ASCII Grid, .bmp for BMP, .gif for GIF, .img for an
837ERDAS IMAGINE file, .jpg for JPEG, .jp2 for JPEG 2000, .png for PNG,
838.tif for GeoTIFF, or no extension for ArcInfo Binary Grid. The default
839expression uses .img.
840
841When storing rasters in a geodatabase, you should provide only one
842expression. That expression specifies the raster's name.
843
844Each expression may contain any sequence of characters permitted by
845the output workspace. Each expression may optionally contain one or
846more of the following case-sensitive codes. The tool replaces the
847codes with appropriate values when creating each raster:
848
849* %(VariableName)s - dataset variable represented in the output
850  raster.
851
852* %%Y - four-digit year of the raster.
853
854* %%m - two-digit month of the first day of the raster.
855
856* %%d - two-digit day of the month of the first day of the raster.
857
858* %%j - three-digit day of the year of the first day of the raster.
859"""),
860    arcGISDisplayName=_(u'Raster name expressions'))
861
862AddArgumentMetadata(HYCOMGOMl0043D.CreateArcGISRasters, u'spatialExtent',
863    typeMetadata=EnvelopeTypeMetadata(canBeNone=True),
864    description=_(
865u"""Spatial extent of the output rasters, in the units specified by
866the Linear Units parameter.
867
868If you do not specify a spatial extent, it will default to
869approximately 98 to 76 W, 18 to 32 N. The rasters can only be clipped
870in whole grid cells. The values you provide will be rounded off to the
871closest cell."""),
872    arcGISDisplayName=_(u'Spatial extent'),
873    arcGISCategory=_(u'Spatiotemporal extent'))
874
875AddArgumentMetadata(HYCOMGOMl0043D.CreateArcGISRasters, u'linearUnit',
876    typeMetadata=UnicodeStringTypeMetadata(allowedValues=[u'Degrees', u'Meters'], makeLowercase=True),
877    description=_(
878u"""Specifies the unit of the Spatial Extent parameter, one of:
879
880* Degrees - Decimal degrees.
881
882* Meters - Meters, in the coordinate system of the output rasters.
883"""),
884    arcGISDisplayName=_(u'Linear unit'),
885    arcGISCategory=_(u'Spatiotemporal extent'))
886
887AddArgumentMetadata(HYCOMGOMl0043D.CreateArcGISRasters, u'startDate',
888    typeMetadata=DateTimeTypeMetadata(canBeNone=True),
889    description=_(
890u"""Start date for the rasters to create.
891
892Rasters will be created for images that occur on or after the start
893date and on or before the end date. The HYCOM GOMl0.04 dataset
894provides a five-day forecast; its temporal extent ranges from 1
895January 2003 to today's date plus five days. If you do not specify a
896start date, 1 January 2003 will be used."""),
897    arcGISDisplayName=_(u'Start date'),
898    arcGISCategory=_(u'Spatiotemporal extent'))
899
900AddArgumentMetadata(HYCOMGOMl0043D.CreateArcGISRasters, u'endDate',
901    typeMetadata=DateTimeTypeMetadata(canBeNone=True),
902    description=_(
903u"""End date for the rasters to create.
904
905Rasters will be created for images that occur on or after the start
906date and on or before the end date. The HYCOM GOMl0.04 dataset
907provides a five-day forecast; its temporal extent ranges from 1
908January 2003 to today's date plus five days. If you do not specify an
909end date, the most recent day available will be used (typically
910today's date plus five days)."""),
911    arcGISDisplayName=_(u'End date'),
912    arcGISCategory=_(u'Spatiotemporal extent'))
913
914CopyArgumentMetadata(HYCOMGOMl0043D.__init__, u'timeout', HYCOMGOMl0043D.CreateArcGISRasters, u'timeout')
915CopyArgumentMetadata(HYCOMGOMl0043D.__init__, u'cacheDirectory', HYCOMGOMl0043D.CreateArcGISRasters, u'cacheDirectory')
916
917AddArgumentMetadata(HYCOMGOMl0043D.CreateArcGISRasters, u'calculateStatistics',
918    typeMetadata=BooleanTypeMetadata(),
919    description=_CalculateStatisticsDescription,
920    arcGISDisplayName=_(u'Calculate statistics'),
921    arcGISCategory=_(u'Additional raster processing options'))
922
923AddArgumentMetadata(HYCOMGOMl0043D.CreateArcGISRasters, u'buildPyramids',
924    typeMetadata=BooleanTypeMetadata(),
925    description=_BuildPyramidsDescription,
926    arcGISDisplayName=_(u'Build pyramids'),
927    arcGISCategory=_(u'Additional raster processing options'))
928
929AddResultMetadata(HYCOMGOMl0043D.CreateArcGISRasters, u'updatedOutputWorkspace',
930    typeMetadata=ArcGISWorkspaceTypeMetadata(),
931    description=_(u'Updated output workspace.'),
932    arcGISDisplayName=_(u'Updated output workspace'),
933    arcGISParameterDependencies=[u'outputWorkspace'])
934
935###############################################################################
936# Metadata: _HYCOMGridGOMl0044D class
937###############################################################################
938
939AddClassMetadata(_HYCOMGridGOMl0044D,
940    shortDescription=_(u'An OPeNDAPGrid for a 4D variable of a HYCOM GOMl0.04 OPeNDAP URL.')
941    longDescription=_(
942u"""This class is intended for private use within GeoEco and is not
943intended for external callers."""))
944
945###############################################################################
946# Metadata: HYCOMGOMl0044D class
947###############################################################################
948
949AddClassMetadata(HYCOMGOMl0044D,
950    shortDescription=_(u'Represents a HYCOM GOMl0.04 3D variable as a Grid Dataset.'),
951    longDescription=_HYCOMGOMl004_LongDescription % {u'name': 'class'})
952
953# Constructor
954
955AddMethodMetadata(HYCOMGOMl0044D.__init__,
956    shortDescription=_(u'Constructs a new HYCOMGOMl0044D instance.'),
957    isExposedToPythonCallers=True,
958    dependencies=[PythonAggregatedModuleDependency('numpy')])
959
960AddArgumentMetadata(HYCOMGOMl0044D.__init__, u'self',
961    typeMetadata=ClassInstanceTypeMetadata(cls=HYCOMGOMl0044D),
962    description=_(u'HYCOMGOMl0044D instance.'))
963
964AddArgumentMetadata(HYCOMGOMl0044D.__init__, u'variableName',
965    typeMetadata=UnicodeStringTypeMetadata(allowedValues=[u'salinity', u'temperature', u'u', u'v', u'w'], makeLowercase=True),
966    description=_(
967u"""HYCOM GOMl0.04 4D variable (dimensions x, y, depth, and time), one
968of:
969
970* salinity - Sea water salinity, in psu.
971
972* temperature - Sea water potential temperature, in degrees C.
973
974* u - Eastward sea water velocity, in m/s.
975
976* v - Northward sea water velocity, in m/s.
977
978* w - Upward sea water velocity, in m/s.
979
980Please see the HYCOM documentation for more information about these
981variables."""),
982    arcGISDisplayName=_(u'Dataset variable'))
983
984CopyArgumentMetadata(HYCOMGOMl0043D.__init__, u'startYear', HYCOMGOMl0044D.__init__, u'startYear')
985CopyArgumentMetadata(HYCOMGOMl0043D.__init__, u'endYear', HYCOMGOMl0044D.__init__, u'endYear')
986CopyArgumentMetadata(HYCOMGOMl0043D.__init__, u'timeout', HYCOMGOMl0044D.__init__, u'timeout')
987CopyArgumentMetadata(HYCOMGOMl0043D.__init__, u'cacheDirectory', HYCOMGOMl0044D.__init__, u'cacheDirectory')
988
989CopyResultMetadata(HYCOMGOMl0043D.__init__, u'grid', HYCOMGOMl0044D.__init__, u'grid')
990
991# Public method: HYCOMGOMl0044D.CreateArcGISRasters
992
993AddMethodMetadata(HYCOMGOMl0044D.CreateArcGISRasters,
994    shortDescription=_(u'Downloads a HYCOM GOMl0.04 4D variable and creates ArcGIS rasters.'),
995    longDescription=_HYCOMGOMl004_LongDescription % {u'name': 'class'})
996    isExposedByCOM=True,
997    isExposedAsArcGISTool=True,
998    arcGISDisplayName=_(u'Download HYCOM GOMl0.04 4D Variable to ArcGIS Rasters'),
999    arcGISToolCategory=_(u'Data Products\\HYCOM Consortium\\HYCOM + NCODA Gulf of Mexico 1/25 Degree Analysis (GLMl0.04)'),
1000    dependencies=[ArcGISDependency(9, 1), PythonAggregatedModuleDependency('numpy')])
1001
1002AddArgumentMetadata(HYCOMGOMl0044D.CreateArcGISRasters, u'cls',
1003    typeMetadata=ClassOrClassInstanceTypeMetadata(cls=HYCOMGOMl0044D),
1004    description=_(u'HYCOMGOMl0044D class or instance.'))
1005
1006CopyArgumentMetadata(HYCOMGOMl0044D.__init__, u'variableName', HYCOMGOMl0044D.CreateArcGISRasters, u'variableName')
1007CopyArgumentMetadata(HYCOMGOMl0043D.CreateArcGISRasters, u'outputWorkspace', HYCOMGOMl0044D.CreateArcGISRasters, u'outputWorkspace')
1008CopyArgumentMetadata(HYCOMGOMl0043D.CreateArcGISRasters, u'mode', HYCOMGOMl0044D.CreateArcGISRasters, u'mode')
1009
1010AddArgumentMetadata(HYCOMGOMl0044D.CreateArcGISRasters, u'rasterNameExpressions',
1011    typeMetadata=ListTypeMetadata(elementType=UnicodeStringTypeMetadata(), minLength=1),
1012    description=_(
1013u"""List of expressions specifying how the output rasters should be
1014named.
1015
1016The default expression assumes you are storing rasters in a file
1017system directory and creates them in a tree structure with names that
1018imitate those used by the original data provider. When storing rasters
1019in a directory, the final expression specifies the file name of the
1020raster and any preceding expressions specify subdirectories. The
1021extension of the final expression determines the output raster format:
1022.asc for ArcInfo ASCII Grid, .bmp for BMP, .gif for GIF, .img for an
1023ERDAS IMAGINE file, .jpg for JPEG, .jp2 for JPEG 2000, .png for PNG,
1024.tif for GeoTIFF, or no extension for ArcInfo Binary Grid. The default
1025expression uses .img.
1026
1027When storing rasters in a geodatabase, you should provide only one
1028expression. That expression specifies the raster's name.
1029
1030Each expression may contain any sequence of characters permitted by
1031the output workspace. Each expression may optionally contain one or
1032more of the following case-sensitive codes. The tool replaces the
1033codes with appropriate values when creating each raster:
1034
1035* %(VariableName)s - dataset variable represented in the output
1036  raster.
1037
1038* %(Depth)f - depth of the output raster. The f may be preceded by
1039  Python's string formatting codes. Please see the Python
1040  documentation for more information.
1041
1042* %%Y - four-digit year of the raster.
1043
1044* %%m - two-digit month of the first day of the raster.
1045
1046* %%d - two-digit day of the month of the first day of the raster.
1047
1048* %%j - three-digit day of the year of the first day of the raster.
1049"""),
1050    arcGISDisplayName=_(u'Raster name expressions'))
1051
1052CopyArgumentMetadata(HYCOMGOMl0043D.CreateArcGISRasters, u'spatialExtent', HYCOMGOMl0044D.CreateArcGISRasters, u'spatialExtent')
1053CopyArgumentMetadata(HYCOMGOMl0043D.CreateArcGISRasters, u'linearUnit', HYCOMGOMl0044D.CreateArcGISRasters, u'linearUnit')
1054
1055AddArgumentMetadata(HYCOMGOMl0044D.CreateArcGISRasters, u'minDepth',
1056    typeMetadata=FloatTypeMetadata(minValue=0.0, maxValue=5500.0, canBeNone=True),
1057    description=_(
1058u"""Minimum depth, in meters, for the rasters to create.
1059
1060The value must be between 0 and 5500, inclusive. Rasters will be
1061created for images with depths that are greater than or equal to the
1062minimum depth and less than or equal to the maximum depth. If you do
1063not specify a minimum depth, 0 will be used."""),
1064    arcGISDisplayName=_(u'Minimum depth'),
1065    arcGISCategory=_(u'Spatiotemporal extent'))
1066
1067AddArgumentMetadata(HYCOMGOMl0044D.CreateArcGISRasters, u'maxDepth',
1068    typeMetadata=FloatTypeMetadata(minValue=0.0, maxValue=5500.0, canBeNone=True),
1069    description=_(
1070u"""Maximum depth, in meters, for the rasters to create.
1071
1072The value must be between 0 and 5500, inclusive. Rasters will be
1073created for images with depths that are greater than or equal to the
1074minimum depth and less than or equal to the maximum depth. If you do
1075not specify a maximum depth, 5500 will be used. This depth encompasses
1076the deepest HYCOM layer."""),
1077    arcGISDisplayName=_(u'Maximum depth'),
1078    arcGISCategory=_(u'Spatiotemporal extent'))
1079
1080CopyArgumentMetadata(HYCOMGOMl0043D.CreateArcGISRasters, u'startDate', HYCOMGOMl0044D.CreateArcGISRasters, u'startDate')
1081CopyArgumentMetadata(HYCOMGOMl0043D.CreateArcGISRasters, u'endDate', HYCOMGOMl0044D.CreateArcGISRasters, u'endDate')
1082CopyArgumentMetadata(HYCOMGOMl0043D.CreateArcGISRasters, u'timeout', HYCOMGOMl0044D.CreateArcGISRasters, u'timeout')
1083CopyArgumentMetadata(HYCOMGOMl0043D.CreateArcGISRasters, u'cacheDirectory', HYCOMGOMl0044D.CreateArcGISRasters, u'cacheDirectory')
1084CopyArgumentMetadata(HYCOMGOMl0043D.CreateArcGISRasters, u'calculateStatistics', HYCOMGOMl0044D.CreateArcGISRasters, u'calculateStatistics')
1085CopyArgumentMetadata(HYCOMGOMl0043D.CreateArcGISRasters, u'buildPyramids', HYCOMGOMl0044D.CreateArcGISRasters, u'buildPyramids')
1086
1087CopyResultMetadata(HYCOMGOMl0043D.CreateArcGISRasters, u'updatedOutputWorkspace', HYCOMGOMl0044D.CreateArcGISRasters, u'updatedOutputWorkspace')
1088
1089###############################################################################
1090# Names exported by this module
1091###############################################################################
1092
1093__all__ = ['HYCOMGOMl0043D', 'HYCOMGOMl0044D']
Note: See TracBrowser for help on using the browser.