Exemplo n.º 1
0
def compare_k_propagation(
    p1, p2, k_constant, test_vars, n_simulations=10000, k_uncertainty_percent=0.1
):
    """Compare uncertainty propagation from the equilibrium constant internal overrides
    vs Monte-Carlo simulations.
    """
    # Solve MCS
    par_args = dict(
        par1=pars_true[p1],
        par2=pars_true[p2],
        par1_type=partypes[p1],
        par2_type=partypes[p2],
    )
    results = pyco2.sys(**par_args, **kwargs)
    # Simulate uncertainty in the selected k_constant
    k_value = results[k_constant]
    k_uncertainty = k_value * k_uncertainty_percent / 100
    kwargs_u = copy.deepcopy(kwargs)
    kwargs_u.update(
        {k_constant: rng.normal(loc=k_value, scale=k_uncertainty, size=n_simulations)}
    )
    # Solve MCS with uncertain k_constant
    results_u = pyco2.sys(**par_args, **kwargs_u)
    k_uncertainty__simulated = {k: np.std(results_u[k]) for k in test_vars}
    # Propagate uncertainty
    k_uncertainty__direct = pyco2.uncertainty.propagate_nd(
        results, test_vars, {k_constant: k_uncertainty}, dx=1e-6, **kwargs
    )[0]
    return k_uncertainty__simulated, k_uncertainty__direct
Exemplo n.º 2
0
def compare_par1par2(i, fixedpartype, uncertainties_in):
    """Do uncertainties in par1, par2, and both together, propagate equivalently between
    the direct calculation and Monte-Carlo simulations?
    """
    fixedpar = partypes == fixedpartype
    par1s_true = pars_true[~fixedpar]
    par1u_true = paru_true[~fixedpar]
    par1types = partypes[~fixedpar]
    par2s_true = np.full_like(par1s_true, pars_true[fixedpar][0])
    par2u_true = np.full_like(par1u_true, paru_true[fixedpar][0])
    par2types = np.full_like(par1types, partypes[fixedpar][0])
    par1 = par1s_true[i]
    par1type = par1types[i]
    par2 = par2s_true[i]
    par2type = par2types[i]
    co2d = pyco2.sys(par1, par2, par1type, par2type, **kwargs)
    # Propagate directly
    uncertainties_in = [uncertainties_in]
    uncertainties, components = pyco2.uncertainty.propagate_nd(
        co2d, uncertainties_in, {"par1": par1u_true[i], "par2": par2u_true[i]}, **kwargs
    )
    # Estimate the same with Monte-Carlo simulation
    mcsize = (10000,)
    par1sim = rng.normal(size=mcsize, loc=par1, scale=par1u_true[i])
    par2sim = rng.normal(size=mcsize, loc=par2, scale=par2u_true[i])
    co2d_par1sim = pyco2.sys(par1sim, par2, par1type, par2type, **kwargs)
    co2d_par2sim = pyco2.sys(par1, par2sim, par1type, par2type, **kwargs)
    co2d_bothsim = pyco2.sys(par1sim, par2sim, par1type, par2type, **kwargs)
    umc1 = np.std(co2d_par1sim[uncertainties_in[0]])
    umc2 = np.std(co2d_par2sim[uncertainties_in[0]])
    umcBoth = np.std(co2d_bothsim[uncertainties_in[0]])
    compare1 = get_compare(umc1, components[uncertainties_in[0]]["par1"])
    compare2 = get_compare(umc2, components[uncertainties_in[0]]["par2"])
    compareBoth = get_compare(umcBoth, uncertainties[uncertainties_in[0]])
    return compare1, compare2, compareBoth
Exemplo n.º 3
0
def compare_Kunc(p1, p2, Kstr, io):
    """Compare uncertainty propagation from the equilibrium constant internal overrides
    vs Monte-Carlo simulations.
    """
    mcsize = 10000
    Kunc_pct = 0.05
    co2d = pyco2.CO2SYS(np.full(mcsize, pars_true[p1]), pars_true[p2],
                        partypes[p1], partypes[p2], *args, **kwargs)
    if io == "in":
        equilibria_in = {
            Kstr:
            np.random.normal(
                loc=co2d["{}{}put".format(Kstr, io)][0],
                scale=co2d["{}{}put".format(Kstr, io)][0] * Kunc_pct,
                size=mcsize,
            )
        }
        co2d_mcsim = pyco2.CO2SYS(np.full(mcsize, pars_true[p1]),
                                  pars_true[p2],
                                  partypes[p1],
                                  partypes[p2],
                                  *args,
                                  **kwargs,
                                  equilibria_in=equilibria_in)
    elif io == "out":
        equilibria_out = {
            Kstr:
            np.random.normal(
                loc=co2d["{}{}put".format(Kstr, io)][0],
                scale=co2d["{}{}put".format(Kstr, io)][0] * Kunc_pct,
                size=mcsize,
            )
        }
        co2d_mcsim = pyco2.CO2SYS(np.full(mcsize, pars_true[p1]),
                                  pars_true[p2],
                                  partypes[p1],
                                  partypes[p2],
                                  *args,
                                  **kwargs,
                                  equilibria_out=equilibria_out)
    testvar = "isoQ{}".format(io)
    testunc_Mcsim = np.std(co2d_mcsim[testvar])
    uncertainties, components = pyco2.uncertainty.propagate(
        co2d,
        [testvar],
        {
            "{}{}put".format(Kstr, io):
            Kunc_pct * co2d["{}{}put".format(Kstr, io)][0]
        },
    )
    comparison = get_compare(testunc_Mcsim, uncertainties[testvar][0])
    print(p1, p2, Kstr)
    if comparison > -1:
        print(testunc_Mcsim)
        print(uncertainties[testvar][0])
        print(comparison)
    assert (comparison < 4) or (uncertainties[testvar][0] < 1e-9)
Exemplo n.º 4
0
def test_pH_conversions_sys():
    r1 = pyco2.sys(par1=8.1, par1_type=3, opt_pH_scale=1)
    r2 = pyco2.sys(par1=r1["pH_sws"], par1_type=3, opt_pH_scale=2)
    r3 = pyco2.sys(par1=r1["pH_free"], par1_type=3, opt_pH_scale=3)
    r4 = pyco2.sys(par1=r1["pH_nbs"], par1_type=3, opt_pH_scale=4)
    for scale in ["pH_total", "pH_sws", "pH_free", "pH_nbs"]:
        assert np.isclose(r1[scale], r2[scale], rtol=0, atol=1e-12)
        assert np.isclose(r2[scale], r3[scale], rtol=0, atol=1e-12)
        assert np.isclose(r3[scale], r4[scale], rtol=0, atol=1e-12)
Exemplo n.º 5
0
def test_virial_coefficient():
    # Calculate fugacity factors
    fugfac_seaflux = sf.fco2_pco2_conversion.virial_coeff(
        temperature_K, pres_atm)
    fugfac_pyco2 = pyco2.sys(2100, 8.1, 2, 3,
                             temperature=temperature)["fugacity_factor"]
    # Compare results
    assert np.all(np.isclose(fugfac_seaflux, fugfac_pyco2, rtol=0, atol=1e-7))
Exemplo n.º 6
0
def propagate_both_and_compare(k):
    # Propagate "both" uncertainties through PyCO2SYS and also get derivatives
    u_into = ["isocapnic_quotient_out"]
    u_from = {"{}_both".format(k): 0.5}
    grads_wrt = [k, "{}_out".format(k)]
    kwargs = dict(
        par1=2300,
        par2=8.1,
        par1_type=1,
        par2_type=3,
        temperature_out=0,
        pressure_out=10000,
        grads_of=u_into,
        grads_wrt=grads_wrt,
        uncertainty_into=u_into,
        uncertainty_from=u_from,
    )
    results = pyco2.sys(**kwargs)
    u_result__both = results["u_{}".format(u_into[0])]
    # Assemble uncertainty matrix with complete covariance and Jacobian
    u_mx = np.full((2, 2), u_from["{}_both".format(k)]**2)
    jac = np.array([[
        results["d_{}__d_{}".format(of, wrt)]
        for of, wrt in itertools.product(u_into, grads_wrt)
    ]])
    u_result__jac = np.sqrt((jac @ u_mx @ jac.T)[0][0])
    # Manual increment
    if k.startswith("p"):
        kk = k[1:]
        da = 1e-6
        kwargs[kk] = 10.0**-(-np.log10(results[kk]) + da)
        kwargs["{}_out".format(
            kk)] = 10.0**-(-np.log10(results["{}_out".format(kk)]) + da)
    else:
        kk = k
        da__f = 1e-6
        da = da__f * results[kk]
        kwargs[kk] = results[kk] + da
        kwargs["{}_out".format(kk)] = results["{}_out".format(kk)] + da
    results_manual = pyco2.sys(**kwargs)
    u_result__manual = np.abs(results_manual[u_into[0]] - results[u_into[0]])
    u_result__manual *= u_from["{}_both".format(k)]
    u_result__manual /= da
    return u_result__both, u_result__jac, u_result__manual
Exemplo n.º 7
0
def test_fCO2_to_pCO2_conversion():
    # Convert fCO2 to pCO2
    pCO2_pyco2 = pyco2.sys(pCO2_or_fCO2, 8.1, 5, 3,
                           temperature=temperature)["pCO2"]
    pCO2_seaflux = sf.fCO2_to_pCO2(pCO2_or_fCO2, temperature)
    # Compare results - not perfect agreement, but "good enough"(?) i.e. <0.01 microatm
    not_nan = ~np.isnan(pCO2_seaflux)
    assert np.all(
        np.isclose(pCO2_pyco2[not_nan],
                   pCO2_seaflux[not_nan],
                   rtol=0,
                   atol=0.01))
Exemplo n.º 8
0
def compare_par1par2(i, fixedpartype, uncertainties_in):
    fixedpar = partypes == fixedpartype
    par1s_true = pars_true[~fixedpar]
    par1u_true = paru_true[~fixedpar]
    par1types = partypes[~fixedpar]
    par2s_true = np.full_like(par1s_true, pars_true[fixedpar][0])
    par2u_true = np.full_like(par1u_true, paru_true[fixedpar][0])
    par2types = np.full_like(par1types, partypes[fixedpar][0])
    par1 = par1s_true[i]
    par1type = par1types[i]
    par2 = par2s_true[i]
    par2type = par2types[i]
    co2d = pyco2.CO2SYS(par1, par2, par1type, par2type, *args, **kwargs)
    # Propagate directly
    uncertainties_in = [uncertainties_in]
    uncertainties, components = pyco2.uncertainty.propagate(
        co2d, uncertainties_in, {
            "PAR1": par1u_true[i],
            "PAR2": par2u_true[i]
        })
    # Estimate the same with Monte-Carlo simulation
    mcsize = (10000, )
    par1sim = np.random.normal(size=mcsize, loc=par1, scale=par1u_true[i])
    par2sim = np.random.normal(size=mcsize, loc=par2, scale=par2u_true[i])
    co2d_par1sim = pyco2.CO2SYS(par1sim, par2, par1type, par2type, *args,
                                **kwargs)
    co2d_par2sim = pyco2.CO2SYS(par1, par2sim, par1type, par2type, *args,
                                **kwargs)
    co2d_bothsim = pyco2.CO2SYS(par1sim, par2sim, par1type, par2type, *args,
                                **kwargs)
    umc1 = np.std(co2d_par1sim[uncertainties_in[0]])
    umc2 = np.std(co2d_par2sim[uncertainties_in[0]])
    umcBoth = np.std(co2d_bothsim[uncertainties_in[0]])
    compare1 = get_compare(umc1, components[uncertainties_in[0]]["PAR1"])
    compare2 = get_compare(umc2, components[uncertainties_in[0]]["PAR2"])
    compareBoth = get_compare(umcBoth, uncertainties[uncertainties_in[0]])
    return compare1, compare2, compareBoth
Exemplo n.º 9
0
def run_co2sys_ta_ph(ta, ph, sal, temp=25, press_dbar=0):
    """
    Runs the PyCO2SYS function using input TA and pH data.
    opt_pH_scale=1 is the default (Total scale), including here for clarity.
    opt_k_carbonic=4 is MCHP73 (Mehrbach et al 1973) refit by DM87 (Dickson & Millero 1987)
    opt_k_bisulfate=1 is the default (Dickson 1990), including here for clarity
    opt_total_borate=1 is the default (Uppstrom 1974), including here for clarity
    opt_k_fluoride=2 is PF87 (Perez & Fraga 1987)
    :param ta: Total Alkalinity array
    :param ph: pH array
    :param sal: salinity array
    :param temp: temperature array, default=25
    :param press_dbar: pressure (in units=dbar) array, default=0
    :return: calculated aragonite saturation, pCO2, revelle factor
    """
    # define input conditions
    par1 = ta  # Total Alkalinity
    par1_type = 1  # parameter 1 type (TA)
    par2 = ph
    par2_type = 3  # parameter 2 type (pH)

    kwargs = dict(salinity=sal,
                  temperature=temp,
                  pressure=press_dbar,
                  opt_pH_scale=1,
                  opt_k_carbonic=4,
                  opt_k_bisulfate=1,
                  opt_total_borate=1,
                  opt_k_fluoride=2)

    results = pyco2.sys(par1, par2, par1_type, par2_type, **kwargs)
    omega_arag = results['saturation_aragonite']  # aragonite saturation state
    pco2 = results['pCO2']  # units = uatm
    revelle = results['revelle_factor']

    return omega_arag, pco2, revelle
 pyco2.sys(
     co2inputs[0],
     co2inputs[1],
     co2inputs[2],
     co2inputs[3],
     salinity=co2inputs[4],
     temperature=co2inputs[5],
     temperature_out=co2inputs[6],
     pressure=co2inputs[7],
     pressure_out=co2inputs[8],
     total_silicate=co2inputs[9],
     total_phosphate=co2inputs[10],
     total_ammonia=co2inputs[11],
     total_sulfide=co2inputs[12],
     opt_pH_scale=co2inputs[13],
     opt_k_carbonic=co2inputs[14],
     opt_k_bisulfate=co2inputs[15],
     opt_k_fluoride=co2inputs[16],
     opt_total_borate=co2inputs[17],
     opt_gas_constant=3,
     grads_of=[
         "alkalinity",
         "dic",
         "pCO2",
         "fCO2",
         "bicarbonate",
         "carbonate",
         "aqueous_CO2",
         "xCO2",
         "pCO2_out",
         "fCO2_out",
         "bicarbonate_out",
         "carbonate_out",
         "aqueous_CO2_out",
         "xCO2_out",
     ],
     grads_wrt=["temperature", "salinity", "k_CO2", "k_carbonic_1", "k_carbonic_2"],
 )
Exemplo n.º 11
0
import PyCO2SYS as pyco2, numpy as np

# Run PyCO2SYS to begin with some silicate
args = (2250, [2100, 8.1, 400, 150, 500, 10000], 1, [2, 3, 4, 5, 2, 2])
opt_pH_scale = 3
r0 = pyco2.sys(*args, total_silicate=100, opt_pH_scale=3)

# Add alpha instead of silicate
r1 = pyco2.sys(
    *args,
    total_silicate=0,
    total_alpha=r0["total_silicate"],
    k_alpha=r0["k_silicate"],
    opt_pH_scale=opt_pH_scale,
)

# Add beta instead of fluoride - note HF used in pK scale conversions so you have to
# provide them all ready-converted
r2 = pyco2.sys(
    *args,
    total_silicate=r0["total_silicate"],
    total_fluoride=0,
    total_beta=r0["total_fluoride"],
    k_beta=r0["k_fluoride"],
    k_carbonic_1=r0["k_carbonic_1"],
    k_carbonic_2=r0["k_carbonic_2"],
    k_water=r0["k_water"],
    k_borate=r0["k_borate"],
    k_bisulfate=r0["k_bisulfate"],
    k_silicate=r0["k_silicate"],
    opt_pH_scale=opt_pH_scale,
Exemplo n.º 12
0
import copy
import PyCO2SYS as pyco2, numpy as np

# Seed random number generator for reproducibility
rng = np.random.default_rng(7)

# Generate inputs
npts = 1000
alkalinity = rng.normal(loc=2300, scale=500, size=npts)
dic = rng.normal(loc=2100, scale=500, size=npts)
kwargs = dict(par1=alkalinity, par2=dic, par1_type=1, par2_type=2,)

# Solve the marine carbonate system
r_explicit = pyco2.sys(**kwargs, buffers_mode="explicit")
r_automatic = pyco2.sys(**kwargs, buffers_mode="auto")

# Compare the buffers
buffers = [
    "beta_alk",
    "beta_dic",
    "gamma_alk",
    "gamma_dic",
    "omega_alk",
    "omega_dic",
    "psi",
    "isocapnic_quotient",
    "revelle_factor",
]
buffers_difference = {}
buffers_percent = {}
for buffer in buffers:
Exemplo n.º 13
0
phos = 3
h2s = 0.12
nh3 = 0.5
k1k2c = 16
kso4c = 3
phscale = 3
# - get the co2dict
co2dict = pyco2.CO2SYS(
    par1,
    par2,
    par1type,
    par2type,
    sal,
    tempin,
    tempout,
    presin,
    presout,
    si,
    phos,
    phscale,
    k1k2c,
    kso4c,
    H2S=h2s,
    NH3=nh3,
)
# - propagate the uncertainties
grads_of = "all"
grads_wrt = "all"
co2derivs, dxs = pyco2.uncertainty.forward(
    co2dict,
    grads_of,
    grads_wrt,
Exemplo n.º 14
0
    "opt_k_fluoride": rng.integers(size=npts, low=1, high=2, endpoint=True),
    "opt_gas_constant": 3,
    "buffers_mode": "none",
    "total_alpha": rng.uniform(size=npts, low=0, high=100),
    "k_alpha": rng.uniform(size=npts, low=2, high=12),
    "total_beta": rng.uniform(size=npts, low=0, high=100),
    "k_beta": rng.uniform(size=npts, low=2, high=12),
}
# Remove Peng options (bad alkalinity equation!)
opt_kc = pyco2_kwargs["opt_k_carbonic"]
pyco2_kwargs["opt_k_carbonic"][opt_kc == 7] = 16

# Set MCS parameters and solve with PyCO2SYS
pH = np.append(rng.uniform(size=npts - 1, low=3, high=10), 8.1)
dic = np.append(rng.uniform(size=npts - 1, low=0, high=5000), 0)
results_pyco2 = pyco2.sys(pH, dic, 3, 2, **pyco2_kwargs)
alkalinity_pyco2 = results_pyco2["alkalinity"]

# Solve with Calkulate
results_for_calk = {
    k: v * 1e-6 if k.startswith("total_") or k == "dic" else v
    for k, v in results_pyco2.items()
}
components_calk = calk.simulate.alkalinity_components(pH, results_for_calk,
                                                      results_for_calk)
alkalinity_calk = calk.simulate.alkalinity(pH, results_for_calk,
                                           results_for_calk) * 1e6

# Compare individual components
results_pyco2["H"] = results_pyco2["Hfree"]
results_pyco2["alk_alpha"] = results_pyco2["alkalinity_alpha"]
Exemplo n.º 15
0
import numpy as np, PyCO2SYS as pyco2

# Calculate initial results
kwargs = {
    "salinity": 32,
    "k_carbonic_1": 1e-6,
}
par1 = np.linspace(2000, 2100, 11)
par2 = np.vstack(np.linspace(2300, 2400, 21))
par1_type = 2
par2_type = 1
results = pyco2.sys(par1, par2, par1_type, par2_type, **kwargs)

# Get gradients
grads_of = ["pH", "k_carbonic_1"]
grads_wrt = ["par1", "par2", "k_carbonic_1", "pk_carbonic_1", "temperature"]
CO2SYS_derivs, dxs = pyco2.uncertainty.forward_nd(
    results, grads_of, grads_wrt, **kwargs
)

# Do independent uncertainty propagation
uncertainties_into = ["pH", "isocapnic_quotient", "dic"]
uncertainties_from = {
    "par1": 2,
    "par2": 2,
    "pk_carbonic_1": 0.02,
}
uncertainties, components = pyco2.uncertainty.propagate_nd(
    results, uncertainties_into, uncertainties_from, **kwargs,
)
Exemplo n.º 16
0
# Import MATLAB results and recalculate with PyCO2SYS
matlab = pd.read_csv(
    "manuscript/results/compare_equilibrium_constants_v3_1_1.csv")
python = pd.DataFrame(
    pyco2.sys(
        matlab.PAR1.values,
        matlab.PAR2.values,
        matlab.PAR1TYPE.values,
        matlab.PAR2TYPE.values,
        salinity=matlab.SAL.values,
        temperature=matlab.TEMPIN.values,
        temperature_out=matlab.TEMPOUT.values,
        pressure=matlab.PRESIN.values,
        pressure_out=matlab.PRESOUT.values,
        opt_pH_scale=matlab.pHSCALEIN.values,
        opt_gas_constant=3,
        opt_k_carbonic=matlab.K1K2CONSTANTS.values,
        opt_total_borate=matlab.BORON.values,
        opt_k_bisulfate=matlab.KSO4CONSTANT.values,
        opt_k_fluoride=matlab.KFCONSTANT.values,
        total_phosphate=matlab.PO4.values,
        total_silicate=matlab.SI.values,
        total_ammonia=matlab.TNH4.values,
        total_sulfide=matlab.TH2S.values,
        buffers_mode="none",
    ))


def test_equilibrium_constants():
    for m, p in (
        ("K0input", "k_CO2"),
Exemplo n.º 17
0
    "pCO2_out",
    "fCO2_out",
    "bicarbonate_out",
    "carbonate_out",
    "aqueous_CO2_out",
    "saturation_calcite_out",
    "saturation_aragonite_out",
    "xCO2_out",
]
uncert_from = {"{}_both".format(k): v for k, v in pyco2.uncertainty.pKs_OEDG18.items()}
# uncert_from = {"{}_out".format(k): v for k, v in pyco2.uncertainty.pKs_OEDG18.items()}
# uncert_from.update(pyco2.uncertainty.pKs_OEDG18)
uncert_from["total_borate__f"] = pyco2.uncertainty_OEDG18["total_borate__f"]
uncert_from.update({"par1": co2ml.UPAR1.values, "par2": co2ml.UPAR2.values})
results = pd.DataFrame(
    pyco2.sys(**kwargs, uncertainty_into=uncert_into, uncertainty_from=uncert_from)
)
pyco2sys_u = pd.DataFrame(
    {
        "u_TAlk_": results.u_alkalinity,
        "u_TCO2_": results.u_dic,
        "u_pCO2in_": results.u_pCO2,
        "u_fCO2in_": results.u_fCO2,
        "u_HCO3in_": results.u_bicarbonate,
        "u_CO3in_": results.u_carbonate,
        "u_CO2in_": results.u_aqueous_CO2,
        "u_OmegaCAin_": results.u_saturation_calcite,
        "u_OmegaARin_": results.u_saturation_aragonite,
        "u_xCO2in_": results.u_xCO2,
        "u_pCO2out_": results.u_pCO2_out,
        "u_fCO2out_": results.u_fCO2_out,
Exemplo n.º 18
0
# Assemble inputs into dicts
if np.isscalar(temperature):
    temperature = np.array([temperature])
if np.isscalar(salinity):
    salinity = np.array([salinity])
kwargs_core = dict(
    temperature=temperature,
    salinity=salinity,
    opt_pH_scale=3,
    opt_k_carbonic=16,
    opt_total_borate=1,
)

# Calculate total alkalinity
co2sys_core = pyco2.sys(dic, pH_free, 2, 3, **kwargs_core)
alkalinity_core = co2sys_core["alkalinity"]

# Simulate titration(s)
dilution_factor = sample_mass / (sample_mass + titrant_mass)
alkalinity_titration = (1e6 * (sample_mass * co2sys_core["alkalinity"] * 1e-6 -
                               titrant_mass * titrant_molinity) /
                        (sample_mass + titrant_mass))
dic_titration = dic * dilution_factor
kwargs_titration = copy.deepcopy(kwargs_core)
kwargs_titration.update(
    total_borate=co2sys_core["total_borate"],
    total_fluoride=co2sys_core["total_fluoride"],
    total_sulfate=co2sys_core["total_sulfate"],
)
for k in [
Exemplo n.º 19
0
import numpy as np
import PyCO2SYS as pyco2

# Set conditions
alkalinity = 0
dic = 2500

# Get all pHs from TA and DIC
opt_pH_scale = np.array([1, 2, 3, 4])
results_original = pyco2.sys(alkalinity, dic, 1, 2, opt_pH_scale=opt_pH_scale)

# Get all pHs from TA and DIC, again
results_fixed = pyco2.sys(alkalinity,
                          dic,
                          1,
                          2,
                          opt_pH_scale=np.array([1, 2, 3, 4]))


# Check they're consistent regardless of input scale
def test_pH_scale_consistency():
    assert np.all(
        np.isclose(results_fixed["pH_total"],
                   results_fixed["pH"][opt_pH_scale == 1]))
    assert np.all(
        np.isclose(results_fixed["pH_sws"],
                   results_fixed["pH"][opt_pH_scale == 2]))
    assert np.all(
        np.isclose(results_fixed["pH_free"],
                   results_fixed["pH"][opt_pH_scale == 3]))
    assert np.all(
Exemplo n.º 20
0
import pandas as pd, numpy as np
import PyCO2SYS as pyco2

# Use the EZIO function
filestem = "tests/data/EZIO_input_template"
df = pyco2.ezio(filestem + ".xlsx")
df_cols = [c for c in df.columns if c != "-"]
df_numpy = df[df_cols].to_numpy(dtype=float)
df_saved = pd.read_csv(filestem + "_processed.csv")


def test_ezio_df():
    """Does the EZIO function return a pandas DataFrame with non-NaN values?"""
    assert isinstance(df, pd.DataFrame)
    assert ~np.any(np.isnan(df_numpy))


def test_ezio_output():
    """Does the EZIO function save its results to a file?"""
    assert isinstance(df_saved, pd.DataFrame)
    for col in df_cols:
        assert np.all(np.isclose(df[col].to_numpy(dtype=float), df_saved[col]))


# test_ezio_df()
# test_ezio_output()
Exemplo n.º 21
0
        "SAL",
        "TEMPIN",
        "TEMPOUT",
        "PRESIN",
        "PRESOUT",
        "SI",
        "PO4",
        "pHSCALEIN",
        "K1K2CONSTANTS",
        "KSO4CONSTANTS",
        "NH3",
        "H2S",
        "KFCONSTANT",
    ]
]
co2py = pyco2.CO2SYS(*co2inputs, buffers_mode="auto")

# Get override input dicts from co2py and use them in CO2SYS
totals = pyco2.engine.dict2totals_umol(co2py)
equilibria_in, equilibria_out = pyco2.engine.dict2equilibria(co2py)
co2py_override = pyco2.CO2SYS(*co2inputs,
                              buffers_mode="auto",
                              totals=totals,
                              equilibria_in=equilibria_in,
                              equilibria_out=equilibria_out)

# Compare results - should be ~identical
co2py_diff = {
    k: co2py_override[k] - co2py[k]
    for k in co2py if k != "buffers_mode"
}
Exemplo n.º 22
0

test_conditioning()

#%% Now move on to the main function
par1 = [2300, 2150, 8.3]
par2 = [2150]
par1_type = [1, 1, 3]
par2_type = 2
kwargs = {
    "salinity": [[35, 31, 0.8], [34, 34, 34]],
    "total_sulfate": [[3], [5]],
    "k_carbonic_1": [1e-6, 1.1e-6, 1.2e-6],
    "temperature_out": 0,
}
co2nd = pyco2.sys(par1, par2, par1_type, par2_type, **kwargs)


def test_nd_misc():
    assert (np.shape(co2nd["k_carbonic_2"]) == pyco2.engine.nd.broadcast1024(
        par1, par2, par1_type, par2_type, *kwargs.values()).shape)


test_nd_misc()

# Test with all scalar inputs
co2nd_scalar = pyco2.CO2SYS_nd(2300, 2150, 1, 2)


def test_scalars():
    assert np.all([np.size(v) == 1 for v in co2nd_scalar.values()])
Exemplo n.º 23
0
# Import packages
import PyCO2SYS as pyco2
import pandas as pd

# Why not
pyco2.say_hello()

# Define test conditions
par1 = 2300  # parameter 1, here total alkalinity in μmol/kg-sw
par2 = 8.1  # parameter 2, here pH on the Total scale
par1type = 1  # "parameter 1 is total alkalinity"
par2type = 3  # "parameter 2 is pH"
sal = 33  # practical salinity
temp = 22  # temperature in °C
pres = 1000  # pressure in dbar
si = 10  # total silicate in μmol/kg-sw
phos = 1  # total phosphate in μmol/kg-sw
nh3 = 2  # total ammonia in μmol/kg-sw
h2s = 3  # total sulfide in μmol/kg-sw
pHscale = 1  # "input pH is on the Total scale"
k1k2c = 10  # "use LDK00 constants for carbonic acid dissociation"
kso4c = 3  # "use D90a for bisulfate dissociation and LKB10 for borate:salinity"

# Run the test
res, diff = pyco2.test.roundrobin(
    par1,
    par2,
    par1type,
    par2type,
    sal,
    temp,
Exemplo n.º 24
0
test_co2py_matlab()


# Compare new n-d approach
co2nd = pd.DataFrame(
    pyco2.sys(
        co2inputs[0],
        co2inputs[1],
        co2inputs[2],
        co2inputs[3],
        salinity=co2inputs[4],
        temperature=co2inputs[5],
        temperature_out=co2inputs[6],
        pressure=co2inputs[7],
        pressure_out=co2inputs[8],
        total_silicate=co2inputs[9],
        total_phosphate=co2inputs[10],
        total_ammonia=co2inputs[11],
        total_sulfide=co2inputs[12],
        opt_pH_scale=co2inputs[13],
        opt_k_carbonic=co2inputs[14],
        opt_k_bisulfate=co2inputs[15],
        opt_k_fluoride=co2inputs[16],
        opt_total_borate=co2inputs[17],
        opt_gas_constant=3,
    )
)


def test_nd():
    assert np.all(co2nd.isocapnic_quotient_out.values == co2py.isoQout.values)
orr2 = pd.read_csv("manuscript/data/orr2018-table2.csv")
orr = dict(
    par1=2300,
    par2=2000,
    par1_type=1,
    par2_type=2,
    temperature=18,
    salinity=35,
    total_phosphate=0,
    total_silicate=0,
    opt_k_carbonic=10,
    opt_total_borate=2,
)
grads_of = [c for c in orr2.columns if c not in ["wrt", "program"]]
grads_wrt = ["par1", "par2", "temperature", "salinity"]
results = pyco2.sys(**orr, grads_of=grads_of, grads_wrt=grads_wrt)
for wrt in grads_wrt:
    if wrt == "par1":
        wrt_label = "alkalinity"
    elif wrt == "par2":
        wrt_label = "dic"
    else:
        wrt_label = wrt
    nrow = pd.Series({"wrt": wrt_label, "program": "PyCO2SYS"})
    for of in grads_of:
        nrow[of] = results["d_{}__d_{}".format(of, wrt)]
        if of == "Hfree":
            nrow[of] *= 1e3
    orr2 = orr2.append(nrow, ignore_index=True)
orr2_groups = orr2.groupby("wrt").mean()
orr2.set_index(["wrt", "program"], inplace=True)
Exemplo n.º 26
0
titrant_molinity = 0.3  # mol/kg
titrant_mass = np.arange(0, 2.51, 0.05) * 1e-3  # kg
dilution_factor = sample_mass / (sample_mass + titrant_mass)

# Dilute alkalinity etc. through the titration
alkalinity = (
    1e6
    * (sample_mass * alkalinity * 1e-6 - titrant_molinity * titrant_mass)
    / (sample_mass + titrant_mass)
)
dic *= dilution_factor
for k in ["total_borate", "total_fluoride", "total_sulfate"]:
    kwargs[k] *= dilution_factor

# Solve for pH, no phosphate
results_pH = pyco2.CO2SYS_nd(alkalinity, dic, 1, 2, **kwargs)
pH = results_pH["pH_free"]

# And again, with phosphate
kwargs.update(
    {
        "total_phosphate": 10 * dilution_factor,
        "k_phosphate_1": 1 / 5.68e1,
        "k_phosphate_2": 8e-7,
        "k_phosphate_3": 1.32e-15 / 8e-7,
    }
)
pH_phosphate = pyco2.CO2SYS_nd(alkalinity, dic, 1, 2, **kwargs)["pH_free"]

# Compare with D81's tables
d81_pH = np.genfromtxt(
Exemplo n.º 27
0
    salinity=33,  # practical salinity
    temperature=22,  # temperature in °C
    pressure=1234,  # pressure in dbar
    total_silicate=10,  # total silicate in μmol/kg-sw
    total_phosphate=1,  # total phosphate in μmol/kg-sw
    total_ammonia=2,  # total ammonia in μmol/kg-sw
    total_sulfide=3,  # total sulfide in μmol/kg-sw
    total_alpha=5,
    k_alpha=1e-4,
    total_beta=6,
    k_beta=1e-8,
    buffers_mode="none",  # don't bother calculating buffer factors
)

# Solve the system initially
results = pyco2.sys(par1, par2, par1_type, par2_type, **kwargs)

# Define parameter types and names in output
partypes = {
    1: "alkalinity",
    2: "dic",
    3: "pH",
    4: "pCO2",
    5: "fCO2",
    6: "carbonate",
    7: "bicarbonate",
    8: "aqueous_CO2",
    9: "xCO2",
}

Exemplo n.º 28
0
        "PAR1TYPE",
        "PAR2TYPE",
        "SAL",
        "TEMPIN",
        "TEMPOUT",
        "PRESIN",
        "PRESOUT",
        "SI",
        "PO4",
        "pHSCALEIN",
        "K1K2CONSTANTS",
        "KSO4CONSTANTS",
    ]
]
go = time()
co2py = pyco2.CO2SYS(*co2inputs, buffers_mode="none")
print("PyCO2SYS runtime = {:.6f} s".format(time() - go))
co2py = pd.DataFrame(co2py)

# short = ((co2inputs[2] == 1) & (co2inputs[3] == 4)) | (
#     (co2inputs[2] == 4) & (co2inputs[3] == 1)
# )
# short_ix = co2py.index[short]
# co2py_short = pd.DataFrame(
#     pyco2.CO2SYS(*[i[short] for i in co2inputs], buffers_mode="none")
# )
# short_diff = co2py.loc[short_ix, "BAlkin"].values - co2py_short["BAlkin"].values

# Also test the original CO2SYS clone
go = time()
DATA, HEADERS, _ = pyco2.original.CO2SYS(*co2inputs)
Exemplo n.º 29
0
ta = 2250
tmp = 25
sal = 35
prs = 0
si = 0
phos = 0

# Run CO2SYS
cdict = pyco2.sys(
    ta,
    dic,
    1,
    2,
    salinity=sal,
    temperature=tmp,
    pressure=prs,
    total_silicate=si,
    total_phosphate=phos,
    opt_pH_scale=1,
    opt_k_carbonic=10,  # not sure which options were used by ESM10...
    opt_k_fluoride=1,
    opt_total_borate=2,
    buffers_mode="auto",
)

# Recreate ESM10 Fig. 2
fvars = [
    "gamma_dic", "gamma_alk", "beta_dic", "beta_alk", "omega_dic", "omega_alk"
]
fmults = [1, -1, 1, -1, -1, 1]
fclrs = ["#453c90", "#b84690", "#b84690", "#007831", "#df0023", "#40b4b6"]
flabels = [
import numpy as np
import PyCO2SYS as pyco2

# Set conditions
alkalinity = 0
dic = 2500

# Get all pHs from TA and DIC
opt_pH_scale = np.array([1, 2, 3, 4])
results = pyco2.sys(alkalinity, dic, 1, 2, opt_pH_scale=np.array([1, 2, 3, 4]))


# Check they're consistent regardless of input scale
def test_pH_scale_consistency():
    assert np.all(
        np.isclose(results["pH_total"], results["pH"][opt_pH_scale == 1]))
    assert np.all(
        np.isclose(results["pH_sws"], results["pH"][opt_pH_scale == 2]))
    assert np.all(
        np.isclose(results["pH_free"], results["pH"][opt_pH_scale == 3]))
    assert np.all(
        np.isclose(results["pH_nbs"], results["pH"][opt_pH_scale == 4]))


# test_pH_scale_consistency()