---
title: "Introduction to rtransparency"
author: Stylianos Serghiou
date: "`r Sys.Date()`"
output: rmarkdown::html_vignette
description: >
  How to use the rtransparency package to identify and extract indicators of
  transparency from published biomedical articles, and how the detection works.
vignette: >
  %\VignetteIndexEntry{Introduction to rtransparency}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

```{r, include = FALSE}
knitr::opts_chunk$set(
  collapse = TRUE,
  comment = "#>",
  message = FALSE,
  warning = FALSE
)
```

```{r setup}
library(rtransparency)
```

# Overview

`rtransparency` identifies and extracts **indicators of transparency** from the
full text of published biomedical articles. It works on two inputs: plain TXT
files (typically converted from PDFs) and PMC XML files (the JATS XML served by
PubMed Central). For each indicator it returns whether the indicator was found
and, when found, the sentence or statement that triggered the detection.

| Indicator | What it captures | TXT | PMC XML |
|---|---|:--:|:--:|
| Conflicts of interest | A COI / competing-interests disclosure | `rt_coi` | `rt_coi_pmc` |
| Funding | A funding / financial-support statement | `rt_fund` | `rt_fund_pmc` |
| Protocol registration | Registration on a trial / review registry | `rt_register` | `rt_register_pmc` |
| Novelty | Claims of novelty ("for the first time") | `rt_novelty` | `rt_novelty_pmc` |
| Replication | Replication / independent-validation components | `rt_replication` | `rt_replication_pmc` |
| Data sharing | Data deposited or made openly available | `rt_data_code` | `rt_data_code_pmc` |
| Code sharing | Source code / scripts made available | `rt_data_code` | `rt_data_code_pmc` |
| AI-use disclosure | A statement that generative AI was (or was not) used to prepare the manuscript | `rt_ai` | `rt_ai_pmc` |
| Open-access license | Whether the article is openly licensed, and which license | `rt_oa` | `rt_oa_pmc` |
| Reporting guideline | Whether a reporting guideline was followed, and which one | `rt_reporting` | `rt_reporting_pmc` |

`rt_all_pmc` runs all ten detectors together in a single pass: COI, funding,
registration, novelty, replication, data sharing, code sharing, AI-use
disclosure, open-access licensing and reporting-guideline use. (`rt_all` covers
the first five from TXT; the others also have standalone TXT detectors, such as
`rt_data_code`, `rt_ai`, `rt_oa` and `rt_reporting`, but are not part of the
`rt_all` wrapper.)

AI-use disclosure is the newest indicator. Journals have asked authors to
disclose any use of generative AI (ChatGPT and similar) in preparing a
manuscript only since 2023, so `rt_ai_pmc` evaluates the indicator only for
articles published in 2023 or later and returns `NA` for earlier ones.

The package and its validation are described in Serghiou et al., *Assessment of
transparency indicators across the biomedical literature: How open is open?*
(PLOS Biology, 2021, doi:10.1371/journal.pbio.3001107).

# How detection works

## Article parsing

PMC XML is parsed with `xml2`. The XML root is standardized to the `<article>`
node (the package accepts the OAI-PMH, EFetch `<pmc-articleset>`, Europe PMC and
bare `<article>` shapes), default namespaces are always stripped, and the text
is split into the sections where each indicator usually appears:
acknowledgments, footnotes / author notes, the body, the methods, the abstract
and supplementary material. TXT files are read whole and split into paragraphs.

## Rule-based detection

Detection is **rule-based and interpretable**: each indicator is a curated set
of regular expressions applied to the relevant sections, rather than a machine
learning model. This keeps the output auditable (the matched statement is
returned) and reproducible.

* **Conflicts of interest.** Detected from structured COI footnotes
  (`fn-type = "conflict"`), from section titles ("Conflicts of interest",
  "Competing interests", "Declaration of interest", "Duality of interest"), and
  from a set of text patterns covering financial relationships, consulting,
  fees, board membership, patents and explicit "no competing interests"
  declarations. Honoraria-to-subjects and reference text are masked to reduce
  false positives.
* **Funding.** Detected from the XML `<funding-group>` element, from funding
  section titles, and from text patterns such as "supported by", "funded by",
  "grant from / number", named funders and award types. Acknowledged funding is
  required to use explicit funding language (a funding verb tied to a funder),
  so a bare mention of an institution or the word "support" is not enough.
  No-funding declarations are excluded.
* **Protocol registration.** Detected from registry identifiers
  (ClinicalTrials.gov `NCT`, PROSPERO `CRD`, ISRCTN, ANZCTR `ACTRN`, DRKS, IRCT,
  UMIN, ChiCTR) and from registration phrasing in the methods or footnotes.
* **Novelty and replication.** Detected from claim patterns such as "for the
  first time", "to our knowledge", "novel finding" (novelty) and "replicate",
  "independently validated", "confirmatory cohort" (replication), with negation
  filters ("failed to replicate").
* **Data and code sharing.** Detected by a native detector (`.detect_data_code`)
  built from public repository facts and curated benchmark statements:
  field-specific accession
  schemes (GEO `GSE`, SRA / BioProject `PRJNA`, PDB, ArrayExpress, dbGaP,
  ProteomeXchange, Dryad / Zenodo / figshare DOIs, ...), repository URLs and
  names, deposit / availability / data-availability-statement language, and
  supplement and file-format signals. Crucially it distinguishes **sharing**
  ("data were deposited in GEO") from **reuse** ("data were downloaded from
  GEO") and excludes "available on request". Code repositories (GitHub, GitLab,
  Bitbucket) only count as data when paired with a data noun, so a code-only
  GitHub link is not mistaken for data sharing.
* **AI-use disclosure.** Detected from a "Declaration of generative AI" type
  section title, and from text that names a generative-AI tool (ChatGPT, GPT-4,
  Copilot, Gemini, an LLM, ...) in a manuscript-preparation context ("used
  ChatGPT to improve the readability") or in an explicit negation ("no
  generative AI was used"). A negative lookahead keeps the tool sense of "large
  language model" out of the writing-object pattern, and AI used purely as a
  research method (not for writing) is not counted. Only evaluated for 2023
  onward.
* **Open-access licensing.** Read from the JATS `<license>` element and its
  license-reference URL, and classified to a canonical identifier
  (`CC-BY-4.0`, `CC-BY-NC-ND-4.0`, `CC0-1.0`, ...). A Creative Commons or CC0
  license (or an explicit open-access declaration) sets `is_open_access`; a
  CC0 data-waiver is not mistaken for the article license. This is the reuse
  ("R") dimension of FAIR and feeds the [`rfair`](https://github.com/choxos/rfair)
  assessment.
* **Reporting-guideline use.** Detected when authors state they followed a
  reporting guideline (the EQUATOR checklists: CONSORT, PRISMA and its
  extensions, STROBE, ARRIVE, STARD, TRIPOD, COREQ, SQUIRE, CHEERS, CARE, and
  the wider reportilo list), returning which one. Detection is precision-first:
  a guideline counts only in a reporting context; common-word acronyms (ARRIVE,
  CARE, RECORD, ...) require the upper-case form beside a guideline noun; and
  animal-welfare ("Care and Use of Laboratory Animals"), clinical-practice and
  non-adherence mentions are excluded.

## Languages

Conflict-of-interest and funding statements are detected not only in English but
also in **Spanish, Portuguese, French, German and Italian**, using
language-distinctive patterns matched on transliterated (accent-stripped) text.
The German conflict-of-interest detection rate, for example, rose from 33% to
97% once these were added. The other indicators are English-only for now.

# Usage: PMC XML

The package ships an example PMC XML file. We use it below; replace the path
with your own file to analyze a different article.

```{r}
xml_path <- system.file(
  "extdata", "PMID32171256-PMC7071725.xml", package = "rtransparency"
)
```

## All indicators at once

`rt_all_pmc` returns all ten indicators in one call, together with the matched
statement text, the publication `year` and article metadata.

```{r}
all_indicators <- rt_all_pmc(xml_path)

dplyr::glimpse(
  all_indicators[, c("pmid", "year", "is_coi_pred", "is_fund_pred",
                     "is_register_pred", "is_novelty_pred", "is_replication_pred",
                     "is_open_data", "is_open_code", "is_ai_pred",
                     "is_open_access", "is_reporting_pred")]
)
```

`is_ai_pred` is `NA` here because this example article predates 2023; for a 2023
or later article it would be `TRUE` or `FALSE`.

## Individual indicators

```{r}
coi <- rt_coi_pmc(xml_path)
c(is_coi = coi$is_coi_pred, text = substr(coi$coi_text, 1, 120))
```

```{r}
fund <- rt_fund_pmc(xml_path)
c(is_fund = fund$is_fund_pred, text = substr(fund$fund_text, 1, 120))
```

```{r}
register <- rt_register_pmc(xml_path)
register$is_register_pred
```

## Data and code sharing

`rt_all_pmc` already reports `is_open_data` and `is_open_code`; `rt_data_code_pmc`
is the focused view that also returns the matched statements. Detection is native
and needs no external packages.

```{r}
data_code <- rt_data_code_pmc(xml_path)

dplyr::glimpse(
  data_code[, c("is_open_data", "open_data_statements",
                "is_open_code", "open_code_statements")]
)
```

`rt_all_pmc` and `rt_data_code_pmc` also return `open_data_links` and
`open_code_links`: the repository and accession URLs extracted from the
statements, ready to pass to FAIR-assessment tooling such as
[`rfair`](https://github.com/choxos/rfair). Article metadata (title, journal,
identifiers, dates) is available separately via `rt_meta_pmc`.

```{r}
meta <- rt_meta_pmc(xml_path)
dplyr::glimpse(meta[, c("pmid", "doi")])
```

## AI-use disclosure

`rt_ai_pmc` reports the publication `year`, the year-gated prediction
`is_ai_pred` (`NA` before 2023) and the matched text. The `ai-disclosure`
vignette covers this indicator in depth.

```{r}
ai <- rt_ai_pmc(xml_path)
c(year = ai$year, is_ai = ai$is_ai_pred)
```

# Usage: TXT files

The plain-text detectors take either a file path or the text itself, and
return the same indicator columns as the XML detectors. `rt_all_pdf()` scores a
PDF in one call (it needs the poppler `pdftotext` utility). The chunks below are
illustrative and are not executed when the vignette is built.

```{r, eval = FALSE}
pdf_path <- system.file(
  "extdata", "PMID32171256-PMC7071725.pdf", package = "rtransparency"
)
rt_all_pdf(pdf_path)                 # all ten indicators from a PDF

article <- rt_read_pdf(pdf_path)     # or extract the text once ...
rt_coi(text = article)               # ... and run any detector on it
rt_all(text = article)

rt_all("article.txt")                # a text file works the same way
rt_all_txt_dir("path/to/articles")   # a directory of TXT and PDF files
```

`rt_ai` is the plain-text counterpart of `rt_ai_pmc`. A text file carries no
reliable publication date, so `rt_ai` applies no 2023 year gate (`is_ai_pred` is
always `TRUE` or `FALSE`, never `NA`) and cannot confine the scan to back-matter
sections the way the XML detector does. Restrict it to articles published in 2023
or later, and expect a slightly higher false-positive rate on papers that use AI
as a research method.

# Processing many articles

`rt_all_pmc_dir()` runs all ten indicators over an entire directory (or a
vector of file paths) in one call, designed for corpus-scale analysis.

```{r, eval = FALSE}
# Sequential, in memory
res <- rt_all_pmc_dir("path/to/xml")

# Resumable and parallel: results are written to a CSV in chunks, a re-run skips
# files already recorded, and a malformed file yields an is_success = FALSE row
# instead of aborting the run.
future::plan("multisession")
res <- rt_all_pmc_dir(
  "path/to/xml", output = "results.csv", parallel = TRUE
)
```

# Summarizing a corpus

With one row per article, `rt_summary()` reports per-indicator prevalence with a
Wilson confidence interval and a sensitivity/specificity-corrected (Rogan-Gladen)
prevalence; `rt_score()` adds a per-article count of openness practices; and
`rt_plot()` draws prevalence bars and yearly trends. The
`transparency-summary` vignette covers this in depth.

```{r}
data(rt_demo)            # a small simulated example shipped with the package
rt_summary(rt_demo)[, c("indicator", "percent", "adj_percent")]
```

# Downloading PMC XML

`rt_fetch_pmc()` downloads full-text XML for PMCIDs, PubMed IDs or DOIs from NCBI
(or Europe PMC with `source = "europepmc"`), reusing files already downloaded
and reporting which articles have a full-text body. `rt_convert_ids()` maps
between the identifier types.

```{r, eval = FALSE}
got <- rt_fetch_pmc(c("PMC7071725", "32171256"), dir = "xml")
res <- rt_all_pmc_dir("xml")
```

# Beyond presence of a statement

A few functions go further than detecting whether a statement exists:

* `rt_authors_pmc()` and `rt_funders_pmc()` read tagged JATS metadata: ORCID
  coverage and CRediT contribution roles, and funders with their Crossref Funder
  Registry and ROR identifiers and award numbers.
* `rt_trial_ids()` extracts registry identifiers from the registration text, and
  `rt_registration_timing()` asks ClinicalTrials.gov whether each trial was
  registered before it started.
* `rt_fill_coi_pubmed()` recovers conflict-of-interest statements that PubMed
  records but the full-text XML lacks.
* `rt_check_links()` checks whether the data and code links a statement gives
  actually resolve.
* `rt_ethics_pmc()` and `rt_ethics()` detect ethics approval and informed
  consent statements. They are experimental: not yet validated against hand
  labels, so they are kept out of `rt_all_pmc()`.

# Validation

Every indicator is benchmarked against hand labels; the current numbers, their
provenance and the scripts that reproduce them are in `inst/benchmark/` and
`data-raw/benchmark/` of the source repository, and the README summarizes them.
The accuracy table `rt_accuracy` used by `rt_summary()` records each estimate
with its validation counts, so the corrected prevalence carries the
uncertainty of the validation.

# Naming convention and dependencies

Functions that operate on TXT files do not end in `_pmc`; functions that operate
on PMC XML end in `_pmc`. Data and code detection is implemented natively and no
longer requires the `oddpub` or `tokenizers` packages.
