Ejemplo n.º 1
0
def load_data(wind_files, ice_files, wind_files_size, ice_files_size):

    Wu = np.zeros(
        [177 * 119, wind_files_size],
        dtype=np.float)  # 2D array to save LOCAL (X) WIND VELOCITY values
    Wv = np.zeros(
        [177 * 119, wind_files_size],
        dtype=np.float)  # 2D array to save MERIDIONAL (Y) WIND VELOCITY values
    Iu = ma.zeros(
        [177 * 119, ice_files_size],
        dtype=np.float)  # 2D array to save LOCAL (X) ICE VELOCITY values
    Iv = ma.zeros(
        [177 * 119, ice_files_size],
        dtype=np.float)  # 2D array to save MERIDIONAL (X) ICE VELOCITY values

    #Wu[:,:] = np.nan
    #Wv[:,:] = np.nan
    #Iu[:,:] = np.nan
    #Iv[:,:] = np.nan

    n = -1  # initial value of counter
    nn = -1

    for windf in wind_files:
        with Dataset(windf, mode='r') as datum1:
            lat1 = datum1.variables['lat1'][:]
            lon1 = datum1.variables['lon1'][:]
            wu = datum1.variables['u_wind_avg'][:]
            wv = datum1.variables['v_wind_avg'][:]

        gsiz = lat1.size
        gshp = lat1.shape

        n += 1
        Wu[:, n] = wu.flat
        Wv[:, n] = wv.flat
    #print(Wu)
    for icef in ice_files:
        with Dataset(icef, mode='r') as datum2:
            lat1 = datum2.variables['lat1'][:]
            lon1 = datum2.variables['lon1'][:]
            iu = datum2.variables['dX'][:]
            try:
                iv = datum2.variables['dY_v1p4'][:]
            except KeyError:
                iv = datum2.variables['dY'][:]

        iu = iu[0, :, :] * (1000.0 /
                            (2 * 86400))  # convert to m/s from km/2days
        iv = iv[0, :, :] * (1000.0 /
                            (2 * 86400))  # before transforming to columns

        nn += 1
        Iu[:,
           n] = ma.ravel(iu)  # saves LOCAL (X) ICE VELOCITY values in columns
        Iv[:, n] = ma.ravel(
            iv)  # saves MERIDIONAL (Y) ICE VELOCITY values in columns
    #print(Iu)
    return (Wu, Wv, Iu, Iv)
Ejemplo n.º 2
0
def _chk2_asarray(a, b, axis):
    a = ma.asanyarray(a)
    b = ma.asanyarray(b)
    if axis is None:
        a = ma.ravel(a)
        b = ma.ravel(b)
        outaxis = 0
    else:
        outaxis = axis
    return a, b, outaxis
Ejemplo n.º 3
0
def _pfromz_MA(z, lapse_rate, P_bott, T_bott, z_bott):
    """Pressure given altitude in a constant lapse rate layer.

    The dry gas constant is used in calculations requiring the gas
    constant.  See the docstring for press2alt for references.

    Input Arguments:
    * z:  Geopotential altitude [m].
    * lapse_rate:  -dT/dz [K/m] over the layer.
    * P_bott:  Pressure [hPa] at the base of the layer.
    * T_bott:  Temperature [K] at the base of the layer.
    * z_bott:  Geopotential altitude [m] of the base of the layer.

    Output:
    * Pressure [hPa] for each element given in the input arguments.

    All input arguments can be either a scalar or an MA array.  All 
    arguments that are MA arrays, however, are of the same size and 
    shape.  If every input argument is a scalar, the output is a scalar.  
    If any of the input arguments is an MA array, the output is an MA 
    array of the same size and shape.
    """
    #jfp was import Numeric as N
    import numpy as N
    #jfp was import MA
    import numpy.ma as MA
    from atmconst import AtmConst

    const = AtmConst()

    if MA.size(lapse_rate) == 1:
        #jfp was if MA.array(lapse_rate)[0] == 0.0:
        if MA.array(lapse_rate) == 0.0:
            return P_bott * \
                   MA.exp( -const.g / (const.R_d*T_bott) * (z-z_bott) )
        else:
            exponent = const.g / (const.R_d * lapse_rate)
            return P_bott * \
                   ( (1.0 - (lapse_rate * (z-z_bott) / T_bott))**exponent )
    else:
        exponent = const.g / (const.R_d * lapse_rate)
        P = P_bott * \
            ( (1.0 - (lapse_rate * (z-z_bott) / T_bott))**exponent )
        P_at_0 = P_bott * \
                 MA.exp( -const.g / (const.R_d*T_bott) * (z-z_bott) )

        zero_lapse_mask = MA.filled(MA.where(lapse_rate == 0., 1, 0), 0)
        zero_lapse_mask_indices_flat = N.nonzero(N.ravel(zero_lapse_mask))
        P_flat = MA.ravel(P)
        MA.put( P_flat, zero_lapse_mask_indices_flat \
              , MA.take(MA.ravel(P_at_0), zero_lapse_mask_indices_flat) )
        return MA.reshape(P_flat, P.shape)
Ejemplo n.º 4
0
def _pfromz_MA(z, lapse_rate, P_bott, T_bott, z_bott):
    """Pressure given altitude in a constant lapse rate layer.

    The dry gas constant is used in calculations requiring the gas
    constant.  See the docstring for press2alt for references.

    Input Arguments:
    * z:  Geopotential altitude [m].
    * lapse_rate:  -dT/dz [K/m] over the layer.
    * P_bott:  Pressure [hPa] at the base of the layer.
    * T_bott:  Temperature [K] at the base of the layer.
    * z_bott:  Geopotential altitude [m] of the base of the layer.

    Output:
    * Pressure [hPa] for each element given in the input arguments.

    All input arguments can be either a scalar or an MA array.  All 
    arguments that are MA arrays, however, are of the same size and 
    shape.  If every input argument is a scalar, the output is a scalar.  
    If any of the input arguments is an MA array, the output is an MA 
    array of the same size and shape.
    """
    #jfp was import Numeric as N
    import numpy as N
    #jfp was import MA
    import numpy.ma as MA
    from atmconst import AtmConst

    const = AtmConst()

    if MA.size(lapse_rate) == 1:
        #jfp was if MA.array(lapse_rate)[0] == 0.0:
        if MA.array(lapse_rate) == 0.0:
            return P_bott * \
                   MA.exp( -const.g / (const.R_d*T_bott) * (z-z_bott) )
        else:
            exponent = const.g / (const.R_d * lapse_rate)
            return P_bott * \
                   ( (1.0 - (lapse_rate * (z-z_bott) / T_bott))**exponent )
    else:
        exponent = const.g / (const.R_d * lapse_rate)
        P = P_bott * \
            ( (1.0 - (lapse_rate * (z-z_bott) / T_bott))**exponent )
        P_at_0 = P_bott * \
                 MA.exp( -const.g / (const.R_d*T_bott) * (z-z_bott) )

        zero_lapse_mask = MA.filled(MA.where(lapse_rate == 0., 1, 0), 0)
        zero_lapse_mask_indices_flat = N.nonzero(N.ravel(zero_lapse_mask))
        P_flat = MA.ravel(P)
        MA.put( P_flat, zero_lapse_mask_indices_flat \
              , MA.take(MA.ravel(P_at_0), zero_lapse_mask_indices_flat) )
        return MA.reshape(P_flat, P.shape)
Ejemplo n.º 5
0
def _zfromp_MA(P, lapse_rate, P_bott, T_bott, z_bott):
    """Altitude given pressure in a constant lapse rate layer.

    The dry gas constant is used in calculations requiring the gas
    constant.  See the docstring for press2alt for references.

    Input Arguments:
    * P:  Pressure [hPa].
    * lapse_rate:  -dT/dz [K/m] over the layer.
    * P_bott:  Pressure [hPa] at the base of the layer.
    * T_bott:  Temperature [K] at the base of the layer.
    * z_bott:  Geopotential altitude [m] of the base of the layer.

    Output:
    * Altitude [m] for each element given in the input arguments.

    All input arguments can be either a scalar or an MA array.  All 
    arguments that are MA arrays, however, are of the same size and 
    shape.  If every input argument is a scalar, the output is a scalar.
    If any of the input arguments is an MA array, the output is an MA 
    array of the same size and shape.
    """
    import numpy as N
    #jfp was import Numeric as N
    import numpy.ma as MA
    #jfp was import MA
    from atmconst import AtmConst

    const = AtmConst()

    if MA.size(lapse_rate) == 1:
        if MA.array(lapse_rate)[0] == 0.0:
            return ( (-const.R_d * T_bott / const.g) * MA.log(P/P_bott) ) + \
                   z_bott
        else:
            exponent = (const.R_d * lapse_rate) / const.g
            return ((T_bott / lapse_rate) * (1. - (P/P_bott)**exponent)) + \
                   z_bott
    else:
        exponent = (const.R_d * lapse_rate) / const.g
        z = ((T_bott / lapse_rate) * (1. - (P / P_bott)**exponent)) + z_bott
        z_at_0 = ( (-const.R_d * T_bott / const.g) * MA.log(P/P_bott) ) + \
                 z_bott

        zero_lapse_mask = MA.filled(MA.where(lapse_rate == 0., 1, 0), 0)
        zero_lapse_mask_indices_flat = N.nonzero(N.ravel(zero_lapse_mask))
        z_flat = MA.ravel(z)
        MA.put( z_flat, zero_lapse_mask_indices_flat \
              , MA.take(MA.ravel(z_at_0), zero_lapse_mask_indices_flat) )
        return MA.reshape(z_flat, z.shape)
Ejemplo n.º 6
0
def _zfromp_MA(P, lapse_rate, P_bott, T_bott, z_bott):
    """Altitude given pressure in a constant lapse rate layer.

    The dry gas constant is used in calculations requiring the gas
    constant.  See the docstring for press2alt for references.

    Input Arguments:
    * P:  Pressure [hPa].
    * lapse_rate:  -dT/dz [K/m] over the layer.
    * P_bott:  Pressure [hPa] at the base of the layer.
    * T_bott:  Temperature [K] at the base of the layer.
    * z_bott:  Geopotential altitude [m] of the base of the layer.

    Output:
    * Altitude [m] for each element given in the input arguments.

    All input arguments can be either a scalar or an MA array.  All 
    arguments that are MA arrays, however, are of the same size and 
    shape.  If every input argument is a scalar, the output is a scalar.
    If any of the input arguments is an MA array, the output is an MA 
    array of the same size and shape.
    """
    import numpy as N
    #jfp was import Numeric as N
    import numpy.ma as MA
    #jfp was import MA
    from atmconst import AtmConst

    const = AtmConst()

    if MA.size(lapse_rate) == 1:
        if MA.array(lapse_rate)[0] == 0.0:
            return ( (-const.R_d * T_bott / const.g) * MA.log(P/P_bott) ) + \
                   z_bott
        else:
            exponent = (const.R_d * lapse_rate) / const.g
            return ((T_bott / lapse_rate) * (1. - (P/P_bott)**exponent)) + \
                   z_bott
    else:
        exponent = (const.R_d * lapse_rate) / const.g
        z = ((T_bott / lapse_rate) * (1. - (P/P_bott)**exponent)) + z_bott
        z_at_0 = ( (-const.R_d * T_bott / const.g) * MA.log(P/P_bott) ) + \
                 z_bott

        zero_lapse_mask = MA.filled(MA.where(lapse_rate == 0., 1, 0), 0)
        zero_lapse_mask_indices_flat = N.nonzero(N.ravel(zero_lapse_mask))
        z_flat = MA.ravel(z)
        MA.put( z_flat, zero_lapse_mask_indices_flat \
              , MA.take(MA.ravel(z_at_0), zero_lapse_mask_indices_flat) )
        return MA.reshape(z_flat, z.shape)
Ejemplo n.º 7
0
    def test_testMinMax(self):
        # Test minimum and maximum.
        (x, y, a10, m1, m2, xm, ym, z, zm, xf, s) = self.d
        xr = np.ravel(x)  # max doesn't work if shaped
        xmr = ravel(xm)

        # true because of careful selection of data
        assert_(eq(max(xr), maximum.reduce(xmr)))
        assert_(eq(min(xr), minimum.reduce(xmr)))
Ejemplo n.º 8
0
def _chk_asarray(a, axis):
    # Always returns a masked array, raveled for axis=None
    a = ma.asanyarray(a)
    if axis is None:
        a = ma.ravel(a)
        outaxis = 0
    else:
        outaxis = axis
    return a, outaxis
Ejemplo n.º 9
0
    def test_testMinMax(self):
        # Test minimum and maximum.
        (x, y, a10, m1, m2, xm, ym, z, zm, xf, s) = self.d
        xr = np.ravel(x)  # max doesn't work if shaped
        xmr = ravel(xm)

        # true because of careful selection of data
        assert_(eq(max(xr), maximum.reduce(xmr)))
        assert_(eq(min(xr), minimum.reduce(xmr)))
Ejemplo n.º 10
0
def add_masked_grid(wks,plot,lat,lon,mask):
#
# Create 2D arrays of lat/lon so we can draw markers outside the 
# masked area
#
  nlat  = len(lat)
  nlon  = len(lon)
  lat2d = numpy.tile(lat,nlon)
  lat2d = numpy.reshape(lat2d,[nlon,nlat])
  lat2d = numpy.transpose(lat2d)
  lon2d = numpy.tile(lon,nlat)
  lon2d = numpy.reshape(lon2d,[nlat,nlon])

  lat1d_mask = ma.ravel(ma.masked_where(mask==0,lat2d))
  lon1d_mask = ma.ravel(ma.masked_where(mask==0,lon2d))

  mkres               = Ngl.Resources()
  mkres.gsMarkerIndex = 16          # filled dot
  mkres.gsMarkerSizeF = 0.003
  mkres.gsMarkerColor = "purple"

  return Ngl.add_polymarker(wks,plot,lon1d_mask,lat1d_mask,mkres)
Ejemplo n.º 11
0
    def recache(self):
        #if self.axes is None: print 'recache no axes'
        #else: print 'recache units', self.axes.xaxis.units, self.axes.yaxis.units
        if ma.isMaskedArray(self._xorig) or ma.isMaskedArray(self._yorig):
            x = ma.asarray(self.convert_xunits(self._xorig), float)
            y = ma.asarray(self.convert_yunits(self._yorig), float)
            x = ma.ravel(x)
            y = ma.ravel(y)
        else:
            x = np.asarray(self.convert_xunits(self._xorig), float)
            y = np.asarray(self.convert_yunits(self._yorig), float)
            x = np.ravel(x)
            y = np.ravel(y)

        if len(x) == 1 and len(y) > 1:
            x = x * np.ones(y.shape, float)
        if len(y) == 1 and len(x) > 1:
            y = y * np.ones(x.shape, float)

        if len(x) != len(y):
            raise RuntimeError('xdata and ydata must be the same length')

        x = x.reshape((len(x), 1))
        y = y.reshape((len(y), 1))

        if ma.isMaskedArray(x) or ma.isMaskedArray(y):
            self._xy = ma.concatenate((x, y), 1)
        else:
            self._xy = np.concatenate((x, y), 1)
        self._x = self._xy[:, 0]  # just a view
        self._y = self._xy[:, 1]  # just a view

        # Masked arrays are now handled by the Path class itself
        self._path = Path(self._xy)
        self._transformed_path = TransformedPath(self._path,
                                                 self.get_transform())

        self._invalid = False
Ejemplo n.º 12
0
    def recache(self):
        #if self.axes is None: print 'recache no axes'
        #else: print 'recache units', self.axes.xaxis.units, self.axes.yaxis.units
        if ma.isMaskedArray(self._xorig) or ma.isMaskedArray(self._yorig):
            x = ma.asarray(self.convert_xunits(self._xorig), float)
            y = ma.asarray(self.convert_yunits(self._yorig), float)
            x = ma.ravel(x)
            y = ma.ravel(y)
        else:
            x = np.asarray(self.convert_xunits(self._xorig), float)
            y = np.asarray(self.convert_yunits(self._yorig), float)
            x = np.ravel(x)
            y = np.ravel(y)

        if len(x)==1 and len(y)>1:
            x = x * np.ones(y.shape, float)
        if len(y)==1 and len(x)>1:
            y = y * np.ones(x.shape, float)

        if len(x) != len(y):
            raise RuntimeError('xdata and ydata must be the same length')

        x = x.reshape((len(x), 1))
        y = y.reshape((len(y), 1))

        if ma.isMaskedArray(x) or ma.isMaskedArray(y):
            self._xy = ma.concatenate((x, y), 1)
        else:
            self._xy = np.concatenate((x, y), 1)
        self._x = self._xy[:, 0] # just a view
        self._y = self._xy[:, 1] # just a view

        # Masked arrays are now handled by the Path class itself
        self._path = Path(self._xy)
        self._transformed_path = TransformedPath(self._path, self.get_transform())

        self._invalid = False
Ejemplo n.º 13
0
 def attribute_average(self, name):
     """Return the value of the given attribute averaged over the dataset.
     """
     return ma.average(ma.ravel(self.get_attribute(name)))
Ejemplo n.º 14
0
 def attribute_sum(self, name):
     """Return the sum of values of the given attribute.
     """
     return (ma.ravel(self.get_attribute(name))).sum()
Ejemplo n.º 15
0
    for filename in filenames2:  # extracts data from each .nc file one by one
        datum2 = Dataset(filename, mode='r')

        print 'filename: ', filename

        ui = datum2.variables['dX'][:]
        vi = datum2.variables['dY'][:]

        nn += 1

        ui = ui[0, :, :] * (1000.0 / (2 * 86400))
        vi = vi[0, :, :] * (1000.0 / (2 * 86400))

        Iu[:,
           nn] = ma.ravel(ui)  # saves LOCAL (X) ICE VELOCITY values in columns
        Iv[:, nn] = ma.ravel(
            vi)  # saves MERIDIONAL (Y) ICE VELOCITY values in columns

    Kov = np.zeros(
        [
            21063,
        ], dtype=np.complex
    )  # list to save MODULUS COVARIANCE values as they're generated
    R = np.zeros(
        [
            21063,
        ], dtype=np.complex
    )  # list to save MODULUS CORRELATION COEFFICIENT values as they're generated
    R2 = np.zeros(
        [
Ejemplo n.º 16
0
    def pcolormesh(self, *args, **kwargs):
        """
        A temporary, modified duplicate of :func:`~matplotlib.pyplot.pcolormesh'.
        
        This function contains a workaround for a matplotlib issue
        and will be removed once the issue has been resolved.
        https://github.com/matplotlib/matplotlib/pull/1314
        
        """
        import warnings
        import numpy as np
        import numpy.ma as ma
        import matplotlib as mpl
        import matplotlib.cbook as cbook
        import matplotlib.colors as mcolors
        import matplotlib.cm as cm
        from matplotlib import docstring
        import matplotlib.transforms as transforms
        import matplotlib.artist as artist
        from matplotlib.artist import allow_rasterization
        import matplotlib.backend_bases as backend_bases
        import matplotlib.path as mpath
        import matplotlib.mlab as mlab
        import matplotlib.collections as mcoll
        
        if not self._hold: self.cla()

        alpha = kwargs.pop('alpha', None)
        norm = kwargs.pop('norm', None)
        cmap = kwargs.pop('cmap', None)
        vmin = kwargs.pop('vmin', None)
        vmax = kwargs.pop('vmax', None)
        shading = kwargs.pop('shading', 'flat').lower()
        antialiased = kwargs.pop('antialiased', False)
        kwargs.setdefault('edgecolors', 'None')

        X, Y, C = self._pcolorargs('pcolormesh', *args)
        Ny, Nx = X.shape

        # convert to one dimensional arrays
        if shading != 'gouraud':
            C = ma.ravel(C[0:Ny-1, 0:Nx-1]) # data point in each cell is value at
                                            # lower left corner
        else:
            C = C.ravel()
        X = X.ravel()
        Y = Y.ravel()

        coords = np.zeros(((Nx * Ny), 2), dtype=float)
        coords[:, 0] = X
        coords[:, 1] = Y

        collection = mcoll.QuadMesh(
            Nx - 1, Ny - 1, coords,
            antialiased=antialiased, shading=shading, **kwargs)
        collection.set_alpha(alpha)
        collection.set_array(C)
        if norm is not None: assert(isinstance(norm, mcolors.Normalize))
        collection.set_cmap(cmap)
        collection.set_norm(norm)
        collection.set_clim(vmin, vmax)
        collection.autoscale_None()

        self.grid(False)

        # Transform from native to data coordinates?
        t = collection._transform
        if (not isinstance(t, mtransforms.Transform)
            and hasattr(t, '_as_mpl_transform')):
            t = t._as_mpl_transform(self.axes)

        if t and any(t.contains_branch_seperately(self.transData)):
            trans_to_data = t - self.transData
            pts = np.vstack([X, Y]).T.astype(np.float)
            transformed_pts = trans_to_data.transform(pts)
            X = transformed_pts[..., 0]
            Y = transformed_pts[..., 1]

            # XXX Not a mpl 1.2 thing...
            no_inf = (X != np.inf) & (Y != np.inf)
            X = X[no_inf]
            Y = Y[no_inf]

        minx = np.amin(X)
        maxx = np.amax(X)
        miny = np.amin(Y)
        maxy = np.amax(Y)
        
        corners = (minx, miny), (maxx, maxy)
        self.update_datalim( corners)
        self.autoscale_view()
        self.add_collection(collection)
        return collection
Ejemplo n.º 17
0
    def pcolormesh(self, *args, **kwargs):
        import warnings
        import numpy as np
        import numpy.ma as ma
        import matplotlib as mpl
        import matplotlib.cbook as cbook
        import matplotlib.colors as mcolors
        import matplotlib.cm as cm
        from matplotlib import docstring
        import matplotlib.transforms as transforms
        import matplotlib.artist as artist
        from matplotlib.artist import allow_rasterization
        import matplotlib.backend_bases as backend_bases
        import matplotlib.path as mpath
        import matplotlib.mlab as mlab
        import matplotlib.collections as mcoll
        
        if not self._hold: self.cla()

        alpha = kwargs.pop('alpha', None)
        norm = kwargs.pop('norm', None)
        cmap = kwargs.pop('cmap', None)
        vmin = kwargs.pop('vmin', None)
        vmax = kwargs.pop('vmax', None)
        shading = kwargs.pop('shading', 'flat').lower()
        antialiased = kwargs.pop('antialiased', False)
        kwargs.setdefault('edgecolors', 'None')

        X, Y, C = self._pcolorargs('pcolormesh', *args)
        Ny, Nx = X.shape

        # convert to one dimensional arrays
        if shading != 'gouraud':
            C = ma.ravel(C[0:Ny-1, 0:Nx-1]) # data point in each cell is value at
                                            # lower left corner
        else:
            C = C.ravel()
        X = X.ravel()
        Y = Y.ravel()

        coords = np.zeros(((Nx * Ny), 2), dtype=float)
        coords[:, 0] = X
        coords[:, 1] = Y

        collection = mcoll.QuadMesh(
            Nx - 1, Ny - 1, coords,
            antialiased=antialiased, shading=shading, **kwargs)
        collection.set_alpha(alpha)
        collection.set_array(C)
        if norm is not None: assert(isinstance(norm, mcolors.Normalize))
        collection.set_cmap(cmap)
        collection.set_norm(norm)
        collection.set_clim(vmin, vmax)
        collection.autoscale_None()

        self.grid(False)

        # Transform from native to data coordinates?
        t = collection._transform
        if (not isinstance(t, mtransforms.Transform)
            and hasattr(t, '_as_mpl_transform')):
            t = t._as_mpl_transform(self.axes)

        if t and any(t.contains_branch_seperately(self.transData)):
            trans_to_data = t - self.transData
            pts = np.vstack([X, Y]).T.astype(np.float)
            transformed_pts = trans_to_data.transform(pts)
            X = transformed_pts[..., 0]
            Y = transformed_pts[..., 1]

            # XXX Not a mpl 1.2 thing...
            no_inf = (X != np.inf) & (Y != np.inf)
            X = X[no_inf]
            Y = Y[no_inf]

        minx = np.amin(X)
        maxx = np.amax(X)
        miny = np.amin(Y)
        maxy = np.amax(Y)
        
        corners = (minx, miny), (maxx, maxy)
        self.update_datalim( corners)
        self.autoscale_view()
        self.add_collection(collection)
        return collection
Ejemplo n.º 18
0
def press2alt(arg, P0=None, T0=None, missing=1e+20, invert=0):
    """Calculate elevation given pressure (or vice versa).

    Calculations are made assuming that the temperature distribution
    follows the 1976 Standard Atmosphere.  Technically the standard
    atmosphere defines temperature distribution as a function of
    geopotential altitude, and this routine actually calculates geo-
    potential altitude rather than geometric altitude.


    Method Positional Argument:
    * arg:  Numeric floating point vector of any shape and size, or a
      Numeric floating point scalar.  If invert=0 (the default), arg 
      is air pressure [hPa].  If invert=1, arg is elevation [m].


    Method Keyword Arguments:
    * P0:  Pressure [hPa] at the surface (altitude equals 0).  Numeric 
      floating point vector of same size and shape as arg or a scalar.
      Default of keyword is set to None, in which case the routine 
      uses the value of instance attribute sea_level_press (converted
      to hPa) from the AtmConst class.  Keyword value is used if the 
      keyword is set in the function call.  This keyword cannot have 
      any missing values.

    * T0:  Temperature [K] at the surface (altitude equals 0).  Numeric 
      floating point vector of same size and shape as arg or a scalar.  
      Default of keyword is set to None, in which case the routine uses 
      the value of instance attribute sea_level_temp from the AtmConst
      class.  Keyword value is used if the keyword is set in the func-
      tion call.  This keyword cannot have any missing values.

    * missing:  If arg has missing values, this is the missing value 
      value.  Floating point scalar.  Default is 1e+20.

    * invert:  If set to 1, function calculates pressure [hPa] from 
      altitude [m].  In that case, positional input variable arg is 
      altitude [m] and the output is pressure [hPa].  Default value of 
      invert=0, which means the function calculates altitude given 
      pressure.


    Output:
    * If invert=0 (the default), output is elevation [m] at each 
      element of arg, relative to the surface.  If invert=1, output
      is the air pressure [hPa].  Numeric floating point array of 
      the same size and shape as arg.

      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.


    References:
    * Carmichael, Ralph (2003):  "Definition of the 1976 Standard Atmo-
      sphere to 86 km," Public Domain Aeronautical Software (PDAS).
      URL:  http://www.pdas.com/coesa.htm.

    * Wallace, J. M., and P. V. Hobbs (1977): Atmospheric Science:
      An Introductory Survey.  San Diego, CA:  Academic Press, ISBN
      0-12-732950-1, pp. 60-61.


    Examples:

    (1) Calculating altitude given pressure:

    >>> from press2alt import press2alt
    >>> import Numeric as N
    >>> press = N.array([200., 350., 850., 1e+20, 50.])
    >>> alt = press2alt(press, missing=1e+20)
    >>> ['%.7g' % alt[i] for i in range(5)]
    ['11783.94', '8117.19', '1457.285', '1e+20', '20575.96']

    (2) Calculating pressure given altitude:

    >>> alt = N.array([0., 10000., 15000., 20000., 50000.])
    >>> press = press2alt(alt, missing=1e+20, invert=1)
    >>> ['%.7g' % press[i] for i in range(5)]
    ['1013.25', '264.3589', '120.443', '54.74718', '0.7593892']

    (3) Input is a Numeric floating point scalar, and using a keyword
        set surface pressure to a different scalar:

    >>> alt = press2alt(N.array(850.), P0=1000.)
    >>> ['%.7g' % alt[0]]
    ['1349.778']
    """
    import numpy as N
    import numpy.ma as MA
    #jfp was import MA
    #jfp was import Numeric as N
    from atmconst import AtmConst
    from is_numeric_float import is_numeric_float


    #- Check input is of the correct type:

    if is_numeric_float(arg) != 1:
        raise TypeError, "press2alt:  Arg not Numeric floating"


    #- Import general constants and set additional constants.  h1_std
    #  is the lower limit of the Standard Atmosphere layer geopoten-
    #  tial altitude [m], h2_std is the upper limit [m] of the layer,
    #  and dT/dh is the temperature gradient (i.e. negative of the
    #  lapse rate) [K/m]:

    const = AtmConst()

    h1_std   = N.array([0., 11., 20., 32., 47., 51., 71.]) * 1000.
    h2_std   = N.array( MA.concatenate([h1_std[1:], [84.852*1000.]]) )
    dTdh_std = N.array([-6.5, 0.0, 1.0, 2.8, 0.0, -2.8, -2.0]) / 1000.


    #- Prep arrays for masked array calculation and set conditions
    #  at sea-level.  Pressures are in hPa and temperatures in K.
    #  Sea-level conditions arrays are same shape/size as P_or_z.
    #  If input argument is a scalar, make the local variable used
    #  for calculations a 1-element vector:

    if missing == None: P_or_z = MA.masked_array(arg)
    else:               P_or_z = MA.masked_values(arg, missing, copy=0)

    if P_or_z.shape == ():
        P_or_z = MA.reshape(P_or_z, (1,))

    if P0 == None:
        #jfp was P0_use = MA.zeros(P_or_z.shape, typecode=MA.Float) \
        P0_use = MA.zeros(P_or_z.shape) \
               + (const.sea_level_press / 100.)
    else:
        #jfp was P0_use = MA.zeros(P_or_z.shape, typecode=MA.Float) \
        P0_use = MA.zeros(P_or_z.shape) \
               + MA.masked_array(P0)

    if T0 == None:
        #jfp was T0_use = MA.zeros(P_or_z.shape, typecode=MA.Float) \
        T0_use = MA.zeros(P_or_z.shape) \
               + const.sea_level_temp
    else:
        #jfp was T0_use = MA.zeros(P_or_z.shape, typecode=MA.Float) \
        T0_use = MA.zeros(P_or_z.shape) \
               + MA.masked_array(T0)


    #- Calculate P and T for the boundaries of the 7 layers of the
    #  Standard Atmosphere for the given P0 and T0 (layer 0 goes from
    #  P0 to P1, layer 1 from P1 to P2, etc.).  These are given as
    #  8 element dictionaries P_std and T_std where the key is the
    #  location (P_std[0] is at the bottom of layer 0, P_std[1] is the
    #  top of layer 0 and bottom of layer 1, ... and P_std[7] is the
    #  top of layer 6).  Remember P_std and T_std are dictionaries but
    #  dTdh_std, h1_std, and h2_std are vectors:

    P_std = {0:P0_use}
    T_std = {0:T0_use}

    for i in range(len(h1_std)):
        P_std[i+1] = _pfromz_MA( h2_std[i], -dTdh_std[i] \
                               , P_std[i], T_std[i], h1_std[i] )
        T_std[i+1] = T_std[i] + ( dTdh_std[i] * (h2_std[i]-h1_std[i]) )

    #- Test input is within Standard Atmosphere limits:

    if invert == 0:
        tmp = MA.where(P_or_z < P_std[len(h1_std)], 1, 0)
        if MA.sum(MA.ravel(tmp)) > 0:
            raise ValueError, "press2alt:  Pressure out-of-range"
    else:
        tmp = MA.where(P_or_z > MA.maximum(h2_std), 1, 0)
        if MA.sum(MA.ravel(tmp)) > 0:
            raise ValueError, "press2alt:  Altitude out-of-range"


    #- What layer number is each element of P_or_z in?

    P_or_z_layer = MA.zeros(P_or_z.shape)

    if invert == 0:
        for i in range(len(h1_std)):
            tmp = MA.where( MA.logical_and( (P_or_z <= P_std[i]) \
                                          , (P_or_z >  P_std[i+1]) ) \
                          , i, 0 )
            P_or_z_layer += tmp
    else:
        for i in range(len(h1_std)):
            tmp = MA.where( MA.logical_and( (P_or_z >= h1_std[i]) \
                                          , (P_or_z <  h2_std[i]) ) \
                          , i, 0 )
            P_or_z_layer += tmp


    #- Fill in the bottom-of-the-layer variables and the lapse rate
    #  for the layers that the levels are in.  The *_actual variables 
    #  are the values of dTdh, P_bott, etc. for each element in the
    #  P_or_z_flat array:

    P_or_z_flat = MA.ravel(P_or_z)
    P_or_z_flat_mask = P_or_z_flat.mask
    if P_or_z_flat.mask==False:
        P_or_z_flat_mask = MA.make_mask_none(P_or_z_flat.shape)
    #jfp was:
    #if P_or_z_flat.mask() == None:
    #    P_or_z_flat_mask = MA.make_mask_none(P_or_z_flat.shape)
    #else:
    #    P_or_z_flat_mask = P_or_z_flat.mask()

    P_or_z_layer_flat = MA.ravel(P_or_z_layer)
    #jfp was dTdh_actual       = MA.zeros(P_or_z_flat.shape, typecode=MA.Float)
    #jfp was P_bott_actual     = MA.zeros(P_or_z_flat.shape, typecode=MA.Float)
    #jfp was T_bott_actual     = MA.zeros(P_or_z_flat.shape, typecode=MA.Float)
    #jfp was z_bott_actual     = MA.zeros(P_or_z_flat.shape, typecode=MA.Float)
    dTdh_actual       = MA.zeros(P_or_z_flat.shape)
    P_bott_actual     = MA.zeros(P_or_z_flat.shape)
    T_bott_actual     = MA.zeros(P_or_z_flat.shape)
    z_bott_actual     = MA.zeros(P_or_z_flat.shape)

    for i in xrange(MA.size(P_or_z_flat)):
        if P_or_z_flat_mask[i] != 1:
            layer_number     = P_or_z_layer_flat[i]
            dTdh_actual[i]   = dTdh_std[layer_number]
            P_bott_actual[i] = MA.ravel(P_std[layer_number])[i]
            T_bott_actual[i] = MA.ravel(T_std[layer_number])[i]
            z_bott_actual[i] = h1_std[layer_number]
        else:
            dTdh_actual[i]   = MA.masked
            P_bott_actual[i] = MA.masked
            T_bott_actual[i] = MA.masked
            z_bott_actual[i] = MA.masked


    #- Calculate pressure/altitude from altitude/pressure (output is
    #  a flat array):
    
    if invert == 0:
        output = _zfromp_MA( P_or_z_flat, -dTdh_actual \
                           , P_bott_actual, T_bott_actual, z_bott_actual )
    else:
        output = _pfromz_MA( P_or_z_flat, -dTdh_actual \
                           , P_bott_actual, T_bott_actual, z_bott_actual )


    #- Return output as same shape as input positional argument:

    return MA.filled( MA.reshape(output, arg.shape), missing )
Ejemplo n.º 19
0
    def _pcolormesh_patched(self, *args, **kwargs):
        """
        A temporary, modified duplicate of
        :func:`~matplotlib.pyplot.pcolormesh'.

        This function contains a workaround for a matplotlib issue
        and will be removed once the issue has been resolved.
        https://github.com/matplotlib/matplotlib/pull/1314

        """
        import warnings
        import numpy as np
        import numpy.ma as ma
        import matplotlib as mpl
        import matplotlib.cbook as cbook
        import matplotlib.colors as mcolors
        import matplotlib.cm as cm
        from matplotlib import docstring
        import matplotlib.transforms as transforms
        import matplotlib.artist as artist
        from matplotlib.artist import allow_rasterization
        import matplotlib.backend_bases as backend_bases
        import matplotlib.path as mpath
        import matplotlib.mlab as mlab
        import matplotlib.collections as mcoll

        if not self._hold:
            self.cla()

        alpha = kwargs.pop('alpha', None)
        norm = kwargs.pop('norm', None)
        cmap = kwargs.pop('cmap', None)
        vmin = kwargs.pop('vmin', None)
        vmax = kwargs.pop('vmax', None)
        shading = kwargs.pop('shading', 'flat').lower()
        antialiased = kwargs.pop('antialiased', False)
        kwargs.setdefault('edgecolors', 'None')

        X, Y, C = self._pcolorargs('pcolormesh', *args)
        Ny, Nx = X.shape

        # convert to one dimensional arrays
        if shading != 'gouraud':
            # data point in each cell is value at lower left corner
            C = ma.ravel(C[0:Ny - 1, 0:Nx - 1])
        else:
            C = C.ravel()
        X = X.ravel()
        Y = Y.ravel()

        coords = np.zeros(((Nx * Ny), 2), dtype=float)
        coords[:, 0] = X
        coords[:, 1] = Y

        collection = mcoll.QuadMesh(
            Nx - 1, Ny - 1, coords,
            antialiased=antialiased, shading=shading, **kwargs)
        collection.set_alpha(alpha)
        collection.set_array(C)
        if norm is not None:
            assert(isinstance(norm, mcolors.Normalize))
        collection.set_cmap(cmap)
        collection.set_norm(norm)
        collection.set_clim(vmin, vmax)
        collection.autoscale_None()

        self.grid(False)

        ########################
        # PATCH FOR MPL 1.2.0rc2

        # Transform from native to data coordinates?
        t = collection._transform
        if (not isinstance(t, mtransforms.Transform)
                and hasattr(t, '_as_mpl_transform')):
            t = t._as_mpl_transform(self.axes)

        if t and any(t.contains_branch_seperately(self.transData)):
            trans_to_data = t - self.transData
            pts = np.vstack([X, Y]).T.astype(np.float)
            transformed_pts = trans_to_data.transform(pts)

            X = transformed_pts[..., 0]
            Y = transformed_pts[..., 1]

            # XXX Not a mpl 1.2 thing...
            no_inf = (X != np.inf) & (Y != np.inf)
            X = X[no_inf]
            Y = Y[no_inf]

        # END OF PATCH
        ##############

        minx = np.amin(X)
        maxx = np.amax(X)
        miny = np.amin(Y)
        maxy = np.amax(Y)

        corners = (minx, miny), (maxx, maxy)
        self.update_datalim(corners)
        self.autoscale_view()
        self.add_collection(collection)

        # XXX Non-standard matplotlib 1.2 thing.
        # Handle a possible wrap around for rectangular projections.
        t = kwargs.get('transform', None)
        if isinstance(t, ccrs.CRS):
            if isinstance(t, ccrs._RectangularProjection) and \
                    isinstance(self.projection, ccrs._RectangularProjection):

                C = C.reshape((Ny - 1, Nx - 1))
                transformed_pts = transformed_pts.reshape((Ny, Nx, 2))

                # compute the vertical line angles of the pcolor in
                # transformed coordinates
                with np.errstate(invalid='ignore'):
                    horizontal_vert_angles = np.arctan2(
                        np.diff(transformed_pts[..., 0], axis=1),
                        np.diff(transformed_pts[..., 1], axis=1)
                    )

                # if the change in angle is greater than 90 degrees (absolute),
                # then mark it for masking later on.
                dx_horizontal = np.diff(horizontal_vert_angles)
                to_mask = ((np.abs(dx_horizontal) > np.pi / 2) |
                           np.isnan(dx_horizontal))

                if np.any(to_mask):
                    # at this point C has a shape of (Ny-1, Nx-1), to_mask has
                    # a shape of (Ny, Nx-2) and pts has a shape of (Ny*Nx, 2)

                    mask = np.zeros(C.shape, dtype=np.bool)

                    # mask out the neighbouring cells if there was a cell
                    # found with an angle change of more than pi/2 . NB.
                    # Masking too much only has a detrimental impact on
                    # performance.
                    to_mask_y_shift = to_mask[:-1, :]
                    mask[:, :-1][to_mask_y_shift] = True
                    mask[:, 1:][to_mask_y_shift] = True

                    to_mask_x_shift = to_mask[1:, :]
                    mask[:, :-1][to_mask_x_shift] = True
                    mask[:, 1:][to_mask_x_shift] = True

                    C_mask = getattr(C, 'mask', None)
                    if C_mask is not None:
                        dmask = mask | C_mask
                    else:
                        dmask = mask

                    # print 'Ratio of masked data: ',
                    # print np.sum(mask) / float(np.product(mask.shape))

                    # create the masked array to be used with this pcolormesh
                    pcolormesh_data = np.ma.array(C, mask=mask)

                    collection.set_array(pcolormesh_data.ravel())

                    # now that the pcolormesh has masked the bad values,
                    # create a pcolor with just those values that were masked
                    pcolor_data = pcolormesh_data.copy()
                    # invert the mask
                    pcolor_data.mask = ~pcolor_data.mask

                    # remember to re-apply the original data mask to the array
                    if C_mask is not None:
                        pcolor_data.mask = pcolor_data.mask | C_mask

                    pts = pts.reshape((Ny, Nx, 2))
                    pcolor_col = self.pcolor(pts[..., 0], pts[..., 1],
                                             pcolor_data, **kwargs)
                    pcolor_col.set_cmap(cmap)
                    pcolor_col.set_norm(norm)
                    pcolor_col.set_clim(vmin, vmax)
                    # scale the data according to the *original* data
                    pcolor_col.norm.autoscale_None(C)

                    # put the pcolor_col on the pcolormesh collection so that
                    # if really necessary, users can do things post this method
                    collection._wrapped_collection_fix = pcolor_col

        return collection
Ejemplo n.º 20
0
def press2alt(arg, P0=None, T0=None, missing=1e+20, invert=0):
    """Calculate elevation given pressure (or vice versa).

    Calculations are made assuming that the temperature distribution
    follows the 1976 Standard Atmosphere.  Technically the standard
    atmosphere defines temperature distribution as a function of
    geopotential altitude, and this routine actually calculates geo-
    potential altitude rather than geometric altitude.


    Method Positional Argument:
    * arg:  Numeric floating point vector of any shape and size, or a
      Numeric floating point scalar.  If invert=0 (the default), arg 
      is air pressure [hPa].  If invert=1, arg is elevation [m].


    Method Keyword Arguments:
    * P0:  Pressure [hPa] at the surface (altitude equals 0).  Numeric 
      floating point vector of same size and shape as arg or a scalar.
      Default of keyword is set to None, in which case the routine 
      uses the value of instance attribute sea_level_press (converted
      to hPa) from the AtmConst class.  Keyword value is used if the 
      keyword is set in the function call.  This keyword cannot have 
      any missing values.

    * T0:  Temperature [K] at the surface (altitude equals 0).  Numeric 
      floating point vector of same size and shape as arg or a scalar.  
      Default of keyword is set to None, in which case the routine uses 
      the value of instance attribute sea_level_temp from the AtmConst
      class.  Keyword value is used if the keyword is set in the func-
      tion call.  This keyword cannot have any missing values.

    * missing:  If arg has missing values, this is the missing value 
      value.  Floating point scalar.  Default is 1e+20.

    * invert:  If set to 1, function calculates pressure [hPa] from 
      altitude [m].  In that case, positional input variable arg is 
      altitude [m] and the output is pressure [hPa].  Default value of 
      invert=0, which means the function calculates altitude given 
      pressure.


    Output:
    * If invert=0 (the default), output is elevation [m] at each 
      element of arg, relative to the surface.  If invert=1, output
      is the air pressure [hPa].  Numeric floating point array of 
      the same size and shape as arg.

      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.


    References:
    * Carmichael, Ralph (2003):  "Definition of the 1976 Standard Atmo-
      sphere to 86 km," Public Domain Aeronautical Software (PDAS).
      URL:  http://www.pdas.com/coesa.htm.

    * Wallace, J. M., and P. V. Hobbs (1977): Atmospheric Science:
      An Introductory Survey.  San Diego, CA:  Academic Press, ISBN
      0-12-732950-1, pp. 60-61.


    Examples:

    (1) Calculating altitude given pressure:

    >>> from press2alt import press2alt
    >>> import Numeric as N
    >>> press = N.array([200., 350., 850., 1e+20, 50.])
    >>> alt = press2alt(press, missing=1e+20)
    >>> ['%.7g' % alt[i] for i in range(5)]
    ['11783.94', '8117.19', '1457.285', '1e+20', '20575.96']

    (2) Calculating pressure given altitude:

    >>> alt = N.array([0., 10000., 15000., 20000., 50000.])
    >>> press = press2alt(alt, missing=1e+20, invert=1)
    >>> ['%.7g' % press[i] for i in range(5)]
    ['1013.25', '264.3589', '120.443', '54.74718', '0.7593892']

    (3) Input is a Numeric floating point scalar, and using a keyword
        set surface pressure to a different scalar:

    >>> alt = press2alt(N.array(850.), P0=1000.)
    >>> ['%.7g' % alt[0]]
    ['1349.778']
    """
    import numpy.ma as MA
    import numpy as N
    from atmconst import AtmConst
    #from is_numeric_float import is_numeric_float

    #- Check input is of the correct type:

    #if is_numeric_float(arg) != 1:
    #    raise TypeError, "press2alt:  Arg not Numeric floating"

    #- Import general constants and set additional constants.  h1_std
    #  is the lower limit of the Standard Atmosphere layer geopoten-
    #  tial altitude [m], h2_std is the upper limit [m] of the layer,
    #  and dT/dh is the temperature gradient (i.e. negative of the
    #  lapse rate) [K/m]:

    const = AtmConst()

    h1_std = N.array([0., 11., 20., 32., 47., 51., 71.]) * 1000.
    h2_std = N.array(MA.concatenate([h1_std[1:], [84.852 * 1000.]]))
    dTdh_std = N.array([-6.5, 0.0, 1.0, 2.8, 0.0, -2.8, -2.0]) / 1000.

    #- Prep arrays for masked array calculation and set conditions
    #  at sea-level.  Pressures are in hPa and temperatures in K.
    #  Sea-level conditions arrays are same shape/size as P_or_z.
    #  If input argument is a scalar, make the local variable used
    #  for calculations a 1-element vector:

    if missing == None: P_or_z = MA.masked_array(arg)
    else: P_or_z = MA.masked_values(arg, missing, copy=0)

    if P_or_z.shape == ():
        P_or_z = MA.reshape(P_or_z, (1, ))

    if P0 == None:
        P0_use = MA.zeros(P_or_z.shape) \
               + (const.sea_level_press / 100.)
    else:
        P0_use = MA.zeros(P_or_z.shape) \
               + MA.masked_array(P0)

    if T0 == None:
        T0_use = MA.zeros(P_or_z.shape) \
               + const.sea_level_temp
    else:
        T0_use = MA.zeros(P_or_z.shape) \
               + MA.masked_array(T0)

    #- Calculate P and T for the boundaries of the 7 layers of the
    #  Standard Atmosphere for the given P0 and T0 (layer 0 goes from
    #  P0 to P1, layer 1 from P1 to P2, etc.).  These are given as
    #  8 element dictionaries P_std and T_std where the key is the
    #  location (P_std[0] is at the bottom of layer 0, P_std[1] is the
    #  top of layer 0 and bottom of layer 1, ... and P_std[7] is the
    #  top of layer 6).  Remember P_std and T_std are dictionaries but
    #  dTdh_std, h1_std, and h2_std are vectors:

    P_std = {0: P0_use}
    T_std = {0: T0_use}

    for i in range(len(h1_std)):
        P_std[i+1] = _pfromz_MA( h2_std[i], -dTdh_std[i] \
                               , P_std[i], T_std[i], h1_std[i] )
        T_std[i + 1] = T_std[i] + (dTdh_std[i] * (h2_std[i] - h1_std[i]))

    #- Test input is within Standard Atmosphere limits:

    if invert == 0:
        tmp = MA.where(P_or_z < P_std[len(h1_std)], 1, 0)
        if MA.sum(MA.ravel(tmp)) > 0:
            raise ValueError, "press2alt:  Pressure out-of-range"
    else:
        tmp = MA.where(P_or_z > MA.maximum(h2_std), 1, 0)
        if MA.sum(MA.ravel(tmp)) > 0:
            raise ValueError, "press2alt:  Altitude out-of-range"

    #- What layer number is each element of P_or_z in?

    P_or_z_layer = 0  #MA.zeros(P_or_z.shape)

    #if invert == 0:
    #    for i in range(len(h1_std)):
    #        tmp = MA.where( MA.logical_and( (P_or_z <= P_std[i]) \
    #                                      , (P_or_z >  P_std[i+1]) ) \
    #                      , i, 0 )
    #        P_or_z_layer += tmp
    #else:
    #    for i in range(len(h1_std)):
    #        tmp = MA.where( MA.logical_and( (P_or_z >= h1_std[i]) \
    #                                      , (P_or_z <  h2_std[i]) ) \
    #                      , i, 0 )
    #        P_or_z_layer += tmp

    #- Fill in the bottom-of-the-layer variables and the lapse rate
    #  for the layers that the levels are in.  The *_actual variables
    #  are the values of dTdh, P_bott, etc. for each element in the
    #  P_or_z_flat array:

    P_or_z_flat = MA.ravel(P_or_z)
    if P_or_z_flat.mask() == None:
        P_or_z_flat_mask = MA.make_mask_none(P_or_z_flat.shape)
    else:
        P_or_z_flat_mask = P_or_z_flat.mask()

    P_or_z_layer_flat = MA.ravel(P_or_z_layer)
    dTdh_actual = MA.zeros(P_or_z_flat.shape)
    P_bott_actual = MA.zeros(P_or_z_flat.shape)
    T_bott_actual = MA.zeros(P_or_z_flat.shape)
    z_bott_actual = MA.zeros(P_or_z_flat.shape)

    for i in xrange(MA.size(P_or_z_flat)):
        if P_or_z_flat_mask[i] != 1:
            layer_number = P_or_z_layer_flat[i]
            dTdh_actual[i] = dTdh_std[layer_number]
            P_bott_actual[i] = MA.ravel(P_std[layer_number])[i]
            T_bott_actual[i] = MA.ravel(T_std[layer_number])[i]
            z_bott_actual[i] = h1_std[layer_number]
        else:
            dTdh_actual[i] = MA.masked
            P_bott_actual[i] = MA.masked
            T_bott_actual[i] = MA.masked
            z_bott_actual[i] = MA.masked

    #- Calculate pressure/altitude from altitude/pressure (output is
    #  a flat array):

    if invert == 0:
        output = _zfromp_MA( P_or_z_flat, -dTdh_actual \
                           , P_bott_actual, T_bott_actual, z_bott_actual )
    else:
        output = _pfromz_MA( P_or_z_flat, -dTdh_actual \
                           , P_bott_actual, T_bott_actual, z_bott_actual )

    #- Return output as same shape as input positional argument:

    return MA.filled(MA.reshape(output, arg.shape), missing)