You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@climate.apache.org by jo...@apache.org on 2014/04/05 07:05:25 UTC

[05/16] git commit: CLIMATE-392 - Add lat/lon normalization helper

CLIMATE-392 - Add lat/lon normalization helper

- Add Alex Goodman's helper for normalizing lat/lon grids and ensuring
  that they're monotonically increasing. This is significantly more
  robust than the current shift that is being done on dataset load.


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

Branch: refs/heads/master
Commit: 5c41b95659d25471fa2be51b519d58372d632a8c
Parents: b75633b
Author: Michael Joyce <jo...@apache.org>
Authored: Fri Apr 4 20:50:42 2014 -0700
Committer: Michael Joyce <jo...@apache.org>
Committed: Fri Apr 4 20:50:42 2014 -0700

----------------------------------------------------------------------
 ocw/utils.py | 56 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 56 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/climate/blob/5c41b956/ocw/utils.py
----------------------------------------------------------------------
diff --git a/ocw/utils.py b/ocw/utils.py
index 95cb9e9..671b2f2 100644
--- a/ocw/utils.py
+++ b/ocw/utils.py
@@ -19,6 +19,9 @@
 
 import sys
 import datetime as dt
+import numpy as np
+
+from mpl_toolkits.basemap import shiftgrid
 
 def decode_time_values(dataset, time_var_name):
     ''' Decode NetCDF time values into Python datetime objects.
@@ -157,3 +160,56 @@ def parse_base_time_string(time_format):
         raise ValueError(err)
 
     return time_format.split('since')[1].strip()
+
+def normalize_lat_lon_values(lats, lons, values):
+    ''' Normalize lat/lon values
+
+    Ensure that lat/lon values are withing [-180, 180)/[-90, 90) as well
+    as monotonically increasing. If they aren't they are adjusted accordingly.
+
+    :param lats: A 1D numpy array of lat values.
+    :type lats: Numpy Array
+    :param lons: A 1D numpy array of lon values.
+    :type lons: Numpy Array
+    :param values: A 3D array of data values.
+
+    :returns: A tuple of the form (adjust_lats, adjusted_lons, adjusted_values)
+
+    :raises ValueError: If the lat or lon values are not monotonically increasing.
+    '''
+    # Avoid unnecessary shifting if all lons are higher than 180
+    if lons.min() > 180:
+        lons -= 360
+
+    # Make sure lats and lons are monotonically increasing
+    lats_decreasing = np.diff(lats) < 0
+    lons_decreasing = np.diff(lons) < 0
+
+    # If all values are decreasing then they just need to be reversed
+    lats_reversed, lons_reversed = lats_decreasing.all(), lons_decreasing.all()
+
+    # If the lat values are unsorted then raise an exception
+    if not lats_reversed and lats_decreasing.any():
+        raise ValueError('Latitudes must be monotonically increasing.')
+
+    # Perform same checks now for lons
+    if not lons_reversed and lons_decreasing.any():
+        raise ValueError('Longitudes must be monotonically increasing.')
+
+    # Also check if lons go from [0, 360), and convert to [-180, 180)
+    # if necessary
+    lons_shifted = lons.max() > 180
+    lats_out, lons_out, data_out = lats[:], lons[:], values[:]
+    # Now correct data if latlon grid needs to be shifted
+    if lats_reversed:
+        lats_out = lats_out[::-1]
+        data_out = data_out[..., ::-1, :]
+
+    if lons_reversed:
+        lons_out = lons_out[::-1]
+        data_out = data_out[..., ::-1]
+
+    if lons_shifted:
+        data_out, lons_out = shiftgrid(180, data_out, lons_out, start=False)
+
+    return lats_out, lons_out, data_out