#!/usr/bin/python -tt #======================================================================= # General Documentation """Single-function module. See function docstring for description. """ #----------------------------------------------------------------------- # Additional Documentation # # RCS Revision Code: # $Id: mix_ratio.py,v 1.3 2004/04/06 20:07:49 jlin Exp $ # # Modification History: # - 16 Mar 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 mix_ratio.py". # - See import statements throughout for more information on non- # built-in packages and modules required. # # Copyright (c) 2003-2004 by Johnny Lin. For licensing, distribution # conditions, contact information, and additional documentation see # the URL http://www.johnny-lin.com/py_pkgs/atmqty/doc/. #======================================================================= #---------------- Module General Import and Declarations --------------- #- Set module version number etc. to package version number etc.: import package_version __version__ = package_version.version __author__ = package_version.author __date__ = package_version.date __credits__ = package_version.credits del package_version #-------------------- General Function: mix_ratio --------------------- def mix_ratio(variables, missing=1e+20): """Calculate mixing ratio. Method Arguments: * variables: A dictionary of input state variables, where for each key:value pair the key labels what state variable it is and the value is the state variable. The value is a Numeric floating point array of any number of dimensions and size. All state variables must be arrays of the same shape and size. Argument variables can have any number of items. Key values may be any value, but values that may be used by this function include: + 'e': Vapor pressure over water [hPa]. + 'p': Total pressure [hPa]. + 'q': Specific humidity [kg/kg]. * missing: If values in variables has missing values, this is the missing value value. Floating point scalar. Default is 1e+20. Optional. Output: * Mixing ratio [kg/kg]. Numeric array of same dimensions and size as state variables in the argument. If there are any missing values in output, those values are set to the value in argument missing from the input. If there are missing values in the output due to math errors and missing is set to None, output will fill those missing values with the MA default value of 1e+20. The mixing ratio can be calculated from a variety of different combinations of state variables. In this function, the following combinations are supported: * Vapor pressure and total pressure. * Specific humidity. The function will automatically apply the correct equation depen- ding on the key values of the argument dictionary. An error is returned if none of the above combinations are present as the input argument. Reference: * Emanuel, K. A. (1994): Atmospheric Convection. New York, NY: Oxford University Press, 580 pp. Example with missing values: >>> from mix_ratio import mix_ratio >>> import Numeric as N >>> p = N.array([1026.8, 840.2, 1e+20, 450.2]) >>> e = N.array([9.00051379, 7.23209979, 1e+20, 2.80541885]) >>> r = mix_ratio({'p':p, 'e':e}, missing=1e+20) >>> ['%.7g' % r[i] for i in range(len(r))] ['0.0055', '0.0054', '1e+20', '0.0039'] """ #- Import statements: import MA from atmconst import AtmConst from is_numeric_float import is_numeric_float #- Atmospheric constants: const = AtmConst() #- Check input is of the correct type: for akey in variables.keys(): if is_numeric_float(variables[akey]) != 1: raise TypeError, "mix_ratio: Arg not Numeric floating" #- Calculate the mixing ratio depending on what the inputs are # (derived from Emanuel eqns. 4.1.4, 4.1.2): if variables.has_key('q') == 1: if missing == None: q = MA.masked_array(variables['q']) else: q = MA.masked_values(variables['q'], missing, copy=0) mix = q / (1.0 - q) elif (variables.has_key('p') == 1) and \ (variables.has_key('e') == 1): if missing == None: e = MA.masked_array(variables['e']) p = MA.masked_array(variables['p']) else: e = MA.masked_values(variables['e'], missing, copy=0) p = MA.masked_values(variables['p'], missing, copy=0) mix = const.epsilon * e / (p - e) else: raise ValueError, "mix_ratio: Bad input keys" #- Return mixing ratio: return MA.filled(mix, missing) #-------------------------- Main: Test Module ------------------------- #- Define additional examples for doctest to use: __test__ = { 'Additional Examples': """ >>> from mix_ratio import mix_ratio >>> import Numeric as N >>> q = N.array([5.5e-3/(1.+5.5e-3), 3.9e-3/(1.+3.9e-3)]) >>> r = mix_ratio({'q':q}) >>> ['%.7g' % r[i] for i in range(len(r))] ['0.0055', '0.0039'] >>> q = N.array(5.5e-3/(1.+5.5e-3)) >>> r = mix_ratio({'q':q}) >>> '%.7g' % r '0.0055' >>> q = N.array(1e+20) >>> r = mix_ratio({'q':q}) >>> '%.7g' % r '1e+20' >>> p = N.array([1026.8, 840.2, 1e+20, 450.2]) >>> e = N.array([9.00051379, 7.23209979, 2.80541885]) >>> r = mix_ratio({'p':p, 'e':e}, missing=1e+20) Traceback (most recent call last): ... ValueError: frames are not aligned >>> p = N.array([1026.8, 840.2, 450.2, 1026.8]) >>> p = N.reshape(p, (2,2)) >>> e = N.array([9.00051379, 7.23209979, 2.80541885, 9.00051379]) >>> e = N.reshape(e, (2,2)) >>> r = mix_ratio({'p':p, 'e':e}) >>> '%.7g %.7g %.7g %.7g' % (r[0,0], r[0,1], r[1,0], r[1,1]) '0.0055 0.0054 0.0039 0.0055' """ } #- 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__. The parent directory is added to sys.path for this module testing case. """ import doctest, sys, os sys.path.append(os.pardir) doctest.testmod(sys.modules[__name__]) # ===== end file =====