---
title: "Analysing vertical flame tests with textileFlame"
output: rmarkdown::html_vignette
vignette: >
  %\VignetteIndexEntry{Analysing vertical flame tests with textileFlame}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

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

`textileFlame` helps to validate, summarise, compare and report specimen-level
results of vertical flame tests of textiles: afterflame time, afterglow time
and char length, as obtained with methods such as ASTM D6413. It does not
implement the test procedure and assumes no acceptance thresholds. Always
consult the full edition of the method you used.

The data in this vignette are **synthetic**. They were generated to illustrate
the package and do not represent any real material or laboratory.

## Importing and validating data

Each row is one specimen. Besides the endpoints, the package needs the
treatment and the identifier of the *independently treated batch* from which
the specimen was cut.

```{r import}
raw <- read.csv(system.file("extdata", "flame_example.csv",
                            package = "textileFlame"))
head(raw[, c("specimen", "treatment", "batch", "direction", "laundering",
             "afterflame", "char_length", "char_length_status")])
```

`flame_data()` checks the data (identifiers, negative or non-numeric values,
treatment and batch labels, status values, duplicates) and converts all values
to seconds and millimetres. Use `validate_flame_data()` to see every finding
without stopping at the first error.

```{r flame-data}
fd <- flame_data(raw, control = "Untreated",
                 method_edition = "synthetic example")
fd
```

## Missing and incomplete observations

Each endpoint can carry a status: `measured`, `missing`, `censored` or
`not_applicable`. In this synthetic example, complete consumption is modelled as a lower-bound
observation and explicitly marked `censored`. This is an analytical convention,
not a rule prescribed by ASTM. Use it only when the recorded value is a valid
lower bound on the quantity being analysed. Complete consumption by itself
does not establish that interpretation; follow the method and laboratory
reporting rules actually used. Censored values are never silently treated as
zero or as ordinary measurements.

```{r status}
table(fd$treatment, fd$char_length_status)
```

## Summaries

Summaries are computed within strata (here direction and laundering) so that
unlike measurements are not pooled by accident. When censored values are
present, `bound` says that the statistics are lower bounds.

```{r summary}
s <- summarize_flame(fd, endpoint = "char_length")
s[s$direction == "warp" & s$laundering == "0",
  c("treatment", "n_specimens", "n_batches", "n_censored", "mean", "bound")]
```

## Batches, not specimens, are the replicates

Strips cut from one treated fabric are not independent treatment replicates.
By default `compare_treatments()` averages specimens within each batch and
compares batch means with a Welch interval. When a group has fewer than two
batches, as the single untreated batch here, the difference is still reported
but no interval is computed, and a note says why.

```{r compare}
cmp <- compare_treatments(fd, endpoint = "afterflame")
cmp[, c("treatment", "direction", "laundering", "n_treated", "n_control",
        "difference", "conf_low", "pct_reduction", "status")]
```

Using `unit = "specimen"` does give intervals, but they only describe
variation among strips within the available batches, and the function warns
accordingly.

```{r compare-specimen}
cmp_spec <- suppressWarnings(
  compare_treatments(fd, endpoint = "afterflame", unit = "specimen")
)
cmp_spec[cmp_spec$direction == "warp" & cmp_spec$laundering == "0",
         c("treatment", "difference", "conf_low", "conf_high",
           "pct_reduction", "pct_low", "pct_high")]
```

### Comparisons that involve censored observations

For char length, all untreated specimens were consumed. By default, such
comparisons are not estimated:

```{r compare-censored}
cmp_char <- compare_treatments(fd, endpoint = "char_length")
head(cmp_char[, c("treatment", "direction", "laundering", "status")], 4)
```

With `censored = "bound"` the recorded values give a one-sided statement: the
untreated control burned at least as far as recorded, so the true char-length
reduction is *at least* the reported one. No interval or test is computed for
bounds.

```{r compare-bound}
cmp_bound <- compare_treatments(fd, endpoint = "char_length",
                                censored = "bound")
cmp_bound[1:4, c("treatment", "direction", "laundering", "difference",
                 "diff_bound", "pct_reduction", "pct_bound", "status")]
```

## Acceptance criteria

The package never assumes thresholds. If a specification or contract gives
limits, enter them together with their source. The values below are
illustrative only.

```{r criteria}
crit <- flame_criteria(
  data.frame(endpoint = c("afterflame", "char_length"),
             statistic = c("mean", "individual"),
             max = c(5, 200)),
  source = "Illustrative values for this vignette only"
)
ev <- evaluate_criteria(fd, crit)
ev[ev$direction == "warp" & ev$laundering == "0",
   c("treatment", "endpoint", "statistic", "limit", "observed", "result")]
```

A result is `indeterminate` when missing or censored observations prevent a
decision.

## Plots and reports

```{r plot-specimens}
plot_specimens(fd, endpoint = "char_length")
```

```{r plot-comparison}
plot_comparison(cmp)
```

`flame_report()` writes a plain Markdown file that records the units, method
edition, handling of censored values and package version.

```{r report}
txt <- flame_report(fd, comparisons = cmp, criteria = crit,
                    date = as.Date("2026-01-01"))
head(txt, 10)
```

Results describe performance under the specified laboratory exposure and do not
by themselves establish real-world fire safety.

## Statistical assumptions and references

Treatment comparisons are unpaired, between independent groups. They do not
model paired batches, repeated measurements, or laboratory effects. Batch means
receive equal weight even when different numbers of strips are tested.
Approximate Welch intervals assume independent batch means and sufficiently
appropriate sampling distributions; very small batch counts require care.
Missing observations are omitted, so estimates are conditional on available
observations. Percentage-reduction intervals use a Fieller construction with
an approximate Welch quantile. Unbounded ratio intervals are returned as
missing limits, not as evidence of a precisely estimated reduction.

When `batch = NA`, per-specimen identifiers are used for bookkeeping and
default batch-level intervals and tests are disabled. Explicit specimen-level
analyses require the user to justify independence.

Unit conversion is for analysis only. It does not certify that mixed SI and
inch-pound test procedures conform to ASTM. No ASTM procedure or proprietary
standard text is distributed with this package.

- ASTM International (2022). *ASTM D6413/D6413M-22: Standard Test Method for
  Flame Resistance of Textiles (Vertical Test).*
  <https://doi.org/10.1520/D6413_D6413M-22>.
- Fieller, E. C. (1954). Some Problems in Interval Estimation.
  *Journal of the Royal Statistical Society, Series B*, 16(2), 175–185.
  <https://doi.org/10.1111/j.2517-6161.1954.tb00159.x>.
