--- title: "Reproducibility and Corpus Certificates" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{Reproducibility and Corpus Certificates} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} resource_files: - figures/logo.svg - figures/logo-dark.svg --- [![R-CMD-check](https://github.com/CTTIR/scimapR/actions/workflows/R-CMD-check.yaml/badge.svg)](https://github.com/CTTIR/scimapR/actions/workflows/R-CMD-check.yaml) [![pkgdown](https://github.com/CTTIR/scimapR/actions/workflows/pkgdown.yaml/badge.svg)](https://cttir.github.io/scimapR/) [![CRAN status](https://www.r-pkg.org/badges/version/scimapR)](https://CRAN.R-project.org/package=scimapR) [![Codecov test coverage](https://codecov.io/gh/CTTIR/scimapR/branch/main/graph/badge.svg)](https://app.codecov.io/gh/CTTIR/scimapR?branch=main) [![CRAN downloads](https://cranlogs.r-pkg.org/badges/scimapR)](https://cran.r-project.org/package=scimapR) [![CRAN downloads total](https://cranlogs.r-pkg.org/badges/grand-total/scimapR)](https://cran.r-project.org/package=scimapR) [![License: MIT](https://img.shields.io/badge/license-MIT-yellow.svg)](https://opensource.org/licenses/MIT) [![Lifecycle: experimental](https://img.shields.io/badge/lifecycle-experimental-orange.svg)](https://lifecycle.r-lib.org/articles/stages.html#experimental) ```{r, include = FALSE} knitr::opts_chunk$set( collapse = TRUE, comment = "#>" ) ``` ## Why certificates? Every bibliometric analysis starts with a corpus, but most analyses don't document *how* the corpus was built. scimapR's corpus certificates solve this: they are structured YAML documents that record the corpus hash, the steps behind the corpus and the local files it was built from, so that another researcher can check a corpus against them and run its searches again. ```{r setup} library(scimapR) corpus <- sm_example_corpus(seed = 42) ``` ## Provenance tracking Every record in a scimapR corpus knows where it came from: ```{r provenance} head(sm_provenance(corpus)) ``` ## Corpus hashing ```{r hash} sm_hash_corpus(corpus) ``` ## Creating a certificate ```{r certificate} cert <- sm_certificate(corpus) str(cert, max.level = 1) ``` ## Verifying a certificate ```{r verify} result <- sm_verify_certificate(corpus, cert) result$pass result$checks[, c("check", "expected", "actual", "status")] ``` ## Local input files A corpus built from local files, such as a database snapshot, an institutional export or an affiliation dictionary, records each file with its SHA-256 hash. `sm_corpus_from_tables(inputs = )` registers the files the tables come from; `sm_register_input()` adds any other file. ```{r local-inputs} tracker <- tempfile(fileext = ".csv") writeLines(c("doi,unit", "10.9999/example.1,Unit A"), tracker) corpus <- sm_register_input(corpus, tracker, role = "publication tracker", builder = "R/01_import.R::read_tracker") cert <- sm_certificate(corpus) sm_verify_certificate(corpus, cert)$checks[, c("check", "status")] # once the file changes, its check fails cat("10.9999/example.2,Unit B\n", file = tracker, append = TRUE) sm_verify_certificate(corpus, cert)$pass ``` A file that verification cannot find is reported as `"not checked"`, with a warning; its relative path is looked for in `base_dir`, in the folder of the certificate file and in the working directory. `sm_rebuild_from_cert()` replays the recorded searches of OpenAlex, PubMed and Crossref, but it cannot replay local files or file reads: for a corpus built only from them it stops and names the files and the code that read them. ## Saving and loading ```{r save-load} tmp <- tempfile(fileext = ".rds") sm_save_corpus(corpus, tmp) loaded <- sm_load_corpus(tmp) nrow(loaded$works) ``` ## Snapshot and diff ```{r snapshot} snap_path <- tempfile(fileext = ".rds") sm_snapshot(corpus, snap_path) ``` ## Citation ```{r cite} sm_cite_corpus(corpus) ``` ## Locking a corpus ```{r lock} locked <- sm_lock(corpus, reason = "Final version for publication") locked$metadata$is_locked # sm_refresh(locked) # This would error -- corpus is locked ```