In respirometry, we want to report oxygen uptake or production rates from experimentally important stages or that represent behavioural or physiological states. These include:

- the
**most linear**, that is most consistent or monotonic rates observed, often most representative of*routine*metabolism - the
**lowest**rates observed, often most representative of*standard*,*resting*,*basal*or*maintenance*metabolism - the
**highest**rates observed, representative of*active*or*maximum*metabolic rates

Identifying and extracting these rates from large datasets is difficult, and if selected visually, subject to observer bias and lack of objectivity. Methods such as fitting multiple, fixed-width linear regressions over an entire dataset to identify regions of lowest or highest slopes (i.e. rates) is computationally intensive, and slopes found via this method highly sensitive to the width chosen, especially if the specimen’s metabolic rate changes rapidly or the data is noisy.

Here we detail `auto_rate()`

, a function that uses machine
learning techniques to *automatically* detect the **most
linear** regions of a dataset. This allows an investigator to
extract rates in a statistically robust, objective manner. It can also
extract and order **highest** and **lowest**
rates, or return an unordered **rolling** rate across the
whole dataset.

In this vignette we detail how `auto_rate`

works, and how
it can be used to extract rates from respirometry data. Importantly,
`auto_rate`

has been optimised to be *extremely fast*.
Other methods on large datasets can take minutes, hours or even days to
run. `auto_rate`

can reduce this wait by orders of magnitude,
fitting tens of thousands of regressions and detecting linear regions in
seconds.

This illustrates the main processes involved in
`auto_rate`

:

`auto_rate`

works by performing an optimised rolling
regression on the dataset of a specified width. For the
`linear`

method, a kernel density estimate is performed on
the rolling regression output, and the kernel bandwidth used to
re-sample linear regions of the data for re-analysis. For other methods,
the results are filtered, ordered, or returned unordered.

The function `auto_rate`

uses a novel method of combining
rolling regression and kernel density estimate algorithms to detect
patterns in time series data. The rolling regression runs all possible
ordinary least-squares (OLS) linear regressions \((y = \beta_0 + \beta_1 X + \epsilon)\) of a
fixed sample width across the dataset, and is expressed as: \[y_t(n) = X_t(n) \beta (n) + \epsilon_t(n), \ t =
n,\ ...,\ T\] where \(T\) is the
total length of the dataset, \(n\) is
the window of width \(n < T\), \(y_t(n)\) is the vector of observations
(e.g. oxygen concentration), \(X_t(n)\)
is the matrix of explanatory variables, \(\beta (n)\) is a vector of regression
parameters and \(\epsilon_t(n)\) is a
vector of error terms. Thus, a total of \((T -
n) + 1\) number of overlapping regressions are fit.

`auto_rate`

has several methods to process, order or
filter the rolling regression results.

`method = "linear"`

This method uses kernel density estimation (KDE) to automatically identify linear regions of the dataset.

First, we take advantage of the key assumption that linear sections of a data series are reflected by stable parameters across the rolling estimates, a property that is often applied in financial statistics to evaluate model stability and make forward predictions on time-series data (see Zivot and Wang 2006). We use kernel density estimation (KDE) techniques, often applied in various inference procedures such as machine learning, pattern recognition and computer vision, to automatically aggregate stable (i.e. linear) segments as they naturally form one or more local maxima (“modes”) in the probability density estimate.

KDE requires no assumption that the data is from a parametric family,
and learns the shape of the density automatically without supervision.
KDE can be expressed as: \[\hat{f}(x) =
\frac{1}{nh^d}\sum_{i = 1}^{n} K \left(\frac{x - X_i}{h}
\right)\] where \(f\) is the
density function from an unknown distribution \(P\) for \(X_1,...,X_n\), \(K\) is the kernel function and \(h\) is the optimal smoothing bandwidth. The
smoothing bandwidth is computed using the solve-the-equation
*plug-in* method (Sheather et al. 1996, Sheather and Jones 1991)
which works well with multimodal or non-normal densities (Raykar and
Duraiswami 2006).

We then use \(h\) to select all values in the rolling regression output that match the range of values around each mode (\(\theta_n\)) of the KDE (i.e. \(\theta_n \pm h\)). These rolling estimates are grouped and ranked by size, and the upper and lower bounds of the data windows they represent are used to re-select the linear segment of the original data series. The rolling estimates are then discarded while the detected data segments are analysed using linear regression.

The output will contain only the regressions identified as coming
from linear regions of the data, ranked by order of the KDE density
analysis. This is present in the `$summary`

component of the
output as `$density`

. Under this method, the
`width`

input is used as a starting seed value, but the
resulting regressions may be of any width.

This method could be applied to virtually any respirometry data when
you are looking for linear regions where rates are *stable*,
*consistent* and *representative* rates for the
behavioural or physiological state of the specimen. This could be a
routine metabolic rate, standard or basal metabolic rate, or in the case
of an animal under constant exercise a consistent active metabolic
rate.

`method = "lowest"`

Every regression of the specified `width`

across the
timeseries is calculated, then ordered using *absolute* rate
values from lowest to highest. This option can only be used when rates
all have the same sign, and it essentially ignores the sign. Rates will
be ordered from lowest to highest in the `$summary`

table by
absolute value regardless of if they are positive or negative.

`method = "highest"`

Every regression of the specified `width`

across the
timeseries is calculated, then ordered using *absolute* rate
values from highest to lowest. This option can only be used when rates
all have the same sign, and it essentially ignores the sign. Rates will
be ordered from highest to lowest in the `$summary`

table by
absolute value regardless of if they are positive or negative.

`method = "minimum"`

,
`method = "maximum"`

These methods are strictly numerical and take full account of the
sign of the rate. In `respR`

oxygen uptake rates are negative
since they represent a negative slope of oxygen against time, and oxygen
production rates are positive.

Every regression of the specified `width`

across the
entire timeseries is calculated, then ordered using *numerical*
rate values from minimum to maximum for the `minimum`

method,
or vice versa for `maximum`

. Generally this method should
only be used when rates are a mix of oxygen consumption and production
rates, such as when positive rates may result from regressions fit over
flush periods in intermittent-flow respirometry.

Generally, for most analyses where high or low rates are of interest
the `highest`

or `lowest`

methods should be used
instead. However, when rates are a mix of negative and positive and you
want the highest or lowest these can be used, but note they order by
*numerical* value; the highest oxygen *uptake* rates will
be most `minimum`

.

`method = "rolling"`

This method returns all regressions of the specified
`width`

in sequential order across the dataset. All results
are returned in the summary table.

This method can be applied when you want to extract a rolling rate of
a specified width for further analyses. Alternatively, if you don’t want
to rely on the `"linear"`

selection or other methods but want
to filter and select the results according to various criteria using
`select_rate()`

. See
`vignette("select_rate")`

.

By default, `auto_rate`

rolling regression uses a rolling
window width in rows of `0.2`

multiplied by the total rows of
the dataset, that is across a rolling window of 20% of the data. This
can be changed using the `width`

input to a different
relative proportion (e.g. for 10% `width = 0.1`

).
Alternatively, if not between 0 and 1, the `width`

by default
equates to a fixed value in rows
(e.g. `width = 2000, by = "row"`

), or can be entered as a
fixed value in the time metric
(`width = 3000, by = "time"`

).

Note that `by = "row"`

is computationally faster.
Specifying a `"time"`

window tells `auto_rate`

that the time data may have gaps or not be evenly spaced, and so the
function calculates each time width using the raw time *values*,
rather than assuming a specific row width represents the same time
window, a less computationally intensive process. If the data are
without gaps and evenly spaced with regards to time,
`by = "row"`

and the correct row `width`

to
represent the time window you want will be much faster.

The `width`

determines the exact width of the data
segments produced for `highest`

, `lowest`

,
`rolling`

etc. rates. This allows the user to consistently
report results across experiments, such as reporting the highest or
lowest rates sustained over a specific time period.

Importantly however, for the `linear`

detection method the
`width`

is a starting seed value, and does *not*
restrict the width of the segments produced. The minimum width of the
segments tends to be close to or slightly lower than the
`width`

input (though not always), however the upper widths
are not restricted and can be of any width if the segments are found to
be linear.

Users should experiment with different `width`

values to
understand how this affects identification of linear regions and rate
values, especially for small datasets or those with a high relative
degree of noise or residual variation. Choosing an inappropriate width
tends to overfit or underfit the rolling rates. See Prinzing
et al. 2021 for an excellent discussion of appropriate widths in
rolling regressions to determine maximum metabolic rates, much of which
is relevant to extracting rates of any kind.

Note also that the `linear`

method works best on high
resolution data which has a relatively stable structure, such as a
general decline or increase in oxygen. Patterns such as oscillating
levels of oxygen such as from intermittent-flow respirometry, or flat
areas followed by sudden declines will likely lead to questionable
results. Generally it works best when data is subset to remove regions
which are not of experimental interest. See
`subset_data()`

Below, we show the differences in the shape of the rolling
regressions when using the default `width = 0.2`

versus a
value of `0.6`

with the dataset `sardine.rd`

:

```
# Perform linear detection; default width when not specified is 0.2:
normx <- auto_rate(sardine.rd)
#> auto_rate: Applying default 'width' of 0.2
# Perform linear detection using manual width of 0.6:
overx <- auto_rate(sardine.rd, width = 0.6)
```

For the `linear`

method, since KDE automatically
aggregates stable values, a poor selection of the `width`

may
result in a badly-characterised rolling rate estimate output. Under
perfectly linear conditions, that is completely monotonic rates, we
would expect a rolling regression output plot such as this to consist of
a straight, horizontal line. In these data, while the default width
allowed a pattern of relative stability in rate after around 2500
seconds to be identified, this information was lost when a
`width`

of `0.6`

was used, with stable rates only
being identified much later in the dataset.

Similarly, if we are interested in highest rate values, under the lower width input we could see values around -0.0010 occurring within the first 1000s of the experiment. This information was also completely lost under the higher width input.

By contrast, if the `width`

is too low the rolling rate is
unstable and heavily influenced by data noise and residual variation.
This leads to poor results for the `linear`

method, and also
highly variable results under the other methods.

Here we’ll compare the default `width = 0.2`

to a lower
value of 5% of the data, `width = 0.05`

.

```
# Perform linear detection; default width when not specified is 0.2:
normx <- auto_rate(sardine.rd)
#> auto_rate: Applying default 'width' of 0.2
# Perform linear detection using manual width of 0.05:
underx <- auto_rate(sardine.rd, width = 0.05)
```

A lower width leads to much more variable rolling rate estimates.
Note how we have had to adjust the y-axis limits to fit the results (the
left plot is the same data as in the previous section with different
axis values). In this particular analysis (results not shown) the
`linear`

method performed poorly. If we were interested in
highest or lowest rates, this would also prove problematic since the
rates are so variable.

The `width`

value should be carefully considered; too low
and it fails to capture accurate rolling rates and is unduly influenced
by data noise or variability, too high and the data is overfitted with
important physiological or behavioural states smoothed out. Whatever
value is used, this should be reported in the analytical methods
alongside results.

See Prinzing et al. 2021 for an excellent discussion of appropriate widths in rolling regressions to determine maximum metabolic rates, much of which is relevant to extracting rates of any kind.

Here we’ll run through examples of how to use `auto_rate`

to extract rates from respirometry data.

By default, `auto_rate`

identifies the *most
linear* regions of the data
(i.e. `method = "linear"`

):

```
sard_ar <- auto_rate(sardine.rd)
#> auto_rate: Applying default 'width' of 0.2
```

This method detects the *most consistently linear* regions of
the data, that is the most consistent rates observed during the
experiment. It does this in a rigorous, unsupervised manner, with the
advantage being that this removes observer subjectivity in choosing
which rate is most appropriate to report in their results. It is a
statistically robust way of indentifying and reporting consistent rates
in respirometry data, such as those representative of routine or
standard metabolic rates.

The `linear`

method uses the input `width`

as a
starting seed value to calculate a rolling rate (panel 3). It then uses
these rates to identify linear regions using kernel density estimation
(KDE, panel 6). Peaks in this plot represent linear regions, that is
areas of stable rates at that `width`

representative of that
region as a whole. It then re-samples these regions and runs additional
linear analysis at different widths to arrive at a final rate. This is
why the final, high ranked rates tend to be over widths greater than the
input `width`

, as can be seen here with the top ranked
result.

Generally, the higher and wider the peak in the KDE plot, the more linear the region. Here there are several (the current plotted one denoted by a vertical dashed line) and the strongest results are towards the end of the data, including the highest ranked result. The rate value of the current plotted result can also be seen in panel 3 as a horizontal line. This can help assess if it is a representative rate, although bear in mind these rolling rates are at a different width.

See Plot section below for more information.

Typically, `auto_rate`

will identify multiple linear
regions. These are ranked using the kernel density analysis, with the
results reflected in the ordering of the `$summary`

table in
the output, which is ordered by the `$density`

column. The
first row is the top ranked, most linear region, and subsequent rows
progressively lower rank. By default, this highest ranked result is
returned when `print`

or `plot`

are used, but
other results can be output using the `pos`

input with those
functions.

```
print(sard_ar, pos = 2)
#>
#> # print.auto_rate # ---------------------
#> Data extracted by 'row' using 'width' of 1502.
#> Rates computed using 'linear' method.39 linear regions detected in the kernel density estimate.
#> To see all results use summary().
#>
#> Position 2 of 39 :
#> Rate: -0.000688
#> R.sq: 0.986
#> Rows: 2242 to 5543
#> Time: 2241 to 5542
#> -----------------------------------------
```

`plot(sard_ar, pos = 2)`

**Users should take special note** that as an automated,
unsupervised machine learning method of identifying linear data
`auto_rate`

is fallible, and the results should
*always* be inspected and explored. In this case the function has
identified a total of 46 linear regions. They can be viewed by calling
`summary()`

```
summary(sard_ar)
#>
#> # summary.auto_rate # -------------------
#>
#> === Summary of Results by Kernel Density Rank ===
#> rep rank intercept_b0 slope_b1 rsq density row endrow time endtime oxy endoxy rate
#> <num> <int> <num> <num> <num> <num> <int> <int> <int> <int> <num> <num> <num>
#> 1: NA 1 94.9 -0.000661 0.982 19069 3659 6736 3658 6735 92.6 90.4 -0.000661
#> 2: NA 2 95.1 -0.000688 0.986 17461 2242 5543 2241 5542 93.7 91.2 -0.000688
#> 3: NA 3 94.9 -0.000662 0.987 15969 3628 7164 3627 7163 92.5 90.2 -0.000662
#> 4: NA 4 95.1 -0.000708 0.979 9204 1578 4236 1577 4235 94.2 92.2 -0.000708
#> 5: NA 5 95.1 -0.000706 0.971 7555 1947 4236 1946 4235 93.8 92.2 -0.000706
#> ---
#> 35: NA 35 95.5 -0.000894 0.938 421 1063 2394 1062 2393 94.5 93.5 -0.000894
#> 36: NA 36 95.5 -0.000894 0.937 388 1066 2393 1065 2392 94.7 93.4 -0.000894
#> 37: NA 37 95.3 -0.000803 0.929 375 1315 2641 1314 2640 94.3 93.3 -0.000803
#> 38: NA 38 95.3 -0.000803 0.929 369 1317 2641 1316 2640 94.3 93.3 -0.000803
#> 39: NA 39 95.3 -0.000803 0.928 322 1325 2635 1324 2634 94.2 93.3 -0.000803
#>
#> Regressions : 6012 | Results : 39 | Method : linear | Roll width : 1502 | Roll type : row
#> -----------------------------------------
```

In this case the first rate result looks good: it has a high r-squared, is sustained over a duration of 50 minutes, and the rate value is consistent with the other results. However in some cases, other ranked results may be more appropriate to report depending on the metabolic rate metric being investigated.

While the first result is the highest in terms of the kernel density value, the user is free to select and report other linear results if they satisfy other desirable criteria, for instance are above a particular r-squared value or span a minimum time window. One peculiarity to take note of in the KDE analysis, is that sometimes the top ranked result does not necessarily have the highest r-squared. This is a counter intuitive result, but explained by the fact that the function learns the shape of the entire dataset, so a particular regression from a linear region might be most representative of the rates in that region, but just happen to be fit to values which return a lower r-squared. This does not mean it is not a valid result; arguably, it is more valid, since it is accurately describing the localised shape of the data. See Chabot et al. (2021) for discussion of r-squared values in metabolic rate measurements.

The `pos`

input can also be used in `summary`

to view particular row ranges. We’ll look at the first 10.

```
summary(sard_ar, pos = 1:10)
#>
#> # summary.auto_rate # -------------------
#>
#> === Summary of results from entered 'pos' rank(s) ===
#>
#> rep rank intercept_b0 slope_b1 rsq density row endrow time endtime oxy endoxy rate
#> 1: NA 1 94.9 -0.000661 0.982 19069 3659 6736 3658 6735 92.6 90.4 -0.000661
#> 2: NA 2 95.1 -0.000688 0.986 17461 2242 5543 2241 5542 93.7 91.2 -0.000688
#> 3: NA 3 94.9 -0.000662 0.987 15969 3628 7164 3627 7163 92.5 90.2 -0.000662
#> 4: NA 4 95.1 -0.000708 0.979 9204 1578 4236 1577 4235 94.2 92.2 -0.000708
#> 5: NA 5 95.1 -0.000706 0.971 7555 1947 4236 1946 4235 93.8 92.2 -0.000706
#> 6: NA 6 95.7 -0.001047 0.961 6862 601 1969 600 1968 95.1 93.7 -0.001047
#> 7: NA 7 95.1 -0.000709 0.978 6395 1578 4196 1577 4195 94.2 92.2 -0.000709
#> 8: NA 8 94.8 -0.000628 0.929 6285 5050 6613 5049 6612 91.4 90.5 -0.000628
#> 9: NA 9 94.7 -0.000619 0.912 2609 5123 6507 5122 6506 91.5 90.6 -0.000619
#> 10: NA 10 95.7 -0.001043 0.961 1917 596 1981 595 1980 95.0 93.6 -0.001043
#>
#> Regressions : 6012 | Results : 39 | Method : linear | Roll width : 1502 | Roll type : row
#> -----------------------------------------
```

Here, the 6th ranked result, while being a valid linear region, is conspicuously higher in rate value and occurs close to the start of the experiment. If we were interested in routine or standard metabolic rates, we would want to exclude this one, as it suggests the specimen might not yet be acclimated to the chamber.

In most cases the best option is to use the top ranked result unless
there are specific reasons to exclude it. However, an investigator may
opt to select several and take a mean of the resulting rates. For
instance here, we might decide on a mean of the top 3 since they have
the highest `$density`

values (note that typically we would
do this after rates have been adjusted and converted - see later
sections - but it is possible here too). We could just average the top 3
values ourselves, but the `mean`

function will also work with
`auto_rate`

objects and accepts the `pos`

input.

```
mean(sard_ar, pos = 1:3)
#>
#> # mean.auto_rate # ----------------------
#> Mean of rate results from entered 'pos' ranks:
#>
#> Mean of 3 output rates:
#> [1] -0.00067
#> -----------------------------------------
```

Any rate value determined after such selection can be saved as a
variable, or entered manually as a value in later functions such as
`adjust_rate`

and `convert_rate`

. It can also be
exported as a value by using `export = TRUE`

in the
`mean`

call. However, see next section.

`select_rate`

Alternative selection criteria might also be applied. This might include excluding all results below a certain r-squared, use only the top n’th percentile of results, or exclude those from the certain stages of the experiment.

New in `respR v2.0`

is the `select_rate()`

function which can apply these criteria, along with many others, to
`auto_rate`

results after they have been converted in
`convert_rate`

. See `vignette("select_rate")`

for
how to do advanced filtering of these results.

`auto_rate`

can also be used to detect the
*highest* and *lowest* rates over a fixed
`width`

. This allows for consistent reporting of respirometry
results, such as the highest or lowest rates sustained over a specified
time period.

Here we want to know the highest rates sustained over 15 minutes, or
900s, in the `sardine.rd`

data. Since in these data, oxygen
is recorded every second and `inspect()`

tells us the time
data is gapless and evenly spaced, we can simply specify width in the
same number of rows.

```
sard_insp <- inspect(sardine.rd)
#> inspect: Applying column default of 'time = 1'
#> inspect: Applying column default of 'oxygen = 2'
#> inspect: No issues detected while inspecting data frame.
#>
#> # print.inspect # -----------------------
#> Time Oxygen
#> numeric pass pass
#> Inf/-Inf pass pass
#> NA/NaN pass pass
#> sequential pass -
#> duplicated pass -
#> evenly-spaced pass -
#>
#> -----------------------------------------
```

`high_rate <- auto_rate(sard_insp, width = 900, by = "row", method = "highest")`

```
summary(high_rate)
#>
#> # summary.auto_rate # -------------------
#>
#> === Summary of Results by Highest Rate ===
#> rep rank intercept_b0 slope_b1 rsq density row endrow time endtime oxy endoxy rate
#> <num> <int> <num> <num> <num> <lgcl> <int> <num> <int> <int> <num> <num> <num>
#> 1: NA 1 95.8 -0.001138 0.924 NA 791 1690 790 1689 95.0 93.9 -0.001138
#> 2: NA 2 95.8 -0.001138 0.924 NA 798 1697 797 1696 95.0 93.8 -0.001138
#> 3: NA 3 95.8 -0.001138 0.924 NA 792 1691 791 1690 95.0 93.9 -0.001138
#> 4: NA 4 95.8 -0.001138 0.924 NA 793 1692 792 1691 95.0 93.9 -0.001138
#> 5: NA 5 95.8 -0.001138 0.924 NA 797 1696 796 1695 95.0 93.8 -0.001138
#> ---
#> 6610: NA 6610 94.7 -0.000615 0.793 NA 5717 6616 5716 6615 91.3 90.6 -0.000615
#> 6611: NA 6611 94.7 -0.000615 0.792 NA 5723 6622 5722 6621 91.1 90.7 -0.000615
#> 6612: NA 6612 94.7 -0.000615 0.793 NA 5715 6614 5714 6613 91.1 90.5 -0.000615
#> 6613: NA 6613 94.7 -0.000614 0.792 NA 5720 6619 5719 6618 91.1 90.5 -0.000614
#> 6614: NA 6614 94.7 -0.000613 0.792 NA 5719 6618 5718 6617 91.2 90.7 -0.000613
#>
#> Regressions : 6614 | Results : 6614 | Method : highest | Roll width : 900 | Roll type : row
#> -----------------------------------------
```

In the `highest`

and `lowest`

methods the rates
are ordered by the *absolute* rate value, regardless of the sign.
The top results here have the same rate value as printed, but likely
have small differences at higher precision (what you see printed depends
on your own R `options()`

settings). Again, a user may choose
to report the top result or perform further selection and filtering
using `select_rate()`

after conversion in
`convert_rate`

. This includes the option to remove rates
which overlap, that is share the same rows of data; as we can see here
the top results all come from the same region of the data.

We can similarly find the `lowest`

rate over 15
minutes.

`low_rate <- auto_rate(sard_insp, width = 900, method = "lowest")`

```
print(low_rate)
#>
#> # print.auto_rate # ---------------------
#> Data extracted by 'row' using 'width' of 900.
#> Rates computed using 'lowest' method.To see all results use summary().
#>
#> Position 1 of 6614 :
#> Rate: -0.000613
#> R.sq: 0.792
#> Rows: 5719 to 6618
#> Time: 5718 to 6617
#> -----------------------------------------
```

```
summary(low_rate)
#>
#> # summary.auto_rate # -------------------
#>
#> === Summary of Results by Lowest Rate ===
#> rep rank intercept_b0 slope_b1 rsq density row endrow time endtime oxy endoxy rate
#> <num> <int> <num> <num> <num> <lgcl> <int> <num> <int> <int> <num> <num> <num>
#> 1: NA 1 94.7 -0.000613 0.792 NA 5719 6618 5718 6617 91.2 90.7 -0.000613
#> 2: NA 2 94.7 -0.000614 0.792 NA 5720 6619 5719 6618 91.1 90.5 -0.000614
#> 3: NA 3 94.7 -0.000615 0.793 NA 5715 6614 5714 6613 91.1 90.5 -0.000615
#> 4: NA 4 94.7 -0.000615 0.792 NA 5723 6622 5722 6621 91.1 90.7 -0.000615
#> 5: NA 5 94.7 -0.000615 0.793 NA 5717 6616 5716 6615 91.3 90.6 -0.000615
#> ---
#> 6610: NA 6610 95.8 -0.001138 0.924 NA 797 1696 796 1695 95.0 93.8 -0.001138
#> 6611: NA 6611 95.8 -0.001138 0.924 NA 793 1692 792 1691 95.0 93.9 -0.001138
#> 6612: NA 6612 95.8 -0.001138 0.924 NA 792 1691 791 1690 95.0 93.9 -0.001138
#> 6613: NA 6613 95.8 -0.001138 0.924 NA 798 1697 797 1696 95.0 93.8 -0.001138
#> 6614: NA 6614 95.8 -0.001138 0.924 NA 791 1690 790 1689 95.0 93.9 -0.001138
#>
#> Regressions : 6614 | Results : 6614 | Method : lowest | Roll width : 900 | Roll type : row
#> -----------------------------------------
```

Note, the output objects of the `highest`

and
`lowest`

methods are essentially identical, the only
difference being the results are ordered descending or ascending by
absolute rate value.

The `rolling`

method allows a rolling regression of the
specified `width`

to be returned in sequential order.

`roll_rate <- auto_rate(sard_insp, width = 900, method = "rolling")`

```
summary(roll_rate)
#>
#> # summary.auto_rate # -------------------
#>
#> === Summary of Results by Rolling Order ===
#> rep rank intercept_b0 slope_b1 rsq density row endrow time endtime oxy endoxy rate
#> <num> <int> <num> <num> <num> <lgcl> <int> <num> <int> <int> <num> <num> <num>
#> 1: NA 1 95.6 -0.000817 0.871 NA 1 900 0 899 95.6 94.9 -0.000817
#> 2: NA 2 95.6 -0.000818 0.871 NA 2 901 1 900 95.6 94.7 -0.000818
#> 3: NA 3 95.6 -0.000817 0.871 NA 3 902 2 901 95.6 94.9 -0.000817
#> 4: NA 4 95.6 -0.000817 0.871 NA 4 903 3 902 95.6 94.7 -0.000817
#> 5: NA 5 95.6 -0.000817 0.871 NA 5 904 4 903 95.6 94.8 -0.000817
#> ---
#> 6610: NA 6610 95.0 -0.000666 0.845 NA 6610 7509 6609 7508 90.6 90.0 -0.000666
#> 6611: NA 6611 95.0 -0.000665 0.844 NA 6611 7510 6610 7509 90.7 90.1 -0.000665
#> 6612: NA 6612 94.9 -0.000663 0.843 NA 6612 7511 6611 7510 90.7 90.1 -0.000663
#> 6613: NA 6613 94.9 -0.000660 0.841 NA 6613 7512 6612 7511 90.5 90.2 -0.000660
#> 6614: NA 6614 94.9 -0.000658 0.837 NA 6614 7513 6613 7512 90.5 90.3 -0.000658
#>
#> Regressions : 6614 | Results : 6614 | Method : rolling | Roll width : 900 | Roll type : row
#> -----------------------------------------
```

This outputs every regression of the `width`

in order. The
main utility of this method is for passing to `select_rate`

after conversion in `convert_rate`

where various criteria can
be applied to filter the results manually. See
`vignette("select_rate")`

.

Saved `auto_rate`

objects can be passed to subsequent
`respR`

functions for further processing, such as
`adjust_rate()`

to adjust for background respiration, or
`convert_rate()`

to convert to final oxygen uptake units. See
other vignettes for examples of these operations.

When using `auto_rate`

, a plot of the results is produced
(unless `plot = FALSE`

). If there are multiple results each
can be plotted individually using `pos`

. Each panel can be
plotted on its own using `panel`

with values 1 to 6. If
labels or legends obscure parts of the plot they can be suppressed using
`legend = FALSE`

. Console output messages can be suppressed
with `quiet = TRUE`

. Lastly, the rolling rate plot can be
plotted on an unreversed y-axis with `rate.rev = FALSE`

, if
for instance you are examining oxygen production rates.

The first panel is the complete timeseries of oxygen against both
time (bottom blue axis) and row index (top red axis) with the
`pos`

rate regression (defualt is `pos = 1`

)
highlighted in yellow. The next plot is a close-up of this rate region.
The next is a rolling rate plot across the entire timeseries at the
input `width`

(see here). The next two
are diagnostic plots of the fitted values vs. residuals for the current
rate result. Lastly, the sixth panel (only for the `linear`

method) is a plot of the kernel density analysis output, which is the
density peaks of stable rate values.

See Interpreting the plots section above for more information.

`auto_rate`

does not currently support analysis of flowthrough respirometry data. See`vignette("flowthrough")`

for analysis of these experiments.The

`auto_rate`

`linear`

method works best with data that is fairly monotonic, that is shows an either downward or upward trend without strong fluctuations. With intermittent-flow respirometry data there is a strong possibility flush periods will confuse the`auto_rate`

algorithms, so it should typically only be run on subsets of the data containing actual specimen measurements. The`subset_data`

function is ideal for subsetting and passing data regions of interest to other functions. See`vignette("intermittent_long")`

.