Repository: climate
Updated Branches:
  refs/heads/master 9deb819f7 -> fba1ce638


Adding PO.DAAC data source along with the tests


Project: http://git-wip-us.apache.org/repos/asf/climate/repo
Commit: http://git-wip-us.apache.org/repos/asf/climate/commit/116d16f0
Tree: http://git-wip-us.apache.org/repos/asf/climate/tree/116d16f0
Diff: http://git-wip-us.apache.org/repos/asf/climate/diff/116d16f0

Branch: refs/heads/master
Commit: 116d16f039f2f3e3f1c4cfddec447a49afc459aa
Parents: 91ec7f3
Author: Omkar20895 <omkarreddy2...@gmail.com>
Authored: Tue Aug 9 01:06:40 2016 +0530
Committer: Omkar20895 <omkarreddy2...@gmail.com>
Committed: Tue Aug 9 01:06:40 2016 +0530

----------------------------------------------------------------------
 ocw/data_source/podaac.py | 110 +++++++++++++++++++++++++++++++++++++++++
 ocw/tests/test_podaac.py  |  62 +++++++++++++++++++++++
 2 files changed, 172 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/climate/blob/116d16f0/ocw/data_source/podaac.py
----------------------------------------------------------------------
diff --git a/ocw/data_source/podaac.py b/ocw/data_source/podaac.py
new file mode 100644
index 0000000..1eb0195
--- /dev/null
+++ b/ocw/data_source/podaac.py
@@ -0,0 +1,110 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+import sys
+sys.path.append('/Users/omkar/Documents/Git/podaacpy/podaac')
+from podaac_data_source import Podaac 
+import numpy as np
+from ocw.dataset import Dataset
+from netCDF4 import Dataset as netcdf_dataset
+from netcdftime import utime
+import os, urllib
+import xml.etree.ElementTree as ET
+
+
+def _convert_times_to_datetime(time):
+    '''Convert the time object's values to datetime objects
+
+    The time values are stored as some unit since an epoch. These need to be
+    converted into datetime objects for the OCW Dataset object.
+
+    :param time: The time object's values to convert
+    :type time: pydap.model.BaseType
+
+    :returns: list of converted time values as datetime objects
+    '''
+    units = time.units
+    # parse the time units string into a useful object.
+    # NOTE: This assumes a 'standard' calendar. It's possible (likely?) that
+    # users will want to customize this in the future.
+    parsed_time = utime(units)
+    return [parsed_time.num2date(x) for x in time[:]]
+
+
+
+def load_dataset(variable ,datasetId='', datasetShortName='', name=''):
+    '''Loads a Dataset from PODAAC
+
+    :param variable: The name of the variable to read from the dataset.
+    :type variable: :mod:`string`
+
+       :param datasetId: dataset persistent ID. datasetId or \
+        shortName is required for a granule search. Example: \
+        PODAAC-ASOP2-25X01
+    :type datasetId: :mod:`string` 
+
+    :param shortName: the shorter name for a dataset. \
+        Either shortName or datasetId is required for a \
+        granule search. Example: ASCATA-L2-25km
+    :type shortName: :mod:`string`
+
+    :param name: (Optional) A name for the loaded dataset.
+    :type name: :mod:`string`
+
+    :returns: A :class:`dataset.Dataset` containing the dataset pointed to by
+        the OpenDAP URL.
+
+    :raises: ServerError
+    '''
+    #Downloading the dataset using podaac toolkit
+       podaac = Podaac()
+       path = os.path.dirname(os.path.abspath(__file__))
+       granuleName = podaac.extract_l4_granule(datasetId=datasetId, 
shortName=datasetShortName, path=path)
+       path = path+'/'+granuleName
+       d = netcdf_dataset(path, mode='r')
+       dataset = d.variables[variable]
+
+    # By convention, but not by standard, if the dimensions exist, they will 
be in the order:
+    # time (t), altitude (z), latitude (y), longitude (x)
+    # but conventions aren't always followed and all dimensions aren't always 
present so
+    # see if we can make some educated deductions before defaulting to just 
pulling the first three
+    # columns.
+       temp_dimensions = map(lambda x:x.lower(),dataset.dimensions)
+       dataset_dimensions = dataset.dimensions
+       time = dataset_dimensions[temp_dimensions.index('time') if 'time' in 
temp_dimensions else 0]
+       lat = dataset_dimensions[temp_dimensions.index('lat') if 'lat' in 
temp_dimensions else 1]
+       lon = dataset_dimensions[temp_dimensions.index('lon') if 'lon' in 
temp_dimensions else 2]
+
+    # Time is given to us in some units since an epoch. We need to convert
+    # these values to datetime objects. Note that we use the main object's
+    # time object and not the dataset specific reference to it. We need to
+    # grab the 'units' from it and it fails on the dataset specific object.
+       times = np.array(_convert_times_to_datetime(d[time]))
+       lats = np.array(d.variables[lat][:])
+       lons = np.array(d.variables[lon][:])
+       values = np.array(dataset[:])
+       origin = {
+        'source' : 'PO.DAAC',
+        'url' : 'podaac.jpl.nasa.gov/ws'
+    }
+
+    # Removing the downloaded temporary granule before creating the OCW 
dataset. 
+       d.close()
+       path = os.path.join(os.path.dirname(__file__), granuleName)
+       os.remove(path)
+
+       return Dataset(lats, lons, times, values, variable, name=name, 
origin=origin)

http://git-wip-us.apache.org/repos/asf/climate/blob/116d16f0/ocw/tests/test_podaac.py
----------------------------------------------------------------------
diff --git a/ocw/tests/test_podaac.py b/ocw/tests/test_podaac.py
new file mode 100644
index 0000000..d0c2808
--- /dev/null
+++ b/ocw/tests/test_podaac.py
@@ -0,0 +1,62 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+
+import ocw.data_source.podaac as podaac
+import unittest, os
+from ocw.dataset import Dataset
+
+class TestPodaacDataSource(unittest.TestCase):
+       @classmethod
+       def setUpClass(cls):
+               cls.datasetId = 'PODAAC-GHCMC-4FM02'
+               cls.datasetShortName = 'CMC0.2deg-CMC-L4-GLOB-v2.0'
+               cls.variable = 'sea_ice_fraction'
+               cls.name = 'PO.DAAC_test_dataset'
+               cls.file_path = os.path.dirname(os.path.abspath(__file__))
+               cls.format = '.nc'
+               cls.dataset = podaac.load_dataset(cls.variable, cls.datasetId, 
cls.datasetShortName, cls.name)  
+
+       def test_is_dataset(self):
+               self.assertTrue(isinstance(self.dataset, Dataset))
+       
+       def test_dataset_lats(self):
+               self.assertEquals(len(self.dataset.lats), 901)
+
+       def test_dataset_lons(self):
+               self.assertEquals(len(self.dataset.lons), 1800)
+
+       def test_dataset_times(self):
+               self.assertEquals(len(self.dataset.times), 1)
+
+       def test_dataset_values(self):
+               self.assertEquals(len(self.dataset.values),1)
+
+       def test_valid_date_conversion(self):
+        start = dt.datetime(2006, 6, 7, 12)
+        self.assertTrue(start == self.dataset.times[0])
+
+       def test_dataset_origin(self):
+               self.assertEquals(self.dataset.origin['source'], 'PO.DAAC')
+               self.assertEquals(self.dataset.origin['url'], 
'podaac.jpl.nasa.gov/ws')
+
+       def test_custom_name(self):
+               self.assertEquals(self.dataset.name, self.name)
+
+
+if __name__ == '__main__':
+    unittest.main()

Reply via email to