Detrending & standardization¶
Removing the biological growth trend to produce ring-width index (RWI) series. See the Detrending & standardization guide for when to use each method.
detrend¶
Detrend a series or dataframe to ring-width indices.
Fit a growth curve to each series (a smoothing spline by default) and form the
ring-width index as the ratio (method="ratio", division, the default) or the
difference (method="difference", subtraction) of the data to the curve.
fit chooses the CURVE and method chooses the ARITHMETIC. This differs
from dplR, where method selects the curve; passing a curve name to
method raises a helpful error.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data
|
pandas dataframe or series
|
ring widths from |
required |
fit
|
str or list
|
the growth curve to fit (case-insensitive; dplR's names are canonical):
|
"Spline"
|
method
|
(ratio, difference)
|
how the index is formed: |
"ratio"
|
plot
|
boolean
|
draw the fitted curve and the detrended index. |
True
|
period
|
int or float
|
smoothing wavelength for |
None
|
nyrs0
|
int
|
initial spline stiffness for |
50
|
pos_slope
|
boolean
|
allow a positive slope at the old-age end (the |
False
|
f
|
float
|
spline frequency-response amplitude at |
0.5
|
verbose
|
boolean
|
print, per series, the curve fitted and the arithmetic used. |
False
|
return_info
|
boolean
|
if True, return a dict (like dplR's |
False
|
Returns:
| Name | Type | Description |
|---|---|---|
data |
pandas dataframe or series
|
the detrended data. |
Examples:
>>> import dplpy as dpl
>>> data = dpl.readers("../tests/data/csv/file.csv")
>>> dpl.detrend(data) # all series in a dataframe
>>> dpl.detrend(data["SeriesA"], fit="ModNegExp", method="difference")
Notes
Interior NaN are dropped before fitting. The position-based fits (every curve
except Spline and Mean) reconstruct cambial age by counting the surviving
rings, so an interior gap compresses the age axis after it -- usually a minor
distortion, but for large gaps prefer fit="Spline" or infill first with
dpl.fill_internal. detrend warns when a position-based fit meets a series
with interior gaps. Spline (fit over calendar years) and Mean
(order-invariant) are unaffected.
References
.. [1] https:/opendendro.org/dplpy-man/#detrend
rcs¶
Regional Curve Standardization of a set of ring-width series.
Align every series on a common cambial-age axis using its pith offset, average
to form the regional curve, smooth it, and divide (ratio) or subtract
(difference) the curve value at each ring's cambial age. This preserves the
low-frequency growth signal that per-series detrending removes. Shares the
fit / method / period vocabulary of detrend. Analog of dplR's
rcs.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
rwl
|
DataFrame
|
ring-width series, years as the index and series as columns. |
required |
po
|
DataFrame or None
|
pith offsets, columns |
None
|
fit
|
str or None
|
curve fitted to the age-aligned mean, from the |
"AgeDepSpline"
|
method
|
(ratio, difference)
|
how each index is formed from the ring width and the regional-curve value at
its cambial age: |
"ratio"
|
period
|
int or float
|
smoothing wavelength for |
0.1
|
nyrs0
|
int
|
initial stiffness for |
50
|
f
|
float
|
frequency-response amplitude for |
0.5
|
pos_slope
|
bool
|
whether the regional curve may rise at the old-age end. False keeps a
non-increasing end, avoiding an artefactual old-age upturn. Applies to
|
False
|
biweight
|
bool
|
build the regional curve with a Tukey biweight robust mean (else arithmetic). |
True
|
min_n
|
int or None
|
truncate the regional-curve tail where by-age sample depth falls below this. |
None
|
preset
|
(None, crust)
|
None follows the parameters above. "crust" builds the regional curve the CRUST
way (Melvin & Briffa 2014): an age-dependent spline smoothed only where sample
depth >= 4 with the no-rise tail rule, gaps infilled, a 0.02 mm floor, and flat
tail extension. When set, |
None
|
rescale_difference
|
bool
|
used only when |
False
|
rc_out
|
bool
|
if True, return a dict with both the detrended |
False
|
plot
|
bool
|
draw the regional-curve figure (series and curve vs cambial age). The former
name |
True
|
Returns:
| Type | Description |
|---|---|
DataFrame or dict
|
the detrended |
References
.. [1] https://rdrr.io/cran/dplR/man/rcs.html .. [2] Melvin, T. M. & Briffa, K. R. (2014) CRUST: Software for the implementation of Regional Chronology Standardisation: Part 1, Signal-Free RCS. Dendrochronologia, 32, 7-20. .. [3] Melvin, T. M. & Briffa, K. R. (2014) CRUST: Software for the implementation of Regional Chronology Standardisation: Part 2, Further RCS options and recommendations. Dendrochronologia, 32, 343-356.
sfrcs¶
Signal-Free Regional Curve Standardization of a set of ring-width series.
Ordinary RCS lets the single regional curve absorb some of the common climate
signal when the sample's age structure varies over time, biasing the low
frequencies. Signal-Free RCS breaks that feedback: it iterates, each pass
rebuilding the regional curve from measurements with the current chronology
divided out, while still forming the tree indices from the original
measurements. Iteration stops when the chronology stops changing (tol). Port
of CRUST's single-curve signal-free RCS (Melvin & Briffa 2014).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
rwl
|
DataFrame
|
ring-width series, years as the index and series as columns. |
required |
po
|
DataFrame or None
|
pith offsets, columns |
None
|
method
|
(ratio, difference)
|
how indices are formed: "ratio" divides, "difference" subtracts. |
"ratio"
|
biweight_curve
|
bool
|
build the regional curve with a biweight robust mean by cambial age. Default False (arithmetic mean by age) matches CRUST. |
False
|
biweight_crn
|
bool
|
build the yearly chronology mean with a biweight robust mean. Default False (arithmetic) matches CRUST's default. |
False
|
ss
|
int
|
age-dependent spline stiffness offset for the regional curve; per-point
stiffness is |
10
|
rise
|
bool or None
|
allow the smoothed regional curve to rise in its final third. None uses CRUST's rule (allowed only for curves longer than 1500 years); otherwise the tail is flattened to prevent an artefactual old-age upturn. |
None
|
max_iterations
|
int
|
maximum signal-free iterations. |
40
|
tol
|
float
|
convergence threshold on the maximum chronology change between iterations. |
1e-3
|
plot
|
bool
|
draw the regional-curve figure (series and final curve vs cambial age). The
former name |
True
|
return_info
|
bool
|
if True, return a dict of diagnostics (see Returns) instead of just |
False
|
verbose
|
bool
|
print a convergence line. |
True
|
Returns:
| Type | Description |
|---|---|
DataFrame or dict
|
the detrended |
Notes
Single-curve case (CRUST trc=1, src=1); multiple-curve signal-free RCS is
sfmrcs. There is no dplR reference for this method: the port follows CRUST's
stand.f90 and its spline smoother is validated against CRUST's compiled
kernel, but the full iteration is not checked against a gold standard, so treat
results as CRUST-faithful rather than machine-verified.
References
.. [1] Melvin, T. M. & Briffa, K. R. (2014) CRUST: Software for the implementation of Regional Chronology Standardisation: Part 1, Signal-Free RCS. Dendrochronologia, 32, 7-20. .. [2] Melvin, T. M. & Briffa, K. R. (2014) CRUST: Software for the implementation of Regional Chronology Standardisation: Part 2, Further RCS options and recommendations. Dendrochronologia, 32, 343-356.
mrcs¶
Multiple-curve Regional Curve Standardisation.
Sort trees by relative growth rate, split them into n_curves equal-count
classes, build a regional curve for each class, and standardise each tree by its
own class curve. This removes the modern-sample-bias slope that a single
regional curve injects when the sample's growth-rate (or age) mix changes over
time. Each class curve is built by :func:rcs, so mrcs shares its
fit/method/period/nyrs0/f/pos_slope/preset
vocabulary, and mrcs(rwl, n_curves=1) is identical to rcs(rwl). Port of
CRUST's multiple RCS.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
rwl
|
DataFrame
|
ring-width series, years as the index and series as columns. |
required |
po
|
DataFrame or None
|
pith offsets (columns |
None
|
n_curves
|
int
|
number of regional curves. |
2
|
sort
|
(growth, age, diameter, none)
|
how trees are ranked before the equal-count split: "growth" by relative growth rate, "age" by cambial age, "diameter" by total radius, "none" keeps input order. |
"growth"
|
fit
|
|
'AgeDepSpline'
|
|
method
|
|
'AgeDepSpline'
|
|
period
|
|
'AgeDepSpline'
|
|
nyrs0
|
|
'AgeDepSpline'
|
|
f
|
|
'AgeDepSpline'
|
|
pos_slope
|
|
'AgeDepSpline'
|
|
biweight
|
|
'AgeDepSpline'
|
|
min_n
|
|
'AgeDepSpline'
|
|
preset
|
|
'AgeDepSpline'
|
|
rescale_difference
|
passed through to :func: |
False
|
|
reset_means
|
bool
|
if True (ratios only), rescale each tree's indices to the mean it would have
had under one-curve RCS, recovering the low-frequency variance multiple RCS
removes. Skipped with a warning for |
True
|
rc_out
|
bool
|
if True, return a dict |
False
|
plot
|
bool
|
draw the per-class regional-curve figure. |
True
|
Returns:
| Type | Description |
|---|---|
DataFrame or dict
|
the detrended |
References
.. [1] Melvin, T. M. & Briffa, K. R. (2014) CRUST: Software for the implementation of Regional Chronology Standardisation: Part 2, Further RCS options and recommendations. Dendrochronologia, 32, 343-356.
sfmrcs¶
Signal-Free multiple-curve Regional Curve Standardisation.
Combine :func:sfrcs (signal-free iteration) with :func:mrcs (multiple
curves): sort trees by growth rate into n_curves equal-count classes, then
iteratively rebuild each class's regional curve from measurements that have had
the current chronology divided out, while forming the tree indices from the
original measurements, until the chronology converges. reset_means (ratios
only) restores each tree's one-curve mean to recover the low-frequency variance
multiple RCS removes. sfmrcs(rwl, n_curves=1) is identical to
sfrcs(rwl). Port of CRUST's signal-free multiple RCS.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
rwl
|
DataFrame
|
ring-width series, years as the index and series as columns. |
required |
po
|
DataFrame or None
|
pith offsets (true offset, 0 = pith present), as in :func: |
None
|
n_curves
|
int
|
number of regional curves. |
2
|
sort
|
(growth, age, diameter, none)
|
how trees are ranked before the equal-count split (see :func: |
"growth"
|
method
|
(ratio, difference)
|
ratio (division) or difference (subtraction) indices. |
"ratio"
|
biweight_curve
|
the signal-free settings, identical to :func: |
False
|
|
biweight_crn
|
the signal-free settings, identical to :func: |
False
|
|
ss
|
the signal-free settings, identical to :func: |
False
|
|
rise
|
the signal-free settings, identical to :func: |
False
|
|
max_iterations
|
the signal-free settings, identical to :func: |
False
|
|
tol
|
the signal-free settings, identical to :func: |
False
|
|
verbose
|
the signal-free settings, identical to :func: |
False
|
|
reset_means
|
bool
|
restore each tree's one-curve mean (ratios only; skipped with a warning
for |
True
|
plot
|
bool
|
draw the per-class regional-curve figure ( |
True
|
return_info
|
bool
|
if True, return a dict of diagnostics (see Returns) instead of |
False
|
Returns:
| Type | Description |
|---|---|
DataFrame or dict
|
the detrended |
References
.. [1] Melvin, T. M. & Briffa, K. R. (2014) CRUST: Software for the implementation of Regional Chronology Standardisation: Part 2, Further RCS options and recommendations. Dendrochronologia, 32, 343-356.
ssf¶
Simple signal-free chronology (dplR's ssf()).
Build a signal-free chronology (Melvin & Briffa 2008): form an initial
chronology, divide every series by it to strip the common signal, rescale and
re-detrend the resulting signal-free measurements, and build a new chronology,
repeating until the high-frequency chronology stops changing (the sample-depth-
weighted median absolute difference falls below mad_threshold) or
max_iterations is reached. Reproduces dplR's ssf().
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
rwl
|
DataFrame
|
ring-width series (raw), years as the index and series as columns. |
required |
method
|
(Spline, AgeDepSpline)
|
detrending curve used at each iteration: a cubic smoothing spline (⅔-length stiffness) or an age-dependent spline (dpl.ads()). |
"Spline"
|
nyrs
|
int or None
|
spline stiffness. None uses ⅔ of each series' length for "Spline" or 50 for "AgeDepSpline"; a value in (0, 1) is a fraction of series length. |
None
|
difference
|
bool
|
detrend by subtraction (series - curve) rather than division. |
False
|
max_iterations
|
int
|
maximum signal-free iterations before giving up. |
25
|
mad_threshold
|
float
|
convergence threshold on the median absolute difference of the high-frequency chronology between successive iterations. |
5e-4
|
recode_zeros
|
bool
|
recode zero ring-widths to 0.001 before processing (avoids div-by-zero). |
False
|
return_info
|
bool
|
if True, return a dict of the full iteration history (chronologies, signal-free measurements and curves, MAD vector, ...) instead of just the final chronology. |
False
|
verbose
|
bool
|
print progress and the per-iteration convergence diagnostics. |
True
|
preset
|
(None, crust)
|
None reproduces the basic signal-free method (dplR's ssf; Melvin & Briffa 2008). "crust" adds CRUST's robustness guards (Melvin & Briffa 2014): multiplicative rescaling of the signal-free measurements, the raw measurement kept in any year where the chronology is near zero (< 0.01), and the fitted curves floored at 0.02 mm. These make ssf robust to sensitive sites with many absent rings (e.g. co021) that the basic method cannot standardise. |
None
|
Returns:
| Type | Description |
|---|---|
DataFrame
|
the signal-free chronology with columns |
References
.. [1] https://rdrr.io/cran/dplR/man/ssf.html .. [2] Melvin, T. M. & Briffa, K. R. (2008) A "signal-free" approach to dendroclimatic standardisation. Dendrochronologia, 26(2), 71-86. .. [3] Melvin, T. M. & Briffa, K. R. (2014) CRUST: Software for the implementation of Regional Chronology Standardisation: Part 1, Signal-Free RCS. Dendrochronologia, 32, 7-20. .. [4] Melvin, T. M. & Briffa, K. R. (2014) CRUST: Software for the implementation of Regional Chronology Standardisation: Part 2, Further RCS options and recommendations. Dendrochronologia, 32, 343-356.
ads¶
Age-dependent smoothing spline of a single series (dplR's ads()).
Fit a smoothing spline whose stiffness increases with cambial age: the i-th ring is fit with an (nyrs0 + i - 1)-year spline, so young rings are smoothed least and the curve grows stiffer with age. Ports dplR's ads().
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
y
|
array - like
|
a single ring-width series (no missing values), oldest ring first. |
required |
nyrs0
|
int
|
initial spline stiffness (wavelength, in years) at the first ring. |
50
|
pos_slope
|
bool
|
if False, once the spline stops decreasing its tail is held flat and the spline is refit, preventing an artefactual upturn at the end of the series (dplR uses pos.slope=FALSE inside detrend()). |
True
|
Returns:
| Type | Description |
|---|---|
ndarray
|
the fitted spline curve, same length as |
Examples:
>>> import dplpy as dpl
>>> rwl = dpl.readers("../tests/data/csv/ca533.csv")
>>> curve = dpl.ads(rwl["CAM011"].dropna().to_numpy(), nyrs0=50)
References
.. [1] https://rdrr.io/cran/dplR/man/ads.html .. [2] Melvin, T. M. (2004) Historical Growth Rates and Changing Climatic Sensitivity of Boreal Conifers. PhD Thesis, Climatic Research Unit, University of East Anglia. .. [3] Melvin, T. M., Briffa, K. R., Nicolussi, K. & Grabner, M. (2007) Time-varying-response smoothing. Dendrochronologia, 25(2), 65-69. .. [4] Cook, E. R. & Peters, K. (1981) The Smoothing Spline: A New Approach to Standardizing Forest Interior Tree-Ring Width Series for Dendroclimatic Studies. Tree-Ring Bulletin, 41, 45-53.
powt¶
Adaptive power transformation of ring-width series (variance stabilising).
Stabilise the variance of ring-width series by raising each value to a data-driven power p. For adjacent rings, level M = (x[t] + x[t-1]) / 2 and spread S = |x[t] - x[t-1]|; regressing log(S) on log(M) gives a slope b, and p = |1 - b| removes the level-spread dependence. Port of dplR's powt (Cook & Peters 1997).
Two methods are offered:
"cook"(default) estimates p independently for each series."universal"estimates a single p for the whole data set with a linear mixed-effects model (random intercept per year), matching dplR's default. Requires statsmodels; a log transform is used if the estimate is p <= 0.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
rwl
|
DataFrame or Series
|
ring-width series (raw, non-negative), years as the index. A Series is allowed only with method='cook'. |
required |
method
|
(cook, universal)
|
per-series ('cook') or single mixed-model power ('universal'). |
"cook"
|
rescale
|
bool
|
if True, rescale each transformed series back to its original mean and standard deviation. |
False
|
return_power
|
bool
|
if True, return a (transformed, power) tuple; |
False
|
plot
|
bool
|
if True, draw the data-transform-statistics diagnostic: per-series skew and spread-vs-level correlation, before and after the transform. A successful transform drives the after values toward zero. |
False
|
return_stats
|
bool
|
if True, also return a per-series diagnostics DataFrame with columns
|
False
|
Returns:
| Type | Description |
|---|---|
transformed data of the same type as ``rwl``. With ``return_power`` and/or
|
|
``return_stats`` the return becomes a tuple: ``(data, power)``,
|
|
``(data, stats)``, or ``(data, power, stats)`` (power first, stats last).
|
|
Notes
dplPy reproduces dplR's power exactly. A given series' power can differ slightly
from ARSTAN's, which uses the trailing ring as the level and clamps p to
[0, 1].
Examples:
>>> import dplpy as dpl
>>> rwl = dpl.readers("../tests/data/csv/ca533.csv")
>>> pt = dpl.powt(rwl) # per-series (cook)
>>> pt, p = dpl.powt(rwl, return_power=True)
>>> rwi = dpl.detrend(pt, plot=False) # transform, then detrend
References
.. [1] https://rdrr.io/cran/dplR/man/powt.html .. [2] Cook & Peters (1997), The Holocene, 7, 361-370.