Skip to content
This repository has been archived by the owner on Jan 21, 2025. It is now read-only.

321-collated-nomenclature #130

Closed
wants to merge 14 commits into from
4 changes: 2 additions & 2 deletions bmds/bmds3/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,14 +127,14 @@ class ContinuousModelChoices(Enum):
)
c_exp_m3 = ContinuousModel(
id=ContinuousModelIds.c_exp_m3.value,
verbose="ExponentialM3",
verbose="Exponential 3",
params=("a", "b", "c", "d"),
variance_params=("rho", "log-alpha"),
model_form_str="P[dose] = a * exp(±1 * (b * dose) ^ d)",
)
c_exp_m5 = ContinuousModel(
id=ContinuousModelIds.c_exp_m5.value,
verbose="ExponentialM5",
verbose="Exponential 5",
params=("a", "b", "c", "d"),
variance_params=("rho", "log-alpha"),
model_form_str="P[dose] = a * (c - (c - 1) * exp(-(b * dose) ^ d)",
Expand Down
2 changes: 1 addition & 1 deletion bmds/bmds3/models/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ def cdf_plot(self, figsize: tuple[float, float] | None = None):
fig = plotting.create_empty_figure(figsize=figsize)
ax = fig.gca()
ax.set_xlabel(self.dataset.get_xlabel())
ax.set_ylabel("Percentile")
ax.set_ylabel("Cumulative Probability")
ax.plot(
self.results.fit.bmd_dist[0],
self.results.fit.bmd_dist[1],
Expand Down
2 changes: 1 addition & 1 deletion bmds/bmds3/models/continuous.py
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ class Polynomial(BmdModelContinuous):
degree_required: bool = True

def name(self) -> str:
return self.settings.name or f"Polynomial {self.settings.degree}°"
return self.settings.name or f"Polynomial {self.settings.degree}"

def get_model_settings(
self, dataset: ContinuousDatasets, settings: InputModelSettings
Expand Down
12 changes: 6 additions & 6 deletions bmds/bmds3/reporting.py
Original file line number Diff line number Diff line change
Expand Up @@ -254,8 +254,8 @@ def write_frequentist_table(report: Report, session: BmdsSession):
write_cell(tbl.cell(0, 3), "BMDU", style=hdr)
write_pvalue_header(tbl.cell(0, 4), style=hdr)
write_cell(tbl.cell(0, 5), "AIC", style=hdr)
write_cell(tbl.cell(0, 6), "Scaled Residual for Dose Group near BMD", style=hdr)
write_cell(tbl.cell(0, 7), "Scaled Residual for Control Dose Group", style=hdr)
write_cell(tbl.cell(0, 6), "Scaled Residual near BMD", style=hdr)
write_cell(tbl.cell(0, 7), "Scaled Residual at Control", style=hdr)
write_cell(tbl.cell(0, 8), "Recommendation and Notes", style=hdr)

# write body
Expand Down Expand Up @@ -382,8 +382,8 @@ def write_bayesian_table(report: Report, session: BmdsSession):
write_cell(tbl.cell(0, 4), "BMD", style=hdr)
write_cell(tbl.cell(0, 5), "BMDU", style=hdr)
write_cell(tbl.cell(0, 6), "Unnormalized Log Posterior Probability", style=hdr)
write_cell(tbl.cell(0, 7), "Scaled Residual for Dose Group near BMD", style=hdr)
write_cell(tbl.cell(0, 8), "Scaled Residual for Control Dose Group", style=hdr)
write_cell(tbl.cell(0, 7), "Scaled Residual near BMD", style=hdr)
write_cell(tbl.cell(0, 8), "Scaled Residual at Control", style=hdr)

ma = session.model_average
for idx, model in enumerate(session.models, start=1):
Expand Down Expand Up @@ -441,8 +441,8 @@ def write_model(report: Report, model: BmdModel, bmd_cdf_table: bool, header_lev


def write_bmd_cdf_table(report: Report, model: BmdModel):
df = pd.DataFrame(data=model.results.fit.bmd_dist.T, columns=["BMD", "Percentile"])
df_to_table(report, df[["Percentile", "BMD"]])
df = pd.DataFrame(data=model.results.fit.bmd_dist.T, columns=["BMD", "Cumulative Probability"])
df_to_table(report, df[["Cumulative Probability", "BMD"]])


def write_setting_p(report: Report, title: str, value: str):
Expand Down
2 changes: 1 addition & 1 deletion bmds/bmds3/sessions.py
Original file line number Diff line number Diff line change
Expand Up @@ -319,7 +319,7 @@ def to_docx(
reporting.write_models(report, self, bmd_cdf_table, header_level + 2)

else:
report.document.add_paragraph("Frequentist Summary", h2)
report.document.add_paragraph("Maximum Likelihood Approach Summary", h2)
reporting.write_base_frequentist_table(report, self)
if all_models:
report.document.add_paragraph("Individual Model Results", h2)
Expand Down
74 changes: 44 additions & 30 deletions bmds/bmds3/types/continuous.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,16 +71,31 @@ def confidence_level(self) -> float:
def distribution(self) -> str:
return f"{self.disttype.distribution_type} + {self.disttype.variance_model}"

@property
def is_hybrid(self) -> bool:
if self.bmr_type in [ContinuousRiskType.HybridExtra, ContinuousRiskType.HybridAdded]:
return True

def tbl(self, show_degree: bool = True) -> str:
data = [
["BMR", self.bmr_text],
["Distribution", self.distribution],
["Modeling Direction", self.direction],
["Confidence Level", self.confidence_level],
["Tail Probability", self.tail_prob],
["Modeling Approach", self.priors.prior_class.name],
["Confidence Level (one-sided)", self.confidence_level],
]

if self.priors.prior_class.name in ["frequentist_restricted", "frequentist_unrestricted"]:
data.append(
["Modeling Approach", "MLE"],
)
else:
data.append(
["Modeling Approach", "Bayesian"],
)

if self.is_hybrid:
data.append(["Tail Probability", self.tail_prob])

if show_degree:
data.append(["Degree", self.degree])

Expand All @@ -90,15 +105,17 @@ def tbl(self, show_degree: bool = True) -> str:
return pretty_table(data, "")

def docx_table_data(self) -> list:
return [
data = [
["Setting", "Value"],
["BMR", self.bmr_text],
["Distribution", self.distribution],
["Modeling Direction", self.direction],
["Adverse Direction", self.direction],
["Maximum Polynomial Degree", self.degree],
["Confidence Level", self.confidence_level],
["Tail Probability", self.tail_prob],
["Confidence Level (one-sided)", self.confidence_level],
]
if self.is_hybrid:
data.append(["Tail Probability", self.tail_prob])
return data

def update_record(self, d: dict) -> None:
"""Update data record for a tabular-friendly export"""
Expand Down Expand Up @@ -250,8 +267,6 @@ class ContinuousParameters(BaseModel):
names: list[str]
values: NumpyFloatArray
se: NumpyFloatArray
lower_ci: NumpyFloatArray
upper_ci: NumpyFloatArray
bounded: NumpyFloatArray
cov: NumpyFloatArray
prior_type: NumpyIntArray
Expand Down Expand Up @@ -295,8 +310,6 @@ def from_model(cls, model) -> Self:
values=result.parms,
bounded=summary.bounded,
se=summary.stdErr[:slice],
lower_ci=summary.lowerConf[:slice],
upper_ci=summary.upperConf[:slice],
cov=cov,
prior_type=priors[0],
prior_initial_value=priors[1],
Expand All @@ -306,25 +319,21 @@ def from_model(cls, model) -> Self:
)

def tbl(self) -> str:
headers = "Variable|Estimate|Bounded|Std Error|Lower CI|Upper CI".split("|")
headers = "Variable|Estimate|On Bound|Std Error".split("|")
data = []
for name, value, bounded, se, lower_ci, upper_ci in zip(
for name, value, bounded, se in zip(
self.names,
self.values,
self.bounded,
self.se,
self.lower_ci,
self.upper_ci,
strict=True,
):
data.append(
(
name,
value,
BOOL_ICON[bounded],
"NA" if bounded else f"{se:g}",
"NA" if bounded else f"{lower_ci:g}",
"NA" if bounded else f"{upper_ci:g}",
"Not Reported" if bounded else f"{se:g}",
)
)
return pretty_table(data, headers)
Expand All @@ -344,8 +353,6 @@ def rows(self, extras: dict) -> list[dict]:
name=self.names[i],
value=self.values[i],
se=self.se[i],
lower_ci=self.lower_ci[i],
upper_ci=self.upper_ci[i],
bounded=bool(self.bounded[i]),
initial_distribution=PriorType(self.prior_type[i]).name,
initial_value=self.prior_initial_value[i],
Expand Down Expand Up @@ -397,8 +404,8 @@ def from_model(cls, model) -> Self:
)

def tbl(self, disttype: constants.DistType) -> str:
mean_headers = "Dose|Size|Observed Mean|Calculated Mean|Estimated Mean|Scaled Residual"
sd_headers = "Dose|Size|Observed SD|Calculated SD|Estimated SD"
mean_headers = "Dose|N|Sample Mean|Model fitted Mean|Scaled Residual"
sd_headers = "Dose|N|Sample SD|Model fitted SD"
if disttype == constants.DistType.log_normal:
mean_headers = mean_headers.replace("ted Mean", "ted Median")
sd_headers = sd_headers.replace("ted SD", "ted GSD")
Expand All @@ -410,7 +417,6 @@ def tbl(self, disttype: constants.DistType) -> str:
self.dose[idx],
self.size[idx],
self.obs_mean[idx],
self.calc_mean[idx],
self.est_mean[idx],
self.residual[idx],
]
Expand All @@ -420,7 +426,6 @@ def tbl(self, disttype: constants.DistType) -> str:
self.dose[idx],
self.size[idx],
self.obs_sd[idx],
self.calc_sd[idx],
self.est_sd[idx],
]
)
Expand Down Expand Up @@ -478,7 +483,7 @@ def from_model(cls, model) -> Self:
)

def tbl(self) -> str:
headers = "Name|Loglikelihood Ratio|Test DOF|P-Value".split("|")
headers = "Name|-2* Log(Likelihood Ratio)|Test d.f.|P-Value".split("|")
data = []
for name, ll_ratio, df, p_value in zip(
self.names, self.ll_ratios, self.dfs, self.p_values, strict=True
Expand Down Expand Up @@ -529,28 +534,37 @@ def tbl(self) -> str:
["BMDL", self.bmdl],
["BMDU", self.bmdu],
["AIC", self.fit.aic],
["Log Likelihood", self.fit.loglikelihood],
["-2* Log(Likelihood Ratio)", self.fit.loglikelihood],
["P-Value", self.tests.p_values[3]],
["Model DOF", self.tests.dfs[3]],
["Model d.f.", self.tests.dfs[3]],
]
return pretty_table(data, "")

def bound_footnote(self) -> str:
if any(self.parameters.bounded):
return """
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
"""

def text(self, dataset: ContinuousDatasets, settings: ContinuousModelSettings) -> str:
return multi_lstrip(
f"""
Summary:
Modeling Summary:
{self.tbl()}

Model Parameters:
{self.parameters.tbl()}
{self.bound_footnote()}

Goodness of Fit:
{self.gof.tbl(disttype=settings.disttype)}

Likelihoods of Interest:
Likelihoods:
{self.deviance.tbl()}

Tests of Interest:
Tests of Mean and Variance Fits:
{self.tests.tbl()}
"""
)
Expand Down
2 changes: 1 addition & 1 deletion bmds/bmds3/types/dichotomous.py
Original file line number Diff line number Diff line change
Expand Up @@ -345,7 +345,7 @@ def from_model(cls, model) -> Self:
)

def tbl(self) -> str:
headers = "Model|Log Likelihood|# Params|Deviance|Test DOF|P-Value".split("|")
headers = "Model|Log Likelihood|# Params|Deviance|Test d.f.|P-Value".split("|")
data = []
for i in range(len(self.names)):
# manually format columns b/c tabulate won't format if first row text is str
Expand Down
2 changes: 1 addition & 1 deletion bmds/bmds3/types/nested_dichotomous.py
Original file line number Diff line number Diff line change
Expand Up @@ -328,7 +328,7 @@ def tbl(self) -> str:
["BMDL", self.summary.bmdl],
["BMDU", self.summary.bmdu],
["AIC", self.summary.aic],
["P-value", self.combined_pvalue],
["P-Value", self.combined_pvalue],
["D.O.F", self.dof],
["Chi²", self.summary.chi_squared],
["Log-likelihood", self.ll],
Expand Down
2 changes: 1 addition & 1 deletion bmds/datasets/continuous.py
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ def plot(self, figsize: tuple[float, float] | None = None) -> Figure:
self.doses,
self.means,
yerr=self.errorbars(),
label="Mean ± 95% CI",
label="Observed Mean ± 95% CI",
**plotting.DATASET_POINT_FORMAT,
)
ax.legend(**plotting.LEGEND_OPTS)
Expand Down
2 changes: 1 addition & 1 deletion bmds/stats/anova.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ def output_3tests(tests) -> str:

outputs = [
" Tests of Interest ",
" Test -2*log(Likelihood Ratio) Test df p-value ",
" Test -2*log(Likelihood Ratio) Test df P-Value ",
]
for i, test in enumerate([tests.test1, tests.test2, tests.test3]):
outputs.append(" Test %d %20.6g %10d %16.4g" % (i + 1, test.MSE, test.CDF, test.TEST))
Expand Down
2 changes: 0 additions & 2 deletions tests/bmds3/types/test_continuous.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,6 @@ def test_exp3(self, cdataset):
for field in [
"values",
"se",
"lower_ci",
"upper_ci",
"bounded",
"prior_type",
"prior_initial_value",
Expand Down
2 changes: 1 addition & 1 deletion tests/datasets/test_continuous.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ def test_correct_variance_model(self, cdataset):
def test_anova(self, anova_dataset, bad_anova_dataset):
# Check that anova generates expected output from original specifications.
report = anova_dataset.get_anova_report()
expected = " Tests of Interest \n Test -2*log(Likelihood Ratio) Test df p-value \n Test 1 22.2699 12 0.0346\n Test 2 5.5741 6 0.4725\n Test 3 5.5741 6 0.4725"
expected = " Tests of Interest \n Test -2*log(Likelihood Ratio) Test df P-Value \n Test 1 22.2699 12 0.0346\n Test 2 5.5741 6 0.4725\n Test 3 5.5741 6 0.4725"
assert report == expected

# check bad anova dataset
Expand Down
Loading