strip.rwl() accepts ring-width indices (class "rwi") and strips
them as they are, returning indices. A series is then judged on the
variation the chronology will keep. Indices used to be treated as
widths and detrended again, with a warning.
strip.rwl() gains nyrs, the stiffness of the spline that raw
widths are detrended with before stripping, and detrends once. A
message says which spline was used and that stripping indices is the
better route. It
used to apply a 20-year and then a 200-year spline to the same series.
That was a misreading of Fowler and Boswijk (2003), who made two
separate sets of indices and stripped each, and it came to the 20-year
spline alone, so the default of 20 keeps the old behaviour: the
indices differ in the third decimal place or beyond, and the series
left out are the same in the data sets tried. nyrs = 200 gives the
paper's other version. The warning about spline stiffness that the
second pass raised for every series under 200 years is gone.
strip.rwl() reports what stripping cost. EPS over the whole span can
rise while the years that few trees reach get worse, because a series
that was left out may be one of the few there. When a series is left
out the function now prints the years that lost a tree and the years
in which EPS for the trees present is lower than before, and the
result carries the record as the attribute "dplR.strip": the series
left out, rbar and EPS before and after, and the trees and EPS for
each year. The series returned are the same as before. The help page
gains a caution, after Buras (2017), that a higher EPS is not evidence
of a better chronology for reconstructing climate.
chron.ars() builds the ARSTAN chronology from the residual
chronology, as its help page said it did and as Cook (1985) describes.
It used to add the pooled AR model to each individually whitened
series and average those, which left out the second whitening that the
residual chronology gets. Whitening each series with its own
coefficients can remove more persistence than the series share, and
the mean is then negatively autocorrelated. Where persistence is
mostly within trees the ARSTAN chronology inherited that: for wa082
detrended with a spline its lag-one autocorrelation was -0.16 against
0.19 for the standard chronology, and is now 0.10. Collections with
shared persistence change less (co021 0.15 to 0.22, ca533 0.47 to
0.52). The ars column changes for every data set, and it is now
missing in the same years as res, a few more years at the start
than before. std and res are unchanged.
The help page for chron() says that the residual chronology from
prewhiten = TRUE need not be white. Each series is whitened
separately, and where persistence is mostly within trees their mean
is negatively autocorrelated (about -0.2 at lag one for wa082). It
points to chron.ars(), which whitens the mean a second time. No
change to the function.
treeMean() returns class "rwi" when it is given indices, with the
record of how they were detrended. It used to return class "rwl"
whatever it was given, so chron(), rwi.stats() and the other
functions that want indices warned that tree means of indices were
ring widths. The help page had na.rm backwards: na.rm = FALSE
is the one that keeps only the years where a tree's samples overlap.
plot.crn() gains xlab and ylab, and passes ... on to plot().
Axis labels and graphical parameters such as col were silently
ignored before. One ylab labels the chronology panels and leaves
sample depth and running rbar alone; a vector labels each panel. A
chronology column with a name dplR does not know is now plotted as a
chronology instead of stopping with an error.
rwl.check() gains RWL_ZERO_RUN, a warning for a run of ten or more
zeros in a series (zero.run in rwl.check.control()). A run that
long is filler for wood that was not measured, not absent rings. It
used to be reported as a note, RWL_CONSECUTIVE_ZERO, which now covers
shorter runs only.
New kalman.ar() and kalman.spec() for evolutive spectra. They are
experimental: arguments, defaults and the objects returned may change
in a later release.
kalman.ar() fits an autoregressive model whose coefficients change
through time, by the Kalman filter and a smoother (Kitagawa and Gersch
1985), and kalman.spec() gives the AR spectrum of every year, with a
plot method that shows it as a surface in time and period. The order has no
default. The freedom of the coefficients, lambda, is estimated by
maximum likelihood unless set, and the fit is reported beside the
ordinary AR model with fixed coefficients. profile() on a fit gives
the log-likelihood over a range of lambda, with a plot method, to
show how well the data determine it and what a hand-set value costs.
With variance = "varying" the innovation variance changes through
time as well, estimated from the prediction errors, so that a change
in year-to-year scatter is not read as a change in the coefficients.
Suggested by Ed Cook; written from the published method, not ported
from his programs.
i.detrend() and i.detrend.series() now point to the iDetrend app
(https://github.com/OpenDendro/iDetrend), with a message once in a
session and a note on their help pages. The app does interactive
detrending better: curves can be adjusted and compared on each series,
and it writes R code that reproduces the indices. The functions are
not deprecated and work as before.
read.tucson() honours a stop marker written in an eleventh field,
past column 72, after a line of ten measurements. In 1.8.0 the marker
was dropped, so a 0.001 mm series ending that way was read as 0.01 mm
and every value came back ten times too large, with no warning.
read.tucson.legacy() was not affected. No file in the ITRDB has this
layout.
insert.ring() and delete.ring() work on a whole rwl object as
well as a single series: delete.ring(rwl, series = "50A", year = 1950)
returns the edited rwl. No measurement is dropped; the object gains or
loses years at its ends as needed, and gaps keep their place.
insert.ring() on a vector warns when fix.length = TRUE drops a
measured ring to keep the length.
fill.internal.NA() gains series, to fill only some series, and now
returns the class it was given: an rwl stays an rwl, with its read
record. It used to return a plain data.frame.
fill.internal.NA() gains fill = "Chron", which estimates a missing
ring from the other series in the collection rather than from the
series' own neighbouring rings. It is in the spirit of the gap filling
in ARSTAN, not a copy of it: the numbers will differ. A year is filled
only if min.series other series (default 3) were measured in it;
otherwise the call stops and names the years. An estimate below zero is
returned as zero with a warning. The filled values are estimates built
from the other trees, so they inflate statistics of agreement among
series and should not be used for crossdating. See the help page for
the assumptions and limits.
xdate.floater() dates a series that is longer than the master. It
used to stop with "'x' and 'y' must have the same length". Results for
a series shorter than the master are unchanged. It also stops with a
clear message when min.overlap is more than the years in the master.
xdate.floater() stops when series has NA inside it and says
where. It used to drop every NA, which closed the gap and put the
rings on either side out of step, so the series was dated wrongly, or
only in part, with no warning. Fill the gap first or date the parts
separately. NA before and after the measurements is still dropped.
plot() and print() work on the object xdate.floater() returns.
The methods were documented but not registered, so plot(fo) stopped
with an error and print(fo) listed the whole object.
seg.plot(), and so plot(rwl, plot.type = "seg"), draws an rwl
that holds one series. It used to stop with "wrong sign in 'by'
argument".
corr.rwl.seg() is about three times faster on large collections
(45 s to 13 s on the 597-series chin067), with the same results.
interseries.cor() is four to six times faster on large collections,
and rwl.report(), which computed it twice, now computes it once. On
the 597-series chin067, rwl.report() drops from 72 s to 8 s. The
results are unchanged.
A large release. This file lists what users need to know; the ChangeLog has the full record, with the reasons for each change.
read.tucson() is new, and no longer fills gaps inside a series with
zeros. A gap is now NA, so detrend() and other functions that
reject NA inside a series stop on such data until the gap is filled
on purpose. fill.internal.NA = 0 reproduces the old values. The old
reader is kept as read.tucson.legacy().detrend() and detrend.series() now default to method = "Spline".
The old default ran every method and returned a list, not indices.
Code that relied on it must now name the methods.detrend() with one method, rcs(), cms() and i.detrend() now
return class "rwi" (ring-width indices). This used to be a plain
data.frame, or class "rwl" for rcs(), cms() and i.detrend().
The values are unchanged.bai.in() and bai.out() now return class "bai" (basal area
increment). They used to return class "rwl". The areas are
unchanged.detrend(), rcs(), bai.in(), rwl.report(),
...) warn on class "rwi". Those that want indices (chron(),
rwi.stats(), sss(), ...) warn on class "rwl". Indices read
from a file come back as "rwl"; label them with as.rwi().detrend(), rcs(), cms(), i.detrend(), interseries.cor(),
corr.rwl.seg() and subset() drop series with no values, with a
message naming them. Before, they stopped or kept a column of NA.detrend(difference = TRUE), are no longer sign-flipped when
normalized. That flipping gave wrong rbar, EPS and interseries
correlations (GitHub issue 22). Results for ring widths and ratio
indices are unchanged.detrend.series(difference = TRUE) now uses fitted curves that go
below zero as they are, instead of swapping them for a simpler fit.caps() stops on a series containing NA. Before, it returned all
NA.chron(x) and chron.ars(x) are
now rwi, and sgc(x) is now rwl. Calls that named the argument
x = must change.nyrs and ar.order.max were added to the crossdating and
statistics functions, next to n and prewhiten. Arguments after
them passed by position now shift. An old call that shifts stops with
an error; none silently changes meaning.csv2rwl() is deprecated in favour of read.sheet(), and may refuse
files it used to accept wrongly.rwl.check() looks for defects in a collection (duplicate or empty
series, gaps, zeros, units errors, dating errors) and returns them as
rows with stable IDs, for one file or a whole archive.xdate.report() and write.xdate.report() produce a COFECHA-style
crossdating report, with A and B flags and the lag and correlation
gain for each flagged segment.corr.rwl.seg() gains lag.max. It tests each segment at shifted
dates and returns the best lag. Negative lags mean missing rings, as
in COFECHA.read.sheet() and write.sheet() read and write spreadsheet-shaped
files (years down, series across, or long format). read.rwl() uses
them for csv.read.tucson() records what it saw in a provenance record that
travels with the data."rwi" class has summary(), which gives collection statistics
and flags series that don't fit, and plot(x, plot.type = "image"),
which shows trend left in by detrending."bai" class has as.bai() and methods for [, subset(),
time(), window(), summary() and plot(). chron(),
detrend() and the crossdating functions take it without a warning;
functions that want ring widths warn.window() methods for rwl, rwi, bai and crn objects:
window(x, 1800, 1900).[ and subset() methods for rwl and rwi objects keep the class
and the records, and trim years no series covers.