Dichotomous Data

Quickstart

To run a dichotomous dataset:

import pybmds

dataset = pybmds.DichotomousDataset(
    doses=[0, 25, 75, 125, 200],
    ns=[20, 20, 20, 20, 20],
    incidences=[0, 1, 7, 15, 19],
)

# create a BMD session
session = pybmds.Session(dataset=dataset)

# add all default models
session.add_default_models()

# execute the session
session.execute()

# recommend a best-fitting model
session.recommend()

if session.recommended_model is not None:
    display(session.recommended_model.plot())
    print(session.recommended_model.text())

# 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")
../_images/4e18e0079023808098c6952b746986350e2d3705daa3ace9bd2a1e2fadf7ce62.png
     Quantal Linear Model     
══════════════════════════════

Version: pybmds 25.1 (bmdscore 25.1)

Input Summary:
╒══════════════════════════════╤══════════════════════════╕
│ BMR                          │ 10% Extra Risk           │
│ Confidence Level (one sided) │ 0.95                     │
│ Modeling approach            │ frequentist_unrestricted │
╘══════════════════════════════╧══════════════════════════╛

Parameter Settings:
╒═════════════╤═══════════╤═══════╤═══════╕
│ Parameter   │   Initial │   Min │   Max │
╞═════════════╪═══════════╪═══════╪═══════╡
│ g           │         0 │   -18 │    18 │
│ b           │         0 │     0 │   100 │
╘═════════════╧═══════════╧═══════╧═══════╛

Modeling Summary:
╒════════════════╤════════════╕
│ BMD            │  11.6404   │
│ BMDL           │   8.91584  │
│ BMDU           │  15.4669   │
│ AIC            │  74.7575   │
│ Log-Likelihood │ -36.3787   │
│ P-Value        │   0.142335 │
│ Overall d.f.   │   4        │
│ Chi²           │   6.88058  │
╘════════════════╧════════════╛

Model Parameters:
╒════════════╤════════════╤════════════╤══════════════╕
│ Variable   │   Estimate │ On Bound   │ Std Error    │
╞════════════╪════════════╪════════════╪══════════════╡
│ g          │ 1.523e-08  │ yes        │ Not Reported │
│ b          │ 0.00905126 │ no         │ 0.0015129    │
╘════════════╧════════════╧════════════╧══════════════╛
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 │  4.05013   │  0.202506  │      -1.69715     │
│     75 │     20 │          7 │  9.85595   │  0.492797  │      -1.27735     │
│    125 │     20 │         15 │ 13.5484    │  0.677421  │       0.694349    │
│    200 │     20 │         19 │ 16.7277    │  0.836387  │       1.3735      │
╘════════╧════════╧════════════╧════════════╧════════════╧═══════════════════╛

Analysis of Deviance:
╒═══════════════╤══════════════════╤════════════╤════════════╤═════════════╤═════════════╕
│ Model         │   Log-Likelihood │   # Params │ Deviance   │ Test d.f.   │ P-Value     │
╞═══════════════╪══════════════════╪════════════╪════════════╪═════════════╪═════════════╡
│ Full model    │         -32.1362 │          5 │ -          │ -           │ -           │
│ Fitted model  │         -36.3787 │          1 │ 8.485      │ 4           │ 0.0753431   │
│ Reduced model │         -68.0292 │          1 │ 71.7859    │ 4           │ 9.54792e-15 │
╘═══════════════╧══════════════════╧════════════╧════════════╧═════════════╧═════════════╛

Dichotomous datasets

Creating a dichotomous dataset requires a list of doses, incidences, and the total number of subjects, one item per dose group. Doses must be unique.

You can also add optional attributes, such as name, dose_name, dose_units, response_name, response_units, etc.

For example:

dataset = pybmds.DichotomousDataset(
    name="ChemX Nasal Lesion Incidence",
    dose_name="Concentration",
    dose_units="ppm",
    doses=[0, 25, 75, 125, 200],
    ns=[20, 20, 20, 20, 20],
    incidences=[0, 1, 7, 15, 19],
)

dataset.plot()
../_images/0f42f3b0c601d7883d205e1f7b9dfc3cba382882394d6273c83c3f8013d6d20a.png

Single model fit

You can fit a specific model to the dataset and plot/print the results. The printed results will include the BMD, BMDL, BMDU, p-value, AIC, etc.

The individual models available are shown below. Note that the degrees of the Multistage model can be increased to a maximum of the lesser of N-1 or 8 (as specified in the BMDS User Guide).

from pybmds.models import dichotomous

dichotomous.QuantalLinear(dataset)
dichotomous.Multistage(dataset, settings={"degree": 2})
dichotomous.Multistage(dataset, settings={"degree": 3})
dichotomous.Logistic(dataset)
dichotomous.LogLogistic(dataset)
dichotomous.Probit(dataset)
dichotomous.LogProbit(dataset)
dichotomous.Gamma(dataset)
dichotomous.Weibull(dataset)
dichotomous.DichotomousHill(dataset)

As an example, to fit the Logistic model:

model = dichotomous.Logistic(dataset)
model.execute()
model.plot()
../_images/8104e9a434f33c066e3293d1ec44ad5600f302fab996916607cef58d49979deb.png

To generate an output report:

print(model.text())
        Logistic Model        
══════════════════════════════

Version: pybmds 25.1 (bmdscore 25.1)

Input Summary:
╒══════════════════════════════╤══════════════════════════╕
│ BMR                          │ 10% Extra Risk           │
│ Confidence Level (one sided) │ 0.95                     │
│ Modeling approach            │ frequentist_unrestricted │
╘══════════════════════════════╧══════════════════════════╛

Parameter Settings:
╒═════════════╤═══════════╤═══════╤═══════╕
│ Parameter   │   Initial │   Min │   Max │
╞═════════════╪═══════════╪═══════╪═══════╡
│ a           │         0 │   -18 │    18 │
│ b           │         0 │     0 │   100 │
╘═════════════╧═══════════╧═══════╧═══════╛

Modeling Summary:
╒════════════════╤════════════╕
│ BMD            │  44.8841   │
│ BMDL           │  32.5885   │
│ BMDU           │  59.2      │
│ AIC            │  70.1755   │
│ Log-Likelihood │ -33.0878   │
│ P-Value        │   0.666151 │
│ Overall d.f.   │   3        │
│ Chi²           │   1.57027  │
╘════════════════╧════════════╛

Model Parameters:
╒════════════╤════════════╤════════════╤═════════════╕
│ Variable   │   Estimate │ On Bound   │   Std Error │
╞════════════╪════════════╪════════════╪═════════════╡
│ a          │ -3.62365   │ no         │  0.707213   │
│ b          │  0.0370501 │ no         │  0.00705474 │
╘════════════╧════════════╧════════════╧═════════════╛

Goodness of Fit:
╒════════╤════════╤════════════╤════════════╤════════════╤═══════════════════╕
│   Dose │   Size │   Observed │   Expected │   Est Prob │   Scaled Residual │
╞════════╪════════╪════════════╪════════════╪════════════╪═══════════════════╡
│      0 │     20 │          0 │    0.51983 │  0.0259915 │         -0.730549 │
│     25 │     20 │          1 │    1.26254 │  0.063127  │         -0.241397 │
│     75 │     20 │          7 │    6.01009 │  0.300505  │          0.482793 │
│    125 │     20 │         15 │   14.651   │  0.732552  │          0.176289 │
│    200 │     20 │         19 │   19.5565  │  0.977825  │         -0.845059 │
╘════════╧════════╧════════════╧════════════╧════════════╧═══════════════════╛

Analysis of Deviance:
╒═══════════════╤══════════════════╤════════════╤════════════╤═════════════╤═════════════╕
│ Model         │   Log-Likelihood │   # Params │ Deviance   │ Test d.f.   │ P-Value     │
╞═══════════════╪══════════════════╪════════════╪════════════╪═════════════╪═════════════╡
│ Full model    │         -32.1362 │          5 │ -          │ -           │ -           │
│ Fitted model  │         -33.0878 │          2 │ 1.90305    │ 3           │ 0.592771    │
│ Reduced model │         -68.0292 │          1 │ 71.7859    │ 4           │ 9.54792e-15 │
╘═══════════════╧══════════════════╧════════════╧════════════╧═════════════╧═════════════╛

Change input settings

The default settings use a BMR of 10% Extra Risk and a 95% confidence interval. If you fit a single model to your dataset, settings for that model can be modified:

model = dichotomous.Logistic(
    dataset, settings={"bmr": 0.15, "bmr_type": pybmds.DichotomousRiskType.AddedRisk}
)
print(model.settings.tbl())
╒══════════════════════════════╤══════════════════════════╕
│ BMR                          │ 15% Added Risk           │
│ Confidence Level (one sided) │ 0.95                     │
│ Modeling approach            │ frequentist_unrestricted │
│ Degree                       │ 0                        │
╘══════════════════════════════╧══════════════════════════╛

Change parameter settings

If you want to see a preview of the initial parameter settings, you can run:

model = dichotomous.Logistic(dataset)
print(model.priors_tbl())
╒═════════════╤═══════════╤═══════╤═══════╕
│ Parameter   │   Initial │   Min │   Max │
╞═════════════╪═══════════╪═══════╪═══════╡
│ a           │         0 │   -18 │    18 │
│ b           │         0 │     0 │   100 │
╘═════════════╧═══════════╧═══════╧═══════╛

You can also change the initial parameter settings shown above for any run of a single dichotomous model.

Continuing with the Logistic model example, for the a parameter, you can change the minimum and maximum range from -10 to 10, while b can range from 0 to 50:

model.settings.priors.update("a", min_value=-10, max_value=10)
model.settings.priors.update("b", min_value=0, max_value=50)
print(model.priors_tbl())
╒═════════════╤═══════════╤═══════╤═══════╕
│ Parameter   │   Initial │   Min │   Max │
╞═════════════╪═══════════╪═══════╪═══════╡
│ a           │         0 │   -10 │    10 │
│ b           │         0 │     0 │    50 │
╘═════════════╧═══════════╧═══════╧═══════╛

You can change the range and initial value for any parameter in the model by following the same steps above.

Multiple model fit (sessions) and model recommendation

To run all the default models, save the results, and save the plot of the fit of the recommended model with the data:

dataset = pybmds.DichotomousDataset(
    doses=[0, 25, 75, 125, 200],
    ns=[20, 20, 20, 20, 20],
    incidences=[0, 1, 7, 15, 19],
)

# create a BMD session
session = pybmds.Session(dataset=dataset)

# add all default models
session.add_default_models()

# execute the session
session.execute()

# recommend a best-fitting model
session.recommend()

# print recommended model and plot recommended model with dataset
model_index = session.recommender.results.recommended_model_index
if model_index:
    model = session.models[model_index]
    display(model.plot())
    print(model.text())
../_images/4e18e0079023808098c6952b746986350e2d3705daa3ace9bd2a1e2fadf7ce62.png
     Quantal Linear Model     
══════════════════════════════

Version: pybmds 25.1 (bmdscore 25.1)

Input Summary:
╒══════════════════════════════╤══════════════════════════╕
│ BMR                          │ 10% Extra Risk           │
│ Confidence Level (one sided) │ 0.95                     │
│ Modeling approach            │ frequentist_unrestricted │
╘══════════════════════════════╧══════════════════════════╛

Parameter Settings:
╒═════════════╤═══════════╤═══════╤═══════╕
│ Parameter   │   Initial │   Min │   Max │
╞═════════════╪═══════════╪═══════╪═══════╡
│ g           │         0 │   -18 │    18 │
│ b           │         0 │     0 │   100 │
╘═════════════╧═══════════╧═══════╧═══════╛

Modeling Summary:
╒════════════════╤════════════╕
│ BMD            │  11.6404   │
│ BMDL           │   8.91584  │
│ BMDU           │  15.4669   │
│ AIC            │  74.7575   │
│ Log-Likelihood │ -36.3787   │
│ P-Value        │   0.142335 │
│ Overall d.f.   │   4        │
│ Chi²           │   6.88058  │
╘════════════════╧════════════╛

Model Parameters:
╒════════════╤════════════╤════════════╤══════════════╕
│ Variable   │   Estimate │ On Bound   │ Std Error    │
╞════════════╪════════════╪════════════╪══════════════╡
│ g          │ 1.523e-08  │ yes        │ Not Reported │
│ b          │ 0.00905126 │ no         │ 0.0015129    │
╘════════════╧════════════╧════════════╧══════════════╛
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 │  4.05013   │  0.202506  │      -1.69715     │
│     75 │     20 │          7 │  9.85595   │  0.492797  │      -1.27735     │
│    125 │     20 │         15 │ 13.5484    │  0.677421  │       0.694349    │
│    200 │     20 │         19 │ 16.7277    │  0.836387  │       1.3735      │
╘════════╧════════╧════════════╧════════════╧════════════╧═══════════════════╛

Analysis of Deviance:
╒═══════════════╤══════════════════╤════════════╤════════════╤═════════════╤═════════════╕
│ Model         │   Log-Likelihood │   # Params │ Deviance   │ Test d.f.   │ P-Value     │
╞═══════════════╪══════════════════╪════════════╪════════════╪═════════════╪═════════════╡
│ Full model    │         -32.1362 │          5 │ -          │ -           │ -           │
│ Fitted model  │         -36.3787 │          1 │ 8.485      │ 4           │ 0.0753431   │
│ Reduced model │         -68.0292 │          1 │ 71.7859    │ 4           │ 9.54792e-15 │
╘═══════════════╧══════════════════╧════════════╧════════════╧═════════════╧═════════════╛

You can also plot all models:

session.plot()
../_images/718cbe8b4187fae23a11626e013de71b8afddc2b89b86913b085bbf2db8eb088.png

To print a summary table of modeling results, create a custom function:

import pandas as pd

def summary_table(session):
    data = []
    for model in session.models:
        data.append([
            model.name(),
            model.results.bmdl,
            model.results.bmd,
            model.results.bmdu,
            model.results.gof.p_value,
            model.results.fit.aic
        ])

    df = pd.DataFrame(
        data=data,
        columns=["Model", "BMDL", "BMD", "BMDU", "P-Value", "AIC"]
    )
    return df

summary_table(session)
Model BMDL BMD BMDU P-Value AIC
0 Logistic 32.588454 44.884135 59.199959 0.666151 70.175538
1 LogLogistic 25.629773 40.699410 55.230166 0.828331 69.093671
2 Probit 30.363157 41.862869 55.948994 0.604658 70.259470
3 LogProbit 24.847658 37.801377 50.504284 0.741253 69.462536
4 Quantal Linear 8.915836 11.640424 15.466867 0.142335 74.757493
5 Multistage 2 18.233585 35.929912 42.102724 0.979879 68.456130
6 Multistage 3 16.215191 35.929433 50.620322 0.979879 68.456130
7 Gamma 22.220274 37.500667 51.773296 0.963613 68.546957
8 Weibull 20.810667 35.515406 50.622612 0.980762 68.452316
9 Hill 25.629773 40.699410 55.230167 0.828331 69.093671

To generate Excel and Word reports:

# 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 session settings

If you run all the default models and select the best fit, you can change these settings by:

session.add_default_models(
    settings={
        "bmr": 0.15,
        "bmr_type": pybmds.DichotomousRiskType.AddedRisk,
        "alpha": 0.1
    }
)

This would run the dichotomous models for a BMR of 15% Added Risk at a 90% confidence interval.

Run subset of models

You can select a set of models, rather than using all available models.

For example, to evaluate the Logistic, Probit, Quantal Linear, and Weibull models:

session = pybmds.Session(dataset=dataset)
session.add_model(pybmds.Models.Weibull)
session.add_model(pybmds.Models.Logistic)
session.add_model(pybmds.Models.Probit)
session.add_model(pybmds.Models.QuantalLinear)

session.execute()

Custom models

You can run a session with custom models where the model name has been changed, initial parameter values have been modified and parameter values have been set to a particular value.

We start with a new dataset:

dataset = pybmds.DichotomousDataset(
    doses=[0, 25, 75, 125, 200],
    ns=[20, 20, 20, 20, 20],
    incidences=[0, 1, 5, 15, 20],
)
dataset.plot(figsize=(6,4))
../_images/812e617e25b0a592b1a26cfd63f1c6aef86ac3913d3292c5cd2f84a7a55a93dd.png

And add this dataset to a new modeling session, along with all the standard models:

# create a BMD session
session = pybmds.Session(dataset=dataset)

# add all default models
session.add_default_models()

Next, add a modified Dichotomous Hill model with the slope parameter fixed to 1, resulting in the Michaelis-Menten model:

model = pybmds.models.dichotomous.DichotomousHill(dataset, settings={"name": "Michaelis–Menten"})

# fix the `b` parameter to 1
model.settings.priors.update("b", initial_value=1, min_value=1, max_value=1)

session.models.append(model)

To run the default models and any manually added models, save the results, and save the plot of the fitted recommended model with the data:

# execute the session
session.execute()

# recommend a best-fitting model
session.recommend()

# print recommended model and plot recommended model with dataset
model_index = session.recommender.results.recommended_model_index
if model_index:
    model = session.models[model_index]
    display(model.plot())
    print(model.text())
../_images/31be7a5ee25cf5ee596836eaad4ad77c93213548f8befc3346ed3c0ec6ce9557.png
      Multistage 3 Model      
══════════════════════════════

Version: pybmds 25.1 (bmdscore 25.1)

Input Summary:
╒══════════════════════════════╤════════════════════════╕
│ BMR                          │ 10% Extra Risk         │
│ Confidence Level (one sided) │ 0.95                   │
│ Modeling approach            │ frequentist_restricted │
│ Degree                       │ 3                      │
╘══════════════════════════════╧════════════════════════╛

Parameter Settings:
╒═════════════╤═══════════╤═══════╤═══════╕
│ Parameter   │   Initial │   Min │   Max │
╞═════════════╪═══════════╪═══════╪═══════╡
│ g           │         0 │   -18 │    18 │
│ b1          │         0 │     0 │ 10000 │
│ b2          │         0 │     0 │ 10000 │
│ b3          │         0 │     0 │ 10000 │
╘═════════════╧═══════════╧═══════╧═══════╛

Modeling Summary:
╒════════════════╤════════════╕
│ BMD            │  44.7215   │
│ BMDL           │  23.5185   │
│ BMDU           │  59.29     │
│ AIC            │  55.4222   │
│ Log-Likelihood │ -26.7111   │
│ P-Value        │   0.982997 │
│ Overall d.f.   │   4        │
│ Chi²           │   0.393601 │
╘════════════════╧════════════╛

Model Parameters:
╒════════════╤═════════════╤════════════╤══════════════╕
│ Variable   │    Estimate │ On Bound   │ Std Error    │
╞════════════╪═════════════╪════════════╪══════════════╡
│ g          │ 1.523e-08   │ yes        │ Not Reported │
│ b1         │ 0.00109945  │ no         │ 0.282148     │
│ b2         │ 1.3118e-20  │ yes        │ Not Reported │
│ b3         │ 6.28232e-07 │ yes        │ Not Reported │
╘════════════╧═════════════╧════════════╧══════════════╛
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.732306  │  0.0366153 │       0.318708    │
│     75 │     20 │          5 │  5.87088   │  0.293544  │      -0.427626    │
│    125 │     20 │         15 │ 14.8896    │  0.744478  │       0.0566184   │
│    200 │     20 │         20 │ 19.8946    │  0.99473   │       0.325509    │
╘════════╧════════╧════════════╧════════════╧════════════╧═══════════════════╛

Analysis of Deviance:
╒═══════════════╤══════════════════╤════════════╤════════════╤═════════════╤═══════════╕
│ Model         │   Log-Likelihood │   # Params │ Deviance   │ Test d.f.   │ P-Value   │
╞═══════════════╪══════════════════╪════════════╪════════════╪═════════════╪═══════════╡
│ Full model    │         -26.4637 │          5 │ -          │ -           │ -         │
│ Fitted model  │         -26.7111 │          1 │ 0.494739   │ 4           │ 0.974011  │
│ Reduced model │         -67.6859 │          1 │ 82.4443    │ 4           │ 0         │
╘═══════════════╧══════════════════╧════════════╧════════════╧═════════════╧═══════════╛

You can also plot all models on a single plot:

session.plot()
../_images/899c3002da3b63a01ca4fb6833f11abb44049550c598137b73d956acdf79c2de.png

We can summarize using the summary_table function we defined above:

summary_table(session)
Model BMDL BMD BMDU P-Value AIC
0 Logistic 38.978523 53.621709 68.574734 0.882992 57.937669
1 LogLogistic 42.571336 63.282243 79.375096 0.425015 61.482744
2 Probit 35.679901 49.803548 64.425011 0.904740 57.636693
3 LogProbit 46.554482 64.255617 78.221184 0.482500 61.039679
4 Quantal Linear 9.034209 11.838419 15.792424 0.018000 71.369122
5 Multistage 2 23.966481 35.476547 41.646639 0.714606 57.828036
6 Multistage 3 23.518491 44.721502 59.289977 0.982997 55.422160
7 Gamma 35.295248 62.094483 77.958640 0.531844 60.742566
8 Weibull 31.655618 53.126127 76.403822 0.815826 58.068448
9 Hill 42.537341 63.282242 79.375096 0.425015 61.482745
10 Michaelis–Menten 6.575410 8.848340 9.339927 0.001267 80.014221

Model recommendation and selection

The pybmds package may recommend a best-fitting model based on a decision tree, but expert judgment may be required for model selection. To run model recommendation and view a recommended model, if one is recommended:

session.recommend()

if session.recommended_model is not None:
    display(session.recommended_model.plot())
    print(session.recommended_model.text())
../_images/31be7a5ee25cf5ee596836eaad4ad77c93213548f8befc3346ed3c0ec6ce9557.png
      Multistage 3 Model      
══════════════════════════════

Version: pybmds 25.1 (bmdscore 25.1)

Input Summary:
╒══════════════════════════════╤════════════════════════╕
│ BMR                          │ 10% Extra Risk         │
│ Confidence Level (one sided) │ 0.95                   │
│ Modeling approach            │ frequentist_restricted │
│ Degree                       │ 3                      │
╘══════════════════════════════╧════════════════════════╛

Parameter Settings:
╒═════════════╤═══════════╤═══════╤═══════╕
│ Parameter   │   Initial │   Min │   Max │
╞═════════════╪═══════════╪═══════╪═══════╡
│ g           │         0 │   -18 │    18 │
│ b1          │         0 │     0 │ 10000 │
│ b2          │         0 │     0 │ 10000 │
│ b3          │         0 │     0 │ 10000 │
╘═════════════╧═══════════╧═══════╧═══════╛

Modeling Summary:
╒════════════════╤════════════╕
│ BMD            │  44.7215   │
│ BMDL           │  23.5185   │
│ BMDU           │  59.29     │
│ AIC            │  55.4222   │
│ Log-Likelihood │ -26.7111   │
│ P-Value        │   0.982997 │
│ Overall d.f.   │   4        │
│ Chi²           │   0.393601 │
╘════════════════╧════════════╛

Model Parameters:
╒════════════╤═════════════╤════════════╤══════════════╕
│ Variable   │    Estimate │ On Bound   │ Std Error    │
╞════════════╪═════════════╪════════════╪══════════════╡
│ g          │ 1.523e-08   │ yes        │ Not Reported │
│ b1         │ 0.00109945  │ no         │ 0.282148     │
│ b2         │ 1.3118e-20  │ yes        │ Not Reported │
│ b3         │ 6.28232e-07 │ yes        │ Not Reported │
╘════════════╧═════════════╧════════════╧══════════════╛
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.732306  │  0.0366153 │       0.318708    │
│     75 │     20 │          5 │  5.87088   │  0.293544  │      -0.427626    │
│    125 │     20 │         15 │ 14.8896    │  0.744478  │       0.0566184   │
│    200 │     20 │         20 │ 19.8946    │  0.99473   │       0.325509    │
╘════════╧════════╧════════════╧════════════╧════════════╧═══════════════════╛

Analysis of Deviance:
╒═══════════════╤══════════════════╤════════════╤════════════╤═════════════╤═══════════╕
│ Model         │   Log-Likelihood │   # Params │ Deviance   │ Test d.f.   │ P-Value   │
╞═══════════════╪══════════════════╪════════════╪════════════╪═════════════╪═══════════╡
│ Full model    │         -26.4637 │          5 │ -          │ -           │ -         │
│ Fitted model  │         -26.7111 │          1 │ 0.494739   │ 4           │ 0.974011  │
│ Reduced model │         -67.6859 │          1 │ 82.4443    │ 4           │ 0         │
╘═══════════════╧══════════════════╧════════════╧════════════╧═════════════╧═══════════╛

You can select a best-fitting model and output reports generated will indicate this selection. This is a manual action. The example below selects the recommended model, but any model in the session could be selected.

session.select(model=session.recommended_model, notes="Lowest BMDL; recommended model")

Generated outputs (Excel, Word, JSON) would include model selection information.