# artoo **artoo** is a lightweight, lossless, CDISC-native reader and writer for clinical-trial datasets. It moves data between **SAS XPORT (XPT)**, **CDISC Dataset-JSON v1.1**, **NDJSON**, **Apache Parquet**, and **RDS** through one canonical metadata model, so converting between any two is lossless *by construction* — not by best effort. ## Installation Install the released version from CRAN: ``` r install.packages("artoo") ``` Or the development version from GitHub: ``` r # install.packages("pak") pak::pak("vthanik/artoo") # or remotes::install_github("vthanik/artoo") ``` ## Quick start A spec describes the dataset; [`apply_spec()`](https://vthanik.github.io/artoo/reference/apply_spec.md) conforms a raw frame to it; the writers carry every piece of metadata to disk — one pipeable chain: ``` r library(artoo) # Coerce, order, sort, stamp metadata, then write. The writers return their # input invisibly, so one conformed frame fans out to every deliverable. path <- tempfile(fileext = ".xpt") adsl <- cdisc_adsl |> apply_spec(adam_spec, "ADSL") |> write_xpt(path) #> 6 variables the spec declares are absent from the data (not added): `TRTDURD`, #> `DISONDT`, `EOSSTT`, `DCSREAS`, `EOSDISP`, and `MMS1TSBL`. #> ℹ See `conformance(x)` for the findings. # Read it back — labels, formats, types, and record count intact. get_meta(read_xpt(path))@dataset$records #> [1] 60 ``` [`columns()`](https://vthanik.github.io/artoo/reference/columns.md) is the quick look a SAS programmer expects from `PROC CONTENTS`, on a conformed frame or straight off a file: ``` r columns(adsl) #> ADSL -- 48 variables, 60 obs #> # Variable Type Len Format Label Key #> 1 STUDYID Char 12 Study Identifier 1 #> 2 USUBJID Char 11 Unique Subject Identifier 2 #> 3 SUBJID Char 4 Subject Identifier for the Study #> 4 SITEID Char 3 Study Site Identifier #> 5 SITEGR1 Char 3 Pooled Site Group 1 #> 6 ARM Char 20 Description of Planned Arm #> 7 TRT01P Char 20 Planned Treatment for Period 01 #> 8 TRT01PN Num Planned Treatment for Period 01 (N) #> 9 TRT01A Char 20 Actual Treatment for Period 01 #> 10 TRT01AN Num Actual Treatment for Period 01 (N) #> 11 TRTSDT Num DATE9. Date of First Exposure to Treatment #> 12 TRTEDT Num DATE9. Date of Last Exposure to Treatment #> 13 AVGDD Num 5.1 Avg Daily Dose (as planned) #> 14 CUMDOSE Num 8.1 Cumulative Dose (as planned) #> 15 AGE Num Age #> 16 AGEGR1 Char 5 Pooled Age Group 1 #> 17 AGEGR1N Num Pooled Age Group 1 (N) #> 18 AGEU Char 5 Age Units #> 19 RACE Char 32 Race #> 20 RACEN Num Race (N) #> 21 SEX Char 1 Sex #> 22 ETHNIC Char 22 Ethnicity #> 23 SAFFL Char 1 Safety Population Flag #> 24 ITTFL Char 1 Intent-To-Treat Population Flag #> 25 EFFFL Char 1 Efficacy Population Flag #> 26 COMP8FL Char 1 Completers of Week 8 Population Flag #> 27 COMP16FL Char 1 Completers of Week 16 Population Flag #> 28 COMP24FL Char 1 Completers of Week 24 Population Flag #> 29 DISCONFL Char 1 Subject Discontinued Study Flag #> 30 DSRAEFL Char 1 Subject Discontinued due to AE Flag #> 31 DTHFL Char 1 Subject Death Flag #> 32 BMIBL Num 5.1 Baseline BMI (kg/m^2) #> 33 BMIBLGR1 Char 6 Pooled Baseline BMI Group 1 #> 34 HEIGHTBL Num 6.1 Baseline Height (cm) #> 35 WEIGHTBL Num 6.1 Baseline Weight (kg) #> 36 EDUCLVL Num Years of Education #> 37 DURDIS Num 6.1 Duration of Disease (Months) #> 38 DURDSGR1 Char 4 Pooled Disease Duration Group 1 #> 39 VISIT1DT Num DATE9. Date of Visit 1 #> 40 RFSTDTC Char 10 Subject Reference Start Date/Time #> 41 RFENDTC Char 10 Subject Reference End Date/Time #> 42 VISNUMEN Num End of Trt Visit (Vis 12 or Early Term.) #> 43 RFENDT Num Date of Discontinuation/Completion #> 44 TRTDUR Num #> 45 DISONSDT Num DATE9. #> 46 DCDECOD Char 27 #> 47 DCREASCD Char 18 #> 48 MMSETOT Num ``` ## Why artoo? - **Lossless by construction.** One canonical metadata model carries labels, CDISC data types, lengths, SAS display formats, controlled-terminology references, and sort keys identically across every format, so any-to-any conversion preserves them — not by best effort, by design. - **Lossless or loud.** A coercion that would truncate or an unencodable byte aborts with a classed condition before it can damage data; there is no silent-truncation path. - **Pure R and lightweight.** No external SAS or Java runtime, and no heavy I/O dependency. - **CDISC-native.** Types, dates and `--DTC` text, and codelists follow the Dataset-JSON v1.1 vocabulary; specs read from Define-XML, Pinnacle 21 workbooks, or native JSON. ## Where artoo fits artoo is the carrier between the formats a clinical-trial dataset travels in: the XPORT a regulator expects, the Dataset-JSON modern CDISC exchange uses, the Parquet an analytics stack reads, and an R-native checkpoint. Reach for it whenever a dataset must change formats without losing the metadata that makes it submission-ready — labels, types, lengths, display formats, codelists, and keys — and you want that guarantee enforced rather than hoped for. It is a focused reader/writer, not a validation suite or a table renderer. ## Supported formats | Format | Reader | Writer | Use | |----|----|----|----| | SAS XPORT (XPT) | [`read_xpt()`](https://vthanik.github.io/artoo/reference/read_xpt.md) | [`write_xpt()`](https://vthanik.github.io/artoo/reference/write_xpt.md) | FDA / PMDA submission | | CDISC Dataset-JSON | [`read_json()`](https://vthanik.github.io/artoo/reference/read_json.md) | [`write_json()`](https://vthanik.github.io/artoo/reference/write_json.md) | Modern CDISC interchange | | NDJSON | [`read_ndjson()`](https://vthanik.github.io/artoo/reference/read_ndjson.md) | [`write_ndjson()`](https://vthanik.github.io/artoo/reference/write_ndjson.md) | Streaming Dataset-JSON | | Apache Parquet | [`read_parquet()`](https://vthanik.github.io/artoo/reference/read_parquet.md) | [`write_parquet()`](https://vthanik.github.io/artoo/reference/write_parquet.md) | Analytics, columnar store | | RDS | [`read_rds()`](https://vthanik.github.io/artoo/reference/read_rds.md) | [`write_rds()`](https://vthanik.github.io/artoo/reference/write_rds.md) | Fast R-native storage | The generic [`read_dataset()`](https://vthanik.github.io/artoo/reference/read_dataset.md) / [`write_dataset()`](https://vthanik.github.io/artoo/reference/write_dataset.md) dispatch on the file extension; every reader supports partial reads via `col_select` and `n_max`. Partial ISO 8601 dates are first-class: a character `--DTC` column typed `date` writes to XPT as ISO text — `"1951-12"` survives byte for byte — while `targetDataType = "integer"` drives the ADaM numeric-date convention. SAS `TIME` values arrive as `hms` (seconds since midnight), and `>24h`, negative, and fractional times round-trip every format. ## Documentation - [Get started](https://vthanik.github.io/artoo/articles/artoo.html) — the whole round-trip, start to finish, on bundled data. - [Specifications](https://vthanik.github.io/artoo/articles/specs.html) — read, inspect, and repair a spec. - [Conform & validate](https://vthanik.github.io/artoo/articles/conform.html) — [`apply_spec()`](https://vthanik.github.io/artoo/reference/apply_spec.md) and every conformance finding. - [Formats & lossless conversion](https://vthanik.github.io/artoo/articles/convert.html) — any-to-any round trips and qualification evidence. - [Recipes](https://vthanik.github.io/artoo/articles/recipes.html) — end-to-end ADaM and SDTM builds, dates, and codelists, rendered live. - [Reference](https://vthanik.github.io/artoo/reference/index.html) — every function, grouped by stage. ## License MIT © Vignesh Thanikachalam # Package index ## Specs Build a artoo_spec — the canonical CDISC-shaped description of your datasets, one CDISC standard each — or read one from native JSON, a Pinnacle 21 workbook, or Define-XML, and write it back out. Amend it in R when the data disagrees, then read any slot back with the spec\_\* accessors. - [`artoo_spec()`](https://vthanik.github.io/artoo/reference/artoo_spec.md) : Construct a CDISC specification - [`read_spec()`](https://vthanik.github.io/artoo/reference/read_spec.md) : Read a specification from JSON, Excel, or Define-XML - [`write_spec()`](https://vthanik.github.io/artoo/reference/write_spec.md) : Write a specification to native JSON or a P21 Excel workbook - [`set_type()`](https://vthanik.github.io/artoo/reference/set_type.md) : Override a variable's dataType in a spec - [`repair_spec()`](https://vthanik.github.io/artoo/reference/repair_spec.md) : Repair a spec from its conformance findings - [`is_artoo_spec()`](https://vthanik.github.io/artoo/reference/is_artoo_spec.md) : Test for a artoo_spec object - [`spec_standard()`](https://vthanik.github.io/artoo/reference/spec_standard.md) : The CDISC standard a spec implements - [`spec_study()`](https://vthanik.github.io/artoo/reference/spec_study.md) : Study-level metadata - [`spec_datasets()`](https://vthanik.github.io/artoo/reference/spec_datasets.md) : Dataset names in a spec - [`spec_variables()`](https://vthanik.github.io/artoo/reference/spec_variables.md) : Variables in a spec - [`spec_codelists()`](https://vthanik.github.io/artoo/reference/spec_codelists.md) : Codelist terms - [`spec_keys()`](https://vthanik.github.io/artoo/reference/spec_keys.md) : Sort keys for a dataset - [`spec_methods()`](https://vthanik.github.io/artoo/reference/spec_methods.md) : Derivation methods in a spec - [`spec_comments()`](https://vthanik.github.io/artoo/reference/spec_comments.md) : Comment definitions in a spec - [`spec_documents()`](https://vthanik.github.io/artoo/reference/spec_documents.md) : Document references in a spec ## Conform & validate Apply the spec to a raw frame — coerce, order, sort, stamp metadata — decode single variables through its codelists, and read or replace the artoo_meta the result carries. Then surface every conformance finding for one dataset or a whole study, plus the spec’s own integrity, with the control object that scopes both. - [`apply_spec()`](https://vthanik.github.io/artoo/reference/apply_spec.md) : Conform a data frame to its spec - [`decode_column()`](https://vthanik.github.io/artoo/reference/decode_column.md) : Derive or translate a variable through its codelist - [`get_meta()`](https://vthanik.github.io/artoo/reference/get_meta.md) : Read the metadata a dataset carries - [`set_meta()`](https://vthanik.github.io/artoo/reference/set_meta.md) : Attach metadata to a dataset - [`sync_meta()`](https://vthanik.github.io/artoo/reference/sync_meta.md) : Re-align metadata with a transformed data frame - [`is_artoo_meta()`](https://vthanik.github.io/artoo/reference/is_artoo_meta.md) : Test for a artoo_meta object - [`check_spec()`](https://vthanik.github.io/artoo/reference/check_spec.md) : Check a dataset against its spec - [`check_study()`](https://vthanik.github.io/artoo/reference/check_study.md) : Check a whole study against its spec - [`validate_spec()`](https://vthanik.github.io/artoo/reference/validate_spec.md) : Validate a specification for submission-readiness - [`conformance()`](https://vthanik.github.io/artoo/reference/conformance.md) : Read the conformance findings a dataset carries - [`artoo_checks()`](https://vthanik.github.io/artoo/reference/artoo_checks.md) : Control which conformance checks run - [`is_artoo_checks()`](https://vthanik.github.io/artoo/reference/is_artoo_checks.md) : Test for a artoo_checks control ## Read and write Lossless dataset I/O across every supported format — generic dispatch on the file extension, plus a short wrapper per format — and the SAS-viewer-style variable pane and dataset inventory for any file. - [`read_dataset()`](https://vthanik.github.io/artoo/reference/read_dataset.md) : Read a dataset from any supported format - [`write_dataset()`](https://vthanik.github.io/artoo/reference/write_dataset.md) : Write a dataset to any supported format - [`read_xpt()`](https://vthanik.github.io/artoo/reference/read_xpt.md) : Read a dataset from SAS XPORT - [`write_xpt()`](https://vthanik.github.io/artoo/reference/write_xpt.md) : Write a dataset to SAS XPORT - [`read_json()`](https://vthanik.github.io/artoo/reference/read_json.md) : Read a dataset from CDISC Dataset-JSON - [`write_json()`](https://vthanik.github.io/artoo/reference/write_json.md) : Write a dataset to CDISC Dataset-JSON - [`read_ndjson()`](https://vthanik.github.io/artoo/reference/read_ndjson.md) : Read a dataset from CDISC Dataset-JSON NDJSON - [`write_ndjson()`](https://vthanik.github.io/artoo/reference/write_ndjson.md) : Write a dataset to CDISC Dataset-JSON NDJSON - [`read_parquet()`](https://vthanik.github.io/artoo/reference/read_parquet.md) : Read a dataset from Apache Parquet - [`write_parquet()`](https://vthanik.github.io/artoo/reference/write_parquet.md) : Write a dataset to Apache Parquet - [`read_rds()`](https://vthanik.github.io/artoo/reference/read_rds.md) : Read a dataset from rds - [`write_rds()`](https://vthanik.github.io/artoo/reference/write_rds.md) : Write a dataset to rds - [`columns()`](https://vthanik.github.io/artoo/reference/columns.md) : View a dataset's variable attributes, SAS-style - [`members()`](https://vthanik.github.io/artoo/reference/members.md) : List the datasets in a file or directory - [`xpt_members()`](https://vthanik.github.io/artoo/reference/xpt_members.md) : List the members of a SAS XPORT transport file ## Reference data Reference tables for the codecs this session can read and write and the encoding names R, SAS, and Python share, plus the bundled CDISC pilot specs, metadata tables, and datasets used throughout the docs — all rebuilt from public sources. - [`artoo_formats()`](https://vthanik.github.io/artoo/reference/artoo_formats.md) : Report which formats are available - [`artoo_encodings()`](https://vthanik.github.io/artoo/reference/artoo_encodings.md) : Encodings for clinical datasets, across R, SAS, and Python - [`adam_spec`](https://vthanik.github.io/artoo/reference/cdisc_specs.md) [`sdtm_spec`](https://vthanik.github.io/artoo/reference/cdisc_specs.md) : Bundled CDISC specifications (ADaM and SDTM) - [`cdisc_adam_datasets`](https://vthanik.github.io/artoo/reference/cdisc_spec.md) [`cdisc_adam_variables`](https://vthanik.github.io/artoo/reference/cdisc_spec.md) [`cdisc_sdtm_datasets`](https://vthanik.github.io/artoo/reference/cdisc_spec.md) [`cdisc_sdtm_variables`](https://vthanik.github.io/artoo/reference/cdisc_spec.md) [`cdisc_codelists`](https://vthanik.github.io/artoo/reference/cdisc_spec.md) : CDISC demo specification tables (one standard per pair) - [`cdisc_adsl`](https://vthanik.github.io/artoo/reference/cdisc_adsl.md) : Demo subject-level analysis dataset (ADaM ADSL) - [`cdisc_adae`](https://vthanik.github.io/artoo/reference/cdisc_adae.md) : Demo adverse events analysis dataset (ADaM ADAE) - [`cdisc_dm`](https://vthanik.github.io/artoo/reference/cdisc_dm.md) : Demo demographics dataset (SDTM DM) - [`cdisc_vs`](https://vthanik.github.io/artoo/reference/cdisc_vs.md) : Demo vital signs dataset (SDTM VS) - [`cdisc_ts`](https://vthanik.github.io/artoo/reference/cdisc_ts.md) : Demo trial summary dataset (SDTM TS) - [`cdisc_suppdm`](https://vthanik.github.io/artoo/reference/cdisc_suppdm.md) : Demo supplemental qualifiers dataset (SDTM SUPPDM) # Articles ### Articles - [Specifications](https://vthanik.github.io/artoo/articles/specs.md): - [Conform & validate](https://vthanik.github.io/artoo/articles/conform.md): - [Formats & lossless conversion](https://vthanik.github.io/artoo/articles/convert.md): - [Migrating clinical data from WLATIN1 to UTF-8](https://vthanik.github.io/artoo/articles/migrate-encoding.md): - [Recipes](https://vthanik.github.io/artoo/articles/recipes.md):