Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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