First CRAN submission: the maintainer email address is corrected, the
copyright holders of the bundled Define-XML schema files (CDISC, MIT
License) and stylesheets (Lex Jansen, MIT License) are stated in
Authors@R and inst/COPYRIGHTS (the README had described them as
Apache-licensed), and a spelling word list is added.
Resubmission: the Description explains every acronym and links the CDISC
standards, and the attach test no longer installs the package (it runs
against the installed copy under R CMD check and skips from a source
tree), so pkgbuild leaves Suggests.
inst/COPYRIGHTS lists the source, copyright holder, and license of every bundled file and data table, including the standards metadata tables added in this version.
ig_sdtm, ig_adam, and the new model_sdtm are rebuilt from 34 CDISC
Library CSV exports and carry every standard and version in them, replacing
every row transcribed from the Rsdtm package:
| Table | Standards | Standard versions | Rows |
|-------|-----------|------------------:|-----:|
| model_sdtm | SDTM model | 9 | 3,604 |
| ig_sdtm | SDTMIG, SDTMIG-AP, SDTMIG-MD, SENDIG, SENDIG-AR, SENDIG-DART, SENDIG-GeneTox | 14 | 10,064 |
| ig_adam | ADaMIG, ADaMIG-MD, ADaMIG-NCA, ADaM-ADAE, ADaM-BDS-TTE, ADaM-OCCDS, ADaM-popPK | 11 | 1,804 |
Only variable metadata is carried. The guides' prose (CDISC Notes, Description, Definition, Notes, Examples) is not in the package data.
Breaking: new columns. ig_sdtm is now standard, version, class,
domain, order, variable, label, type, role, core,
codelist_code, codelist_submission_values, described_value_domain,
value_list. ig_adam is standard, version, structure,
variable_set, order, variable, label, type, core,
codelist_code, codelist_submission_values, described_value_domain,
value_list. model_sdtm is standard, version, class, dataset,
order, variable, label, type, role, described_value_domain,
variables_qualified, usage_restrictions, variable_code. The old
source (now standard), dataset and category (ADaM; now structure
and variable_set), codelist (now codelist_code, a C-code rather than a
submission value), length, and notes columns are gone. The SDTM model
moved out of ig_sdtm into model_sdtm.
ig_sources lists the exports each table was built from: file name, the
export's version string, the parsed standard and version, the dataset it was
loaded into, its row count, and its MD5 checksum.
cdash_model (CDASH model 1.0 to 1.3, 1,138 rows), ig_cdash (CDASHIG
1.1 and 2.0 to 2.3, 4,483 rows), and qrs_supplement (75 items of nine
questionnaire, rating-scale, and functional-test supplements, 9 instrument
versions), from 18 more CDISC Library exports. The CDASH tables carry the
collection wording (question_text, prompt) and the SDTM target of each
field, but not the definitions, CRF completion instructions, mapping
instructions, or implementation notes. qrs_supplement carries the
--TEST/--TESTCD names and codes of each item but not the item text. The
QRS exports have no version column, so the instrument and version are read
from the file name.get_cdash(standard, version, domain) for the CDASH tables, with the
same conventions as get_ig(). It is a separate function because the CDASH
tables describe data collection, not a dataset's structure, and so have
different columns. The QRS supplements are reached with
get_dataset("qrs_supplement").get_ig(standard, version, domain). standard now names one
of 15 standards ("SDTM", "SDTMIG", "SDTMIG-AP", "SDTMIG-MD",
"SENDIG", "SENDIG-AR", "SENDIG-DART", "SENDIG-GeneTox", "ADaMIG",
"ADaMIG-MD", "ADaMIG-NCA", "ADaM-ADAE", "ADaM-BDS-TTE",
"ADaM-OCCDS", "ADaM-popPK"). The default is "SDTMIG", and a NULL
version now returns that standard's newest version (compared numerically)
where it used to return every version. The lower-case "sdtm" and "adam"
are kept as aliases for "SDTMIG" and "ADaMIG"; capital "SDTM" is the
model. domain filters by domain (SDTMIG), class or dataset (SDTM model),
or structure (ADaM, where "BDS" and "ADSL" are accepted). An unknown
standard, version, or domain is a classed error
(cdiscdata_error_ig_standard_unavailable,
cdiscdata_error_ig_version_unavailable,
cdiscdata_error_ig_domain_unavailable) listing what is available.get_dataset("ig_sdtm") and get_dataset("ig_adam"). They
silently returned NULL. They now return the table, whole or restricted to
the rows of one version string, and get_dataset("model_sdtm"),
get_dataset("cdash_model"), get_dataset("ig_cdash") and
get_dataset("qrs_supplement") work the same way. list_datasets() reports
the new tables with types "Model", "CDASH", and "QRS", and counts
versions per standard.build_domain_spec() takes a standard (any SDTM-side standard that
defines the domain, e.g. "SENDIG" for PP) and an extension for ADPP:
"ADaMIG-NCA" (or "NCA"), "ADaM-popPK", or "ADaM-BDS-TTE" is unioned
onto the BDS variables, as adsl = TRUE unions ADSL, with extension_version
to pick its version. Unlike the ADSL and PP unions, the extension keeps its
own Core designations: a variable the BDS already defines takes the
extension's Core (DOSEA, DOSEU, and AVISIT become required in
ADaMIG-NCA) and is marked with the extension's name in source. Existing
calls keep working.build_domain_spec("ADPP", extension = "NCA") has 388 variables. sdtm_domain = "PP" adds 24 variables
(22 with sdtmig_version = "3.3").length column is kept but is always NA: the exports carry no
length, which is a sponsor choice. codelist_id takes the first C-code of an
IG codelist list, kept only when that codelist is in the CT release used.test-ig_integrity.R and test-cdash_integrity.R: every
export is loaded exactly once and with as many rows as its file has; every
row is unique on its key; no name or label is NA or contains a newline;
no text field has stray whitespace; no value is long enough to be prose;
type and core hold only published values; and no CSV is tracked under
data-raw. The version-string parser is tested on all 43 version strings
and on the nine QRS file names.helper-ig-exceptions.R: 22 in the SDTM and
ADaM tables (SDTMIG 3.2 and SDTMIG-MD 1.0 long forms that later versions
abbreviate, the SDTM model --TESTCD before 1.7, and ADaMIG PBCHGCyN), 6
in the CDASH model, and 71 in CDASHIG 2.0. Both directions are checked, so a
new over-length label fails and so does an exception that is no longer
true. CDASHIG 1.1 publishes no variable labels at all (NA). Five SDTMIG and
SDTMIG-MD rows have no type or core in the guide and are listed the same way.
Shortening a label to fit an XPT file is for whoever writes the dataset, not
for this package.data-raw/utils_ig.R is tested on synthetic exports written to a
temporary directory, including that no prose column of any export layout
reaches the data.EPOCH,
TAETORD and PPDY first appear in 3.3, and PPANMETH and PPTPTREF in
3.4. PPDTC, not PPPDTC, is the published name, and nca.reporter's
PTAETORD, PPPDTC and PPPDY are not published SDTMIG variables.PPSTRESC is published as "Character Result/Finding in
Standard Format" (43 characters; 3.3 abbreviates it). It is now carried as
published and is one of the exceptions above, where an earlier development
version had abbreviated it.CDISC_SOURCES_DIR (default ../cdisc-sources) by data-raw/build_ig.R,
which stops with a message listing every expected file if any is missing
and refuses a QRS supplement it does not list. data-raw/README.md says how
to obtain them. The Rsdtm copies in data-raw/ig_source/ and the scripts
that read them are removed.get_ig() and build_domain_spec() raise is now
classed (e.g. cdiscdata_error_ig_version_unavailable,
cdiscdata_error_no_ig_variables, cdiscdata_warning_adsl_ignored), so
they can be caught or asserted on by class rather than by matching
message text. Implemented with a small internal .cdiscdata_abort()/
.cdiscdata_warn() helper rather than a new dependency (e.g. rlang), to
keep the package's zero-runtime-dependency design.build_domain_spec() is now at 100% line coverage; two defensive checks
(an SDTMIG/ADaMIG version with no rows for the requested domain/dataset -
not reachable via the public API with the currently bundled ig_sdtm/
ig_adam, since every version there has PP/SUPPQUAL/BDS rows) are
exercised directly via mocking get_ig().data-raw/utils_nci.R) that had silently left
codelist_name NA for every row of ct_sdtm/ct_adam for every NCI
release from 2012 onward (codelist_name and codelist_code are used to
look up a codelist by name, e.g. by get_ig()/build_domain_spec(), so
this previously made resolving PKPARMCD/PKPARM/PKUNIT - or any other
codelist by name - unreliable). The header-row detection this relied on
assumed the NCI source file repeats a codelist's own C-code in both its
"Code" and "Codelist Code" columns; from 2012 on, NCI instead leaves
"Codelist Code" blank on that row, which the previous logic never
matched. All bundled historical releases were re-parsed from scratch with
the fix (re-downloading the ~110 archived releases involved, now cached
as raw text going forward so a future parser fix would not need to). A
handful of older (2007-2010, plus one 2017) archival releases have
further, rarer source-data quirks this could not fully resolve; the
current release is verified clean, and the historical gap is bounded by
tests/testthat/test-data_integrity.R rather than silently tolerated.list_archive_dates(), which had been silently returning zero
dates: NCI rebuilt evs.nci.nih.gov as a JavaScript single-page app at some
point in 2024-2025, so the Archive/ directory URL this scraped for file
names now serves that app's empty HTML shell instead of a plain listing.
It now calls the JSON API the app itself uses
(GET /ftp1/folder?folder=<path>) instead; see the comment above
list_archive_dates() in data-raw/utils_nci.R for that API's one
limitation (no working pagination past 1000 entries) and why it does not
affect finding every release date in practice. fetch_current_release_date()
(previously reading NCI's Publication Date Stamp file, which changed
format at least twice - a bare date, then "SDTM Terminology YYYY-MM-DD",
then, as of 2026, a small table - and 403'd from GitHub Actions in
between) was replaced with a derivation from this same, now-working
archive listing (origin/main PR "fix/nci-stamp-403-fallback", merged
into this branch).available_ct_versions() - SDTM CT
appeared to be missing the 2024-06, 2024-12, 2025-06, 2025-12, and
2026-06 quarterly releases. Verified directly against NCI's own file
listing (not assumed): none of these five releases exist for either
SDTM or ADaM - NCI shifted SDTM CT from quarterly to semi-annual
(March/September) releases starting in 2024, and ADaM CT has never been
reliably quarterly (gaps of 266-448 days recur from 2017 on, long before
2024). There was nothing to backfill. Added
tests/testthat/test-data_integrity.R gap tests calibrated to each
type's actual verified history (200 days for SDTM, 500 days for ADaM;
not a single ~120-day bound, which would flag the genuine 2024-on
semi-annual gaps as failures) plus a freshness check, so a release that
is actually skipped or a fetch workflow that silently stops running
would still fail loudly.PKPARMCD (C85839), PKPARM (C85493), and PKUNIT (C85494)
are present in the 2026-09-25 release and returned by get_ct("sdtm").get_ct(), get_dataset(), list_datasets(),
cdiscdata_versions(), and available_ct_versions() to work via
cdiscdata:: alone, without library(cdiscdata) first. Lazy-loaded
package data (ct_sdtm, ct_adam, ig_sdtm, ig_adam,
datasets_catalogue) is only wired into the search path when the package
is attached; loading just the namespace (as :: does) left an
unqualified reference to that data unresolved, even from inside the
package's own functions - e.g. cdiscdata::get_ct("sdtm") without a
prior library() call errored with object 'datasets_catalogue' not found. Fixed via an internal .pkg_data() helper that loads a dataset
explicitly with utils::data(), independent of attach state. Verified by
a dedicated test (tests/testthat/test-attach.R) that builds and
installs the package into a fresh library and calls it via callr::r()
in a brand-new subprocess with no library() call.ig_sdtm: SDTM Model Findings general-observation-class variables
(versions 1.4-1.7), plus the SDTMIG PP domain and the generic SUPP--
qualifier structure (version 3.2 only - see
data-raw/ig_source/README.md for why no newer SDTMIG version's PP/SUPP--
tables were available to source).ig_adam: ADaMIG ADSL (subject-level) and BDS (Basic Data
Structure, used by ADPP) variable tables, for versions 1.0, 1.1, and 1.2.get_ig(standard, version), mirroring get_ct().build_domain_spec(domain, ig_version, ct_version, adsl), returning
a ready-to-use variable spec (name, label, type, length, core, order,
source, codelist id) for "PP", "SUPPPP" (via the generic SUPP--
structure), or "ADPP" (via the generic BDS structure, joined against CT
for codelist ids). For "ADPP", adsl = TRUE (the default) also unions
in the ADaMIG ADSL variables - a real ADPP carries ADSL's subject-level
variables alongside its own BDS variables - marked source = "ADSL" and
core = "Perm" (ADSL's own Core reflects requirements for ADSL itself,
not for merging a variable into ADPP, which is always optional); a
variable defined by both tables (e.g. STUDYID, USUBJID) keeps its BDS
version rather than being duplicated. adsl = FALSE returns the BDS
variables alone, as before. Neither table carries PP's own variables
(PPTESTCD and the rest) forward into ADPP; that remains a downstream
derivation choice, not IG metadata this function sources.get_ig()/ig_sdtm's SDTMIG-3.2-only coverage of the PP domain and
SUPP-- structure is now called out explicitly in get_ig()'s
documentation, including the specific known gaps versus a newer SDTMIG
(PPANMETH, EPOCH, PTAETORD not yet added; SDTMIG 3.2 still has
PPDTC, not the later PPPDTC rename).data-raw/ig_source/README.md. This supersedes the package's original
plan to leave all IG metadata to a separate cdiscapi package; the
README has been updated accordingly.cdiscdata.get_ct(), get_dataset(), available_ct_versions(),
schema_path(), stylesheet_path(), list_datasets(),
cdiscdata_versions().