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_response
Next, 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]>