---
title: "dendRoAnalyst: end-to-end workflow and function tour"
author: "Package vignette"
output: rmarkdown::html_vignette
vignette: >
  %\VignetteIndexEntry{dendRoAnalyst: end-to-end workflow and function tour}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

```{r setup, include = FALSE}
knitr::opts_chunk$set(
  collapse = TRUE,
  comment = "#>",
  fig.width = 7,
  fig.height = 4.5,
  warning = FALSE,
  message = FALSE
)

library(dendRoAnalyst)

RUN_HEAVY <- FALSE
RUN_INTERACTIVE <- FALSE
```

## Overview

This vignette presents a complete workflow for **dendRoAnalyst** and also acts
as a compact function tour for the user-facing functions covered by the uploaded
source files. The sequence follows a typical dendrometer analysis pipeline:

1. read dendrometer and climate data,
2. check time resolution, jumps, and gaps,
3. resample and truncate,
4. smooth the signal,
5. compute daily summaries,
6. classify stem-cycle phases,
7. classify zero-growth phases,
8. perform superposed epoch analysis,
9. fit growth curves and compare methods,
10. detrend and standardize,
11. compute moving climate correlations,
12. analyze harsh-climate episodes,
13. interpolate missing values from a network, and
14. inspect periodicity with wavelet tools.

The vignette is written in a CRAN-friendly style. Lightweight sections are
executed; heavier, interactive, or computationally expensive sections are shown
as code examples with `eval = FALSE`. All the summary and plot functions can also
be executed by simply applying `summary()` and `plot()` functions. 

## Example datasets

```{r data}
data(gf_nepa17)
data(nepa17)
data(ktm_clim_hourly)
data(ktm_rain17)

head(gf_nepa17[, 1:3])
head(ktm_clim_hourly)
```

Throughout this vignette we use:

- `gf_nepa17` for subdaily dendrometer workflows,
- `nepa17[1:1000, ]` for compact daily examples,
- `ktm_clim_hourly` for climate-feature examples, and
- `ktm_rain17` for harsh-climate examples.

```{r objects}
dm_hourly <- gf_nepa17
dm_daily_demo <- nepa17[1:1000, ]
dm_phase_demo <- gf_nepa17[1:800, ]
clim_hourly <- ktm_clim_hourly
clim_rain <- ktm_rain17
```

## 1. Reading dendrometer and climate data

### `read.dendrometer()`

When users start from raw files, `read.dendrometer()` is the recommended entry
point.

```{r read-dendrometer, eval = FALSE}
raw_dm <- read.dendrometer(
  file = "inst/extdata/my_dendrometer_file.csv",
  detect_resolution = TRUE,
  return_report = TRUE,
  quiet = FALSE
)
```

This call returns an imported dendrometer table and, optionally, an import
report describing parsing and time-resolution diagnostics.

### `read.climate()`

```{r read-climate}
clim_std <- read.climate(
  x = clim_hourly,
  time_col = "TIME",
  vars = c("temp", "prec", "VPD", "RH"),
  verbose = FALSE
)
head(clim_std)
```

The standardized climate object can later be aggregated to daily scale,
converted to subdaily climate features, or joined directly to dendrometer
outputs.

## 2. Looking for jumps or gaps in dendrometer data

### `reso_dm()`

```{r reso}
reso_dm(dm_hourly[[1]])
```

This returns the dominant sampling interval in minutes and helps diagnose
irregular logging intervals before subsequent processing.

### `jump.locator()` and `i.jump.locator()`

```{r jump-manual}
jump_free_manual <- jump.locator(
  df = dm_daily_demo[, 1:3],
  detection_method = "manual",
  manual_threshold = 1,
  adjustment_method = "window_median"
)
head(jump_free_manual)
```

```{r jump-auto, eval = FALSE}
jump_free_auto <- jump.locator(
  df = dm_daily_demo[, 1:3],
  detection_method = "auto",
  auto_method_penalty = 10,
  adjustment_method = "window_median"
)
```

```{r jump-interactive, eval = FALSE}
# Interactive graphical workflow
if (RUN_INTERACTIVE) {
  i.jump.locator(df = dm_daily_demo[, 1:3])
}
```

### `dm.na.interpolation()` and its plot methods

```{r gap-detect}
gap_demo <- dm_daily_demo[, 1:3]
gap_demo[150:170, 2] <- NA

gap_info <- dm.na.interpolation(
  df = gap_demo,
  resolution = 60,
  fill = FALSE,
  assess = FALSE
)
head(gap_info$gap_info)
```

```{r gap-fill}
gap_fill <- dm.na.interpolation(
  df = gap_demo,
  resolution = 60,
  fill = TRUE,
  method = "spline",
  assess = TRUE,
  assess_lengths_hours = c(6, 12)
)
head(gap_fill$data)
```

```{r gap-plots, fig.height=5}
plot(gap_fill)
plot(gap_fill)
plot(gap_fill, original = gap_demo)
plot(gap_fill)
```

These functions provide both the filled series and visual diagnostics of where
and how the gaps were handled.

## 3. Resample and truncate the dataset

### `dendro.resample()`

```{r resample}
resampled_hourly <- dendro.resample(
  df = dm_hourly,
  by = "H",
  value = "mean",
  method = "auto"
)
head(resampled_hourly)
```

### `dendro.truncate()`

```{r truncate}
truncated_demo <- dendro.truncate(dm_hourly, CalYear = 2017, DOY = c(1, 120))
head(truncated_demo)
```

Resampling harmonizes time steps; truncation helps focus on one year or one
season.

## 4. Smoothing

### `smooth_dm()`

```{r smooth}
res_minutes <- reso_dm(dm_phase_demo[[1]])
smoothed_medmean <- smooth_dm(
  time = dm_phase_demo[[1]],
  dm = dm_phase_demo[[2]],
  resolution_min = res_minutes,
  method = "median_mean",
  window_hours = 3
)
head(smoothed_medmean)
```

```{r smooth-other, eval = FALSE}
smoothed_pspline <- smooth_dm(
  time = dm_phase_demo[[1]],
  dm = dm_phase_demo[[2]],
  resolution_min = res_minutes,
  method = "pspline",
  window_hours = 6
)
```

Smoothing is often applied before phase classification to suppress short spikes.

## 5. Daily approach and daily climate functions

### `daily.data()` and `plot.daily_output()`

```{r daily-data}
daily_out <- daily.data(df = dm_daily_demo, TreeNum = 1)
head(daily_out)
```

```{r daily-plots}
plot(daily_out)
plot(daily_out, type = "timing")
plot(daily_out, type = "change")
```

```{r daily-more-plots, eval = FALSE}
plot(daily_out, type = "timing_violin", Year = 2017, DOY = c(1, 6))
plot(daily_out, type = "boxplot", stat = "amplitude", by = "month_of_year")
plot(daily_out, type = "heatmap")
```

### `dm_daily_clim()` and `dm_join_daily_clim()`

```{r daily-clim}
clim_day <- dm_daily_clim(
  clim_std,
  mean_vars = c("temp", "VPD", "RH"),
  max_vars  = c("VPD"),
  sum_vars  = c("prec"),
  lag_vars = c("VPD_max", "temp_mean"),
  lagmean_vars = c("temp_mean", "VPD_mean"),
  lagsum_vars = c("prec_sum"),
  lag_days = c(1, 3, 7)
)
head(clim_day)
```

```{r daily-join}
daily_clim_joined <- dm_join_daily_clim(daily_out, clim_day)
head(daily_clim_joined)
```

### `dm_add_climate()` for daily outputs

```{r add-climate-daily}
daily_clim_added <- dm_add_climate(
  daily_out,
  clim_hourly,
  scale = "daily",
  mean_vars = c("temp", "VPD", "RH"),
  max_vars  = c("temp", "VPD"),
  sum_vars  = c("prec")
)
head(daily_clim_added)
```

## 6. Stem-cycle approach and associated functions

### `phase.sc()` and `plot.SC_output()`

```{r sc-out}
sc_out <- phase.sc(df = dm_phase_demo, TreeNum = 1)
sc_out_sm <- phase.sc(df = dm_phase_demo, TreeNum = 1, smoothing = 12)
head(sc_out$SC_phase)
head(sc_out$SC_cycle)
```

```{r sc-plots}
plot(sc_out)
plot(sc_out, type = "ribbon")
plot(sc_out, type = "increment")
```

```{r sc-more-plots, eval = FALSE}
plot(sc_out, type = "transition", x_axis = "doy", Year = 2017, DOY = c(50, 100))
plot(sc_out, type = "balance", temporal = "daily")
plot(sc_out, type = "frequency", temporal = "monthly")
plot(sc_out, type = "heatmap", temporal = "daily")
plot(sc_out, type = "boxplot", stat = "Magnitude", temporal = "monthly")
```

### `dm_subdaily_clim()`, `dm_join_subdaily_clim()`, `dm_join_phase_clim()`, and `dm_add_climate()`

```{r subdaily-clim}
clim_sub <- dm_subdaily_clim(
  clim_hourly,
  mean_vars = c("temp", "VPD", "RH"),
  sum_vars  = c("prec"),
  lag_vars  = c("temp", "VPD", "RH"),
  roll_hours = c(1, 3, 6, 24),
  lag_hours  = c(1, 3, 6, 24)
)
head(clim_sub)
```

```{r sc-joins}
sc_phase_clim <- dm_join_phase_clim(
  sc_out,
  clim_hourly,
  mean_vars = c("temp", "VPD", "RH"),
  max_vars  = c("temp", "VPD"),
  sum_vars  = c("prec")
)
head(sc_phase_clim$SC_cycle)

sc_point_clim <- dm_join_subdaily_clim(sc_out_sm, clim_sub)
head(sc_point_clim$SC_phase)

sc_added_clim <- dm_add_climate(
  sc_out_sm,
  clim_hourly,
  scale = "subdaily",
  sub_mean_vars = c("temp", "VPD", "RH"),
  sub_sum_vars  = c("prec"),
  sub_lag_vars  = c("temp", "VPD", "RH"),
  roll_hours = c(1, 3, 6, 24),
  lag_hours  = c(1, 3, 6, 24)
)
head(sc_added_clim$SC_phase)
```

## 7. Zero-growth approach and associated functions

### `phase.zg()`, `twd.maxima()`, and `plot.ZG_output()`

```{r zg-out}
zg_out <- phase.zg(df = dm_phase_demo, TreeNum = 1)
zg_out_sm <- phase.zg(df = dm_phase_demo, TreeNum = 1, smoothing = 6)
head(zg_out$ZG_phase)
head(zg_out$ZG_cycle)
```

```{r twd-maxima}
max_twd_tbl <- twd.maxima(dm_phase_demo, TreeNum = 1, smoothing = 5)
head(max_twd_tbl)
```

```{r zg-plots}
plot(zg_out)
plot(zg_out, temporal = "daily")
plot(zg_out, temporal = "monthly", type = "twd")
```

```{r zg-more-plots, eval = FALSE}
plot(zg_out, temporal = "monthly", type = "abr")
plot(zg_out, type = "transition", x_axis = "doy", Year = 2017, DOY = c(50, 100))
plot(zg_out, type = "boxplot", stat = "max.twd", temporal = "daily")
```

### Climate joins and climate-phase plots

```{r zg-clim-joins}
zg_phase_clim <- dm_join_phase_clim(
  zg_out,
  clim_hourly,
  mean_vars = c("temp", "VPD", "RH"),
  max_vars  = c("temp", "VPD"),
  sum_vars  = c("prec")
)
head(zg_phase_clim$ZG_cycle)

zg_point_clim <- dm_join_subdaily_clim(zg_out_sm, clim_sub)
head(zg_point_clim$ZG_phase)

zg_phase_added <- dm_add_climate(
  zg_out,
  clim_hourly,
  scale = "phase",
  mean_vars = c("temp", "VPD", "RH"),
  max_vars  = c("temp", "VPD"),
  sum_vars  = c("prec")
)
head(zg_phase_added$ZG_cycle)
```

```{r climate-phase-plots}
plot(zg_phase_added, climate_var = "VPD_mean_phase", scale = "cycle", type = "boxplot", temporal = 'daily')
```

```{r climate-phase-compare, eval = FALSE}
plot(zg_phase_added, climate_var = "temp_mean_phase", scale = "cycle", type = "timeseries")

plot(
  zg_phase_added,
  climate_vars = c("temp_mean_phase", "VPD_mean_phase", "RH_mean_phase"),
  scale = "cycle",
  type = "boxplot"
)

plot(
  zg_phase_added,
  scale = "cycle",
  type = "cor_heatmap",
  numeric_vars = c("Duration_h", "max.twd", "ABr.value",
                   "temp_mean_phase", "VPD_mean_phase", "RH_mean_phase")
)
```

## 8. Superposed epoch and associated functions

### `dm_event_times()`, `dm_epoch_extract()`, `dm_epoch_test()`, and method dispatch

```{r epoch}
event_tbl <- dm_event_times(zg_out, event = "all")
head(event_tbl)
```

```{r epoch-extract, eval = FALSE}
epoch_extract <- dm_epoch_extract(
  x = zg_out,
  clim = clim_hourly,
  event = "phase_start",
  phase = "all",
  response_var = c("temp", "VPD"),
  before = 24,
  after = 24,
  unit = "hours"
)
head(epoch_extract)
```

```{r epoch-test, eval = FALSE}
epoch_test <- dm_epoch_test(
  x = zg_out,
  clim = clim_hourly,
  event = "phase_start",
  phase = "all",
  response_var = c("temp", "VPD"),
  before = 24,
  after = 24,
  unit = "hours",
  n_boot = 99
)

epoch_summary <- summary(epoch_test)   # summary.dm_epoch()
print(epoch_summary)                   # print.summary.dm_epoch()
plot(epoch_test)
```

## 9. Event-based climate functions

```{r event-climate, eval = FALSE}
evt_zg <- dm_event_climate(
  zg_out,
  clim_hourly,
  event = "phase_start",
  phase = "all",
  windows = c(0, 3, 6, 12, 24),
  mean_vars = c("temp", "VPD", "RH"),
  max_vars  = c("VPD"),
  sum_vars  = c("prec")
)
head(evt_zg)
```

```{r event-climate-summary, eval = FALSE}
evt_summary <- dm_event_climate_summary(
  evt_zg,
  climate_var = "VPD_mean_prev_6h",
  group_var = "Phase",
  by = "month_of_year"
)
head(evt_summary)
```

```{r event-climate-test, eval = FALSE}
evt_test <- dm_event_climate_test(
  evt_zg,
  climate_var = "VPD_mean_prev_6h",
  group_var = "Phase",
  by = "month_of_year",
  method = "auto"
)
head(evt_test$summary)
head(evt_test$overall_tests)
head(evt_test$pairwise_tests)
```

```{r event-climate-plots, eval = FALSE}
plot(
  evt_zg,
  climate_var = "VPD_mean_prev_6h",
  group_var = "Phase",
  facet_by = "month_of_year",
  geom = "both",
  add_test = TRUE
)

evt_maxtwd <- dm_event_climate(
  zg_out,
  clim_hourly,
  event = "max_twd",
  windows = c(0, 3, 6, 12, 24),
  mean_vars = c("temp", "VPD", "RH"),
  max_vars  = c("VPD"),
  sum_vars  = c("prec")
)

plot(
  evt_maxtwd,
  climate_var = "VPD_mean_prev_6h",
  response_var = "max.twd",
  group_var = "Phase"
)
```

## 10. Growth fit and evaluation

### `dm.fit.gompertz()`

```{r legacy-gompertz, eval = FALSE}
gomp_legacy <- dm.fit.gompertz(df = dm_hourly, TreeNum = 1, CalYear = 2017, verbose = FALSE)
head(gomp_legacy)
```

### `dm.growth.fit()`, `plot.dm_growth_fit()`, and print/summary methods

```{r growth-fit, eval = FALSE}
fit_single <- dm.growth.fit(
  df = dm_hourly,
  TreeNum = 1:2,
  method = "gompertz",
  year_mode = "yearly",
  verbose = FALSE
)

print(fit_single)                 # print.dm_growth_fit()
fit_single_summary <- summary(fit_single)   # summary.dm_growth_fit()
print(fit_single_summary)         # print.summary.dm_growth_fit()
```

```{r growth-fit-plots, eval = FALSE}
plot(fit_single, type = "fit")
plot(fit_single, type = "season")
plot(fit_single, type = "residuals")
plot(fit_single, type = "timing")
plot(fit_single, type = "overlay")
plot(fit_single, type = "parameters")
```

### `dm.growth.fit.double()` and `dm.growth.evaluate()`

```{r growth-fit-double, eval = FALSE}
fit_double <- dm.growth.fit.double(
  df = dm_hourly,
  TreeNum = 1:2,
  method = "gompertz",
  year_mode = "yearly",
  verbose = FALSE
)
print(fit_double)
```

```{r growth-evaluate, eval = FALSE}
growth_eval <- dm.growth.evaluate(
  df = dm_hourly,
  TreeNum = 1:2,
  methods = c("gompertz", "loess", "spline", "double_gompertz"),
  year_mode = "yearly",
  verbose = FALSE
)
head(growth_eval)
```

```{r growth-evaluate-plots, eval = FALSE}
plot(growth_eval, metric = "rmse", type = "boxplot")
plot(growth_eval, metric = "r2", type = "heatmap")
```

## 11. Detrending and associated functions

```{r detrend, eval = FALSE}
detrended_fit <- dm.detrend.fit(fit_single)
plot(detrended_fit, type = "compare")
plot(detrended_fit, type = "fit")
plot(detrended_fit, type = "residual")
plot(detrended_fit, type = "detrended")
plot(detrended_fit, type = "boxplot")
```

```{r mean-detrended, eval = FALSE}
mean_det <- mean_detrended.dm(detrended_fit)
head(mean_det)
plot(mean_det)
```

### `dm_standardize()` and `plot.dm_standardized()`

```{r standardize}
std_nh <- dm_standardize(
  df = dm_hourly,
  season_type = "NH",
  method = "robust_amplitude"
)
head(std_nh$data)
head(std_nh$parameters)
```

```{r standardize-plot}
plot(std_nh)
```

## 12. Moving correlations and associated functions

```{r mov-cor, eval = FALSE}
mov_out <- mov.cor.dm(
  df = dm_hourly,
  Clim = clim_hourly,
  TreeNum = 1,
  win_size = 15,
  cor_method = "pearson",
  boot = FALSE
)

print(mov_out)                # print.mov_cor_dm()
mov_summary <- summary(mov_out)   # summary.mov_cor_dm()
print(mov_summary)            # print.summary_mov_cor_dm()
```

```{r mov-cor-plots, eval = FALSE}
plot(mov_out, type = "heatmap")
plot(mov_out, type = "line", annotate_peak = TRUE)
plot(mov_out, type = "facet")
plot(mov_out, type = "peak")
plot(mov_out, type = "line")
plot(mov_summary, type = "peak_corr")
```

```{r mov-cor-boot, eval = FALSE}
mov_boot <- mov.cor.dm(
  df = dm_hourly,
  Clim = clim_hourly,
  TreeNum = 1,
  win_size = 15,
  cor_method = "pearson",
  boot = TRUE,
  R = 99,
  set_seed = 1
)
plot(mov_boot, type = "line", show_ci = TRUE)
```

## 13. Harsh climate using `clim.twd()` and associated functions

```{r clim-twd, eval = FALSE}
rel_out <- clim.twd(
  df = dm_hourly,
  Clim = clim_rain,
  thresholdClim = "<10",
  thresholdDays = ">5",
  showPlot = FALSE
)
```

```{r clim-twd-stats, eval = FALSE}
clim_stats <- clim.twd.stats(
  rel_out,
  response = "full_period_change",
  group_by = "tree"
)

clim_stats_summary <- summary(clim_stats)   # summary.clim_twd_stats()
print(clim_stats_summary)                   # print.summary.clim_twd_stats()
plot(clim_stats, type = "trajectory")
```

```{r clim-twd-test, eval = FALSE}
tree_info <- data.frame(
  tree = c("T2", "T3"),
  species = c("Pinus", "Pinus"),
  site = c("Ktm", "Ktm")
)

clim_test <- clim.twd.test(
  rel_out,
  tree_info = tree_info,
  parameter = "lag_to_return_zero",
  compare_by = "species",
  within = "year"
)

clim_test_summary <- summary(clim_test)   # summary.clim_twd_test()
print(clim_test_summary)                  # print.summary.clim_twd_test()
plot(clim_test)
```

## 14. Network interpolation

### `network.interpolation()` and `plot.network_interpolation()`

```{r network-interp, eval = FALSE}
df1 <- dm_hourly
df1[40:50, "T2"] <- NA

ref_net <- cbind(dm_hourly, dm_hourly[, 2:3], dm_hourly[, 2:3])
colnames(ref_net) <- c("Time", "T1", "T2", "T3", "T4", "T5", "T6")

net_interp <- network.interpolation(
  df1,
  ref_net,
  niMethod = "proportional",
  n_boot = 100,
  return_flags = TRUE,
  return_pi = TRUE,
  assess = TRUE,
  assess_lengths_steps = c(1, 2, 4),
  correct_gap_jumps = TRUE,
  jump_threshold = 0.05
)
head(net_interp)
# to get the assessment stats we can use attr() function
attr(out, "network_validation_summary")
attr(out, "network_validation_points")
attr(out, "network_validation_seasonal")
```

```{r network-interp-plots, eval = FALSE}
plot(net_interp)
plot(net_interp, type = "uncertainty")
plot(net_interp, type = "availability")
plot(net_interp, type = "summary", summary_metric = "n_gap_jumps_removed")
plot(net_interp, type = "validation", validation_metric = "MAPE")
plot(net_interp, type = "coverage")
plot(net_interp, type = "compare")
plot(net_interp, type = "seasonal_error", seasonal_metric = "mean_abs_error")
```

## 15. Wavelet analysis and associated functions

### `dm_wavelet()`, `summary.dm_wavelet()`, and `plot.dm_wavelet()`

```{r wavelet, eval = FALSE}
wv <- dm_wavelet(
  x = dm_hourly,
  TreeNum = 1:2,
  source = "raw",
  make_pval = TRUE,
  verbose = FALSE
)

wv_summary <- summary(wv)   # summary.dm_wavelet()
print(wv_summary)           # print.summary.dm_wavelet()
```

```{r wavelet-plots, eval = FALSE}
plot(wv, type = "series")
plot(wv, type = "average")
plot(wv, type = "power")
plot(wv, series = names(wv$results)[1], type = "power")
```

### `dm_wavelet_reconstruct()` and its methods

```{r wavelet-reconstruct, eval = FALSE}
rec_extract <- dm_wavelet_reconstruct(
  wv,
  mode = "extract",
  lower_hours = 20,
  upper_hours = 28,
  only_sig = TRUE
)

rec_remove <- dm_wavelet_reconstruct(
  wv,
  mode = "remove",
  lower_hours = 20,
  upper_hours = 28,
  only_sig = TRUE
)

rec_extract_summary <- summary(rec_extract)   # summary.dm_wavelet_reconstruct()
print(rec_extract_summary)                    # print.summary.dm_wavelet_reconstruct()
```

```{r wavelet-reconstruct-plots, eval = FALSE}
plot(rec_extract)
plot(rec_remove)
```

### `dm_wavelet_coherence()` and `plot.dm_wavelet_coherence()`

```{r wavelet-coherence, eval = FALSE}
wc <- dm_wavelet_coherence(
  dm = dm_hourly,
  clim = clim_hourly,
  TreeNum = 1,
  clim_vars = c("temp", "VPD"),
  source = "raw",
  dm_fun = "mean",
  clim_funs = c(temp = "mean", VPD = "mean"),
  loess_span = 0,
  make.pval = TRUE,
  n.sim = 10,
  verbose = FALSE
)
```

```{r wavelet-coherence-plots, eval = FALSE}
plot(wc)
plot(wc, type = "cross_power")
plot(wc, type = "average_coherence")
plot(wc, type = "phase")
plot(wc, type = "series")
```

## Closing note

This vignette is intended to be both a workflow guide and a compact reference
for the main user-facing functions in the current **dendRoAnalyst** 
analysis pipeline. For classroom teaching, the companion demonstration script
can be run section by section; for package documentation, this vignette keeps
only the lighter sections evaluated and leaves heavy or interactive examples in
place for users to run locally.

## For suggestions, comments and questions please contact : <sugam.aryal@fau.de>
