Пример #1
0
def heatcap(depth, latitude, temperature, salinity) -> np.ndarray:
    """
    Calculates the heat capacity of sea water.

    Parameters:
    depth: The depth(s) in meters
    latitude: The latitude(s) in degrees North
    temperature: The temperatures(s) in Celsius
    salinity: The salinity (unitless)
    """

    press = __calc_pressure(depth, latitude)

    heatcap = seawater.cp(salinity, temperature, press)
    return np.array(heatcap)
Пример #2
0
 #
 empta = empt * 1.
 emptp = empt * 1.
 empti = empt * 1.
 #
 # Compute density
 rhon[t, ...] = eosNeutral(tost.data, sost.data) - 1000.
 rhon[t, ...].mask = maski
 rhon[t, ...] = maskVal(rhon[t, ...], valmask)
 rhonl = rhon.data[t, ...]
 # Compute buoyancy/density flux as mass fluxes in kg/m2/s (SI units)
 #  convwf : kg/m2/s = mm/s -> m/s
 convwf = 1.e-3
 pres = tost.data * 0.
 denflxh[t, ...] = (-sw.alpha(sost.data, tost.data, pres) /
                    sw.cp(sost.data, tost.data, pres)) * heft.data
 if empsw == 0:
     denflxw[t, ...] = (rhonl + 1000.) * sw.beta(
         sost.data, tost.data, pres) * sost.data * empt.data * convwf
 else:
     denflxw[t, ...] = (rhonl + 1000.) * sw.beta(
         sost.data, tost.data, pres) * empt.data * convwf
 denflx[t, ...] = denflxh[t, ...] + denflxw[t, ...]
 denflx[t, ...].mask = maski
 denflxh[t, ...].mask = maski
 denflxw[t, ...].mask = maski
 denflx[t, ...] = maskVal(denflx[t, ...], valmask)
 denflxh[t, ...] = maskVal(denflxh[t, ...], valmask)
 denflxw[t, ...] = maskVal(denflxw[t, ...], valmask)
 dflxh = denflxh.data[t, :, :]
 dflxw = denflxw.data[t, :, :]
def test(fileout='python-test.txt'):
    r"""Copy of the Matlab test.

    Modifications: Phil Morgan
                   03-12-12. Lindsay Pender, Converted to ITS-90.
    """
    f = open(fileout, 'w')
    asterisks = '*' * 76

    f.write(asterisks)
    f.write('\n    TEST REPORT    ')
    f.write('\n')
    f.write('\n SEA WATER LIBRARY %s' % sw.__version__)
    f.write('\n')
    # Show some info about this Python.
    f.write('\npython version: %s' % sys.version)
    f.write('\n on %s computer %s' % (uname()[0], uname()[-1]))
    f.write('\n')
    f.write('\n')
    f.write(asctime(localtime()))
    f.write('\n')
    f.write('\n')

    # Test main module  ptmp.
    f.write('\n%s' % asterisks)
    f.write('\n**  TESTING MODULE: ptmp')
    f.write('\n**  and SUB-MODULE: adtg')
    f.write('\n%s' % asterisks)
    f.write('\n')
    f.write('\n')

    # Test 1 - data from Unesco 1983 p45.
    T = np.array([[0, 0, 0, 0, 0, 0], [10, 10, 10, 10, 10, 10],
                  [20, 20, 20, 20, 20, 20], [30, 30, 30, 30, 30, 30],
                  [40, 40, 40, 40, 40, 40]])

    T = T / 1.00024

    S = np.array([[25, 25, 25, 35, 35, 35], [25, 25, 25, 35, 35, 35],
                  [25, 25, 25, 35, 35, 35], [25, 25, 25, 35, 35, 35],
                  [25, 25, 25, 35, 35, 35]])

    P = np.array([[0, 5000, 10000, 0, 5000, 10000],
                  [0, 5000, 10000, 0, 5000, 10000],
                  [0, 5000, 10000, 0, 5000, 10000],
                  [0, 5000, 10000, 0, 5000, 10000],
                  [0, 5000, 10000, 0, 5000, 10000]])

    Pr = np.array([0, 0, 0, 0, 0, 0])

    UN_ptmp = np.array([[0, -0.3061, -0.9667, 0, -0.3856, -1.0974],
                        [10, 9.3531, 8.4684, 10, 9.2906, 8.3643],
                        [20, 19.0438, 17.9426, 20, 18.9985, 17.8654],
                        [30, 28.7512, 27.4353, 30, 28.7231, 27.3851],
                        [40, 38.4607, 36.9254, 40, 38.4498, 36.9023]])

    PT = sw.ptmp(S, T, P, Pr) * 1.00024

    # Display results.
    f.write('\n')
    f.write('\n%s' % asterisks)
    f.write('\nComparison of accepted values from UNESCO 1983 ')
    f.write('\n (Unesco Tech. Paper in Marine Sci. No. 44, p45)')
    f.write('\n%s' % asterisks)
    f.write('\n')

    m, n = S.shape  # TODO: so many loops there must be a better way.
    for icol in range(0, n):
        f.write('\n   Sal  Temp  Press     PTMP       ptmp')
        f.write('\n  (psu)  (C)   (db)     (C)          (C)\n')
        result = np.vstack(
            (S[:, icol], T[:, icol], P[:, icol], UN_ptmp[:, icol], PT[:,
                                                                      icol]))
        for iline in range(0, m):
            f.write(" %4.0f  %4.0f   %5.0f   %8.4f  %11.5f\n" %
                    tuple(result[:, iline]))

    # Test main module svan.
    f.write('\n%s' % asterisks)
    f.write('\n**  TESTING MODULE: svan')
    f.write('\n**  and SUB-MODULE: dens dens0 smow seck pden ptmp')
    f.write('\n%s' % asterisks)

    # Test data FROM: Unesco Tech. Paper in Marine Sci. No. 44, p22.
    s = np.array([0, 0, 0, 0, 35, 35, 35, 35])
    p = np.array([0, 10000, 0, 10000, 0, 10000, 0, 10000])
    t = np.array([0, 0, 30, 30, 0, 0, 30, 30]) / 1.00024

    UN_svan = np.array(
        [2749.54, 2288.61, 3170.58, 3147.85, 0.0, 0.00, 607.14, 916.34])

    SVAN = sw.svan(s, t, p)

    # DISPLAY RESULTS
    f.write('\n')
    f.write('\n%s' % asterisks)
    f.write('\n')
    f.write('\nComparison of accepted values from UNESCO 1983')
    f.write('\n (Unesco Tech. Paper in Marine Sci. No. 44, p22)')
    f.write('\n%s' % asterisks)
    f.write('\n')
    f.write('\n   Sal  Temp  Press        SVAN        svan')
    f.write('\n  (psu)  (C)   (db)    (1e-8*m3/kg)  (1e-8*m3/kg)\n')
    result = np.vstack([s, t, p, UN_svan, 1e+8 * SVAN])
    for iline in range(0, len(SVAN)):
        f.write(" %4.0f  %4.0f   %5.0f   %11.2f    %11.3f\n" %
                tuple(result[:, iline]))

    # Test main module salt.
    f.write('\n%s' % asterisks)
    f.write('\n**  TESTING MODULE: salt')
    f.write('\n**  and SUB-MODULE: salrt salrp sals')
    f.write('\n%s' % asterisks)
    f.write('\n')

    # Test 1 - data from Unesco 1983 p9.
    R = np.array([1, 1.2, 0.65])  # cndr = R.
    T = np.array([15, 20, 5]) / 1.00024
    P = np.array([0, 2000, 1500])
    #Rt   = np.array([  1, 1.0568875, 0.81705885])
    UN_S = np.array([35, 37.245628, 27.995347])

    S = sw.salt(R, T, P)

    # Display results.
    f.write('\n')
    f.write('\n%s' % asterisks)
    f.write('\nComparison of accepted values from UNESCO 1983 ')
    f.write('\n(Unesco Tech. Paper in Marine Sci. No. 44, p9)')
    f.write('\n%s' % asterisks)
    f.write('\n')

    f.write('\n   Temp    Press       R              S           salt')
    f.write('\n   (C)     (db)    (no units)       (psu)          (psu)\n')
    table = np.vstack([T, P, R, UN_S, S])
    m, n = table.shape
    for iline in range(0, n):
        f.write(" %4.0f       %4.0f  %8.2f      %11.6f  %14.7f\n" %
                tuple(table[:, iline]))

    # Test main module cndr.
    f.write('\n%s' % asterisks)
    f.write('\n**  TESTING MODULE: cndr')
    f.write('\n**  and SUB-MODULE: salds')
    f.write('\n%s' % asterisks)

    # Test 1 - data from Unesco 1983 p9.
    T = np.array([0, 10, 0, 10, 10, 30]) / 1.00024
    P = np.array([0, 0, 1000, 1000, 0, 0])
    S = np.array([25, 25, 25, 25, 40, 40])
    UN_R = np.array(
        [0.498088, 0.654990, 0.506244, 0.662975, 1.000073, 1.529967])
    R = sw.cndr(S, T, P)

    # Display results.
    f.write('\n')
    f.write('\n%s' % asterisks)
    f.write('\nComparison of accepted values from UNESCO 1983 ')
    f.write('\n (Unesco Tech. Paper in Marine Sci. No. 44, p14)')
    f.write('\n%s' % asterisks)
    f.write('\n')
    f.write('\n')

    f.write('\n   Temp    Press       S            cndr         cndr')
    f.write('\n   (C)     (db)      (psu)        (no units)    (no units)\n')
    table = np.vstack([T, P, S, UN_R, R])
    m, n = table.shape
    for iline in range(0, n):
        f.write(" %4.0f       %4.0f   %8.6f   %11.6f  %14.8f\n" %
                tuple(table[:, iline]))

    # Test main module depth.
    f.write('\n%s' % asterisks)
    f.write('\n**  TESTING MODULE: depth')
    f.write('\n%s' % asterisks)

    # Test data - matrix "pressure", vector "lat"  Unesco 1983 data p30.
    lat = np.array([0, 30, 45, 90])
    P = np.array([[500, 500, 500, 500], [5000, 5000, 5000, 5000],
                  [10000, 10000, 10000, 10000]])

    UN_dpth = np.array([[496.65, 496.00, 495.34, 494.03],
                        [4915.04, 4908.56, 4902.08, 4889.13],
                        [9725.47, 9712.65, 9699.84, 9674.23]])

    dpth = sw.dpth(P, lat)

    # Display results.
    f.write('\n')
    f.write('\n%s' % asterisks)
    f.write('\nComparison of accepted values from Unesco 1983 ')
    f.write('\n(Unesco Tech. Paper in Marine Sci. No. 44, p28)')
    f.write('\n%s' % asterisks)
    f.write('\n')

    f.write('\n')
    for irow in range(0, 3):
        f.write('\n    Lat       Press     DPTH      dpth')
        f.write('\n  (degree)    (db)     (meter)    (meter)\n')
        table = np.vstack([lat, P[irow, :], UN_dpth[irow, :], dpth[irow, :]])
        m, n = table.shape
        for iline in range(0, n):
            f.write("  %6.3f     %6.0f   %8.2f   %8.3f\n" %
                    tuple(table[:, iline]))

    # Test main module fp.
    f.write('\n%s' % asterisks)
    f.write('\n**  TESTING MODULE: fp')
    f.write('\n%s' % asterisks)

    # Test 1 - UNESCO data p.30.
    S = np.array([[5, 10, 15, 20, 25, 30, 35, 40],
                  [5, 10, 15, 20, 25, 30, 35, 40]])

    P = np.array([[0, 0, 0, 0, 0, 0, 0, 0],
                  [500, 500, 500, 500, 500, 500, 500, 500]])

    UN_fp = np.array(
        [[-0.274, -0.542, -0.812, -1.083, -1.358, -1.638, -1.922, -2.212],
         [-0.650, -0.919, -1.188, -1.460, -1.735, -2.014, -2.299, -2.589]])

    FP = sw.fp(S, P)

    # Display results.
    f.write('\n')
    f.write('\n%s' % asterisks)
    f.write('\nComparison of accepted values from UNESCO 1983 ')
    f.write('\n (Unesco Tech. Paper in Marine Sci. No. 44, p30)')
    f.write('\n%s' % asterisks)
    f.write('\n')

    f.write('\n')
    for irow in range(0, 2):
        f.write('\n   Sal   Press      fp        fp')
        f.write('\n  (psu)   (db)      (C)        (C)\n')
        table = np.vstack(
            [S[irow, :], P[irow, :], UN_fp[irow, :], FP[irow, :]])
        m, n = table.shape
        for iline in range(0, n):
            f.write(" %4.0f   %5.0f   %8.3f  %11.4f\n" %
                    tuple(table[:, iline]))

    # Test main module cp.
    f.write('\n%s' % asterisks)
    f.write('\n**  TESTING MODULE: cp')
    f.write('\n%s' % asterisks)

    # Test 1.
    # Data from Pond and Pickard Intro. Dynamical Oceanography 2nd ed. 1986
    T = np.array([[0, 0, 0, 0, 0, 0], [10, 10, 10, 10, 10, 10],
                  [20, 20, 20, 20, 20, 20], [30, 30, 30, 30, 30, 30],
                  [40, 40, 40, 40, 40, 40]]) / 1.00024

    S = np.array([[25, 25, 25, 35, 35, 35], [25, 25, 25, 35, 35, 35],
                  [25, 25, 25, 35, 35, 35], [25, 25, 25, 35, 35, 35],
                  [25, 25, 25, 35, 35, 35]])

    P = np.array([[0, 5000, 10000, 0, 5000, 10000],
                  [0, 5000, 10000, 0, 5000, 10000],
                  [0, 5000, 10000, 0, 5000, 10000],
                  [0, 5000, 10000, 0, 5000, 10000],
                  [0, 5000, 10000, 0, 5000, 10000]])

    UN_cp = np.array([[4048.4, 3896.3, 3807.7, 3986.5, 3849.3, 3769.1],
                      [4041.8, 3919.6, 3842.3, 3986.3, 3874.7, 3804.4],
                      [4044.8, 3938.6, 3866.7, 3993.9, 3895.0, 3828.3],
                      [4049.1, 3952.0, 3883.0, 4000.7, 3909.2, 3844.3],
                      [4051.2, 3966.1, 3905.9, 4003.5, 3923.9, 3868.3]])

    CP = sw.cp(S, T, P)

    # Display results.
    f.write('\n')
    f.write('\n%s' % asterisks)
    f.write('\nComparison of accepted values from UNESCO 1983 ')
    f.write('\n (Unesco Tech. Paper in Marine Sci. No. 44, p37)')
    f.write('\n%s' % asterisks)
    f.write('\n')

    m, n = S.shape
    f.write('\n')
    for icol in range(0, n):
        f.write('\n   Sal  Temp  Press      Cp        cp')
        f.write('\n  (psu)  (C)   (db)    (J/kg.C)   (J/kg.C)\n')
        result = np.vstack(
            [S[:, icol], T[:, icol], P[:, icol], UN_cp[:, icol], CP[:, icol]])
        for iline in range(0, m):
            f.write(" %4.0f  %4.0f   %5.0f   %8.1f  %11.2f\n" %
                    tuple(result[:, iline]))

    # Test main module svel.
    f.write('\n%s' % asterisks)
    f.write('\n**  TESTING MODULE: svel')
    f.write('\n%s' % asterisks)

    # Test 1.
    # Data from Pond and Pickard Intro. Dynamical Oceanography 2nd ed. 1986
    T = np.array([[0, 0, 0, 0, 0, 0], [10, 10, 10, 10, 10, 10],
                  [20, 20, 20, 20, 20, 20], [30, 30, 30, 30, 30, 30],
                  [40, 40, 40, 40, 40, 40]]) / 1.00024

    S = np.array([[25, 25, 25, 35, 35, 35], [25, 25, 25, 35, 35, 35],
                  [25, 25, 25, 35, 35, 35], [25, 25, 25, 35, 35, 35],
                  [25, 25, 25, 35, 35, 35]])

    P = np.array([[0, 5000, 10000, 0, 5000, 10000],
                  [0, 5000, 10000, 0, 5000, 10000],
                  [0, 5000, 10000, 0, 5000, 10000],
                  [0, 5000, 10000, 0, 5000, 10000],
                  [0, 5000, 10000, 0, 5000, 10000]])

    UN_svel = np.array([[1435.8, 1520.4, 1610.4, 1449.1, 1534.0, 1623.2],
                        [1477.7, 1561.3, 1647.4, 1489.8, 1573.4, 1659.0],
                        [1510.3, 1593.6, 1676.8, 1521.5, 1604.5, 1687.2],
                        [1535.2, 1619.0, 1700.6, 1545.6, 1629.0, 1710.1],
                        [1553.4, 1638.0, 1719.2, 1563.2, 1647.3, 1727.8]])

    SVEL = sw.svel(S, T, P)

    # Display results.
    f.write('\n')
    f.write('\n%s' % asterisks)
    f.write('\nComparison of accepted values from UNESCO 1983 ')
    f.write('\n (Unesco Tech. Paper in Marine Sci. No. 44, p50)')
    f.write('\n%s' % asterisks)
    f.write('\n')

    m, n = SVEL.shape
    f.write('\n')
    for icol in range(0, n):
        f.write('\n   Sal  Temp  Press     SVEL       svel')
        f.write('\n  (psu)  (C)   (db)     (m/s)       (m/s)\n')

        result = np.vstack([
            S[:, icol], T[:, icol], P[:, icol], UN_svel[:, icol], SVEL[:, icol]
        ])
        for iline in range(0, m):
            f.write(" %4.0f  %4.0f   %5.0f   %8.1f  %11.3f\n" %
                    tuple(result[:, iline]))

    # Test submodules alpha beta aonb.
    f.write('\n%s' % asterisks)
    f.write('\n**  and SUB-MODULE: alpha beta aonb')
    f.write('\n%s' % asterisks)

    # Data from McDouogall 1987.
    s = 40
    PT = 10
    p = 4000
    beta_lit = 0.72088e-03
    aonb_lit = 0.34763
    alpha_lit = aonb_lit * beta_lit

    BETA = sw.beta(s, PT, p, pt=True)
    ALPHA = sw.alpha(s, PT, p, pt=True)
    AONB = sw.aonb(s, PT, p, pt=True)

    # Display results.
    f.write('\n')
    f.write('\n%s' % asterisks)
    f.write('\nComparison of accepted values from MCDOUGALL 1987 ')
    f.write('\n%s' % asterisks)
    f.write('\n')
    f.write('\n')

    f.write('\n   Sal  Temp  Press     BETA       beta')
    f.write('\n  (psu)  (C)   (db)   (psu^-1)     (psu^-1)\n')
    table = np.hstack([s, PT, p, beta_lit, BETA])
    f.write(" %4.0f  %4.0f   %5.0f   %11.4e  %11.5e\n" % tuple(table))

    f.write('\n   Sal  Temp  Press     AONB       aonb')
    f.write('\n  (psu)  (C)   (db)   (psu C^-1)   (psu C^-1)\n')
    table = np.hstack([s, PT, p, aonb_lit, AONB])
    f.write(" %4.0f  %4.0f   %5.0f   %8.5f  %11.6f\n" % tuple(table))

    f.write('\n   Sal  Temp  Press     ALPHA       alpha')
    f.write('\n  (psu)  (C)   (db)    (psu^-1)     (psu^-1)\n')
    table = np.hstack([s, PT, p, alpha_lit, ALPHA])
    f.write(" %4.0f  %4.0f   %5.0f   %11.4e  %11.4e\n" % tuple(table))

    # Test main moduleS  satO2 satN2 satAr.
    f.write('\n%s' % asterisks)
    f.write('\n**  TESTING MODULE: satO2 satN2 satAr')
    f.write('\n%s' % asterisks)
    f.write('\n')

    # Data from Weiss 1970.
    T = np.array([[-1, -1], [10, 10], [20, 20], [40, 40]]) / 1.00024

    S = np.array([[20, 40], [20, 40], [20, 40], [20, 40]])

    lit_O2 = np.array([[9.162, 7.984], [6.950, 6.121], [5.644, 5.015],
                       [4.050, 3.656]])

    lit_N2 = np.array([[16.28, 14.01], [12.64, 11.01], [10.47, 9.21],
                       [7.78, 6.95]])

    lit_Ar = np.array([[0.4456, 0.3877], [0.3397, 0.2989], [0.2766, 0.2457],
                       [0.1986, 0.1794]])

    O2 = sw.satO2(S, T)
    N2 = sw.satN2(S, T)
    Ar = sw.satAr(S, T)

    # Display results.
    f.write('\n')
    f.write('\n%s' % asterisks)
    f.write('\nComparison of accepted values from Weiss, R.F. 1979 ')
    f.write('\n"The solubility of nitrogen, oxygen and argon in water')
    f.write('\n and seawater." Deep-Sea Research., 1970, Vol 17, pp721-735.')
    f.write('\n%s' % asterisks)
    f.write('\n')

    m, n = S.shape
    f.write('\n')
    for icol in range(0, n):
        f.write('\n   Sal  Temp      O2         satO2')
        f.write('\n  (psu)  (C)      (ml/l)     (ml/l)\n')
        result = np.vstack(
            [S[:, icol], T[:, icol], lit_O2[:, icol], O2[:, icol]])
        for iline in range(0, m):
            f.write(" %4.0f  %4.0f    %8.2f   %9.3f\n" %
                    tuple(result[:, iline]))

    for icol in range(0, n):
        f.write('\n   Sal  Temp      N2         satN2')
        f.write('\n  (psu)  (C)      (ml/l)     (ml/l)\n')
        result = np.vstack(
            [S[:, icol], T[:, icol], lit_N2[:, icol], N2[:, icol]])
        for iline in range(0, m):
            f.write(" %4.0f  %4.0f    %8.2f  %9.3f\n" %
                    tuple(result[:, iline]))

    for icol in range(0, n):
        f.write('\n   Sal  Temp      Ar         satAr')
        f.write('\n  (psu)  (C)      (ml/l)     (ml/l)\n')
        result = np.vstack(
            [S[:, icol], T[:, icol], lit_Ar[:, icol], Ar[:, icol]])
        for iline in range(0, m):
            f.write(" %4.0f  %4.0f     %8.4f  %9.4f\n" %
                    tuple(result[:, iline]))
Пример #4
0
def makeHeatContent(salt,temp,destMask,thetao,pressure):
    """
    The makeHeatContent() function takes 3D (not temporal) arguments and creates
    heat content which is then mapped to a destination grid and written to a
    specified variable

    Author: Paul J. Durack : [email protected] : @durack1.
    Created on Tue Nov 24 15:34:30 2015.

    Inputs:
    ------
    - salt(lev,lat,lon) - 3D array.
    - temp(lev,lat,lon) - 3D array either in-situ or potential temperature.
    - destGridArray(str) - 2D array with valid grid and mask.
    - thetao(bool) - boolean value specifying either in-situ or potential temperature arrays provided.
    - pressure(bool) - boolean value specifying whether lev-coordinate is pressure (dbar) or depth (m).

    Usage:
    ------
        >>> from oceanLib import makeHeatContent
        >>> makeHeatContent(salt,temp,destGridArray,thetao=True,pressure=False)

    Notes:
    -----
    - PJD 24 Nov 2015 - Migrated into new oceanLib from heatContentLib
    - TODO: Better deal with insitu vs thetao variables
    - TODO:
    """

    # Remap variables to short names
    #print salt.getAxisIds()
    s       = salt(squeeze=1) ; # Trim off singleton time dimension
    #print s.getAxisIds()
    t       = temp(squeeze=1)
    mask    = destMask
    #print mask.getAxisIds()
    del(salt,temp,destMask) ; gc.collect()
    depthInd = 0 ; # Set depth coordinate index

    #print 's:    ',s.min(),s.max()
    #print 't:    ',t.min(),t.max()

    # Fix out of bounds values
    t = mv.where(t<-2.6,-2.6,t) ; # Fix for NaN values

    # Calculate pressure - inputs depth & lat
    # Create z-coordinate from salinity input
    if not pressure:
        zCoord                         = s.getAxis(depthInd) ; # Assume time,depth,latitude,longitude grid
        yCoord                         = s.getAxis(depthInd+1)
        yCoord                         = tile(yCoord,(s.shape[depthInd+2],1)).transpose()
        depthLevels                    = tile(zCoord.getValue(),(s.shape[depthInd+2],s.shape[depthInd+1],1)).transpose()
        pressureLevels                 = sw.pres(np.array(depthLevels),np.array(yCoord))
        del(zCoord,yCoord,depthLevels) ; gc.collect()
    else:
        pressureLevels                 = s.getAxis(depthInd)
        #print pressureLevels.getValue()
        pressureLevels                 = transpose(tile(pressureLevels,(s.shape[depthInd+2],s.shape[depthInd+1],1)))
    pressureLevels                 = cdm.createVariable(pressureLevels,id='pressureLevels')
    pressureLevels.setAxis(0,s.getAxis(depthInd))
    pressureLevels.setAxis(1,s.getAxis(depthInd+1))
    pressureLevels.setAxis(2,s.getAxis(depthInd+2))
    pressureLevels.units_long      = 'decibar (pressure)'
    pressureLevels.positive        = 'down'
    pressureLevels.long_name       = 'sea_water_pressure'
    pressureLevels.standard_name   = 'sea_water_pressure'
    pressureLevels.units           = 'decibar'
    pressureLevels.axis            = 'Z'

    #print 'pres: ',pressureLevels.min(),pressureLevels.max()
    #print pressureLevels.shape
    #print s.shape
    #print t.shape
    #print mask.shape

    # Calculate temp,rho,cp - inputs temp,salt,pressure
    if thetao:
        # Process potential temperature to in-situ
        temp        = sw.temp(np.array(s),np.array(t),np.array(pressureLevels)); # units degrees C
    rho             = sw.dens(np.array(s),np.array(temp),np.array(pressureLevels)) ; # units kg m-3
    cp              = sw.cp(np.array(s),np.array(temp),np.array(pressureLevels)) ; # units J kg-1 C-1

    # Correct instances of NaN values and fix masks - applied before cdms variables are created otherwise names/ids/attributes are reset
    temp            = scrubNaNAndMask(temp,s)
    rho             = scrubNaNAndMask(rho,s)
    cp              = scrubNaNAndMask(cp,s)

    #print 'temp: ',temp.min(),temp.max()
    #print 'rho:  ',rho.min(),rho.max()
    #print 'cp:   ',cp.min(),cp.max()

    # Calculate heatContent - inputs temp,rho,cp
    heatContent     = np.array(temp)*np.array(rho)*np.array(cp) ; # units J

    # Correct instances of NaN values and fix masks - applied before cdms variables are created otherwise names/ids/attributes are reset
    heatContent     = scrubNaNAndMask(heatContent,s)
    #print 'hc:   ',heatContent.min(),heatContent.max()

    # Interpolate to standard levels - inputs heatContent,levels
    newDepth        = np.array([5,10,20,30,40,50,75,100,125,150,200,300,500,700,1000,1500,1800,2000]).astype('f');
    newDepth_bounds = np.array([[0,5],[5,10],[10,20],[20,30],[30,40],[40,50],[50,75],[75,100],[100,125],[125,150],
                                [150,200],[200,300],[300,500],[500,700],[700,1000],[1000,1500],[1500,1800],[1800,2000]]).astype('f')
    # Interpolate to standard levels
    #print heatContent.shape
    #print heatContent.getAxisIds()
    #print pressureLevels.shape
    #print pressureLevels.getAxisIds()

    # Reset variable axes
    heatContent.setAxis(0,s.getAxis(0))
    #heatContent.setAxis(1,s.getAxis(1))
    #heatContent.setAxis(2,s.getAxis(2))

    pdb.set_trace()

    heatContent.setGrid(s.getGrid())


    #print heatContent.shape
    #print heatContent.getAxisIds()
    #print pressureLevels.shape
    #print pressureLevels.getAxisIds()

    heatContent_depthInterp     = cdu.linearInterpolation(heatContent,pressureLevels,levels=newDepth)
    # Fix bounds
    newDepth = heatContent_depthInterp.getAxis(0)
    newDepth.setBounds(newDepth_bounds)
    del(newDepth_bounds)
    newDepth.id             = 'depth2'
    newDepth.units_long     = 'decibar (pressure)'
    newDepth.positive       = 'down'
    newDepth.long_name      = 'sea_water_pressure'
    newDepth.standard_name  = 'sea_water_pressure'
    newDepth.units          = 'decibar'
    newDepth.axis           = 'Z'

    #print 'hc_interp:',heatContent_depthInterp.min(),heatContent_depthInterp.max()

    # Integrate to 700 dbar - inputs heatContent

    heatContent_depthInteg = cdu.averager(heatContent_depthInterp[0:14,...],axis=0,weights='weighted',action='sum')(squeeze=1) # Calculate depth-weighted-integrated thetao
    # Assign all axis info

    #print heatContent_depthInteg.shape
    pdb.set_trace()
    # Interpolate in x,y - inputs heatContent
    #tmp1 = heatContent_depthInteg.regrid(mask.getGrid(),regridTool='esmf',regridMethod='linear') ; # Use defaults - ,coordSys='deg',diag = {},periodicity=1)
    tmp1 = heatContent_depthInteg.regrid(mask,regridTool='esmf',regridMethod='linear') ; # Use defaults - ,coordSys='deg',diag = {},periodicity=1)
    #print tmp1.shape

    tmp1 = mv.where(tmp1<0,0,tmp1) ; # Fix for negative values

    # Infill - inputs heatContent
    # Create inputs for interpolation
    points = np.zeros([(mask.shape[0]*mask.shape[1]),2]) ; # Create 25380 vectors of lon/lat
    latcounter = 0 ; loncounter = 0
    for count,data in enumerate(points):
        if not np.mod(count,180) and not count == 0:
            latcounter = latcounter + 1
            loncounter = 0
        points[count,0] = mask.getLatitude().getValue()[latcounter]
        points[count,1] = mask.getLongitude().getValue()[loncounter]
        loncounter = loncounter + 1
    del(count,data,latcounter,loncounter); gc.collect()
    valid = np.logical_not(tmp1.mask) ; # Get inverted-logic boolean mask from variable
    if valid.size == 1:
        print '** No valid mask found, skipping **'
        return
    valid = valid.flatten() ; # Flatten 2D to 1D

    #maskFilled  = mask(tmp,points,valid)
    interpolant = interpolate.LinearNDInterpolator(points[valid,:],np.array(tmp1.flatten())[valid]) ; # Create interpolant
    maskFill    = interpolant(points[:,0].squeeze(),points[:,1].squeeze()) ; # Use interpolant to create filled matrix
    maskFill    = np.reshape(maskFill,mask.shape) ; # Resize to original dimensions

    # Fix issues with interpolant
    tmp2 = mv.where(np.isnan(maskFill),1e+20,maskFill) ; # Fix for NaN values
    tmp2 = mv.where(tmp2>tmp1.max(),0,tmp2) ; # Fix for max values
    tmp2 = mv.where(tmp2<tmp1.min(),0,tmp2) ; # Fix for min values
    tmp = mv.masked_where(mask.mask,tmp2)
    #print tmp.shape

    # Redress variable
    heatContent                 = cdm.createVariable([tmp],id='heatContent')
    depthInt                    = cdm.createAxis([350],id='depth')
    depthInt.setBounds(np.array([0,700]))
    depthInt.units_long     = 'decibar (pressure)'
    depthInt.positive       = 'down'
    depthInt.long_name      = 'sea_water_pressure'
    depthInt.standard_name  = 'sea_water_pressure'
    depthInt.units          = 'decibar'
    depthInt.axis           = 'Z'
    heatContent.setAxis(0,depthInt)
    heatContent.setAxis(1,mask.getAxis(0))
    heatContent.setAxis(2,mask.getAxis(1))
    heatContent.units_long      = 'Joules'
    heatContent.long_name       = 'sea_water_heat_content'
    heatContent.standard_name   = 'sea_water_heat_content'
    heatContent.units           = 'J'

    return heatContent ; #,tmp1 ; # 0-700 dbar standard masked variable
Пример #5
0
def makeSteric(salinity,salinityChg,temp,tempChg,outFileName,thetao,pressure):
    """
    The makeSteric() function takes 3D (not temporal) arguments and creates
    heat content and steric fields which are written to a specified outfile

    Author: Paul J. Durack : [email protected] : @durack1.
    Created on Thu Jul 18 13:03:37 2013.

    Inputs:
    ------
    - salinity(lev,lat,lon) - 3D array for the climatological period.
    - salinityChg(lev,lat,lon) - 3D array for the temporal change period.
    - temp(lev,lat,lon) - 3D array for the climatological period either in-situ or potential temperature.
    - tempChg(lev,lat,lon) - 3D array for the temporal change period as with temp, either in-situ or potential temperature.
    - outFileName(str) - output filename with full path specified.
    - thetao(bool) - boolean value specifying either in-situ or potential temperature arrays provided.
    - pressure(bool) - boolean value specifying whether lev-coordinate is pressure (dbar) or depth (m).

    Usage:
    ------
        >>> from makeStericLib import makeSteric
        >>> makeSteric(salinity,salinityChg,thetao,thetaoChg,'outfile.nc',True,False)

    Notes:
    -----
    - PJD 18 Jul 2013 - Validated Ishii v6.13 data against WOA94 - checks out ok. Units: dyn decimeter compared to http://www.nodc.noaa.gov/OC5/WOA94/dyn.html uses cm (not decimeter; x 10)
    - PJD 18 Jul 2013 - Added attribute scrub to incoming variables (so,so_chg,temp,temp_chg) to maintain output consistency
    - PJD 22 Jul 2013 - Added name attributes to so and temp variables, added units to so_chg
    - PJD 22 Jul 2013 - removed duplicated code by converting repetition to function scrubNaNAndMask
    - PJD 23 Jul 2013 - Further cleaned up so,so_chg,temp,temp_chg outputs specifying id/name attributes
    - PJD  5 Aug 2013 - Updated python-seawater library to version 3.3.1 from github repo, git clone http://github.com/ocefpaf/python-seawater, python setup.py install --user
    - PJD  7 Aug 2013 - FIXED: thetao rather than in-situ temperature propagating throughout calculations
    - PJD  7 Aug 2013 - Replaced looping with 3D gpan
    - PJD  7 Aug 2013 - Further code duplication cleanup
    - PJD  8 Aug 2013 - FIXED: scrubNanAndMask function type/mask/grid issue - encase sw arguments in np.array() (attempt to strip cdms fluff)
    - PJD  8 Aug 2013 - FIXED: removed depth variable unit edits - not all inputs are depth (m)
    - PJD 15 Aug 2013 - Increased interpolated field resolution [200,300,500,700,1000,1500,1800,2000] - [5,10,20,30,40,50,75,100,125,150,200, ...]
    - PJD 18 Aug 2013 - AR5 hard coded rho=1020,cp=4187 == 4.3e6 vs Ishii 1970 rho.mean=1024,cp.mean=3922 == 4.1e6 ~5% too high
    - PJD 13 Jan 2014 - Corrected steric_height_anom and steric_height_thermo_anom to true anomaly fields, needed to remove climatology
    - PJD  3 May 2014 - Turned off thetao conversion, although convert to numpy array rather than cdms2 transient variable
    - PJD 13 Oct 2014 - Added seawater_library_version as a global attribute
    - PJD 13 Oct 2014 - FIXED: bug with calculation of rho_halo variable was calculating gpan
    - PJD 13 Oct 2014 - Added alternate calculation of halosteric anomaly (direct salinity anomaly calculation, rather than total-thermosteric)
    - PJD 13 Oct 2014 - Added makeSteric_version as a global attribute
    - TODO: Better deal with insitu vs thetao variables
    - TODO: Query Charles on why *.name attributes are propagating
    - TODO: validate outputs and compare to matlab versions - 10e-7 errors.
    """

    # Remap all variables to short names
    so          = salinity
    so_chg      = salinityChg
    temp        = temp
    temp_chg    = tempChg
    del(salinity,salinityChg,tempChg) ; gc.collect()

    # Strip attributes to maintain consistency between datasets
    for count,x in enumerate(so.attributes.keys()):
        delattr(so,x)
    #print so.listattributes() ; # Print remaining attributes
    for count,x in enumerate(so_chg.attributes.keys()):
        delattr(so_chg,x)
    for count,x in enumerate(temp.attributes.keys()):
        delattr(temp,x)
    for count,x in enumerate(temp_chg.attributes.keys()):
        delattr(temp_chg,x)
    del(count,x)

    # Create z-coordinate from salinity input
    if not pressure:
        z_coord                         = so.getAxis(0)
        y_coord                         = so.getAxis(1)
        y_coord                         = tile(y_coord,(so.shape[2],1)).transpose()
        depth_levels                    = tile(z_coord.getValue(),(so.shape[2],so.shape[1],1)).transpose()
        pressure_levels                 = sw.pres(np.array(depth_levels),np.array(y_coord))
        del(z_coord,y_coord,depth_levels) ; gc.collect()
    else:
        pressure_levels                 = so.getAxis(0)
        pressure_levels                 = transpose(tile(pressure_levels,(so.shape[2],so.shape[1],1)))

    pressure_levels                 = cdm.createVariable(pressure_levels,id='pressure_levels')
    pressure_levels.setAxis(0,so.getAxis(0))
    pressure_levels.setAxis(1,so.getAxis(1))
    pressure_levels.setAxis(2,so.getAxis(2))
    pressure_levels.id              = 'pressure_levels'
    pressure_levels.units_long      = 'decibar (pressure)'
    pressure_levels.positive        = 'down'
    pressure_levels.long_name       = 'sea_water_pressure'
    pressure_levels.standard_name   = 'sea_water_pressure'
    pressure_levels.units           = 'decibar'
    pressure_levels.axis            = 'Z'

    # Cleanup depth axis attributes
    depth               = so.getAxis(0)
    depth.id            = 'depth'
    depth.name          = 'depth'
    depth.long_name     = 'depth'
    depth.standard_name = 'depth'
    depth.axis          = 'Z'
    so.setAxis(0,depth)
    so_chg.setAxis(0,depth)
    temp.setAxis(0,depth)
    temp_chg.setAxis(0,depth)
    del(depth)

    # Convert using python-seawater library (v3.3.1 - 130807)
    if thetao:
        # Process potential temperature to in-situ - default conversion sets reference pressure to 0 (surface)
        #temp_chg                = sw.temp(np.array(so),np.array(temp_chg),np.array(pressure_levels)); # units degrees C
        #temp                    = sw.temp(np.array(so),np.array(temp),np.array(pressure_levels)); # units degrees C
        #temp_chg                = sw.ptmp(np.array(so),np.array(temp_chg),np.array(pressure_levels),np.array(pressure_levels)); # units degrees C
        #temp                    = sw.ptmp(np.array(so),np.array(temp),np.array(pressure_levels),np.array(pressure_levels)); # units degrees C
        temp_chg                = np.array(temp_chg); # units degrees C
        temp                    = np.array(temp); # units degrees C

    # Climatologies - rho,cp,steric_height
    rho                         = sw.dens(np.array(so),np.array(temp),np.array(pressure_levels)) ; # units kg m-3
    cp                          = sw.cp(np.array(so),np.array(temp),np.array(pressure_levels)) ; # units J kg-1 C-1
    steric_height               = sw.gpan(np.array(so),np.array(temp),np.array(pressure_levels)) ; # units m3 kg-1 Pa == m2 s-2 == J kg-1 (dynamic decimeter)

    # Halosteric - rho,cp
    ss                          = map(array,(so+so_chg))
    rho_halo                    = sw.dens(np.array(ss),np.array(temp),np.array(pressure_levels)) ; # units kg m-3
    cp_halo                     = sw.cp(np.array(ss),np.array(temp),np.array(pressure_levels)) ; # units J kg-1 C-1
    tmp                         = sw.gpan(np.array(ss),np.array(temp),np.array(pressure_levels)) ; # units m3 kg-1 Pa == m2 s-2 == J kg-1 (dynamic decimeter)
    steric_height_halo_anom2    = tmp-steric_height ; # units m3 kg-1 Pa == m2 s-2 == J kg-1 (dynamic decimeter)

    # Full steric - steric_height
    tt                          = map(array,(temp+temp_chg))
    tmp                         = sw.gpan(np.array(ss),np.array(tt),np.array(pressure_levels)) ; # units m3 kg-1 Pa == m2 s-2 == J kg-1 (dynamic decimeter)
    steric_height_anom          = tmp-steric_height ; # units m3 kg-1 Pa == m2 s-2 == J kg-1 (dynamic decimeter)
    del(ss,tmp) ; gc.collect()

    # Thermosteric - rho,cp,steric_height
    rho_thermo                  = sw.dens(np.array(so),np.array(tt),np.array(pressure_levels)) ; # units kg m-3
    cp_thermo                   = sw.cp(np.array(so),np.array(tt),np.array(pressure_levels)) ; # units J kg-1 C-1
    tmp                         = sw.gpan(np.array(so),np.array(tt),np.array(pressure_levels)) ; # units m3 kg-1 Pa == m2 s-2 == J kg-1 (dynamic decimeter)
    steric_height_thermo_anom   = tmp-steric_height ; # units m3 kg-1 Pa == m2 s-2 == J kg-1 (dynamic decimeter)
    del(tt,tmp) ; gc.collect()

    # Halosteric - steric_height
    steric_height_halo_anom     = steric_height_anom-steric_height_thermo_anom ; # units m3 kg-1 Pa == m2 s-2 == J kg-1 (dynamic decimeter)

    # Create heat content
    heat_content                = np.array(temp)*np.array(rho)*np.array(cp) ; # units J
    heat_content_sanom          = np.array(temp)*np.array(rho_halo)*np.array(cp_halo) ; # units J
    heat_content_tanom          = np.array(temp_chg)*np.array(rho)*np.array(cp) ; # units J
    #heat_content_tanom          = np.array(temp_chg)*np.array(1020)*np.array(4187) ; # units J - try hard-coded - AR5 numbers
    heat_content_tsanom         = np.array(temp_chg)*np.array(rho_halo)*np.array(cp_halo) ; # units J

    # Correct all instances of NaN values and fix masks - applied before cdms variables are created otherwise names/ids/attributes are reset
    temp                        = scrubNaNAndMask(temp,so)
    temp_chg                    = scrubNaNAndMask(temp_chg,so)
    rho                         = scrubNaNAndMask(rho,so)
    cp                          = scrubNaNAndMask(cp,so)
    rho_halo                    = scrubNaNAndMask(rho_halo,so)
    cp_halo                     = scrubNaNAndMask(cp_halo,so)
    rho_thermo                  = scrubNaNAndMask(rho_thermo,so)
    cp_thermo                   = scrubNaNAndMask(cp_thermo,so)
    steric_height               = scrubNaNAndMask(steric_height,so)
    steric_height_anom          = scrubNaNAndMask(steric_height_anom,so)
    steric_height_thermo_anom   = scrubNaNAndMask(steric_height_thermo_anom,so)
    steric_height_halo_anom     = scrubNaNAndMask(steric_height_halo_anom,so)
    steric_height_halo_anom2    = scrubNaNAndMask(steric_height_halo_anom2,so)
    heat_content                = scrubNaNAndMask(heat_content,so)
    heat_content_sanom          = scrubNaNAndMask(heat_content_sanom,so)
    heat_content_tanom          = scrubNaNAndMask(heat_content_tanom,so)
    heat_content_tsanom         = scrubNaNAndMask(heat_content_tsanom,so)

    # Recreate and redress variables
    so.id                           = 'so_mean'
    so.units                        = '1e-3'
    so_chg.id                       = 'so_chg'
    so_chg.units                    = '1e-3'
    temp                            = cdm.createVariable(temp,id='temp_mean')
    temp.setAxis(0,so.getAxis(0))
    temp.setAxis(1,so.getAxis(1))
    temp.setAxis(2,so.getAxis(2))
    temp.units                      = 'degrees_C'
    temp_chg                        = cdm.createVariable(temp_chg,id='temp_chg')
    temp_chg.setAxis(0,so.getAxis(0))
    temp_chg.setAxis(1,so.getAxis(1))
    temp_chg.setAxis(2,so.getAxis(2))
    temp_chg.units                  = 'degrees_C'
    rho                             = cdm.createVariable(rho,id='rho')
    rho.setAxis(0,so.getAxis(0))
    rho.setAxis(1,so.getAxis(1))
    rho.setAxis(2,so.getAxis(2))
    rho.name                        = 'density_mean'
    rho.units                       = 'kg m^-3'
    cp                              = cdm.createVariable(cp,id='cp')
    cp.setAxis(0,so.getAxis(0))
    cp.setAxis(1,so.getAxis(1))
    cp.setAxis(2,so.getAxis(2))
    cp.name                         = 'heat_capacity_mean'
    cp.units                        = 'J kg^-1 C^-1'
    rho_halo                        = cdm.createVariable(rho_halo,id='rho_halo')
    rho_halo.setAxis(0,so.getAxis(0))
    rho_halo.setAxis(1,so.getAxis(1))
    rho_halo.setAxis(2,so.getAxis(2))
    rho_halo.name                   = 'density_mean_halo'
    rho_halo.units                  = 'kg m^-3'
    cp_halo                         = cdm.createVariable(cp_halo,id='cp_halo')
    cp_halo.setAxis(0,so.getAxis(0))
    cp_halo.setAxis(1,so.getAxis(1))
    cp_halo.setAxis(2,so.getAxis(2))
    cp_halo.name                    = 'heat_capacity_mean_halo'
    cp_halo.units                   = 'J kg^-1 C^-1'
    rho_thermo                      = cdm.createVariable(rho_thermo,id='rho_thermo')
    rho_thermo.setAxis(0,so.getAxis(0))
    rho_thermo.setAxis(1,so.getAxis(1))
    rho_thermo.setAxis(2,so.getAxis(2))
    rho_thermo.name                 = 'density_mean_thermo'
    rho_thermo.units                = 'kg m^-3'
    cp_thermo                       = cdm.createVariable(cp_thermo,id='cp_thermo')
    cp_thermo.setAxis(0,so.getAxis(0))
    cp_thermo.setAxis(1,so.getAxis(1))
    cp_thermo.setAxis(2,so.getAxis(2))
    cp_thermo.name                  = 'heat_capacity_mean_thermo'
    cp_thermo.units                 = 'J kg^-1 C^-1'
    steric_height                   = cdm.createVariable(steric_height,id='steric_height')
    steric_height.setAxis(0,so.getAxis(0))
    steric_height.setAxis(1,so.getAxis(1))
    steric_height.setAxis(2,so.getAxis(2))
    steric_height.units             = 'm^3 kg^-1 Pa (dynamic decimeter)'
    steric_height_anom              = cdm.createVariable(steric_height_anom,id='steric_height_anom')
    steric_height_anom.setAxis(0,so.getAxis(0))
    steric_height_anom.setAxis(1,so.getAxis(1))
    steric_height_anom.setAxis(2,so.getAxis(2))
    steric_height_anom.units        = 'm^3 kg^-1 Pa (dynamic decimeter)'
    steric_height_thermo_anom       = cdm.createVariable(steric_height_thermo_anom,id='steric_height_thermo_anom')
    steric_height_thermo_anom.setAxis(0,so.getAxis(0))
    steric_height_thermo_anom.setAxis(1,so.getAxis(1))
    steric_height_thermo_anom.setAxis(2,so.getAxis(2))
    steric_height_thermo_anom.units = 'm^3 kg^-1 Pa (dynamic decimeter)'
    steric_height_halo_anom         = cdm.createVariable(steric_height_halo_anom,id='steric_height_halo_anom')
    steric_height_halo_anom.setAxis(0,so.getAxis(0))
    steric_height_halo_anom.setAxis(1,so.getAxis(1))
    steric_height_halo_anom.setAxis(2,so.getAxis(2))
    steric_height_halo_anom.units   = 'm^3 kg^-1 Pa (dynamic decimeter)'
    steric_height_halo_anom2         = cdm.createVariable(steric_height_halo_anom2,id='steric_height_halo_anom2')
    steric_height_halo_anom2.setAxis(0,so.getAxis(0))
    steric_height_halo_anom2.setAxis(1,so.getAxis(1))
    steric_height_halo_anom2.setAxis(2,so.getAxis(2))
    steric_height_halo_anom2.units   = 'm^3 kg^-1 Pa (dynamic decimeter)'
    heat_content                    = cdm.createVariable(heat_content,id='heat_content')
    heat_content.setAxis(0,so.getAxis(0))
    heat_content.setAxis(1,so.getAxis(1))
    heat_content.setAxis(2,so.getAxis(2))
    heat_content.units         = 'J'
    heat_content_sanom              = cdm.createVariable(heat_content_sanom,id='heat_content_sanom')
    heat_content_sanom.setAxis(0,so.getAxis(0))
    heat_content_sanom.setAxis(1,so.getAxis(1))
    heat_content_sanom.setAxis(2,so.getAxis(2))
    heat_content_sanom.units        = 'J'
    heat_content_tanom              = cdm.createVariable(heat_content_tanom,id='heat_content_tanom')
    heat_content_tanom.setAxis(0,so.getAxis(0))
    heat_content_tanom.setAxis(1,so.getAxis(1))
    heat_content_tanom.setAxis(2,so.getAxis(2))
    heat_content_tanom.units        = 'J'
    heat_content_tsanom             = cdm.createVariable(heat_content_tsanom,id='heat_content_tsanom')
    heat_content_tsanom.setAxis(0,so.getAxis(0))
    heat_content_tsanom.setAxis(1,so.getAxis(1))
    heat_content_tsanom.setAxis(2,so.getAxis(2))
    heat_content_tsanom.units       = 'J'

    # Create model-based depth index for subset target levels
    newdepth = np.array([5,10,20,30,40,50,75,100,125,150,200,300,500,700,1000,1500,1800,2000]).astype('f');
    newdepth_bounds = np.array([[0,5],[5,10],[10,20],[20,30],[30,40],[40,50],[50,75],[75,100],[100,125],[125,150],
    [150,200],[200,300],[300,500],[500,700],[700,1000],[1000,1500],[1500,1800],[1800,2000]]).astype('f')
    #newdepth = np.array([200,300,500,700,1000,1500,1800,2000]).astype('f');
    #newdepth_bounds = np.array([[0,200],[200,300],[300,500],[500,700],[700,1000],[1000,1500],[1500,1800],[1800,2000]]).astype('f')

    # Interpolate to depths
    so_depthInterp                          = cdu.linearInterpolation(so,pressure_levels,levels=newdepth)
    temp_depthInterp                        = cdu.linearInterpolation(temp,pressure_levels,levels=newdepth)
    steric_height_depthInterp               = cdu.linearInterpolation(steric_height,pressure_levels,levels=newdepth)
    steric_height_anom_depthInterp          = cdu.linearInterpolation(steric_height_anom,pressure_levels,levels=newdepth)
    steric_height_thermo_anom_depthInterp   = cdu.linearInterpolation(steric_height_thermo_anom,pressure_levels,levels=newdepth)
    steric_height_halo_anom_depthInterp     = cdu.linearInterpolation(steric_height_halo_anom,pressure_levels,levels=newdepth)
    steric_height_halo_anom2_depthInterp    = cdu.linearInterpolation(steric_height_halo_anom2,pressure_levels,levels=newdepth)
    heat_content_sanom_depthInterp          = cdu.linearInterpolation(heat_content_sanom,pressure_levels,levels=newdepth)
    heat_content_tanom_depthInterp          = cdu.linearInterpolation(heat_content_tanom,pressure_levels,levels=newdepth)
    heat_content_tsanom_depthInterp         = cdu.linearInterpolation(heat_content_tanom,pressure_levels,levels=newdepth)

    # Fix masks - applied before cdms variables are created otherwise names/ids/attributes are reset
    temp_depthInterp                        = scrubNaNAndMask(temp_depthInterp,so_depthInterp)
    steric_height_depthInterp               = scrubNaNAndMask(steric_height_depthInterp,so_depthInterp)
    steric_height_anom_depthInterp          = scrubNaNAndMask(steric_height_anom_depthInterp,so_depthInterp)
    steric_height_thermo_anom_depthInterp   = scrubNaNAndMask(steric_height_thermo_anom_depthInterp,so_depthInterp)
    steric_height_halo_anom_depthInterp     = scrubNaNAndMask(steric_height_halo_anom_depthInterp,so_depthInterp)
    steric_height_halo_anom2_depthInterp    = scrubNaNAndMask(steric_height_halo_anom2_depthInterp,so_depthInterp)
    heat_content_sanom_depthInterp          = scrubNaNAndMask(heat_content_sanom_depthInterp,so_depthInterp)
    heat_content_tanom_depthInterp          = scrubNaNAndMask(heat_content_tanom_depthInterp,so_depthInterp)
    heat_content_tsanom_depthInterp         = scrubNaNAndMask(heat_content_tsanom_depthInterp,so_depthInterp)

    # Fix bounds
    newdepth = so_depthInterp.getAxis(0)
    newdepth.setBounds(newdepth_bounds)
    del(newdepth_bounds)
    newdepth.id             = 'depth2'
    newdepth.units_long     = 'decibar (pressure)'
    newdepth.positive       = 'down'
    newdepth.long_name      = 'sea_water_pressure'
    newdepth.standard_name  = 'sea_water_pressure'
    newdepth.units          = 'decibar'
    newdepth.axis           = 'Z'

    # Assign corrected bounds
    so_depthInterp.setAxis(0,newdepth)
    temp_depthInterp.setAxis(0,newdepth)
    steric_height_depthInterp.setAxis(0,newdepth)
    steric_height_anom_depthInterp.setAxis(0,newdepth)
    steric_height_thermo_anom_depthInterp.setAxis(0,newdepth)
    steric_height_halo_anom_depthInterp.setAxis(0,newdepth)
    steric_height_halo_anom2_depthInterp.setAxis(0,newdepth)
    heat_content_sanom_depthInterp.setAxis(0,newdepth)
    heat_content_tanom_depthInterp.setAxis(0,newdepth)
    heat_content_tsanom_depthInterp.setAxis(0,newdepth)

    # Average/integrate to surface - configure bounds
    # Preallocate arrays
    so_depthAve                     = np.ma.zeros([len(newdepth),shape(so)[1],shape(so)[2]])
    temp_depthAve                   = so_depthAve.copy()
    heat_content_sanom_depthInteg   = so_depthAve.copy()
    heat_content_tanom_depthInteg   = so_depthAve.copy()
    heat_content_tsanom_depthInteg  = so_depthAve.copy()
    for count,depth in enumerate(newdepth):
        tmp = cdu.averager(so_depthInterp[0:(count+1),...],axis=0,weights='weighted',action='average')
        so_depthAve[count,]                     = tmp;
        tmp = cdu.averager(temp_depthInterp[0:(count+1),...],axis=0,weights='weighted',action='average')
        temp_depthAve[count,]                   = tmp;
        tmp = cdu.averager(heat_content_sanom_depthInterp[0:(count+1),...],axis=0,weights='weighted',action='sum')
        heat_content_sanom_depthInteg[count,]   = tmp
        tmp = cdu.averager(heat_content_tanom_depthInterp[0:(count+1),...],axis=0,weights='weighted',action='sum')
        heat_content_tanom_depthInteg[count,]   = tmp
        tmp = cdu.averager(heat_content_tsanom_depthInterp[0:(count+1),...],axis=0,weights='weighted',action='sum')
        heat_content_tsanom_depthInteg[count,]  = tmp
    del(heat_content_tanom_depthInterp,heat_content_tsanom_depthInterp); gc.collect()

    # Fix masks - applied before cdms variables are created otherwise names/ids/attributes are reset
    so_depthAve = scrubNaNAndMask(so_depthAve,so_depthInterp)
    temp_depthAve = scrubNaNAndMask(temp_depthAve,so_depthInterp)
    heat_content_sanom_depthInteg = scrubNaNAndMask(heat_content_sanom_depthInteg,so_depthInterp)
    heat_content_tanom_depthInteg = scrubNaNAndMask(heat_content_tanom_depthInteg,so_depthInterp)
    heat_content_tsanom_depthInteg = scrubNaNAndMask(heat_content_tsanom_depthInteg,so_depthInterp)
    del(so_depthInterp)

    # Convert numpy arrays to cdms objects
    heat_content_sanom_depthInteg               = cdm.createVariable(heat_content_sanom_depthInteg,id='heat_content_sanom_depthInteg')
    heat_content_sanom_depthInteg.id            = 'heat_content_sanom_depthInteg'
    heat_content_sanom_depthInteg.setAxis(0,newdepth)
    heat_content_sanom_depthInteg.setAxis(1,so.getAxis(1))
    heat_content_sanom_depthInteg.setAxis(2,so.getAxis(2))
    heat_content_sanom_depthInteg.units         = 'J'
    heat_content_tanom_depthInteg               = cdm.createVariable(heat_content_tanom_depthInteg,id='heat_content_tanom_depthInteg')
    heat_content_tanom_depthInteg.id            = 'heat_content_tanom_depthInteg'
    heat_content_tanom_depthInteg.setAxis(0,newdepth)
    heat_content_tanom_depthInteg.setAxis(1,so.getAxis(1))
    heat_content_tanom_depthInteg.setAxis(2,so.getAxis(2))
    heat_content_tanom_depthInteg.units         = 'J'
    heat_content_tsanom_depthInteg              = cdm.createVariable(heat_content_tsanom_depthInteg,id='heat_content_tsanom_depthInteg')
    heat_content_tsanom_depthInteg.id           = 'heat_content_tsanom_depthInteg'
    heat_content_tsanom_depthInteg.setAxis(0,newdepth)
    heat_content_tsanom_depthInteg.setAxis(1,so.getAxis(1))
    heat_content_tsanom_depthInteg.setAxis(2,so.getAxis(2))
    heat_content_tsanom_depthInteg.units        = 'J'
    so_depthAve                                 = cdm.createVariable(so_depthAve,id='so_depthAve')
    so_depthAve.id                              = 'so_depthAve'
    so_depthAve.setAxis(0,newdepth)
    so_depthAve.setAxis(1,so.getAxis(1))
    so_depthAve.setAxis(2,so.getAxis(2))
    so_depthAve.units                           = '1e-3'
    temp_depthAve                               = cdm.createVariable(temp_depthAve,id='temp_depthAve')
    temp_depthAve.id                            = 'temp_depthAve'
    temp_depthAve.setAxis(0,newdepth)
    temp_depthAve.setAxis(1,so.getAxis(1))
    temp_depthAve.setAxis(2,so.getAxis(2))
    temp_depthAve.units                         = 'degrees_C'
    steric_height_depthInterp                   = cdm.createVariable(steric_height_depthInterp,id='steric_height_depthInterp')
    steric_height_depthInterp.setAxis(0,newdepth)
    steric_height_depthInterp.setAxis(1,so.getAxis(1))
    steric_height_depthInterp.setAxis(2,so.getAxis(2))
    steric_height_depthInterp.units             = 'm^3 kg^-1 Pa (dynamic decimeter)'
    steric_height_anom_depthInterp              = cdm.createVariable(steric_height_anom_depthInterp,id='steric_height_anom_depthInterp')
    steric_height_anom_depthInterp.setAxis(0,newdepth)
    steric_height_anom_depthInterp.setAxis(1,so.getAxis(1))
    steric_height_anom_depthInterp.setAxis(2,rho.getAxis(2))
    steric_height_anom_depthInterp.units        = 'm^3 kg^-1 Pa (dynamic decimeter)'
    steric_height_thermo_anom_depthInterp       = cdm.createVariable(steric_height_thermo_anom_depthInterp,id='steric_height_thermo_anom_depthInterp')
    steric_height_thermo_anom_depthInterp.setAxis(0,newdepth)
    steric_height_thermo_anom_depthInterp.setAxis(1,so.getAxis(1))
    steric_height_thermo_anom_depthInterp.setAxis(2,so.getAxis(2))
    steric_height_thermo_anom_depthInterp.units = 'm^3 kg^-1 Pa (dynamic decimeter)'
    steric_height_halo_anom_depthInterp         = cdm.createVariable(steric_height_halo_anom_depthInterp,id='steric_height_halo_anom_depthInterp')
    steric_height_halo_anom_depthInterp.setAxis(0,newdepth)
    steric_height_halo_anom_depthInterp.setAxis(1,so.getAxis(1))
    steric_height_halo_anom_depthInterp.setAxis(2,so.getAxis(2))
    steric_height_halo_anom_depthInterp.units   = 'm^3 kg^-1 Pa (dynamic decimeter)'
    steric_height_halo_anom2_depthInterp         = cdm.createVariable(steric_height_halo_anom2_depthInterp,id='steric_height_halo_anom2_depthInterp')
    steric_height_halo_anom2_depthInterp.setAxis(0,newdepth)
    steric_height_halo_anom2_depthInterp.setAxis(1,so.getAxis(1))
    steric_height_halo_anom2_depthInterp.setAxis(2,so.getAxis(2))
    steric_height_halo_anom2_depthInterp.units   = 'm^3 kg^-1 Pa (dynamic decimeter)'
    # Cleanup workspace
    del(newdepth) ; gc.collect()


    # Write variables to file
    if os.path.isfile(outFileName):
        os.remove(outFileName)
    filehandle = cdm.open(outFileName,'w')
    # Global attributes
    globalAttWrite(filehandle,options=None) ; # Use function to write standard global atts
    # Write seawater version
    filehandle.seawater_library_version = sw.__version__
    # Write makeSteric version
    makeStericPath = str(makeSteric.__code__).split(' ')[6]
    makeStericPath = replace(replace(makeStericPath,'"',''),',','') ; # Clean scraped path
    filehandle.makeSteric_version = ' '.join(getGitInfo(makeStericPath)[0:3])
    # Master variables
    filehandle.write(so.astype('float32'))
    filehandle.write(so_chg.astype('float32'))
    filehandle.write(so_depthAve.astype('float32'))
    filehandle.write(temp.astype('float32'))
    filehandle.write(temp_chg.astype('float32'))
    filehandle.write(temp_depthAve.astype('float32'))
    # Derived variables
    filehandle.write(cp.astype('float32'))
    filehandle.write(cp_halo.astype('float32'))
    filehandle.write(cp_thermo.astype('float32'))
    filehandle.write(rho.astype('float32'))
    filehandle.write(rho_halo.astype('float32'))
    filehandle.write(rho_thermo.astype('float32'))
    filehandle.write(heat_content.astype('float32'))
    filehandle.write(heat_content_sanom.astype('float32'))
    filehandle.write(heat_content_sanom_depthInteg.astype('float32'))
    filehandle.write(heat_content_tanom.astype('float32'))
    filehandle.write(heat_content_tanom_depthInteg.astype('float32'))
    filehandle.write(heat_content_tsanom.astype('float32'))
    filehandle.write(heat_content_tsanom_depthInteg.astype('float32'))
    filehandle.write(steric_height.astype('float32'))
    filehandle.write(steric_height_depthInterp.astype('float32'))
    filehandle.write(steric_height_anom.astype('float32'))
    filehandle.write(steric_height_anom_depthInterp.astype('float32'))
    filehandle.write(steric_height_halo_anom.astype('float32'))
    filehandle.write(steric_height_halo_anom2.astype('float32'))
    filehandle.write(steric_height_halo_anom_depthInterp.astype('float32'))
    filehandle.write(steric_height_halo_anom2_depthInterp.astype('float32'))
    filehandle.write(steric_height_thermo_anom.astype('float32'))
    filehandle.write(steric_height_thermo_anom_depthInterp.astype('float32'))
    filehandle.close()
    # Cleanup workspace
    del(outFileName) ; gc.collect()
Пример #6
0
def makeHeatContent(salt, temp, destMask, thetao, pressure):
    """
    The makeHeatContent() function takes 3D (not temporal) arguments and creates
    heat content which is then mapped to a destination grid and written to a
    specified variable

    Author: Paul J. Durack : [email protected] : @durack1.
    Created on Tue Nov 24 15:34:30 2015.

    Inputs:
    ------
    - salt(lev,lat,lon) - 3D array.
    - temp(lev,lat,lon) - 3D array either in-situ or potential temperature.
    - destGridArray(str) - 2D array with valid grid and mask.
    - thetao(bool) - boolean value specifying either in-situ or potential temperature arrays provided.
    - pressure(bool) - boolean value specifying whether lev-coordinate is pressure (dbar) or depth (m).

    Usage:
    ------
        >>> from oceanLib import makeHeatContent
        >>> makeHeatContent(salt,temp,destGridArray,thetao=True,pressure=False)

    Notes:
    -----
    - PJD 24 Nov 2015 - Migrated into new oceanLib from heatContentLib
    - TODO: Better deal with insitu vs thetao variables
    - TODO:
    """

    # Remap variables to short names
    #print salt.getAxisIds()
    s = salt(squeeze=1)
    # Trim off singleton time dimension
    #print s.getAxisIds()
    t = temp(squeeze=1)
    mask = destMask
    #print mask.getAxisIds()
    del (salt, temp, destMask)
    gc.collect()
    depthInd = 0
    # Set depth coordinate index

    #print 's:    ',s.min(),s.max()
    #print 't:    ',t.min(),t.max()

    # Fix out of bounds values
    t = mv.where(t < -2.6, -2.6, t)
    # Fix for NaN values

    # Calculate pressure - inputs depth & lat
    # Create z-coordinate from salinity input
    if not pressure:
        zCoord = s.getAxis(depthInd)
        # Assume time,depth,latitude,longitude grid
        yCoord = s.getAxis(depthInd + 1)
        yCoord = tile(yCoord, (s.shape[depthInd + 2], 1)).transpose()
        depthLevels = tile(
            zCoord.getValue(),
            (s.shape[depthInd + 2], s.shape[depthInd + 1], 1)).transpose()
        pressureLevels = sw.pres(np.array(depthLevels), np.array(yCoord))
        del (zCoord, yCoord, depthLevels)
        gc.collect()
    else:
        pressureLevels = s.getAxis(depthInd)
        #print pressureLevels.getValue()
        pressureLevels = transpose(
            tile(pressureLevels,
                 (s.shape[depthInd + 2], s.shape[depthInd + 1], 1)))
    pressureLevels = cdm.createVariable(pressureLevels, id='pressureLevels')
    pressureLevels.setAxis(0, s.getAxis(depthInd))
    pressureLevels.setAxis(1, s.getAxis(depthInd + 1))
    pressureLevels.setAxis(2, s.getAxis(depthInd + 2))
    pressureLevels.units_long = 'decibar (pressure)'
    pressureLevels.positive = 'down'
    pressureLevels.long_name = 'sea_water_pressure'
    pressureLevels.standard_name = 'sea_water_pressure'
    pressureLevels.units = 'decibar'
    pressureLevels.axis = 'Z'

    #print 'pres: ',pressureLevels.min(),pressureLevels.max()
    #print pressureLevels.shape
    #print s.shape
    #print t.shape
    #print mask.shape

    # Calculate temp,rho,cp - inputs temp,salt,pressure
    if thetao:
        # Process potential temperature to in-situ
        temp = sw.temp(np.array(s), np.array(t), np.array(pressureLevels))
        # units degrees C
    rho = sw.dens(np.array(s), np.array(temp), np.array(pressureLevels))
    # units kg m-3
    cp = sw.cp(np.array(s), np.array(temp), np.array(pressureLevels))
    # units J kg-1 C-1

    # Correct instances of NaN values and fix masks - applied before cdms variables are created otherwise names/ids/attributes are reset
    temp = scrubNaNAndMask(temp, s)
    rho = scrubNaNAndMask(rho, s)
    cp = scrubNaNAndMask(cp, s)

    #print 'temp: ',temp.min(),temp.max()
    #print 'rho:  ',rho.min(),rho.max()
    #print 'cp:   ',cp.min(),cp.max()

    # Calculate heatContent - inputs temp,rho,cp
    heatContent = np.array(temp) * np.array(rho) * np.array(cp)
    # units J

    # Correct instances of NaN values and fix masks - applied before cdms variables are created otherwise names/ids/attributes are reset
    heatContent = scrubNaNAndMask(heatContent, s)
    #print 'hc:   ',heatContent.min(),heatContent.max()

    # Interpolate to standard levels - inputs heatContent,levels
    newDepth = np.array([
        5, 10, 20, 30, 40, 50, 75, 100, 125, 150, 200, 300, 500, 700, 1000,
        1500, 1800, 2000
    ]).astype('f')
    newDepth_bounds = np.array([[0, 5], [5, 10], [10, 20], [20, 30], [30, 40],
                                [40, 50], [50, 75], [75, 100], [100, 125],
                                [125, 150], [150, 200], [200, 300], [300, 500],
                                [500, 700], [700, 1000], [1000, 1500],
                                [1500, 1800], [1800, 2000]]).astype('f')
    # Interpolate to standard levels
    #print heatContent.shape
    #print heatContent.getAxisIds()
    #print pressureLevels.shape
    #print pressureLevels.getAxisIds()

    # Reset variable axes
    heatContent.setAxis(0, s.getAxis(0))
    #heatContent.setAxis(1,s.getAxis(1))
    #heatContent.setAxis(2,s.getAxis(2))

    pdb.set_trace()

    heatContent.setGrid(s.getGrid())

    #print heatContent.shape
    #print heatContent.getAxisIds()
    #print pressureLevels.shape
    #print pressureLevels.getAxisIds()

    heatContent_depthInterp = cdu.linearInterpolation(heatContent,
                                                      pressureLevels,
                                                      levels=newDepth)
    # Fix bounds
    newDepth = heatContent_depthInterp.getAxis(0)
    newDepth.setBounds(newDepth_bounds)
    del (newDepth_bounds)
    newDepth.id = 'depth2'
    newDepth.units_long = 'decibar (pressure)'
    newDepth.positive = 'down'
    newDepth.long_name = 'sea_water_pressure'
    newDepth.standard_name = 'sea_water_pressure'
    newDepth.units = 'decibar'
    newDepth.axis = 'Z'

    #print 'hc_interp:',heatContent_depthInterp.min(),heatContent_depthInterp.max()

    # Integrate to 700 dbar - inputs heatContent

    heatContent_depthInteg = cdu.averager(
        heatContent_depthInterp[0:14, ...],
        axis=0,
        weights='weighted',
        action='sum')(squeeze=1)  # Calculate depth-weighted-integrated thetao
    # Assign all axis info

    #print heatContent_depthInteg.shape
    pdb.set_trace()
    # Interpolate in x,y - inputs heatContent
    #tmp1 = heatContent_depthInteg.regrid(mask.getGrid(),regridTool='esmf',regridMethod='linear') ; # Use defaults - ,coordSys='deg',diag = {},periodicity=1)
    tmp1 = heatContent_depthInteg.regrid(mask,
                                         regridTool='esmf',
                                         regridMethod='linear')
    # Use defaults - ,coordSys='deg',diag = {},periodicity=1)
    #print tmp1.shape

    tmp1 = mv.where(tmp1 < 0, 0, tmp1)
    # Fix for negative values

    # Infill - inputs heatContent
    # Create inputs for interpolation
    points = np.zeros([(mask.shape[0] * mask.shape[1]), 2])
    # Create 25380 vectors of lon/lat
    latcounter = 0
    loncounter = 0
    for count, data in enumerate(points):
        if not np.mod(count, 180) and not count == 0:
            latcounter = latcounter + 1
            loncounter = 0
        points[count, 0] = mask.getLatitude().getValue()[latcounter]
        points[count, 1] = mask.getLongitude().getValue()[loncounter]
        loncounter = loncounter + 1
    del (count, data, latcounter, loncounter)
    gc.collect()
    valid = np.logical_not(tmp1.mask)
    # Get inverted-logic boolean mask from variable
    if valid.size == 1:
        print '** No valid mask found, skipping **'
        return
    valid = valid.flatten()
    # Flatten 2D to 1D

    #maskFilled  = mask(tmp,points,valid)
    interpolant = interpolate.LinearNDInterpolator(
        points[valid, :],
        np.array(tmp1.flatten())[valid])
    # Create interpolant
    maskFill = interpolant(points[:, 0].squeeze(), points[:, 1].squeeze())
    # Use interpolant to create filled matrix
    maskFill = np.reshape(maskFill, mask.shape)
    # Resize to original dimensions

    # Fix issues with interpolant
    tmp2 = mv.where(np.isnan(maskFill), 1e+20, maskFill)
    # Fix for NaN values
    tmp2 = mv.where(tmp2 > tmp1.max(), 0, tmp2)
    # Fix for max values
    tmp2 = mv.where(tmp2 < tmp1.min(), 0, tmp2)
    # Fix for min values
    tmp = mv.masked_where(mask.mask, tmp2)
    #print tmp.shape

    # Redress variable
    heatContent = cdm.createVariable([tmp], id='heatContent')
    depthInt = cdm.createAxis([350], id='depth')
    depthInt.setBounds(np.array([0, 700]))
    depthInt.units_long = 'decibar (pressure)'
    depthInt.positive = 'down'
    depthInt.long_name = 'sea_water_pressure'
    depthInt.standard_name = 'sea_water_pressure'
    depthInt.units = 'decibar'
    depthInt.axis = 'Z'
    heatContent.setAxis(0, depthInt)
    heatContent.setAxis(1, mask.getAxis(0))
    heatContent.setAxis(2, mask.getAxis(1))
    heatContent.units_long = 'Joules'
    heatContent.long_name = 'sea_water_heat_content'
    heatContent.standard_name = 'sea_water_heat_content'
    heatContent.units = 'J'

    return heatContent
Пример #7
0
def makeSteric(salinity, salinityChg, temp, tempChg, outFileName, thetao,
               pressure):
    """
    The makeSteric() function takes 3D (not temporal) arguments and creates
    heat content and steric fields which are written to a specified outfile

    Author: Paul J. Durack : [email protected] : @durack1.
    Created on Thu Jul 18 13:03:37 2013.

    Inputs:
    ------
    - salinity(lev,lat,lon) - 3D array for the climatological period.
    - salinityChg(lev,lat,lon) - 3D array for the temporal change period.
    - temp(lev,lat,lon) - 3D array for the climatological period either in-situ or potential temperature.
    - tempChg(lev,lat,lon) - 3D array for the temporal change period as with temp, either in-situ or potential temperature.
    - outFileName(str) - output filename with full path specified.
    - thetao(bool) - boolean value specifying either in-situ or potential temperature arrays provided.
    - pressure(bool) - boolean value specifying whether lev-coordinate is pressure (dbar) or depth (m).

    Usage:
    ------
        >>> from makeStericLib import makeSteric
        >>> makeSteric(salinity,salinityChg,thetao,thetaoChg,'outfile.nc',True,False)

    Notes:
    -----
    - PJD 18 Jul 2013 - Validated Ishii v6.13 data against WOA94 - checks out ok. Units: dyn decimeter compared to http://www.nodc.noaa.gov/OC5/WOA94/dyn.html uses cm (not decimeter; x 10)
    - PJD 18 Jul 2013 - Added attribute scrub to incoming variables (so,so_chg,temp,temp_chg) to maintain output consistency
    - PJD 22 Jul 2013 - Added name attributes to so and temp variables, added units to so_chg
    - PJD 22 Jul 2013 - removed duplicated code by converting repetition to function scrubNaNAndMask
    - PJD 23 Jul 2013 - Further cleaned up so,so_chg,temp,temp_chg outputs specifying id/name attributes
    - PJD  5 Aug 2013 - Updated python-seawater library to version 3.3.1 from github repo, git clone http://github.com/ocefpaf/python-seawater, python setup.py install --user
    - PJD  7 Aug 2013 - FIXED: thetao rather than in-situ temperature propagating throughout calculations
    - PJD  7 Aug 2013 - Replaced looping with 3D gpan
    - PJD  7 Aug 2013 - Further code duplication cleanup
    - PJD  8 Aug 2013 - FIXED: scrubNanAndMask function type/mask/grid issue - encase sw arguments in np.array() (attempt to strip cdms fluff)
    - PJD  8 Aug 2013 - FIXED: removed depth variable unit edits - not all inputs are depth (m)
    - PJD 15 Aug 2013 - Increased interpolated field resolution [200,300,500,700,1000,1500,1800,2000] - [5,10,20,30,40,50,75,100,125,150,200, ...]
    - PJD 18 Aug 2013 - AR5 hard coded rho=1020,cp=4187 == 4.3e6 vs Ishii 1970 rho.mean=1024,cp.mean=3922 == 4.1e6 ~5% too high
    - PJD 13 Jan 2014 - Corrected steric_height_anom and steric_height_thermo_anom to true anomaly fields, needed to remove climatology
    - PJD  3 May 2014 - Turned off thetao conversion, although convert to numpy array rather than cdms2 transient variable
    - PJD 13 Oct 2014 - Added seawater_library_version as a global attribute
    - PJD 13 Oct 2014 - FIXED: bug with calculation of rho_halo variable was calculating gpan
    - PJD 13 Oct 2014 - Added alternate calculation of halosteric anomaly (direct salinity anomaly calculation, rather than total-thermosteric)
    - PJD 13 Oct 2014 - Added makeSteric_version as a global attribute
    - TODO: Better deal with insitu vs thetao variables
    - TODO: Query Charles on why *.name attributes are propagating
    - TODO: validate outputs and compare to matlab versions - 10e-7 errors.
    """

    # Remap all variables to short names
    so = salinity
    so_chg = salinityChg
    temp = temp
    temp_chg = tempChg
    del (salinity, salinityChg, tempChg)
    gc.collect()

    # Strip attributes to maintain consistency between datasets
    for count, x in enumerate(so.attributes.keys()):
        delattr(so, x)
    #print so.listattributes() ; # Print remaining attributes
    for count, x in enumerate(so_chg.attributes.keys()):
        delattr(so_chg, x)
    for count, x in enumerate(temp.attributes.keys()):
        delattr(temp, x)
    for count, x in enumerate(temp_chg.attributes.keys()):
        delattr(temp_chg, x)
    del (count, x)

    # Create z-coordinate from salinity input
    if not pressure:
        z_coord = so.getAxis(0)
        y_coord = so.getAxis(1)
        y_coord = tile(y_coord, (so.shape[2], 1)).transpose()
        depth_levels = tile(z_coord.getValue(),
                            (so.shape[2], so.shape[1], 1)).transpose()
        pressure_levels = sw.pres(np.array(depth_levels), np.array(y_coord))
        del (z_coord, y_coord, depth_levels)
        gc.collect()
    else:
        pressure_levels = so.getAxis(0)
        pressure_levels = transpose(
            tile(pressure_levels, (so.shape[2], so.shape[1], 1)))

    pressure_levels = cdm.createVariable(pressure_levels, id='pressure_levels')
    pressure_levels.setAxis(0, so.getAxis(0))
    pressure_levels.setAxis(1, so.getAxis(1))
    pressure_levels.setAxis(2, so.getAxis(2))
    pressure_levels.id = 'pressure_levels'
    pressure_levels.units_long = 'decibar (pressure)'
    pressure_levels.positive = 'down'
    pressure_levels.long_name = 'sea_water_pressure'
    pressure_levels.standard_name = 'sea_water_pressure'
    pressure_levels.units = 'decibar'
    pressure_levels.axis = 'Z'

    # Cleanup depth axis attributes
    depth = so.getAxis(0)
    depth.id = 'depth'
    depth.name = 'depth'
    depth.long_name = 'depth'
    depth.standard_name = 'depth'
    depth.axis = 'Z'
    so.setAxis(0, depth)
    so_chg.setAxis(0, depth)
    temp.setAxis(0, depth)
    temp_chg.setAxis(0, depth)
    del (depth)

    # Convert using python-seawater library (v3.3.1 - 130807)
    if thetao:
        # Process potential temperature to in-situ - default conversion sets reference pressure to 0 (surface)
        #temp_chg                = sw.temp(np.array(so),np.array(temp_chg),np.array(pressure_levels)); # units degrees C
        #temp                    = sw.temp(np.array(so),np.array(temp),np.array(pressure_levels)); # units degrees C
        #temp_chg                = sw.ptmp(np.array(so),np.array(temp_chg),np.array(pressure_levels),np.array(pressure_levels)); # units degrees C
        #temp                    = sw.ptmp(np.array(so),np.array(temp),np.array(pressure_levels),np.array(pressure_levels)); # units degrees C
        temp_chg = np.array(temp_chg)
        # units degrees C
        temp = np.array(temp)
        # units degrees C

    # Climatologies - rho,cp,steric_height
    rho = sw.dens(np.array(so), np.array(temp), np.array(pressure_levels))
    # units kg m-3
    cp = sw.cp(np.array(so), np.array(temp), np.array(pressure_levels))
    # units J kg-1 C-1
    steric_height = sw.gpan(np.array(so), np.array(temp),
                            np.array(pressure_levels))
    # units m3 kg-1 Pa == m2 s-2 == J kg-1 (dynamic decimeter)

    # Halosteric - rho,cp
    ss = map(array, (so + so_chg))
    rho_halo = sw.dens(np.array(ss), np.array(temp), np.array(pressure_levels))
    # units kg m-3
    cp_halo = sw.cp(np.array(ss), np.array(temp), np.array(pressure_levels))
    # units J kg-1 C-1
    tmp = sw.gpan(np.array(ss), np.array(temp), np.array(pressure_levels))
    # units m3 kg-1 Pa == m2 s-2 == J kg-1 (dynamic decimeter)
    steric_height_halo_anom2 = tmp - steric_height
    # units m3 kg-1 Pa == m2 s-2 == J kg-1 (dynamic decimeter)

    # Full steric - steric_height
    tt = map(array, (temp + temp_chg))
    tmp = sw.gpan(np.array(ss), np.array(tt), np.array(pressure_levels))
    # units m3 kg-1 Pa == m2 s-2 == J kg-1 (dynamic decimeter)
    steric_height_anom = tmp - steric_height
    # units m3 kg-1 Pa == m2 s-2 == J kg-1 (dynamic decimeter)
    del (ss, tmp)
    gc.collect()

    # Thermosteric - rho,cp,steric_height
    rho_thermo = sw.dens(np.array(so), np.array(tt), np.array(pressure_levels))
    # units kg m-3
    cp_thermo = sw.cp(np.array(so), np.array(tt), np.array(pressure_levels))
    # units J kg-1 C-1
    tmp = sw.gpan(np.array(so), np.array(tt), np.array(pressure_levels))
    # units m3 kg-1 Pa == m2 s-2 == J kg-1 (dynamic decimeter)
    steric_height_thermo_anom = tmp - steric_height
    # units m3 kg-1 Pa == m2 s-2 == J kg-1 (dynamic decimeter)
    del (tt, tmp)
    gc.collect()

    # Halosteric - steric_height
    steric_height_halo_anom = steric_height_anom - steric_height_thermo_anom
    # units m3 kg-1 Pa == m2 s-2 == J kg-1 (dynamic decimeter)

    # Create heat content
    heat_content = np.array(temp) * np.array(rho) * np.array(cp)
    # units J
    heat_content_sanom = np.array(temp) * np.array(rho_halo) * np.array(
        cp_halo)
    # units J
    heat_content_tanom = np.array(temp_chg) * np.array(rho) * np.array(cp)
    # units J
    #heat_content_tanom          = np.array(temp_chg)*np.array(1020)*np.array(4187) ; # units J - try hard-coded - AR5 numbers
    heat_content_tsanom = np.array(temp_chg) * np.array(rho_halo) * np.array(
        cp_halo)
    # units J

    # Correct all instances of NaN values and fix masks - applied before cdms variables are created otherwise names/ids/attributes are reset
    temp = scrubNaNAndMask(temp, so)
    temp_chg = scrubNaNAndMask(temp_chg, so)
    rho = scrubNaNAndMask(rho, so)
    cp = scrubNaNAndMask(cp, so)
    rho_halo = scrubNaNAndMask(rho_halo, so)
    cp_halo = scrubNaNAndMask(cp_halo, so)
    rho_thermo = scrubNaNAndMask(rho_thermo, so)
    cp_thermo = scrubNaNAndMask(cp_thermo, so)
    steric_height = scrubNaNAndMask(steric_height, so)
    steric_height_anom = scrubNaNAndMask(steric_height_anom, so)
    steric_height_thermo_anom = scrubNaNAndMask(steric_height_thermo_anom, so)
    steric_height_halo_anom = scrubNaNAndMask(steric_height_halo_anom, so)
    steric_height_halo_anom2 = scrubNaNAndMask(steric_height_halo_anom2, so)
    heat_content = scrubNaNAndMask(heat_content, so)
    heat_content_sanom = scrubNaNAndMask(heat_content_sanom, so)
    heat_content_tanom = scrubNaNAndMask(heat_content_tanom, so)
    heat_content_tsanom = scrubNaNAndMask(heat_content_tsanom, so)

    # Recreate and redress variables
    so.id = 'so_mean'
    so.units = '1e-3'
    so_chg.id = 'so_chg'
    so_chg.units = '1e-3'
    temp = cdm.createVariable(temp, id='temp_mean')
    temp.setAxis(0, so.getAxis(0))
    temp.setAxis(1, so.getAxis(1))
    temp.setAxis(2, so.getAxis(2))
    temp.units = 'degrees_C'
    temp_chg = cdm.createVariable(temp_chg, id='temp_chg')
    temp_chg.setAxis(0, so.getAxis(0))
    temp_chg.setAxis(1, so.getAxis(1))
    temp_chg.setAxis(2, so.getAxis(2))
    temp_chg.units = 'degrees_C'
    rho = cdm.createVariable(rho, id='rho')
    rho.setAxis(0, so.getAxis(0))
    rho.setAxis(1, so.getAxis(1))
    rho.setAxis(2, so.getAxis(2))
    rho.name = 'density_mean'
    rho.units = 'kg m^-3'
    cp = cdm.createVariable(cp, id='cp')
    cp.setAxis(0, so.getAxis(0))
    cp.setAxis(1, so.getAxis(1))
    cp.setAxis(2, so.getAxis(2))
    cp.name = 'heat_capacity_mean'
    cp.units = 'J kg^-1 C^-1'
    rho_halo = cdm.createVariable(rho_halo, id='rho_halo')
    rho_halo.setAxis(0, so.getAxis(0))
    rho_halo.setAxis(1, so.getAxis(1))
    rho_halo.setAxis(2, so.getAxis(2))
    rho_halo.name = 'density_mean_halo'
    rho_halo.units = 'kg m^-3'
    cp_halo = cdm.createVariable(cp_halo, id='cp_halo')
    cp_halo.setAxis(0, so.getAxis(0))
    cp_halo.setAxis(1, so.getAxis(1))
    cp_halo.setAxis(2, so.getAxis(2))
    cp_halo.name = 'heat_capacity_mean_halo'
    cp_halo.units = 'J kg^-1 C^-1'
    rho_thermo = cdm.createVariable(rho_thermo, id='rho_thermo')
    rho_thermo.setAxis(0, so.getAxis(0))
    rho_thermo.setAxis(1, so.getAxis(1))
    rho_thermo.setAxis(2, so.getAxis(2))
    rho_thermo.name = 'density_mean_thermo'
    rho_thermo.units = 'kg m^-3'
    cp_thermo = cdm.createVariable(cp_thermo, id='cp_thermo')
    cp_thermo.setAxis(0, so.getAxis(0))
    cp_thermo.setAxis(1, so.getAxis(1))
    cp_thermo.setAxis(2, so.getAxis(2))
    cp_thermo.name = 'heat_capacity_mean_thermo'
    cp_thermo.units = 'J kg^-1 C^-1'
    steric_height = cdm.createVariable(steric_height, id='steric_height')
    steric_height.setAxis(0, so.getAxis(0))
    steric_height.setAxis(1, so.getAxis(1))
    steric_height.setAxis(2, so.getAxis(2))
    steric_height.units = 'm^3 kg^-1 Pa (dynamic decimeter)'
    steric_height_anom = cdm.createVariable(steric_height_anom,
                                            id='steric_height_anom')
    steric_height_anom.setAxis(0, so.getAxis(0))
    steric_height_anom.setAxis(1, so.getAxis(1))
    steric_height_anom.setAxis(2, so.getAxis(2))
    steric_height_anom.units = 'm^3 kg^-1 Pa (dynamic decimeter)'
    steric_height_thermo_anom = cdm.createVariable(
        steric_height_thermo_anom, id='steric_height_thermo_anom')
    steric_height_thermo_anom.setAxis(0, so.getAxis(0))
    steric_height_thermo_anom.setAxis(1, so.getAxis(1))
    steric_height_thermo_anom.setAxis(2, so.getAxis(2))
    steric_height_thermo_anom.units = 'm^3 kg^-1 Pa (dynamic decimeter)'
    steric_height_halo_anom = cdm.createVariable(steric_height_halo_anom,
                                                 id='steric_height_halo_anom')
    steric_height_halo_anom.setAxis(0, so.getAxis(0))
    steric_height_halo_anom.setAxis(1, so.getAxis(1))
    steric_height_halo_anom.setAxis(2, so.getAxis(2))
    steric_height_halo_anom.units = 'm^3 kg^-1 Pa (dynamic decimeter)'
    steric_height_halo_anom2 = cdm.createVariable(
        steric_height_halo_anom2, id='steric_height_halo_anom2')
    steric_height_halo_anom2.setAxis(0, so.getAxis(0))
    steric_height_halo_anom2.setAxis(1, so.getAxis(1))
    steric_height_halo_anom2.setAxis(2, so.getAxis(2))
    steric_height_halo_anom2.units = 'm^3 kg^-1 Pa (dynamic decimeter)'
    heat_content = cdm.createVariable(heat_content, id='heat_content')
    heat_content.setAxis(0, so.getAxis(0))
    heat_content.setAxis(1, so.getAxis(1))
    heat_content.setAxis(2, so.getAxis(2))
    heat_content.units = 'J'
    heat_content_sanom = cdm.createVariable(heat_content_sanom,
                                            id='heat_content_sanom')
    heat_content_sanom.setAxis(0, so.getAxis(0))
    heat_content_sanom.setAxis(1, so.getAxis(1))
    heat_content_sanom.setAxis(2, so.getAxis(2))
    heat_content_sanom.units = 'J'
    heat_content_tanom = cdm.createVariable(heat_content_tanom,
                                            id='heat_content_tanom')
    heat_content_tanom.setAxis(0, so.getAxis(0))
    heat_content_tanom.setAxis(1, so.getAxis(1))
    heat_content_tanom.setAxis(2, so.getAxis(2))
    heat_content_tanom.units = 'J'
    heat_content_tsanom = cdm.createVariable(heat_content_tsanom,
                                             id='heat_content_tsanom')
    heat_content_tsanom.setAxis(0, so.getAxis(0))
    heat_content_tsanom.setAxis(1, so.getAxis(1))
    heat_content_tsanom.setAxis(2, so.getAxis(2))
    heat_content_tsanom.units = 'J'

    # Create model-based depth index for subset target levels
    newdepth = np.array([
        5, 10, 20, 30, 40, 50, 75, 100, 125, 150, 200, 300, 500, 700, 1000,
        1500, 1800, 2000
    ]).astype('f')
    newdepth_bounds = np.array([[0, 5], [5, 10], [10, 20], [20, 30], [30, 40],
                                [40, 50], [50, 75], [75, 100], [100, 125],
                                [125, 150], [150, 200], [200, 300], [300, 500],
                                [500, 700], [700, 1000], [1000, 1500],
                                [1500, 1800], [1800, 2000]]).astype('f')
    #newdepth = np.array([200,300,500,700,1000,1500,1800,2000]).astype('f');
    #newdepth_bounds = np.array([[0,200],[200,300],[300,500],[500,700],[700,1000],[1000,1500],[1500,1800],[1800,2000]]).astype('f')

    # Interpolate to depths
    so_depthInterp = cdu.linearInterpolation(so,
                                             pressure_levels,
                                             levels=newdepth)
    temp_depthInterp = cdu.linearInterpolation(temp,
                                               pressure_levels,
                                               levels=newdepth)
    steric_height_depthInterp = cdu.linearInterpolation(steric_height,
                                                        pressure_levels,
                                                        levels=newdepth)
    steric_height_anom_depthInterp = cdu.linearInterpolation(
        steric_height_anom, pressure_levels, levels=newdepth)
    steric_height_thermo_anom_depthInterp = cdu.linearInterpolation(
        steric_height_thermo_anom, pressure_levels, levels=newdepth)
    steric_height_halo_anom_depthInterp = cdu.linearInterpolation(
        steric_height_halo_anom, pressure_levels, levels=newdepth)
    steric_height_halo_anom2_depthInterp = cdu.linearInterpolation(
        steric_height_halo_anom2, pressure_levels, levels=newdepth)
    heat_content_sanom_depthInterp = cdu.linearInterpolation(
        heat_content_sanom, pressure_levels, levels=newdepth)
    heat_content_tanom_depthInterp = cdu.linearInterpolation(
        heat_content_tanom, pressure_levels, levels=newdepth)
    heat_content_tsanom_depthInterp = cdu.linearInterpolation(
        heat_content_tanom, pressure_levels, levels=newdepth)

    # Fix masks - applied before cdms variables are created otherwise names/ids/attributes are reset
    temp_depthInterp = scrubNaNAndMask(temp_depthInterp, so_depthInterp)
    steric_height_depthInterp = scrubNaNAndMask(steric_height_depthInterp,
                                                so_depthInterp)
    steric_height_anom_depthInterp = scrubNaNAndMask(
        steric_height_anom_depthInterp, so_depthInterp)
    steric_height_thermo_anom_depthInterp = scrubNaNAndMask(
        steric_height_thermo_anom_depthInterp, so_depthInterp)
    steric_height_halo_anom_depthInterp = scrubNaNAndMask(
        steric_height_halo_anom_depthInterp, so_depthInterp)
    steric_height_halo_anom2_depthInterp = scrubNaNAndMask(
        steric_height_halo_anom2_depthInterp, so_depthInterp)
    heat_content_sanom_depthInterp = scrubNaNAndMask(
        heat_content_sanom_depthInterp, so_depthInterp)
    heat_content_tanom_depthInterp = scrubNaNAndMask(
        heat_content_tanom_depthInterp, so_depthInterp)
    heat_content_tsanom_depthInterp = scrubNaNAndMask(
        heat_content_tsanom_depthInterp, so_depthInterp)

    # Fix bounds
    newdepth = so_depthInterp.getAxis(0)
    newdepth.setBounds(newdepth_bounds)
    del (newdepth_bounds)
    newdepth.id = 'depth2'
    newdepth.units_long = 'decibar (pressure)'
    newdepth.positive = 'down'
    newdepth.long_name = 'sea_water_pressure'
    newdepth.standard_name = 'sea_water_pressure'
    newdepth.units = 'decibar'
    newdepth.axis = 'Z'

    # Assign corrected bounds
    so_depthInterp.setAxis(0, newdepth)
    temp_depthInterp.setAxis(0, newdepth)
    steric_height_depthInterp.setAxis(0, newdepth)
    steric_height_anom_depthInterp.setAxis(0, newdepth)
    steric_height_thermo_anom_depthInterp.setAxis(0, newdepth)
    steric_height_halo_anom_depthInterp.setAxis(0, newdepth)
    steric_height_halo_anom2_depthInterp.setAxis(0, newdepth)
    heat_content_sanom_depthInterp.setAxis(0, newdepth)
    heat_content_tanom_depthInterp.setAxis(0, newdepth)
    heat_content_tsanom_depthInterp.setAxis(0, newdepth)

    # Average/integrate to surface - configure bounds
    # Preallocate arrays
    so_depthAve = np.ma.zeros([len(newdepth), shape(so)[1], shape(so)[2]])
    temp_depthAve = so_depthAve.copy()
    heat_content_sanom_depthInteg = so_depthAve.copy()
    heat_content_tanom_depthInteg = so_depthAve.copy()
    heat_content_tsanom_depthInteg = so_depthAve.copy()
    for count, depth in enumerate(newdepth):
        tmp = cdu.averager(so_depthInterp[0:(count + 1), ...],
                           axis=0,
                           weights='weighted',
                           action='average')
        so_depthAve[count, ] = tmp
        tmp = cdu.averager(temp_depthInterp[0:(count + 1), ...],
                           axis=0,
                           weights='weighted',
                           action='average')
        temp_depthAve[count, ] = tmp
        tmp = cdu.averager(heat_content_sanom_depthInterp[0:(count + 1), ...],
                           axis=0,
                           weights='weighted',
                           action='sum')
        heat_content_sanom_depthInteg[count, ] = tmp
        tmp = cdu.averager(heat_content_tanom_depthInterp[0:(count + 1), ...],
                           axis=0,
                           weights='weighted',
                           action='sum')
        heat_content_tanom_depthInteg[count, ] = tmp
        tmp = cdu.averager(heat_content_tsanom_depthInterp[0:(count + 1), ...],
                           axis=0,
                           weights='weighted',
                           action='sum')
        heat_content_tsanom_depthInteg[count, ] = tmp
    del (heat_content_tanom_depthInterp, heat_content_tsanom_depthInterp)
    gc.collect()

    # Fix masks - applied before cdms variables are created otherwise names/ids/attributes are reset
    so_depthAve = scrubNaNAndMask(so_depthAve, so_depthInterp)
    temp_depthAve = scrubNaNAndMask(temp_depthAve, so_depthInterp)
    heat_content_sanom_depthInteg = scrubNaNAndMask(
        heat_content_sanom_depthInteg, so_depthInterp)
    heat_content_tanom_depthInteg = scrubNaNAndMask(
        heat_content_tanom_depthInteg, so_depthInterp)
    heat_content_tsanom_depthInteg = scrubNaNAndMask(
        heat_content_tsanom_depthInteg, so_depthInterp)
    del (so_depthInterp)

    # Convert numpy arrays to cdms objects
    heat_content_sanom_depthInteg = cdm.createVariable(
        heat_content_sanom_depthInteg, id='heat_content_sanom_depthInteg')
    heat_content_sanom_depthInteg.id = 'heat_content_sanom_depthInteg'
    heat_content_sanom_depthInteg.setAxis(0, newdepth)
    heat_content_sanom_depthInteg.setAxis(1, so.getAxis(1))
    heat_content_sanom_depthInteg.setAxis(2, so.getAxis(2))
    heat_content_sanom_depthInteg.units = 'J'
    heat_content_tanom_depthInteg = cdm.createVariable(
        heat_content_tanom_depthInteg, id='heat_content_tanom_depthInteg')
    heat_content_tanom_depthInteg.id = 'heat_content_tanom_depthInteg'
    heat_content_tanom_depthInteg.setAxis(0, newdepth)
    heat_content_tanom_depthInteg.setAxis(1, so.getAxis(1))
    heat_content_tanom_depthInteg.setAxis(2, so.getAxis(2))
    heat_content_tanom_depthInteg.units = 'J'
    heat_content_tsanom_depthInteg = cdm.createVariable(
        heat_content_tsanom_depthInteg, id='heat_content_tsanom_depthInteg')
    heat_content_tsanom_depthInteg.id = 'heat_content_tsanom_depthInteg'
    heat_content_tsanom_depthInteg.setAxis(0, newdepth)
    heat_content_tsanom_depthInteg.setAxis(1, so.getAxis(1))
    heat_content_tsanom_depthInteg.setAxis(2, so.getAxis(2))
    heat_content_tsanom_depthInteg.units = 'J'
    so_depthAve = cdm.createVariable(so_depthAve, id='so_depthAve')
    so_depthAve.id = 'so_depthAve'
    so_depthAve.setAxis(0, newdepth)
    so_depthAve.setAxis(1, so.getAxis(1))
    so_depthAve.setAxis(2, so.getAxis(2))
    so_depthAve.units = '1e-3'
    temp_depthAve = cdm.createVariable(temp_depthAve, id='temp_depthAve')
    temp_depthAve.id = 'temp_depthAve'
    temp_depthAve.setAxis(0, newdepth)
    temp_depthAve.setAxis(1, so.getAxis(1))
    temp_depthAve.setAxis(2, so.getAxis(2))
    temp_depthAve.units = 'degrees_C'
    steric_height_depthInterp = cdm.createVariable(
        steric_height_depthInterp, id='steric_height_depthInterp')
    steric_height_depthInterp.setAxis(0, newdepth)
    steric_height_depthInterp.setAxis(1, so.getAxis(1))
    steric_height_depthInterp.setAxis(2, so.getAxis(2))
    steric_height_depthInterp.units = 'm^3 kg^-1 Pa (dynamic decimeter)'
    steric_height_anom_depthInterp = cdm.createVariable(
        steric_height_anom_depthInterp, id='steric_height_anom_depthInterp')
    steric_height_anom_depthInterp.setAxis(0, newdepth)
    steric_height_anom_depthInterp.setAxis(1, so.getAxis(1))
    steric_height_anom_depthInterp.setAxis(2, rho.getAxis(2))
    steric_height_anom_depthInterp.units = 'm^3 kg^-1 Pa (dynamic decimeter)'
    steric_height_thermo_anom_depthInterp = cdm.createVariable(
        steric_height_thermo_anom_depthInterp,
        id='steric_height_thermo_anom_depthInterp')
    steric_height_thermo_anom_depthInterp.setAxis(0, newdepth)
    steric_height_thermo_anom_depthInterp.setAxis(1, so.getAxis(1))
    steric_height_thermo_anom_depthInterp.setAxis(2, so.getAxis(2))
    steric_height_thermo_anom_depthInterp.units = 'm^3 kg^-1 Pa (dynamic decimeter)'
    steric_height_halo_anom_depthInterp = cdm.createVariable(
        steric_height_halo_anom_depthInterp,
        id='steric_height_halo_anom_depthInterp')
    steric_height_halo_anom_depthInterp.setAxis(0, newdepth)
    steric_height_halo_anom_depthInterp.setAxis(1, so.getAxis(1))
    steric_height_halo_anom_depthInterp.setAxis(2, so.getAxis(2))
    steric_height_halo_anom_depthInterp.units = 'm^3 kg^-1 Pa (dynamic decimeter)'
    steric_height_halo_anom2_depthInterp = cdm.createVariable(
        steric_height_halo_anom2_depthInterp,
        id='steric_height_halo_anom2_depthInterp')
    steric_height_halo_anom2_depthInterp.setAxis(0, newdepth)
    steric_height_halo_anom2_depthInterp.setAxis(1, so.getAxis(1))
    steric_height_halo_anom2_depthInterp.setAxis(2, so.getAxis(2))
    steric_height_halo_anom2_depthInterp.units = 'm^3 kg^-1 Pa (dynamic decimeter)'
    # Cleanup workspace
    del (newdepth)
    gc.collect()

    # Write variables to file
    if os.path.isfile(outFileName):
        os.remove(outFileName)
    filehandle = cdm.open(outFileName, 'w')
    # Global attributes
    globalAttWrite(filehandle, options=None)
    # Use function to write standard global atts
    # Write seawater version
    filehandle.seawater_library_version = sw.__version__
    # Write makeSteric version
    makeStericPath = str(makeSteric.__code__).split(' ')[6]
    makeStericPath = replace(replace(makeStericPath, '"', ''), ',', '')
    # Clean scraped path
    filehandle.makeSteric_version = ' '.join(getGitInfo(makeStericPath)[0:3])
    # Master variables
    filehandle.write(so.astype('float32'))
    filehandle.write(so_chg.astype('float32'))
    filehandle.write(so_depthAve.astype('float32'))
    filehandle.write(temp.astype('float32'))
    filehandle.write(temp_chg.astype('float32'))
    filehandle.write(temp_depthAve.astype('float32'))
    # Derived variables
    filehandle.write(cp.astype('float32'))
    filehandle.write(cp_halo.astype('float32'))
    filehandle.write(cp_thermo.astype('float32'))
    filehandle.write(rho.astype('float32'))
    filehandle.write(rho_halo.astype('float32'))
    filehandle.write(rho_thermo.astype('float32'))
    filehandle.write(heat_content.astype('float32'))
    filehandle.write(heat_content_sanom.astype('float32'))
    filehandle.write(heat_content_sanom_depthInteg.astype('float32'))
    filehandle.write(heat_content_tanom.astype('float32'))
    filehandle.write(heat_content_tanom_depthInteg.astype('float32'))
    filehandle.write(heat_content_tsanom.astype('float32'))
    filehandle.write(heat_content_tsanom_depthInteg.astype('float32'))
    filehandle.write(steric_height.astype('float32'))
    filehandle.write(steric_height_depthInterp.astype('float32'))
    filehandle.write(steric_height_anom.astype('float32'))
    filehandle.write(steric_height_anom_depthInterp.astype('float32'))
    filehandle.write(steric_height_halo_anom.astype('float32'))
    filehandle.write(steric_height_halo_anom2.astype('float32'))
    filehandle.write(steric_height_halo_anom_depthInterp.astype('float32'))
    filehandle.write(steric_height_halo_anom2_depthInterp.astype('float32'))
    filehandle.write(steric_height_thermo_anom.astype('float32'))
    filehandle.write(steric_height_thermo_anom_depthInterp.astype('float32'))
    filehandle.close()
    # Cleanup workspace
    del (outFileName)
    gc.collect()
Пример #8
0
 hefti = heft*1.
 #
 empta = empt*1.
 emptp = empt*1.
 empti = empt*1.
 #
 # Compute density
 rhon[t,...] = eosNeutral(tost.data, sost.data) - 1000.
 rhon[t,...].mask  = maski
 rhon[t,...] = maskVal(rhon[t,...], valmask)
 rhonl = rhon.data[t,...]
 # Compute buoyancy/density flux as mass fluxes in kg/m2/s (SI units)
 #  convwf : kg/m2/s = mm/s -> m/s
 convwf = 1.e-3
 pres = tost.data*0.
 denflxh[t,...] = (-sw.alpha(sost.data,tost.data,pres)/sw.cp(sost.data,tost.data,pres))*heft.data
 if empsw == 0:
     denflxw[t,...] = (rhonl+1000.)*sw.beta(sost.data,tost.data,pres)*sost.data*empt.data*convwf
 else:
     denflxw[t,...] = (rhonl+1000.)*sw.beta(sost.data,tost.data,pres)*empt.data*convwf            
 denflx [t,...] = denflxh[t,...] + denflxw[t,...]
 denflx [t,...].mask  = maski
 denflxh[t,...].mask  = maski
 denflxw[t,...].mask  = maski
 denflx [t,...] = maskVal(denflx [t,...], valmask)
 denflxh[t,...] = maskVal(denflxh[t,...], valmask)
 denflxw[t,...] = maskVal(denflxw[t,...], valmask)
 dflxh = denflxh.data[t,:,:]
 dflxw = denflxw.data[t,:,:]
 #
 # Transformation (integral of density flux on density outcrops)
Пример #9
0
def test(fileout='python-test.txt'):
    r"""Copy of the Matlab test.

    Modifications: Phil Morgan
                   03-12-12. Lindsay Pender, Converted to ITS-90.
    """
    f = open(fileout, 'w')
    asterisks = '*' * 76

    f.write(asterisks)
    f.write('\n    TEST REPORT    ')
    f.write('\n')
    f.write('\n SEA WATER LIBRARY %s' % sw.__version__)
    f.write('\n')
    # Show some info about this Python.
    f.write('\npython version: %s' % sys.version)
    f.write('\n on %s computer %s' % (uname()[0], uname()[-1]))
    f.write('\n')
    f.write('\n')
    f.write(asctime(localtime()))
    f.write('\n')
    f.write('\n')

    # Test main module  ptmp.
    f.write('\n%s' % asterisks)
    f.write('\n**  TESTING MODULE: ptmp')
    f.write('\n**  and SUB-MODULE: adtg')
    f.write('\n%s' % asterisks)
    f.write('\n')
    f.write('\n')

    # Test 1 - data from Unesco 1983 p45.
    T = np.array([[0,  0,  0,  0,  0,  0],
                  [10, 10, 10, 10, 10, 10],
                  [20, 20, 20, 20, 20, 20],
                  [30, 30, 30, 30, 30, 30],
                  [40, 40, 40, 40, 40, 40]])

    T = T / 1.00024

    S = np.array([[25, 25, 25, 35, 35, 35],
                  [25, 25, 25, 35, 35, 35],
                  [25, 25, 25, 35, 35, 35],
                  [25, 25, 25, 35, 35, 35],
                  [25, 25, 25, 35, 35, 35]])

    P = np.array([[0, 5000, 10000, 0, 5000, 10000],
                  [0, 5000, 10000, 0, 5000, 10000],
                  [0, 5000, 10000, 0, 5000, 10000],
                  [0, 5000, 10000, 0, 5000, 10000],
                  [0, 5000, 10000, 0, 5000, 10000]])

    Pr = np.array([0, 0, 0, 0, 0, 0])

    UN_ptmp = np.array([[0, -0.3061, -0.9667,  0, -0.3856, -1.0974],
                        [10,  9.3531,  8.4684, 10,  9.2906,  8.3643],
                        [20, 19.0438, 17.9426, 20, 18.9985, 17.8654],
                        [30, 28.7512, 27.4353, 30, 28.7231, 27.3851],
                        [40, 38.4607, 36.9254, 40, 38.4498, 36.9023]])

    PT = sw.ptmp(S, T, P, Pr) * 1.00024

    # Display results.
    f.write('\n')
    f.write('\n%s' % asterisks)
    f.write('\nComparison of accepted values from UNESCO 1983 ')
    f.write('\n (Unesco Tech. Paper in Marine Sci. No. 44, p45)')
    f.write('\n%s' % asterisks)
    f.write('\n')

    m, n = S.shape  # TODO: so many loops there must be a better way.
    for icol in range(0, n):
        f.write('\n   Sal  Temp  Press     PTMP       ptmp')
        f.write('\n  (psu)  (C)   (db)     (C)          (C)\n')
        result = np.vstack((S[:, icol], T[:, icol], P[:, icol],
                            UN_ptmp[:, icol], PT[:, icol]))
        for iline in range(0, m):
            f.write(" %4.0f  %4.0f   %5.0f   %8.4f  %11.5f\n" %
                    tuple(result[:, iline]))

    # Test main module svan.
    f.write('\n%s' % asterisks)
    f.write('\n**  TESTING MODULE: svan')
    f.write('\n**  and SUB-MODULE: dens dens0 smow seck pden ptmp')
    f.write('\n%s' % asterisks)

    # Test data FROM: Unesco Tech. Paper in Marine Sci. No. 44, p22.
    s = np.array([0,     0,  0,     0, 35,    35, 35,   35])
    p = np.array([0, 10000,  0, 10000,  0, 10000,  0, 10000])
    t = np.array([0,     0, 30,    30,  0,     0, 30,    30]) / 1.00024

    UN_svan = np.array([2749.54, 2288.61, 3170.58, 3147.85,
                        0.0,    0.00,  607.14,  916.34])

    SVAN = sw.svan(s, t, p)

    # DISPLAY RESULTS
    f.write('\n')
    f.write('\n%s' % asterisks)
    f.write('\n')
    f.write('\nComparison of accepted values from UNESCO 1983')
    f.write('\n (Unesco Tech. Paper in Marine Sci. No. 44, p22)')
    f.write('\n%s' % asterisks)
    f.write('\n')
    f.write('\n   Sal  Temp  Press        SVAN        svan')
    f.write('\n  (psu)  (C)   (db)    (1e-8*m3/kg)  (1e-8*m3/kg)\n')
    result = np.vstack([s, t, p, UN_svan, 1e+8 * SVAN])
    for iline in range(0, len(SVAN)):
        f.write(" %4.0f  %4.0f   %5.0f   %11.2f    %11.3f\n" %
                tuple(result[:, iline]))

    # Test main module salt.
    f.write('\n%s' % asterisks)
    f.write('\n**  TESTING MODULE: salt')
    f.write('\n**  and SUB-MODULE: salrt salrp sals')
    f.write('\n%s' % asterisks)
    f.write('\n')

    # Test 1 - data from Unesco 1983 p9.
    R = np.array([1, 1.2, 0.65])  # cndr = R.
    T = np.array([15, 20, 5]) / 1.00024
    P = np.array([0, 2000, 1500])
    #Rt   = np.array([  1, 1.0568875, 0.81705885])
    UN_S = np.array([35, 37.245628,  27.995347])

    S = sw.salt(R, T, P)

    # Display results.
    f.write('\n')
    f.write('\n%s' % asterisks)
    f.write('\nComparison of accepted values from UNESCO 1983 ')
    f.write('\n(Unesco Tech. Paper in Marine Sci. No. 44, p9)')
    f.write('\n%s' % asterisks)
    f.write('\n')

    f.write('\n   Temp    Press       R              S           salt')
    f.write('\n   (C)     (db)    (no units)       (psu)          (psu)\n')
    table = np.vstack([T, P, R, UN_S, S])
    m, n = table.shape
    for iline in range(0, n):
        f.write(" %4.0f       %4.0f  %8.2f      %11.6f  %14.7f\n" %
                tuple(table[:, iline]))

    # Test main module cndr.
    f.write('\n%s' % asterisks)
    f.write('\n**  TESTING MODULE: cndr')
    f.write('\n**  and SUB-MODULE: salds')
    f.write('\n%s' % asterisks)

    # Test 1 - data from Unesco 1983 p9.
    T = np.array([0, 10, 0, 10, 10, 30]) / 1.00024
    P = np.array([0,  0, 1000, 1000, 0, 0])
    S = np.array([25, 25, 25, 25, 40, 40])
    UN_R = np.array([0.498088, 0.654990, 0.506244, 0.662975, 1.000073,
                     1.529967])
    R = sw.cndr(S, T, P)

    # Display results.
    f.write('\n')
    f.write('\n%s' % asterisks)
    f.write('\nComparison of accepted values from UNESCO 1983 ')
    f.write('\n (Unesco Tech. Paper in Marine Sci. No. 44, p14)')
    f.write('\n%s' % asterisks)
    f.write('\n')
    f.write('\n')

    f.write('\n   Temp    Press       S            cndr         cndr')
    f.write('\n   (C)     (db)      (psu)        (no units)    (no units)\n')
    table = np.vstack([T, P, S, UN_R, R])
    m, n = table.shape
    for iline in range(0, n):
        f.write(" %4.0f       %4.0f   %8.6f   %11.6f  %14.8f\n" %
                tuple(table[:, iline]))

    # Test main module depth.
    f.write('\n%s' % asterisks)
    f.write('\n**  TESTING MODULE: depth')
    f.write('\n%s' % asterisks)

    # Test data - matrix "pressure", vector "lat"  Unesco 1983 data p30.
    lat = np.array([0, 30, 45, 90])
    P = np.array([[500,   500,   500,  500],
                  [5000,  5000,  5000, 5000],
                  [10000, 10000, 10000, 10000]])

    UN_dpth = np.array([[496.65,  496.00,  495.34,  494.03],
                        [4915.04, 4908.56, 4902.08, 4889.13],
                        [9725.47, 9712.65, 9699.84, 9674.23]])

    dpth = sw.dpth(P, lat)

    # Display results.
    f.write('\n')
    f.write('\n%s' % asterisks)
    f.write('\nComparison of accepted values from Unesco 1983 ')
    f.write('\n(Unesco Tech. Paper in Marine Sci. No. 44, p28)')
    f.write('\n%s' % asterisks)
    f.write('\n')

    f.write('\n')
    for irow in range(0, 3):
        f.write('\n    Lat       Press     DPTH      dpth')
        f.write('\n  (degree)    (db)     (meter)    (meter)\n')
        table = np.vstack([lat, P[irow, :], UN_dpth[irow, :], dpth[irow, :]])
        m, n = table.shape
        for iline in range(0, n):
            f.write("  %6.3f     %6.0f   %8.2f   %8.3f\n" %
                    tuple(table[:, iline]))

    # Test main module fp.
    f.write('\n%s' % asterisks)
    f.write('\n**  TESTING MODULE: fp')
    f.write('\n%s' % asterisks)

    # Test 1 - UNESCO data p.30.
    S = np.array([[5, 10, 15, 20, 25, 30, 35, 40],
                  [5, 10, 15, 20, 25, 30, 35, 40]])

    P = np.array([[0,   0,   0,   0,   0,   0,   0,   0],
                  [500, 500, 500, 500, 500, 500, 500, 500]])

    UN_fp = np.array([[-0.274, -0.542, -0.812, -1.083, -1.358, -1.638, -1.922,
                       -2.212], [-0.650, -0.919, -1.188, -1.460, -1.735,
                                 -2.014, -2.299, -2.589]])

    FP = sw.fp(S, P)

    # Display results.
    f.write('\n')
    f.write('\n%s' % asterisks)
    f.write('\nComparison of accepted values from UNESCO 1983 ')
    f.write('\n (Unesco Tech. Paper in Marine Sci. No. 44, p30)')
    f.write('\n%s' % asterisks)
    f.write('\n')

    f.write('\n')
    for irow in range(0, 2):
        f.write('\n   Sal   Press      fp        fp')
        f.write('\n  (psu)   (db)      (C)        (C)\n')
        table = np.vstack([S[irow, :], P[irow, :], UN_fp[irow, :],
                           FP[irow, :]])
        m, n = table.shape
        for iline in range(0, n):
            f.write(" %4.0f   %5.0f   %8.3f  %11.4f\n" %
                    tuple(table[:, iline]))

    # Test main module cp.
    f.write('\n%s' % asterisks)
    f.write('\n**  TESTING MODULE: cp')
    f.write('\n%s' % asterisks)

    # Test 1.
    # Data from Pond and Pickard Intro. Dynamical Oceanography 2nd ed. 1986
    T = np.array([[0,  0,  0,  0,  0,  0],
                  [10, 10, 10, 10, 10, 10],
                  [20, 20, 20, 20, 20, 20],
                  [30, 30, 30, 30, 30, 30],
                  [40, 40, 40, 40, 40, 40]]) / 1.00024

    S = np.array([[25, 25, 25, 35, 35, 35],
                  [25, 25, 25, 35, 35, 35],
                  [25, 25, 25, 35, 35, 35],
                  [25, 25, 25, 35, 35, 35],
                  [25, 25, 25, 35, 35, 35]])

    P = np.array([[0, 5000, 10000, 0, 5000, 10000],
                  [0, 5000, 10000, 0, 5000, 10000],
                  [0, 5000, 10000, 0, 5000, 10000],
                  [0, 5000, 10000, 0, 5000, 10000],
                  [0, 5000, 10000, 0, 5000, 10000]])

    UN_cp = np.array([[4048.4,  3896.3,  3807.7,  3986.5,  3849.3,  3769.1],
                      [4041.8,  3919.6,  3842.3,  3986.3,  3874.7,  3804.4],
                      [4044.8,  3938.6,  3866.7,  3993.9,  3895.0,  3828.3],
                      [4049.1,  3952.0,  3883.0,  4000.7,  3909.2,  3844.3],
                      [4051.2,  3966.1,  3905.9,  4003.5,  3923.9,  3868.3]])

    CP = sw.cp(S, T, P)

    # Display results.
    f.write('\n')
    f.write('\n%s' % asterisks)
    f.write('\nComparison of accepted values from UNESCO 1983 ')
    f.write('\n (Unesco Tech. Paper in Marine Sci. No. 44, p37)')
    f.write('\n%s' % asterisks)
    f.write('\n')

    m, n = S.shape
    f.write('\n')
    for icol in range(0, n):
        f.write('\n   Sal  Temp  Press      Cp        cp')
        f.write('\n  (psu)  (C)   (db)    (J/kg.C)   (J/kg.C)\n')
        result = np.vstack([S[:, icol], T[:, icol], P[:, icol],
                            UN_cp[:, icol], CP[:, icol]])
        for iline in range(0, m):
            f.write(" %4.0f  %4.0f   %5.0f   %8.1f  %11.2f\n" %
                    tuple(result[:, iline]))

    # Test main module svel.
    f.write('\n%s' % asterisks)
    f.write('\n**  TESTING MODULE: svel')
    f.write('\n%s' % asterisks)

    # Test 1.
    # Data from Pond and Pickard Intro. Dynamical Oceanography 2nd ed. 1986
    T = np.array([[0,  0,  0,  0,  0,  0],
                  [10, 10, 10, 10, 10, 10],
                  [20, 20, 20, 20, 20, 20],
                  [30, 30, 30, 30, 30, 30],
                  [40, 40, 40, 40, 40, 40]]) / 1.00024

    S = np.array([[25, 25, 25, 35, 35, 35],
                  [25, 25, 25, 35, 35, 35],
                  [25, 25, 25, 35, 35, 35],
                  [25, 25, 25, 35, 35, 35],
                  [25, 25, 25, 35, 35, 35]])

    P = np.array([[0, 5000, 10000, 0, 5000, 10000],
                  [0, 5000, 10000, 0, 5000, 10000],
                  [0, 5000, 10000, 0, 5000, 10000],
                  [0, 5000, 10000, 0, 5000, 10000],
                  [0, 5000, 10000, 0, 5000, 10000]])

    UN_svel = np.array([[1435.8, 1520.4, 1610.4, 1449.1, 1534.0, 1623.2],
                        [1477.7, 1561.3, 1647.4, 1489.8, 1573.4, 1659.0],
                        [1510.3, 1593.6, 1676.8, 1521.5, 1604.5, 1687.2],
                        [1535.2, 1619.0, 1700.6, 1545.6, 1629.0, 1710.1],
                        [1553.4, 1638.0, 1719.2, 1563.2, 1647.3, 1727.8]])

    SVEL = sw.svel(S, T, P)

    # Display results.
    f.write('\n')
    f.write('\n%s' % asterisks)
    f.write('\nComparison of accepted values from UNESCO 1983 ')
    f.write('\n (Unesco Tech. Paper in Marine Sci. No. 44, p50)')
    f.write('\n%s' % asterisks)
    f.write('\n')

    m, n = SVEL.shape
    f.write('\n')
    for icol in range(0, n):
        f.write('\n   Sal  Temp  Press     SVEL       svel')
        f.write('\n  (psu)  (C)   (db)     (m/s)       (m/s)\n')

        result = np.vstack([S[:, icol], T[:, icol], P[:, icol],
                            UN_svel[:, icol], SVEL[:, icol]])
        for iline in range(0, m):
            f.write(" %4.0f  %4.0f   %5.0f   %8.1f  %11.3f\n" %
                    tuple(result[:, iline]))

    # Test submodules alpha beta aonb.
    f.write('\n%s' % asterisks)
    f.write('\n**  and SUB-MODULE: alpha beta aonb')
    f.write('\n%s' % asterisks)

    # Data from McDouogall 1987.
    s = 40
    PT = 10
    p = 4000
    beta_lit = 0.72088e-03
    aonb_lit = 0.34763
    alpha_lit = aonb_lit * beta_lit

    BETA = sw.beta(s, PT, p, pt=True)
    ALPHA = sw.alpha(s, PT, p, pt=True)
    AONB = sw.aonb(s, PT, p, pt=True)

    # Display results.
    f.write('\n')
    f.write('\n%s' % asterisks)
    f.write('\nComparison of accepted values from MCDOUGALL 1987 ')
    f.write('\n%s' % asterisks)
    f.write('\n')
    f.write('\n')

    f.write('\n   Sal  Temp  Press     BETA       beta')
    f.write('\n  (psu)  (C)   (db)   (psu^-1)     (psu^-1)\n')
    table = np.hstack([s, PT, p, beta_lit, BETA])
    f.write(" %4.0f  %4.0f   %5.0f   %11.4e  %11.5e\n" %
            tuple(table))

    f.write('\n   Sal  Temp  Press     AONB       aonb')
    f.write('\n  (psu)  (C)   (db)   (psu C^-1)   (psu C^-1)\n')
    table = np.hstack([s, PT, p, aonb_lit, AONB])
    f.write(" %4.0f  %4.0f   %5.0f   %8.5f  %11.6f\n" %
            tuple(table))

    f.write('\n   Sal  Temp  Press     ALPHA       alpha')
    f.write('\n  (psu)  (C)   (db)    (psu^-1)     (psu^-1)\n')
    table = np.hstack([s, PT, p, alpha_lit, ALPHA])
    f.write(" %4.0f  %4.0f   %5.0f   %11.4e  %11.4e\n" %
            tuple(table))

    # Test main moduleS  satO2 satN2 satAr.
    f.write('\n%s' % asterisks)
    f.write('\n**  TESTING MODULE: satO2 satN2 satAr')
    f.write('\n%s' % asterisks)
    f.write('\n')

    # Data from Weiss 1970.
    T = np.array([[-1, -1],
                  [10, 10],
                  [20, 20],
                  [40, 40]]) / 1.00024

    S = np.array([[20, 40],
                  [20, 40],
                  [20, 40],
                  [20, 40]])

    lit_O2 = np.array([[9.162, 7.984],
                       [6.950, 6.121],
                       [5.644, 5.015],
                       [4.050, 3.656]])

    lit_N2 = np.array([[16.28, 14.01],
                       [12.64, 11.01],
                       [10.47,  9.21],
                       [7.78,  6.95]])

    lit_Ar = np.array([[0.4456, 0.3877],
                       [0.3397, 0.2989],
                       [0.2766, 0.2457],
                       [0.1986, 0.1794]])

    O2 = sw.satO2(S, T)
    N2 = sw.satN2(S, T)
    Ar = sw.satAr(S, T)

    # Display results.
    f.write('\n')
    f.write('\n%s' % asterisks)
    f.write('\nComparison of accepted values from Weiss, R.F. 1979 ')
    f.write('\n"The solubility of nitrogen, oxygen and argon in water')
    f.write('\n and seawater." Deep-Sea Research., 1970, Vol 17, pp721-735.')
    f.write('\n%s' % asterisks)
    f.write('\n')

    m, n = S.shape
    f.write('\n')
    for icol in range(0, n):
        f.write('\n   Sal  Temp      O2         satO2')
        f.write('\n  (psu)  (C)      (ml/l)     (ml/l)\n')
        result = np.vstack([S[:, icol], T[:, icol],
                            lit_O2[:, icol], O2[:, icol]])
        for iline in range(0, m):
            f.write(" %4.0f  %4.0f    %8.2f   %9.3f\n" %
                    tuple(result[:, iline]))

    for icol in range(0, n):
        f.write('\n   Sal  Temp      N2         satN2')
        f.write('\n  (psu)  (C)      (ml/l)     (ml/l)\n')
        result = np.vstack([S[:, icol], T[:, icol],
                            lit_N2[:, icol], N2[:, icol]])
        for iline in range(0, m):
            f.write(" %4.0f  %4.0f    %8.2f  %9.3f\n" %
                    tuple(result[:, iline]))

    for icol in range(0, n):
        f.write('\n   Sal  Temp      Ar         satAr')
        f.write('\n  (psu)  (C)      (ml/l)     (ml/l)\n')
        result = np.vstack([S[:, icol], T[:, icol],
                            lit_Ar[:, icol], Ar[:, icol]])
        for iline in range(0, m):
            f.write(" %4.0f  %4.0f     %8.4f  %9.4f\n" %
                    tuple(result[:, iline]))