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.
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.
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")])
#> specimen treatment batch direction laundering afterflame char_length
#> 1 U1-wa0-1 Untreated U1 warp 0 36.5 300
#> 2 U1-wa0-2 Untreated U1 warp 0 33.8 300
#> 3 U1-wa0-3 Untreated U1 warp 0 32.4 300
#> 4 U1-wa25-1 Untreated U1 warp 25 35.2 300
#> 5 U1-wa25-2 Untreated U1 warp 25 31.7 300
#> 6 U1-wa25-3 Untreated U1 warp 25 25.6 300
#> char_length_status
#> 1 censored
#> 2 censored
#> 3 censored
#> 4 censored
#> 5 censored
#> 6 censoredflame_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.
fd <- flame_data(raw, control = "Untreated",
method_edition = "synthetic example")
fd
#> <flame_data> 60 specimens, 5 batches, 3 treatments
#> Treatments: Untreated, Plasma-A, Plasma-B
#> Control: Untreated
#> Endpoints: afterflame, afterglow, char_length (stored in s / mm)
#> Strata: direction, laundering
#> Edition: synthetic example
#> afterglow: 0 censored, 1 missing
#> char_length: 13 censored, 0 missing
#>
#> specimen treatment batch direction laundering afterflame afterflame_status
#> 1 U1-wa0-1 Untreated U1 warp 0 36.5 measured
#> 2 U1-wa0-2 Untreated U1 warp 0 33.8 measured
#> 3 U1-wa0-3 Untreated U1 warp 0 32.4 measured
#> 4 U1-wa25-1 Untreated U1 warp 25 35.2 measured
#> 5 U1-wa25-2 Untreated U1 warp 25 31.7 measured
#> 6 U1-wa25-3 Untreated U1 warp 25 25.6 measured
#> afterglow afterglow_status char_length char_length_status melt drip
#> 1 24.7 measured 300 censored FALSE FALSE
#> 2 24.6 measured 300 censored FALSE FALSE
#> 3 20.9 measured 300 censored FALSE FALSE
#> 4 17.5 measured 300 censored FALSE FALSE
#> 5 21.8 measured 300 censored FALSE FALSE
#> 6 24.2 measured 300 censored FALSE FALSE
#> notes
#> 1 specimen consumed over its full length
#> 2 specimen consumed over its full length
#> 3 specimen consumed over its full length
#> 4 specimen consumed over its full length
#> 5 specimen consumed over its full length
#> 6 specimen consumed over its full length
#> # ... with 54 more specimensEach 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.
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.
s <- summarize_flame(fd, endpoint = "char_length")
s[s$direction == "warp" & s$laundering == "0",
c("treatment", "n_specimens", "n_batches", "n_censored", "mean", "bound")]
#> treatment n_specimens n_batches n_censored mean bound
#> 1 Untreated 3 1 3 300.00000 lower_bound
#> 5 Plasma-A 6 2 0 87.33333 exact
#> 9 Plasma-B 6 2 0 133.50000 exactStrips 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.
cmp <- compare_treatments(fd, endpoint = "afterflame")
cmp[, c("treatment", "direction", "laundering", "n_treated", "n_control",
"difference", "conf_low", "pct_reduction", "status")]
#> treatment direction laundering n_treated n_control difference conf_low
#> 1 Plasma-A warp 0 2 1 -32.56667 NA
#> 2 Plasma-B warp 0 2 1 -30.40000 NA
#> 3 Plasma-A warp 25 2 1 -28.93333 NA
#> 4 Plasma-B warp 25 2 1 -25.11667 NA
#> 5 Plasma-A weft 0 2 1 -28.21667 NA
#> 6 Plasma-B weft 0 2 1 -25.28333 NA
#> 7 Plasma-A weft 25 2 1 -31.28333 NA
#> 8 Plasma-B weft 25 2 1 -28.28333 NA
#> pct_reduction status
#> 1 95.13145 estimated
#> 2 88.80234 estimated
#> 3 93.83784 estimated
#> 4 81.45946 estimated
#> 5 95.21935 estimated
#> 6 85.32058 estimated
#> 7 94.41650 estimated
#> 8 85.36217 estimatedUsing unit = "specimen" does give intervals, but they
only describe variation among strips within the available batches, and
the function warns accordingly.
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")]
#> treatment difference conf_low conf_high pct_reduction pct_low pct_high
#> 1 Plasma-A -32.56667 -37.55914 -27.57420 95.13145 92.51478 97.54231
#> 2 Plasma-B -30.40000 -34.76322 -26.03678 88.80234 83.37009 93.92415For char length, all untreated specimens were consumed. By default, such comparisons are not estimated:
cmp_char <- compare_treatments(fd, endpoint = "char_length")
head(cmp_char[, c("treatment", "direction", "laundering", "status")], 4)
#> treatment direction laundering status
#> 1 Plasma-A warp 0 not_estimable
#> 2 Plasma-B warp 0 not_estimable
#> 3 Plasma-A warp 25 not_estimable
#> 4 Plasma-B warp 25 not_estimableWith 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.
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")]
#> treatment direction laundering difference diff_bound pct_reduction pct_bound
#> 1 Plasma-A warp 0 -212.6667 upper 70.88889 lower
#> 2 Plasma-B warp 0 -166.5000 upper 55.50000 lower
#> 3 Plasma-A warp 25 -171.3333 upper 57.11111 lower
#> 4 Plasma-B warp 25 -130.5000 upper 43.50000 lower
#> status
#> 1 estimated
#> 2 estimated
#> 3 estimated
#> 4 estimatedThe package never assumes thresholds. If a specification or contract gives limits, enter them together with their source. The values below are illustrative only.
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")]
#> treatment endpoint statistic limit observed result
#> 1 Untreated afterflame mean 5 34.233333 fail
#> 2 Untreated char_length individual 200 300.000000 fail
#> 9 Plasma-A afterflame mean 5 1.666667 pass
#> 10 Plasma-A char_length individual 200 105.000000 pass
#> 17 Plasma-B afterflame mean 5 3.833333 pass
#> 18 Plasma-B char_length individual 200 142.000000 passA result is indeterminate when missing or censored
observations prevent a decision.
flame_report() writes a plain Markdown file that records
the units, method edition, handling of censored values and package
version.
txt <- flame_report(fd, comparisons = cmp, criteria = crit,
date = as.Date("2026-01-01"))
head(txt, 10)
#> [1] "# Vertical flame test report"
#> [2] ""
#> [3] "Generated: 2026-01-01 "
#> [4] "Package: textileFlame 0.1.0"
#> [5] ""
#> [6] "## Data and method"
#> [7] ""
#> [8] "- Specimens: 60 from 5 treated batches"
#> [9] "- Treatments (specimens): Untreated (12), Plasma-A (24), Plasma-B (24)"
#> [10] "- Control: Untreated"Results describe performance under the specified laboratory exposure and do not by themselves establish real-world fire safety.
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.