siera 0.5.6
CRAN release: 2026-06-17
- Fixed analyses using the wrong population.
readARS()used to apply only the first analysis’s analysis set to a whole output, and picked the dataset to merge the population onto from the third analysis. Now every analysis uses the population its ownanalysisSetIddeclares, and the merge dataset comes from the analysis’s own metadata. In the eTFL disposition table (fda-ds-t04), the per-protocol row now reports 81 / 74 / 79 subjects instead of the All Subjects counts 84 / 84 / 86. Outputs with fewer than three analyses (e.g. a big N plus one content analysis), which used to stop with “invalid ‘replacement’ argument”, now generate normally. Big N analyses still count every subject in the population, wherever they sit in the output, including a second big N for a Total column. Generated scripts change in two visible ways. In outputs drawn only from ADSL, analyses now start fromdf_poptotrather thandf_pop(identical data, so the results are unchanged). An output with several analysis sets names each population after its set (e.g.df_poptot__AnalysisSet_07), and method templates that refer todf_poptot, such as risk differences, use their own analysis’s population (#197). - Fixed
readARS()aborting with “object ‘condition_dataset’ not found” when an analysis set has nocondition, such as an “All Subjects” population. A set without a condition is valid ARS and is now read as the whole dataset, unfiltered: ADSL when any of the set’s analyses uses ADSL (otherwise the first analysis’s dataset, with a warning if it must be merged onto other datasets), merged onto content datasets like any other population. Analysis sets defined by acompoundExpressionare still not supported and keep their existing warning (#200). - Added CDISC Dataset-JSON (v1.1) export of generated ARDs.
readARS(..., output_format = "datasetjson")appends a section to each generatedARD_<OutputId>.Rscript that, when the script runs, writes the ARD toARD_<OutputId>.jsonbeside the script.cardslist-columns are flattened (statto numeric,warning/errorto text) and each column gets a variable label from a built-in dictionary of siera andcardscolumns, falling back to the column name. The optionaldatasetjsonpackage must be installed where the script runs; without it the export is skipped with a message (#160). A newcolumn_labelsargument lets you supply your own labels as a named character vector, e.g.c(TRT01A = "Actual Treatment"); these take precedence over the built-in labels, and a name that matches no ARD column triggers a warning when the script runs (#165). A new vignette, “Exporting ARDs as Dataset-JSON”, walks through the feature (#164). - Added formatted results to generated ARDs. Each ARD row now carries
res(the raw statistic flattened to numeric),pattern(the ARSresultPatternfor the row’s operation) anddisp(the printable, table-ready formatted value, e.g.(N=86), honouring the pattern’s decimal count and prefix/suffix).cardsproportions (stat_name == "p") are multiplied by 100 before formatting, matching the percentage semantics of result patterns. Rounding follows the clinical-reporting norm of rounding halves away from zero (the SASROUND()convention, e.g.1.369becomes1.4and2.5becomes3) rather than R’s default round-half-to-even, sodispaligns with SAS-generated reference tables; the rawresvalue is left unrounded. Thecards-internalfmt_fun/fmt_fnformat-function list-columns, which previously surfaced as unprintable values, are dropped from the final ARD (#167). - Added support for resolving a method’s code template from an external reference instead of inline ARS metadata. When a method’s
codeTemplatecarries adocumentRef(rather than inlinecode),readARS()now follows the ARSreferenceDocumentschain to load the template - and, where the method declares none inline, its parameters - from either a siera method manifest (a.jsonsuperset ofmethod.jsoncarryingtemplateCode+parameters, with a method selected by apageRefsnamed destination = the methodid) or a bare.R/.txtcode file. Resolution is transparent: adocumentRefARS generates the same script as its inline equivalent. The whole method library now also ships as one referenceable catalog,inst/method-library/method-library.json, and new bundled examples (exampleARS_5_documentref.json/.xlsx+exampleARS_methods.json) demonstrate the mechanism. v1 resolves local paths only (relative to the ARS file, or absolute); remote URLs are rejected. JSON and XLSX inputs are supported with parity (via the XLSXReferenceDocumentsandAnalysisMethodDocumentRefssheets) (#175). - Added
method_library(), an exported accessor that lists the bundled analysis-method templates and resolves a method’s files on disk (parallel toARS_example()). - Added a plain-text, testable analysis-method template library under
inst/method-library/(onemethod.json+template.Rper method, plus a reconciledconstructs.jsonvalueSource registry and a generatedMETHODS.mdcatalog). This becomes the reviewable, diff-able source of truth for the code-template recipes that drive ARD generation; its methodids are intended as stable keys an ARS file can reference. A contract test validates every recipe on each run (templates parse, only supported valueSources are referenced, no orphan tokens, no duplicatedcase_whenmappings, and the human-readable catalog stays in sync). Introduced an internal.supported_value_sources()helper as the declared valueSource contract. The legacyinst/extdata/R_siera_codes.xlsxandcards_constructs.xlsxare left untouched (#173). - Added support for per-category risk differences. A new method template computes one risk difference and 95% confidence interval for each data-driven inner category (e.g. one per preferred term or system organ class) by looping over the second grouping and calling
cardx::ard_stats_prop_test()within each, instead of collapsing the analysis to a single overall risk difference (#157). - Added per-category risk differences for pre-defined (non-data-driven) inner groupings. A new method template,
risk_difference_per_predefined_group, honours the groups declared in the ARS metadata instead of looping observed data values: every defined group is emitted - a group whose condition matches no events yields a risk difference of0with a[0, 0]confidence interval - and data values matching no defined group are excluded. It is driven by a newAG_var2_group_valuesvalueSource that resolves the second grouping’s group condition values, in group order (single-valueEQconditions; other comparators are skipped with a warning). Validated on the eTFL “Overview of Adverse Events” table (one risk difference per action taken and per severity) against an independentstats::prop.test()recomputation; the published reference matches on category shape and empty groups, but its non-zero values were found to be computed from only the first adverse-event record per subject rather than from all qualifying events, so they are not used as the value oracle (#171). - Added categorical
n (%)summaries that aggregate per pre-defined group condition. A new method template,categorical_summary_per_predefined_group, reports the groups an ARSanalysisGroupingdeclares rather than the values the data happens to contain: every defined group is emitted for every treatment arm - a group no subject reaches is reported as0 (0.0)instead of being dropped - and data values satisfying no defined group are excluded instead of appearing as rows with missing group identifiers. Because it matches on the group’s condition, a group defined by a multi-valueINcondition is now one row rather than being unrepresentable. It is driven by two new valueSources,AG_var2_group_conditionsandAG_var2_group_levels(EQandINconditions; other comparators are skipped with a warning). Use it where the inner grouping isdataDriven: false;categorical_summaryremains correct for data-driven groupings, where the data is the category list. Validated on the eTFL “Overview of Adverse Events” table (subjects by treatment and action taken) against an independent distinct-subject recomputation, matching the published reference’s row set exactly (#187, and the pre-defined half of #100). - Added a chi-square test over pre-defined group conditions. A new method template,
chisq_per_predefined_group, compares treatment arms over the groups an ARSanalysisGroupingdefines rather than over the raw values of the variable, so the p-value belongs to the same categories then (%)rows ofcategorical_summary_per_predefined_groupreport. A group defined by a multi-valueINcondition is one category - e.g. age< 65vs>= 65(AGEGR1IN ("65-80", ">80")) gives p = 0.4239, where testing the three AGEGR1 values gives 0.1439 - and values satisfying no defined group are excluded. It reuses theAG_var2_group_conditionsvalueSource; for groupings whose groups are one-to-one with data values it equalschisq(#215). - Added per-(category x category) risk differences for analyses with two data-driven inner groupings, such as one risk difference per system organ class and preferred term combination. A new method template,
risk_difference_per_group_pair, loops the distinct combinations of the second and third grouping variables observed in the analysis subset, computes each risk difference withcardx::ard_stats_prop_test(), and stamps both category levels onto the ARD rows. It reuses the existingAG_var3valueSource, so no change toreadARS()was required. Validated on the eTFL “Adverse Events by System Organ Class and Preferred Term” table against an independentstats::prop.test()recomputation over every observed combination (#172). - Fixed data subsets whose single top-level condition is a multi-value
INorNOTINsilently filtering on the wrong values when read from JSON. The value list was collapsed into one string, so anINsubset selected no records and aNOTINsubset excluded none (e.g. “AEs leading to dose modification”,AEACN NOTIN ["NOT APPLICABLE", "DOSE NOT CHANGED"], counted every subject with any AE). The JSON path now matches the XLSX path, which was unaffected (#211). - Fixed multi-value
INandNOTINconditions read from xlsx ARS files silently dropping records. A cell such asPOSSIBLE | PROBABLE(the" | "separator used by TFL Designer and CDISC’sexcel2ars.py) was split into"POSSIBLE "(with a trailing blank) and"PROBABLE", so every value but the last matched nothing. This affected data subsets and pre-defined group conditions: in the bundled Common Safety Displays example, subjects with a drug-related treatment-emergent adverse event were counted as 23/50/49 instead of 43/70/72. Each value is now trimmed; JSON input was not affected (#213). - Fixed
readARS()aborting on xlsx ARS files whose methods carry documentation references. TheAnalysisMethodDocumentRefssheet holds a method’s documentation references (e.g. a SAP section) as well as its code-template reference, and every row was resolved as a code template - so a method resolved from a method library failed with “location does not exist: ./sap.pdf” whenever its documentation row came first. Rows withreferenceTypeDocumentationare now ignored by code generation (#214). - Fixed
readARS()failing on ARS JSON that writes some condition values as a single value ("value": "Y") and others as an array ("value": ["A", "B"]). jsonlite read the two forms into different column types and combining the data subsets aborted; both forms are now read, whichever tool wrote the file (#217). - Fixed
readARS()aborting on ARS JSON that writes an empty array for an operation’sreferencedOperationRelationshipsor an analysis’sreferencedAnalysisOperations. Both are valid ARS, and[]is now read as “no relationships”, exactly like an absent field (#230). - Changed the bundled demo reporting event
Common_Safety_Displays_cards.json(used by the README, the vignettes andARD_script_example("ARD_Out14-1-1.R")) so its demographics output follows its own ARS groupings. The age group, sex, ethnicity and race n (%) analyses use a new method,Mth01_CatVar_Summ_ByPreGrp, with thecategorical_summary_per_predefined_grouptemplate, and the chi-square tests usechisq_per_predefined_group. The ARD now reports the defined age groups< 65and>= 65(AGEGR1IN65-80,>80: 72 / 73 / 76 subjects, previously the threeAGEGR1categories), all nine defined race groups (zero-filled where no subject has that race, previously only the three observed), a group id on every row, and the age-group chi-square over the two defined groups (p = 0.4239, previously 0.1439 over the three categories). The deprecated xlsx twin is unchanged (#216). - Changed the categorical n (%) template (
categorical_summaryin the method library, and the demo reporting event’s adverse-event analyses) so its result rows carry the ARS analysis variable invariable(e.g.USUBJID, withvariable_levelNA) instead of the internal counting columndummy/dummyvar. Statistic values are unchanged (#231). - Changed the level of a pre-defined group in the per-group-condition templates (
categorical_summary_per_predefined_group, its overall variant andchisq_per_predefined_group) from the group’s first condition value to its ARS group name. A group covering several values now reads as one category: the demo’s age groupAGEGR1 IN ("65-80", ">80")is labelled≥ 65 yearsrather than65-80, and single-value groups carry their names too (Malerather thanM). Group ids and statistics are unchanged. Generated scripts write such names as portable string literals, with line breaks and non-ASCII characters escaped (#232). - Fixed zero-event risk-difference analyses returning
NAinstead of0. Methods that compute over the full population (templates referencingdf_poptot, e.g. risk differences) now bypass the empty-data subset guard, so an analysis with no events emits the conventional risk difference of0with a[0, 0]confidence interval (#156). - Accepted SAS transport (
.xpt) ADaM datasets in addition to CSV.readARS()chooses the reader for each ADaM dataset from its file extension (.csvviareadr::read_csv(),.xptviahaven::read_xpt()), with no new argument; the file lookup is case-insensitive so lower-case submission file names (e.g.adsl.xpt) match upper-case ARS dataset names. Reading.xptrequires thehavenpackage. - Fixed
readARS()crash when ARS metadata contains noreferencedAnalysisOperations(continuous-only tables such as shift tables) by ensuring accumulator frames are initialised with their merge key columns. - Normalised Windows backslashes in ADaM file paths to forward slashes so generated scripts run correctly on both Windows and Unix systems.
- Added CDISC ARD-compliant column stamping: generated scripts now write
group[n]_groupingId,group[n]_groupId(for pre-defined groups) andgroup[n]_groupValue(for data-driven groupings) onto each ARD row. - Supported arbitrarily deep nesting in
mainListOfContentsvia a recursive LOPA extraction helper, removing the previous three-level hard limit. - Expanded support for multi-value ARS group conditions (
IN/NOTIN) by unnestingcondition.valuelist columns in the JSON parser. - Coerced
*_levelcolumns to character on each individual ARD frame beforebind_rows, preventing type conflicts between continuous and categorical analyses. - Allowed more than three grouping factors per analysis.
- Updated bundled
cards_constructs.xlsxexample file and extended test coverage across metadata parsing, ADaM loading, and ARD script generation.
siera 0.5.5
CRAN release: 2025-12-01
- Strengthened analysis method validation with clear errors for missing or undefined
MethodIdvalues and warnings when method templates or parameter value sources cannot be resolved. - Added guardrails for analysis set generation that warn on missing or incomplete metadata and fall back to the unfiltered analysis dataset when needed.
- Tightened ARS metadata ingestion by requiring
analysisSetsdefinitions in JSON and the analysis code template sheets in Excel workbooks. - Expanded test coverage for analysis methods, analysis sets, and data subset condition handling to capture more metadata edge cases.
siera 0.5.4
CRAN release: 2025-09-25
- Comprehensive testing added: checking generated ARD result values
- added warning messages with cli()
- cover scenarios for bigN vs table-level subsetting
siera 0.5.3
CRAN release: 2025-08-28
- Cover scenario of multi-value DataSubsets
- Cover scenario of overlapping variables in ADSL merge
