#!/usr/bin/python -tt #======================================================================= # General Documentation """Single-function module. See function docstring for description. """ #----------------------------------------------------------------------- # Additional Documentation # # RCS Revision Code: # $Id: can_use_sphere.py,v 1.1.1.1 2004/02/26 22:53:58 jlin Exp $ # # Modification History: # - 21 Feb 2004: Original by Johnny Lin, Computation Institute, # University of Chicago. Passed passably reasonable tests. # # Notes: # - Written for Python 2.2.2. # - Module docstrings can be tested using the doctest module. To # test, execute "python can_use_sphere.py". Note, in order for # pydoc to test the docstrings correctly, sphere must be installed # on the system you're testing from. # - See import statements for non-built-in packages and modules # required. # # Copyright (c) 2004 by Johnny Lin. For licensing, distribution # conditions, contact information, and additional documentation see # the URL http://www.johnny-lin.com/py_pkgs/gemath/doc/. #======================================================================= #----------------------- Overall Module Imports ------------------------ #- Set module version to package version: import gemath_version __version__ = gemath_version.version del gemath_version #--------------------------- General Function -------------------------- def can_use_sphere(longitude, latitude): """Test if can use sphere package. Calling Sequence: Result = can_use_sphere(longitude, latitude) Note that Result is a 3-element tuple, not a scalar. See the description below for details. Test if the longitude-latitude domain and Python package configur- ation allows use of the NCAR SPHEREPACK 3.0 package. Specifically the function tests: (1) Can you import sphere? (2) Is the longitude vector evenly spaced? (3) Does the longitude vector entirely span the globe, but doesn't repeat? (4) Is the latitude vector gaussian? If not, is it evenly spaced and includes the poles? If the answer to (1) is no, then there's no use to go through the other tests and the function return tuple element [0] is 0. If (2) or (3) is no, return tuple element [0] is 0. If (4) is both not gaussian and not evenly spaced with the poles, return tuple element [0] is 0. Otherwise, return tuple element [0] is 1. Note that (4) uses the latitude checker in the sphere package. Method Arguments: * longitude: Vector of longitudes of the domain [deg]. Can be in any order, and a Numeric array or regular list/tuple. * latitude: Vector of latitudes of the domain [deg]. Can be in any order, and a Numeric array or regular list/tuple. Output Result: * A 3-element tuple: [0]: 1 if the longitude-latitude domain and Python package configuration passes tests to allow use of the NCAR SPHEREPACK 3.0 package. 0 if does not pass those tests. [1]: String containing messages written to stdout by calls to module sphere used for checking latitude (e.g. if it is gaussian, etc.). If there are no messages or there were no calls needed to sphere for checking latitude, value is empty string. [2]: Same as [1] except contains stderr messages. Examples: >>> from can_use_sphere import can_use_sphere >>> import Numeric as N >>> lon = N.arange(36)*10 >>> lat = [-90, -60, -30, 0, 30, 60, 90] >>> can_use_sphere(lon, lat)[0] 1 >>> lat = [-90, -60, -30, 0, 30, 60, 87] >>> can_use_sphere(lon, lat)[0] 0 >>> can_use_sphere(lon, lat)[1].splitlines()[1] 'CANNOT PROCESS THE DATA - Latitude values are incorrect' """ import Numeric as N #- Test if the sphere package exists: try: import sphere except ImportError: return (0,'','') #- Convert input to Numeric and sort: lon = N.sort(N.array(longitude)) lat = N.sort(N.array(latitude)) #- Check if either vector is less than 2 elements. If so, # return false: if (len(lon) < 2) or (len(lat) < 2): return (0,'','') #- Is the longitude vector evenly spaced? If not, return false: diff_lon = lon[1:] - lon[0:-1] if not N.allclose(diff_lon, diff_lon[0]): return (0,'','') #- Does the longitude vector exactly spans the globe but without # repeating? If not, return false: if not N.allclose( (lon[-1]+diff_lon[0]-lon[0]), 360.0 ): return (0,'','') #- Check latitude (e.g. whether it is gaussian, whether it includes # the pole points if they are evenly spaced) and any other bad # conditions for sphere using the sphere package checker. If # sphere can't execute correctly, return 0. Also return standard # error and standard out: import sys, cStringIO temp_out = sys.stdout temp_err = sys.stderr sys.stdout = cStringIO.StringIO() sys.stderr = cStringIO.StringIO() try: try: sph_obj = sphere.Sphere(lon, lat) sph_obj_exception = 0 except: sph_obj_exception = 1 finally: stdout = sys.stdout.getvalue() stderr = sys.stderr.getvalue() sys.stdout.close() sys.stderr.close() sys.stdout = temp_out sys.stderr = temp_err if sph_obj_exception == 1: return (0, stdout, stderr) #- Return true if haven't returned yet: return (1, stdout, stderr) #-------------------------- Main: Test Module ------------------------- #- Define additional examples for doctest to use: __test__ = { 'Additional Examples 1': """ >>> from can_use_sphere import can_use_sphere >>> import Numeric as N >>> lat = [-90, -60, -30, 0, 30, 60, 90] >>> lon = N.arange(35)*10 >>> can_use_sphere(lon, lat)[0] 0 >>> lon = [-180, 0, 180] >>> can_use_sphere(lon, lat)[0] 0 >>> lon = [-180, 180] >>> can_use_sphere(lon, lat)[0] 0 >>> lon = [-180, 170] >>> can_use_sphere(lon, lat)[0] 0 >>> lat = [45] >>> can_use_sphere(lon, lat)[0] 0 >>> lon = N.arange(36)*10 >>> lat = [-87.86380005,-85.0965271 ,-82.31291199,-79.52560425 \ ,-76.73690033,-73.9475174 , -71.15775299,-68.3677597 \ ,-65.5776062 ,-62.78735352,-59.99702072, -57.20663071 \ ,-54.41619873,-51.62573242,-48.83523941,-46.04472733 \ ,-43.25419617,-40.46364975,-37.67308807,-34.88252258 \ ,-32.09194565, -29.30135918,-26.51076889,-23.72017479 \ ,-20.92957497,-18.13897133, -15.34836483,-12.55775642 \ , -9.76714516, -6.97653341, -4.18592072, -1.39530694 \ , 1.39530694, 4.18592072, 6.97653341, 9.76714516 \ , 12.55775642, 15.34836483, 18.13897133, 20.92957497 \ , 23.72017479, 26.51076889, 29.30135918, 32.09194565 \ , 34.88252258, 37.67308807, 40.46364975, 43.25419617 \ , 46.04472733, 48.83523941, 51.62573242, 54.41619873 \ , 57.20663071, 59.99702072, 62.78735352, 65.5776062 \ , 68.3677597 , 71.15775299, 73.9475174 , 76.73690033 \ , 79.52560425, 82.31291199, 85.0965271 , 87.86380005 ] >>> can_use_sphere(lon, lat)[0] 1 >>> can_use_sphere(lon, lat)[1] '' >>> lat[-1] = 88.0 >>> can_use_sphere(lon, lat)[0] 0 >>> can_use_sphere(lon, lat)[1].splitlines()[1] 'CANNOT PROCESS THE DATA - Latitude values are incorrect' >>> can_use_sphere(lon, lat)[2] '' >>> lat = [-60, -30, 0, 30, 60, 90] >>> can_use_sphere(lon, lat)[0] 0 >>> can_use_sphere(lon, lat)[1].splitlines()[1] 'CANNOT PROCESS THE DATA - Evenly spaced grids must include the pole points' """ } #- Execute doctest if module is run from command line: if __name__ == "__main__": """Test the module. Tests the examples in all the module documentation strings, plus __test__. Note: To help ensure that module testing of this file works, the parent directory to the current directory is added to sys.path. """ import doctest, sys, os sys.path.append(os.pardir) doctest.testmod(sys.modules[__name__]) # ===== end file =====