To help statisticians explore wider ranges of possibilities for clinical trials, the write_facts() function generates multiple versions of existing FACTS files with different features. This vignette walks through the process
FACTS files have a special XML format to define clinical trial simulations. Most of the internal configuration settings are defined in <property> tags inside <parameterSet>...</parameterSet> and <parameterSets>...</parameterSets>.
<?xml version="1.0" encoding="utf-8"?>
<facts version="6.2.5.22668" name="contin" host="host">
<parameterSets type="NucleusParameterSet">
<parameterSet name="nucleus">
<property name="type">1</property>
...
<property name="max_subjects">300</property>
<property name="cohort_size">5</property>
<property name="num_cohorts">50</property>
<property name="cohort_time">0</property>
...
</parameterSet>
</parameterSets>
...
<parameterSets type="EfficacyParameterSet">
<parameterSet name="resp2" EndpointType="1">
<property name="true_endpoint_response">
<items>
<item>0</item>
<item>10</item>
</items>
</property>
...
</parameterSet>
...
</parameterSets>
</facst>write_facts() works on the <property> tags located above. Any <property> within a <facts><parameterSets><parameterSet> block can be modified programmatically. To demonstrate, we will create two new FACTS files with modified virtual subject response scenarios and different numbers of patients. We start with a known FACTS file we create from the Windows GUI (or a built-in example from this package).
library(dplyr)
library(rfacts)
library(tibble)
tmp <- file.copy(get_facts_file_example("contin.facts"), getwd())
facts_file <- "contin.facts"Next, we declare the XML fields we want to replace. We define one field to control the maximum number of subjects,
field_subjects <- tibble(
field = "my_subjects", # custom name the user can make up
type = "NucleusParameterSet", # "type" attribute of the <parameterSets> tag
set = "nucleus", # "name" attribute of the <parameterSet> tag
property = "max_subjects" # "name" attribute of the <property> tag
)and another field to modify the "resp2" virtual subject response scenario.
field_vsr <- tibble(
field = "my_vsr",
type = "EfficacyParameterSet",
set = "resp2",
property = "true_endpoint_response"
)We put the fields together in a single data frame.
fields <- bind_rows(field_subjects, field_vsr)
fields
#> # A tibble: 2 × 4
#> field type set property
#> <chr> <chr> <chr> <chr>
#> 1 my_subjects NucleusParameterSet nucleus max_subjects
#> 2 my_vsr EfficacyParameterSet resp2 true_endpoint_responseNext, we define a grid of values to iterate over when we modify these fields. The grid should have one row per FACTS file and one column for every value of fields$field you want to modify in the XML. The values data frame must also contain a facts_file column to identify the source file. You can optionally include an output column to control the output path of each generated FACTS file, but this is not required.
values <- tibble(
facts_file = facts_file,
my_subjects = c(1000, 2000),
my_vsr = list(c(15, 50), c(25, 75))
)
values
#> # A tibble: 2 × 3
#> facts_file my_subjects my_vsr
#> <chr> <dbl> <list>
#> 1 contin.facts 1000 <dbl [2]>
#> 2 contin.facts 2000 <dbl [2]>Above, my_subjects is a vector of max sample sizes, and my_vsr is a list of VSR response means (one for each treatment group). Each value of my_vsr will be inserted as an <item> list in each output FACTS file, and the length of each list element must equal the length of the original <item> list.
To generate the FACTS files, simply call write_facts().
write_facts(fields = fields, values = values)
#> [1] "_facts/38b2cfd4.facts" "_facts/00e8e729.facts"
list.files("_facts")
#> [1] "00e8e729.facts" "38b2cfd4.facts"To control the output paths, add an output column to the values data frame.
unlink("_facts", recursive = TRUE)
values$output <- c("small.facts", "large.facts")
write_facts(fields = fields, values = values)
#> [1] "small.facts" "large.facts"To verify that the generated FACTS files are correct, you can open them in a text or XML editor. Above, small.facts should have 1000 max subjects and resp2 VSR parameters equal to 15 and 50.
<?xml version="1.0" encoding="utf-8"?>
<facts version="6.2.5.22668" name="contin" host="host">
<parameterSets type="NucleusParameterSet">
<parameterSet name="nucleus">
<property name="max_subjects">1000</property>
...
</parameterSet>
</parameterSets>
...
<parameterSets type="EfficacyParameterSet">
<parameterSet name="resp2" EndpointType="1">
<property name="true_endpoint_response">
<items>
<item>15</item>
<item>50</item>
</items>
</property>
...
</parameterSet>
...
</parameterSets>
</facst>Likewise, large.facts should have 2000 max subjects and resp2 VSR parameters equal to 25 and 75.
<?xml version="1.0" encoding="utf-8"?>
<facts version="6.2.5.22668" name="contin" host="host">
<parameterSets type="NucleusParameterSet">
<parameterSet name="nucleus">
<property name="max_subjects">2000</property>
...
</parameterSet>
</parameterSets>
...
<parameterSets type="EfficacyParameterSet">
<parameterSet name="resp2" EndpointType="1">
<property name="true_endpoint_response">
<items>
<item>25</item>
<item>75</item>
</items>
</property>
...
</parameterSet>
...
</parameterSets>
</facst>Other ways to check your work include the following.
run_facts() and check that the output is consistent with the input settings you specified.read_facts() to inspect the settings that should be modified.read_facts(facts_file = facts_file, fields = fields)
#> # A tibble: 1 × 3
#> facts_file my_subjects my_vsr
#> <chr> <chr> <list>
#> 1 contin.facts 300 <chr [2]>
read_facts(facts_file = "small.facts", fields = fields)
#> # A tibble: 1 × 3
#> facts_file my_subjects my_vsr
#> <chr> <chr> <list>
#> 1 small.facts 1000 <chr [2]>
read_facts(facts_file = "large.facts", fields = fields)
#> # A tibble: 1 × 3
#> facts_file my_subjects my_vsr
#> <chr> <chr> <list>
#> 1 large.facts 2000 <chr [2]>