示例#1
0
def partition_from_qc_averages(qcdata, wue):
    """Partition H2O and CO2 fluxes using interval average q and c data.

    All arguments are passed directly to the findroot function

    Parameters
    ----------
    qcdata : QCData namedtuple or equivalent namespace
    wue : float, kg CO2 / kg H2O
        Leaf-level water use efficiency, `wue` < 0

    Returns
    -------
    namedtuples
        :class:`~fluxpart.containers.RootSoln`,
        :class:`~fluxpart.containers.FluxComponents`

    """

    rsoln = findroot(qcdata, wue)
    if rsoln.validroot:
        fluxes = flux_components(rsoln.var_cp, rsoln.corr_cp_cr, qcdata, wue,
                                 rsoln.co2soln_id)
    else:
        fluxes = FluxComponents(*np.full(6, np.nan))
    return rsoln, fluxes
示例#2
0
def adjust_partitioned_fluxes(fc, wue, wq_tot, wc_tot):
    """Adjust partitioned fluxes so they match measured totals.

    If filtering has been applied to the series data, covariances in
    the filtered data may differ from those in the original data.
    Consequently, partitioned flux totals may not match exactly the
    total fluxes indicated by the original data. Here, partitioned fluxes
    are adjusted proportionally so that they match the totals in the
    original data.

    Parameters
    ----------
    fc : :class:`~fluxpart.containers.FluxComponents` or equivalent
        Container holding partitioned flux components, kg/m^2/s.
    wue : float
        Leaf-level water use efficiency (`wue` < 0), kg CO2 / kg H2O
    wq_tot, wc_tot : float
        Desired net total H2O (`wq_tot`) and CO2 (`wc_tot`) fluxes,
        kg/m^2/s.

    Returns
    -------
    namedtuple
        :class:`~fluxpart.containers.FluxComponents`

    """

    wq_diff = wq_tot - (fc.wqe + fc.wqt)
    wqe = fc.wqe + wq_diff * (fc.wqe / (fc.wqt + fc.wqe))
    wqt = wq_tot - wqe
    wcp = wue * wqt
    wcr = wc_tot - wcp
    return FluxComponents(wq=wq_tot, wqt=wqt, wqe=wqe,
                          wc=wc_tot, wcp=wcp, wcr=wcr)
示例#3
0
def partition_from_qc_averages(qcdat, wue, init=None):
    """Partition H2O and CO2 fluxes using interval average q and c data.

    All arguments are passed directly to the findroot function

    Parameters
    ----------
    qcdat : QCData namedtuple or equivalent namespace
    wue : float, kg CO2 / kg H2O
        Leaf-level water use efficiency, `wue` < 0
    init : (float, float), optional
        2-Tuple is initial value for (corr_cp_cr, var_cp).  If `init`
        = None (default), an initial estimate is calculated internally.
        Note when specifying initial values: -1 < `corr_cp_cr` < 0, and
        `var_cp` has units of (kg/m^3)^2.

    Returns
    -------
    namedtuples
        :class:`~fluxpart.containers.NumerSoln`,
        :class:`~fluxpart.containers.FluxComponents`

    """

    nsoln = findroot(qcdat, wue, init)
    if nsoln.success and nsoln.validroot:
        fluxes = flux_components(nsoln.var_cp, nsoln.corr_cp_cr, qcdat, wue,
                                 nsoln.co2soln_id)
    else:
        fluxes = FluxComponents(*np.full(6, np.nan))
    return nsoln, fluxes
示例#4
0
def flux_components(var_cp, corr_cp_cr, qcdata, wue, co2soln_id):
    """Calculate flux components for given (var_cp, corr_cp_cr) pair."""
    wcr_ov_wcp = flux_ratio(var_cp, corr_cp_cr, qcdata, 'co2', co2soln_id)
    # TODO: handle wcr_ov_wcp ~ -1
    wcp = qcdata.wc / (wcr_ov_wcp + 1)
    wcr = qcdata.wc - wcp
    wqt = wcp / wue
    wqe = qcdata.wq - wqt
    return FluxComponents(wq=qcdata.wq, wqt=wqt, wqe=wqe,
                          wc=qcdata.wc, wcp=wcp, wcr=wcr)
示例#5
0
def partition_from_wqc_series(w, q, c, wue, adjust_fluxes=True):
    """Partition H2O and CO2 fluxes using series data for w, q, and c.

    If a valid partitioning solution is not found for the passed series
    data, low-frequency (large-scale) components are progressively
    removed from the data until either a valid solution is found or
    the series decomposition is exhausted.

    Parameters
    ----------
    w,q,c : array_like
        1D time series for vertical wind speed `w` (m/s), water vapor
        concentration `q` (kg/m^3), and CO2 concentration `c` (kg/m^3).
    wue : float
        leaf-level water use efficiency, `wue` < 0, kg CO2 / kg H2O.
    adjust_fluxes : bool, optional
        Indicates whether the obtained partitioned fluxes should be
        adjusted so that the totals match the original data. Default is
        `adjust_fluxes` = True.

    Returns
    -------
    dict
        {'valid_partition': bool, 'partmssg': str,
        'fluxcomps': :class:`~fluxpart.containers.FluxComponents`,
        'rootsoln': :class:`~fluxpart.containers.RootSoln`,
        'qcdata': :class:`~fluxpart.containers.QCData`}

    Notes
    -----
    If a valid partitioning is not found, the returned `numersoln` and `qcdata`
    correspond to the final iteration attempted.

    """

    max_decomp_lvl = int(np.log2(w.size))
    wq_tot = np.cov((w, q))[0, 1]
    wc_tot = np.cov((w, c))[0, 1]

    # The loop progressively filters the data until a physically valid
    # partitioning is found or the loop/filter is exhausted. The first
    # iteration of progressive_lowcut removes only the mean value
    # (q'=q-<q>, etc.), so the first iteration uses the unfiltered
    # deviations.

    for cnt, lowcut_wqc in enumerate(progressive_lowcut(w, q, c)):
        cov = np.cov(lowcut_wqc)
        qcdata = QCData(
            wq=cov[0, 1],
            wc=cov[0, 2],
            var_q=cov[1, 1],
            var_c=cov[2, 2],
            corr_qc=cov[1, 2] / math.sqrt(cov[1, 1] * cov[2, 2]),
            wave_lvl=(max_decomp_lvl - cnt, max_decomp_lvl))

        rsoln, fcomp = partition_from_qc_averages(qcdata, wue)

        if rsoln.validroot:

            if adjust_fluxes:
                fcomp = adjust_partitioned_fluxes(fcomp, wue, wq_tot, wc_tot)

            valid_partition, partition_mssg = isvalid_partition(fcomp)

            if valid_partition:
                break

    if not rsoln.validroot:
        valid_partition = False
        partition_mssg = rsoln.validmssg
    if not valid_partition:
        fcomp = FluxComponents(*np.full(6, np.nan))

    return {'valid_partition': valid_partition,
            'partmssg': partition_mssg,
            'fluxcomps': fcomp,
            'rootsoln': rsoln,
            'qcdata': qcdata}