Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions .github/CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Contributing

Thanks for considering contributing to {gsDesign2}! We welcome your Pull
Requests to improve our software. For potentially larger changes, we advise
first opening an Issue to discuss the new feature.

For more information on the organization of the package, please see the
article [Overview of package architecture][story-package-architecture].

[story-package-architecture]: https://merck.github.io/gsDesign2/articles/story-package-architecture.html
6 changes: 6 additions & 0 deletions _pkgdown.yml
Original file line number Diff line number Diff line change
Expand Up @@ -183,3 +183,9 @@ articles:
Develop designs for binary endpoints.
contents:
- articles/story-risk-difference

- title: "Overview of package architecture"
desc: >
Explanation of how the code is organized and how to contribute
contents:
- articles/story-package-architecture
101 changes: 101 additions & 0 deletions vignettes/articles/story-package-architecture.Rmd
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
---
title: "Overview of package architecture"
author: "John Blischak"
output:
rmarkdown::html_document:
toc: true
toc_float: true
toc_depth: 2
number_sections: true
highlight: "textmate"
css: "custom.css"
---

## Overview of package architecture

The goal of {gsDesign2} is to enable fixed or group sequential design under
non-proportional hazards. When designing a trial, there are a few key important
decisions that affect how the software should behave:

* Is it a fixed or group sequential design?
* Which method to use for testing? For example, average hazard ratio (ahr) or
weighted log rank (wlr)
* For a group sequential design, is the futility bound binding or non-binding?

Internally, {gsDesign2} stores the above decisions using multiple different
implementations.

The main functions have the pattern `{fixed,gs}_{design,power}_{method}`, where:

* The prefix indicates if the trial is a fixed (`fixed`) or group sequential
(`gs`) design
* The middle portion indicates which input information is used to calculate the
trial details:
* `design`: given power and type I error, calculate sample size and bounds
* `power`: given sample size, calculate power
* The suffix indicates which test method is used, e.g. average hazard ratio
(`ahr`) or weighted log rank (`wlr`)

Importantly, these characteristics are stored in the output object.

* The type of design is specified by the class of the object: `"fixed_design"`
or `"gs_design"`
* The method for testing is specified by the list element `design`, which
contains a string abbreviation of the test that matches the original function:
`"ahr"`, `"wlr"`, etc
* The binding status of the futility bound is specified by the attribute
`binding`, which is either `TRUE` or `FALSE`

Since the only class designation used by the package is `"fixed_design"` or
`"gs_design"`, it only contains S3 methods related to this distinction.
Specifically, the package provides S3 methods for `print()`, `summary()`, and
`to_integer()`. Furthermore, the `summary()` S3 method returns corresponding
objects of class `"fixed_design_summary"` or `"gs_design_summary"`, and the
package provides the S3 methods `as_gt()` and `as_rtf()` to convert the summary
tables to [gt][] or [RTF][] format, respectively.

[gt]: https://github.com/rstudio/gt
[rtf]: https://en.wikipedia.org/wiki/Rich_Text_Format

## How to query the trial characteristics from the design object

**Note:** This section is mainly of interest to potential developers that wish
to contribute code. You do not need to be familiar with the internals in order
to successfully use the package for your analyses.

If you contribute code to {gsDesign2}, you may need to write different logic
based on the characteristics of the trial design. Given the general overview
above, below are the practical steps for querying a design object.

To determine if it is a fixed or group sequential design, use `inherits()`:

```R
if (inherits(x, "gs_design")) {
```

To determine the testing method, query the list element `design`. You can use
nested if-else statements or `switch()`.

```R
if (x$design == "ahr") {
# code for ahr designs
} else if (x$design == "wlr") {
# code for wlr designs
} else if (x$design == "rd") {
# code for rd designs
} else {
# something else
}

result <- switch(x$design, ahr = 1, wlr = 2, rd = 3)
```

To determine if the futility is binding, query the attribute `binding`.

```R
if (attr(x, "binding")) {
# code for design with binding futility bound
} else {
# code for design with non-binding futility bound
}
```