Skip to contents

R package version

lint

Versioned analysis job templates for the HVTI CORR group at the Cleveland Clinic.

Start at the template gallery: every template, what it is for, the add_job() call that adds it to your study, and the report it produces on a synthetic study. The full reference is at https://ehrlinger.github.io/hvtiRtemplates/.

Installation

hvtiRtemplates is part of the HVTI R family. Install it with the rest of the family through hvtiR:

# install.packages("pak")
pak::pak("ehrlinger/hvtiR")
hvtiR::install()

hvtiR::install() installs every member in one call, so the versions the members require of one another resolve together. Update later with hvtiR::update(), from a fresh R session: it will not overwrite a package that is already loaded.

To install hvtiRtemplates on its own:

pak::pak("ehrlinger/hvtiRtemplates")

In a project that uses renv, install with renv::install("ehrlinger/hvtiRtemplates") instead, so the package lands in the project library.

What is here

Directory Status Contents
inst/templates/ supported R job templates. See inst/templates/README.md for coverage.

Everything the package installs is supported: tested, maintained, and intended to be run. There is no reference-only material.

There is no SAS corpus here

During development this repository also carried the legacy SAS template corpus (240 files) and the SAS macro library (495 files, with history imported from 2014) as a reference specification. Both were removed before release, and every path was purged from every commit with git filter-repo — they are not recoverable from this repository’s history by design.

Two consequences worth stating plainly. Parity work against the SAS originals needs a source outside this repository; the institutional SAS license runs into 2027, so plan accordingly (2027-09-29 is the working date, not yet confirmed). And a result filed before the migration still cannot say what produced it — that was already true, because %inc bound late to a mutable directory with no version, and removing the corpus neither creates nor worsens that gap.

Why this package exists

Study analyses were created by copying template files into a new study folder and editing them. Two things followed: improvements stayed in the study where they were made, and — the problem that actually hurts — a filed result could not say what produced it. SAS bound its analysis logic with %inc kaplan, resolving at run time against a mutable directory with no version, so the .lst filed in 2006 was produced by a kaplan nobody can now identify.

The design rule is bind late, to something versioned. Late binding is right; SAS could not make it safe because there was no version to pin. renv.lock supplies that, so a study can use the latest while working and pin it on filing.

In practice a study declares hvtiRtemplates in its renv.lock, resolves a template through template_path("ac") instead of copying one into the study folder, and pins the version when results are filed. The lock file is then the answer to “what produced this?” — the question the SAS arrangement could not answer, because %inc had nothing to pin.

API

Function Returns
template_catalog() all 55 template jobs, including queued work and dependencies
hvti_taxonomy() the analysis prefix table: prefix, name, folder, description
template_list() supported templates: name, prefix, qualifier, folder, file
template_path(prefix, qualifier = NULL) path to one supported template
hvti_non_prefixes() leading name fields that are utilities, not analysis prefixes
add_job(prefix, subject, type, dir = NULL, qualifier = NULL) the scaffolded job’s path, invisibly
open_job(prefix, subject, type, dir = NULL, qualifier = NULL) job path; creates a missing job or opens an existing one
render_job(path, final = FALSE, quiet = FALSE) path, invisibly; renders a draft, or with final = TRUE a render that stops on an unfinished job
migrate_job(source, subject, type, prefix, ...) the migrated job’s path, invisibly; writes an evidence report beside it

add_job() also installs idempotent Quarto pre-render and post-render hooks in the study without replacing existing project settings or user hooks. Every managed render captures the registered data actually read, embeds its runtime payload in the completed HTML, and publishes a same-stem .provenance.json beside Quarto’s actual output. A failed render leaves the prior completed HTML and sidecar together when the output stays untouched. If publication fails after an output changes, the hooks expose a prior sidecar only when its recorded output hash still matches. Otherwise they withhold the sidecar and retain its recovery backup with a warning.

Templates are <prefix>[-<qualifier>].qmd in a numbered directory (20_distributions/ac.qmd); a job is <prefix>[.<qualifier>].<subject>.<type>.qmd in the study’s matching taxonomy folder, so a study’s jobs sort by template. Jobs scaffolded before 2026-10 keep their <subject>-<type>-<prefix>[-<qualifier>].qmd names and keep rendering. New studies use numbered folders and existing bare-folder studies keep their layout. The ordinal that once prefixed filenames was dropped in 1.1.0.

The subject groups a job set. It is a statistical endpoint when the job analyses one, such as death; it can instead be an endpoint-free topic such as cohort, treatment, or labs. Each job owns its outcome variables, coding, filters, and any cohort definition. Dataset registration records the data, not a study-wide endpoint or cohort.

qualifier names a job type within a prefix. The current qualified families are dc, dp, rfs, rfc, rfr, and lm. The lm choices are binary, ordinal, nominal, propensity_binary, propensity_ordinal, propensity_nominal, checkpred, and balancing_count. It is NULL and the column is NA for a prefix with a single template. Naming no qualifier where a prefix carries several is an error listing the choices, never a silent pick of the first.

Migrate a legacy job

For a study with SAS programs already in descriptive/ and graphs/, first adopt its directory with hvtiRutilities::study_setup(..., adopt = TRUE) and register its built datasets with register_data(). The tutorial Set up an hvtiR study for descriptive and EDA work walks through new-study creation, recoverable legacy cleanup and adoption, data registration, the EDA analysis set, all five pre-analysis jobs, and output review using synthetic data.

From that study’s root, migrate a descriptive-table job with:

job <- hvtiRtemplates::migrate_job(
  source = "descriptive/dc.tables.sas",
  subject = "cohort", type = "eda", prefix = "dc", qualifier = "tables",
  lst = "descriptive/dc.tables.lst", log = "descriptive/dc.tables.log",
  reference = "documents/general.rtf", dir = "."
)

Use your study’s source and evidence filenames. lst, log, and reference are optional; supplied files must exist beneath dir. The call writes descriptive/dc.tables.cohort.eda.qmd and descriptive/dc.tables.cohort.eda-migration.md in a study with bare folders. It preserves the evidence files and refuses to overwrite either output.

Migration supports dc-tables, dc-gfup, dc-trends, and dc-eda. Each adapter reads a defined source shape. Only deterministic extraction can remove an EDIT: marker; uncertain choices remain in the job and report for you to resolve before rendering. Logs, listings, and RTF/DOCX references help you check the translation but do not supply missing analysis choices.

The table job replaces the SAS RTF output with an editable CORR DOCX through hv_tbl_summary(), hv_man_table(), hv_man_table_save(), and hv_check_docx(). It writes beneath documents/<subject>-<type>/ and stops on a structural finding. Compare the rows, summaries, precision, and footnotes with the legacy reference before accepting the document; the structural check does not establish numerical agreement.