Tumor and Multitumor Data¶
Conducting dose-response analysis on dichotomous tumor data differs from analyzing standard dichotomous tumor data in the following ways:
The Multistage cancer model uses different parameter settings for model fit than the standard Multistage model.
A cancer slope factor is calculated.
In some cases, there may be a need to combine multiple tumor datasets and then calculate a single cancer slope factor.
To that end, this guide covers some different approaches that you can use in pybmds
for handling tumor data.
Quickstart¶
To run a single dataset:
import pybmds
from pybmds.models.dichotomous import MultistageCancer
dataset = pybmds.DichotomousDataset(
doses=[0, 25, 75, 125, 200],
ns=[20, 20, 20, 20, 20],
incidences=[0, 1, 7, 15, 19],
name="Tumor dataset A",
dose_units="mg/kg-d",
)
model = MultistageCancer(dataset, settings={"bmr": 0.1})
model.execute(slope_factor=True)
print(f"BMD = {model.results.bmd:f}")
print(f"BMDL = {model.results.bmdl:f}")
print(f"CSF = {model.results.slope_factor:f}")
model.plot()
BMD = 35.929912
BMDL = 18.233585
CSF = 0.005484
To run multiple datasets and calculate a single combined slope factor:
import pybmds
datasets = [
pybmds.DichotomousDataset(
doses=[0, 25, 75, 125, 200],
ns=[20, 20, 20, 20, 20],
incidences=[0, 1, 7, 15, 19],
name="Tumor A",
dose_units="mg/m³",
),
pybmds.DichotomousDataset(
doses=[0, 25, 75, 125, 200],
ns=[20, 20, 20, 20, 20],
incidences=[0, 0, 1, 7, 11],
name="Tumor B",
dose_units="mg/m³",
),
]
session = pybmds.Multitumor(datasets, settings={"bmr": 0.2}, name="Example")
session.execute()
session.plot()
To view individual model results for selected models for each dataset:
# Print overall results
print("Overall")
print(f"BMD = {session.results.bmd:f}")
print(f"BMDL = {session.results.bmdl:f}")
print(f"CSF = {session.results.slope_factor:f}")
print()
# Print individual model results
selected_model_indexes = session.results.selected_model_indexes
for i, dataset_models in enumerate(session.models):
selected_index = selected_model_indexes[i]
selected_model = dataset_models[selected_index]
print(f"{selected_model.dataset.metadata.name}: {selected_model.name()}")
print(f"BMD = {selected_model.results.bmd:f}")
print(f"BMDL = {selected_model.results.bmdl:f}")
print(f"CSF = {selected_model.results.slope_factor:f}")
print()
Overall
BMD = 18.835597
BMDL = 15.066557
CSF = 0.013274
Tumor A: Multistage 1
BMD = 24.653310
BMDL = 18.882341
CSF = 0.010592
Tumor B: Multistage 1
BMD = 79.818267
BMDL = 55.735346
CSF = 0.003588
Create a tumor dataset¶
Create a tumor dataset using the same method as a dichotomous dataset.
As with a dichotomous dataset, provide a list of doses, incidences, and the total number of subjects, one item per dose-group.
You can also add optional attributes, such as name
, dose_name
, dose_units
, response_name
, response_units
, etc.
dataset = pybmds.DichotomousDataset(
name="Chemical X Tumor A",
dose_units="ppm",
doses=[0, 25, 75, 125, 200],
ns=[20, 20, 20, 20, 20],
incidences=[0, 1, 7, 15, 19],
)
print(dataset.tbl())
dataset.plot()
╒════════╤═════════════╤═════╕
│ Dose │ Incidence │ N │
╞════════╪═════════════╪═════╡
│ 0 │ 0 │ 20 │
│ 25 │ 1 │ 20 │
│ 75 │ 7 │ 20 │
│ 125 │ 15 │ 20 │
│ 200 │ 19 │ 20 │
╘════════╧═════════════╧═════╛
Single dataset fit¶
With a single tumor dataset defined above, you can run a single Multistage cancer model:
import pybmds
from pybmds.models.dichotomous import MultistageCancer
model = MultistageCancer(dataset, settings={"bmr": 0.10, "degree": 2})
model.execute(slope_factor=True)
model.plot()
After executing, results are stored in a results
attribute on the model. You can view individual items in the results by accessing:
print(model.name())
print(f"BMD = {session.results.bmd:f}")
print(f"BMDL = {session.results.bmdl:f}")
print(f"CSF = {session.results.slope_factor:f}")
Multistage 2
BMD = 18.835597
BMDL = 15.066557
CSF = 0.013274
Or generate a text report to view a summary:
print(model.text())
Multistage 2 Model
══════════════════════════════
Version: pybmds 24.1 (bmdscore 24.1)
Input Summary:
╒══════════════════════════════╤════════════════════════╕
│ BMR │ 10% Extra Risk │
│ Confidence Level (one sided) │ 0.95 │
│ Modeling approach │ frequentist_restricted │
│ Degree │ 2 │
╘══════════════════════════════╧════════════════════════╛
Parameter Settings:
╒═════════════╤═══════════╤═══════╤═══════╕
│ Parameter │ Initial │ Min │ Max │
╞═════════════╪═══════════╪═══════╪═══════╡
│ g │ -17 │ -18 │ 18 │
│ b1 │ 0.1 │ 0 │ 10000 │
│ b2 │ 0.1 │ 0 │ 10000 │
╘═════════════╧═══════════╧═══════╧═══════╛
Modeling Summary:
╒════════════════╤══════════════╕
│ BMD │ 35.9299 │
│ BMDL │ 18.2336 │
│ BMDU │ 42.1027 │
│ Slope Factor │ 0.00548438 │
│ AIC │ 68.4561 │
│ Log-Likelihood │ -32.2281 │
│ P-Value │ 0.979879 │
│ Overall d.f. │ 3 │
│ Chi² │ 0.185606 │
╘════════════════╧══════════════╛
Model Parameters:
╒════════════╤═════════════╤════════════╤══════════════╕
│ Variable │ Estimate │ On Bound │ Std Error │
╞════════════╪═════════════╪════════════╪══════════════╡
│ g │ 1.523e-08 │ yes │ Not Reported │
│ b1 │ 3.10908e-05 │ no │ 0.279639 │
│ b2 │ 8.07489e-05 │ no │ 0.795918 │
╘════════════╧═════════════╧════════════╧══════════════╛
Standard errors estimates are not generated for parameters estimated on corresponding bounds,
although sampling error is present for all parameters, as a rule. Standard error estimates may not
be reliable as a basis for confidence intervals or tests when one or more parameters are on bounds.
Goodness of Fit:
╒════════╤════════╤════════════╤════════════╤════════════╤═══════════════════╕
│ Dose │ Size │ Observed │ Expected │ Est Prob │ Scaled Residual │
╞════════╪════════╪════════════╪════════════╪════════════╪═══════════════════╡
│ 0 │ 20 │ 0 │ 3.046e-07 │ 1.523e-08 │ -0.000551905 │
│ 25 │ 20 │ 1 │ 0.999088 │ 0.0499544 │ 0.000935604 │
│ 75 │ 20 │ 7 │ 7.33062 │ 0.366531 │ -0.153425 │
│ 125 │ 20 │ 15 │ 14.3585 │ 0.717926 │ 0.318744 │
│ 200 │ 20 │ 19 │ 19.2137 │ 0.960686 │ -0.245902 │
╘════════╧════════╧════════════╧════════════╧════════════╧═══════════════════╛
Analysis of Deviance:
╒═══════════════╤══════════════════╤════════════╤════════════╤═════════════╤═════════════╕
│ Model │ Log-Likelihood │ # Params │ Deviance │ Test d.f. │ P-Value │
╞═══════════════╪══════════════════╪════════════╪════════════╪═════════════╪═════════════╡
│ Full model │ -32.1362 │ 5 │ - │ - │ - │
│ Fitted model │ -32.2281 │ 2 │ 0.183639 │ 3 │ 0.980186 │
│ Reduced model │ -68.0292 │ 1 │ 71.7859 │ 4 │ 9.54792e-15 │
╘═══════════════╧══════════════════╧════════════╧════════════╧═════════════╧═════════════╛
Change input settings¶
Model settings can be customized for a run, as with standard dichotomous models.
model = MultistageCancer(
dataset,
settings={
"bmr_type": pybmds.DichotomousRiskType.AddedRisk,
"bmr": 0.15,
"degree": 3,
},
)
print(model.settings.tbl())
╒══════════════════════════════╤════════════════════════╕
│ BMR │ 15% Added Risk │
│ Confidence Level (one sided) │ 0.95 │
│ Modeling approach │ frequentist_restricted │
│ Degree │ 3 │
╘══════════════════════════════╧════════════════════════╛
Change parameter settings¶
Initial parameter settings are different for the MultistageCancer
model compared with the dichotomous Multistage
:
from pybmds.models.dichotomous import Multistage, MultistageCancer
model = Multistage(dataset)
print("Multistage parameter settings:")
print(model.priors_tbl())
model = MultistageCancer(dataset)
print("Multistage Cancer parameter settings:")
print(model.priors_tbl())
Multistage parameter settings:
╒═════════════╤═══════════╤═══════╤═══════╕
│ Parameter │ Initial │ Min │ Max │
╞═════════════╪═══════════╪═══════╪═══════╡
│ g │ 0 │ -18 │ 18 │
│ b1 │ 0 │ 0 │ 10000 │
│ b2 │ 0 │ 0 │ 10000 │
╘═════════════╧═══════════╧═══════╧═══════╛
Multistage Cancer parameter settings:
╒═════════════╤═══════════╤═══════╤═══════╕
│ Parameter │ Initial │ Min │ Max │
╞═════════════╪═══════════╪═══════╪═══════╡
│ g │ -17 │ -18 │ 18 │
│ b1 │ 0.1 │ 0 │ 10000 │
│ b2 │ 0.1 │ 0 │ 10000 │
╘═════════════╧═══════════╧═══════╧═══════╛
For Multistage models, the b2
parameter setting is reused for all beta parameters greater than or equal to b2.
These can be updated:
model.settings.priors.update("g", initial_value=0, min_value=-10, max_value=10)
model.settings.priors.update("b1", initial_value=10, min_value=0, max_value=100)
model.settings.priors.update("b2", initial_value=20, min_value=0, max_value=1000)
print(model.priors_tbl())
╒═════════════╤═══════════╤═══════╤═══════╕
│ Parameter │ Initial │ Min │ Max │
╞═════════════╪═══════════╪═══════╪═══════╡
│ g │ 0 │ -10 │ 10 │
│ b1 │ 10 │ 0 │ 100 │
│ b2 │ 20 │ 0 │ 1000 │
╘═════════════╧═══════════╧═══════╧═══════╛
Fit multiple models¶
The previous example runs a single Multitumor model to a single dataset. However, you may want, for example, to run multiple multitumor models of varying degrees to a single dataset.
Multiple dataset fit¶
To fit multiple models and one or more datasets, use an instance of the Multitumor class:
import pybmds
datasets = [
pybmds.DichotomousDataset(
doses=[0, 25, 75, 125, 200],
ns=[20, 20, 20, 20, 20],
incidences=[0, 1, 7, 15, 19],
name="Tumor A",
dose_units="mg/m³",
),
pybmds.DichotomousDataset(
doses=[0, 25, 75, 125, 200],
ns=[20, 20, 20, 20, 20],
incidences=[0, 0, 1, 7, 11],
name="Tumor B",
dose_units="mg/m³",
),
]
session = pybmds.Multitumor(datasets)
session.execute()
print(session.results.tbl())
session.plot()
╒══════════════════════════════════╤════════════╕
│ BMD │ 8.8935 │
│ BMDL │ 7.1139 │
│ BMDU │ 11.2427 │
│ Slope Factor │ 0.014057 │
│ Combined Log-likelihood │ -70.8752 │
│ Combined Log-likelihood Constant │ -53.1841 │
╘══════════════════════════════════╧════════════╛
You can generate Excel and Word exports:
# save excel report
df = session.to_df()
df.to_excel("output/report.xlsx")
# save to a word report
report = session.to_docx()
report.save("output/report.docx")
Change model settings¶
Settings for all datasets and models should be configured globally and are applied to all models:
session = pybmds.Multitumor(datasets, settings={
"bmr_type": pybmds.DichotomousRiskType.AddedRisk,
"bmr": 0.15,
})
Change model degree¶
By default, multiple models are executed for each dataset, where the degree is varied from 1 to the number of doses minus 1 (and a maximum of 8).
For this example, we first create three datasets:
datasets = [
pybmds.DichotomousDataset(
doses=[0, 2, 3, 4, 5, 6, 7, 8, 9],
ns=[20, 20, 20, 20, 20, 20, 20, 20, 20],
incidences=[0, 1, 4, 8, 11, 12, 13, 14, 15],
name="Tumor A (9 groups)",
dose_units="mg/m³",
),
pybmds.DichotomousDataset(
doses=[0, 2, 3, 4, 5, 6, 7, 8, 9],
ns=[20, 20, 20, 20, 20, 20, 20, 20, 20],
incidences=[0, 1, 7, 15, 19, 19, 19, 19, 19],
name="Tumor B (9 groups)",
dose_units="mg/m³",
),
pybmds.DichotomousDataset(
doses=[0, 2, 3, 4, 5],
ns=[20, 20, 20, 20, 20],
incidences=[0, 0, 1, 7, 11],
name="Tumor C (5 groups)",
dose_units="mg/m³",
),
]
Next, we specify which model degrees to run for each dataset using degrees
. Setting a value of 0 runs all degrees available up to a maximum of 8; specifying a specific degree will only run the specified degree.
degrees = [0, 3, 2]
session = pybmds.Multitumor(datasets, degrees=degrees)
session.execute()
session.plot()
The analysis executed the following models for each dataset:
for dataset_models in session.models:
print(f"{dataset_models[0].dataset.metadata.name}")
for model in dataset_models:
print("\t" + model.name())
Tumor A (9 groups)
Multistage 1
Multistage 2
Multistage 3
Multistage 4
Multistage 5
Multistage 6
Multistage 7
Multistage 8
Tumor B (9 groups)
Multistage 3
Tumor C (5 groups)
Multistage 2