Reliability analysis¶
Detection probability with its interval, the smallest detectable deviation, the faults that look alike, and detection against the tolerance scale.
python examples/05_reliability.py
# %% [markdown]
# # Reliability analysis
#
# Compare detection, minimum detectable deviation, ambiguity and tolerance robustness.
# Also runnable as `python examples/05_reliability.py`.
# %%
import sys
from pathlib import Path
import pandas as pd
examples_dir = next(
(root / "examples" for root in (Path.cwd(), *Path.cwd().parents)
if (root / "examples" / "rc_study.py").is_file()),
None,
)
if examples_dir is not None:
sys.path.insert(0, str(examples_dir))
# %%
from rc_study import WORKERS, campaign # noqa: E402
from spicefault.reliability import ReliabilityAnalysis, robustness # noqa: E402
ALPHA = 0.02 # false-alarm rate the detector is set for
# %% [markdown]
# ## Build reliability analyses at two tolerance scales
#
# Compare the declared tolerance population with one three times wider.
# %%
if __name__ == "__main__":
pd.set_option("display.width", 160)
pd.set_option("display.float_format", "{:.3g}".format)
scales = (1.0, 3.0)
analyses = {}
for scale in scales:
run = campaign(f"rc_tolerance_x{scale:g}", tolerance_scale=scale)
run.run(workers=WORKERS, chunk=200, progress=False)
analyses[scale] = ReliabilityAnalysis.from_dataset(run.out_dir)
analysis = analyses[1.0]
# %% [markdown]
# ## Measure false alarms and detection
# %%
if __name__ == "__main__":
detection = analysis.detectability(alpha=ALPHA)
low, high = detection.false_alarm_interval
print(f"limit test set for a false-alarm rate of {ALPHA}")
print(f"measured on {detection.n_evaluation} healthy samples that did not set the limits: "
f"{detection.false_alarm:.3f} [{low:.3f}, {high:.3f}]") # fmt: skip
table = detection.table[["n_ok", "p_detect", "ci_low", "ci_high"]].join(
[analysis.standardised_shift(), analysis.auc()["auc"]]
)
print("\ndetection probability, with its interval; shift of the best feature; AUC:")
print(table)
# %% [markdown]
# ## Find limits and ambiguous faults
# %%
if __name__ == "__main__":
print("\nsmallest deviation detected at least 90 % of the time:")
print(analysis.minimum_detectable(alpha=ALPHA).drop(columns="grid").to_string(index=False))
ambiguity = analysis.ambiguity(threshold=3.0)
print("\nfaults not separated from the healthy circuits:", ambiguity.undetectable)
print("components that can be mistaken for each other:", ambiguity.confusable)
# %% [markdown]
# ## Compare robustness against tolerance
# %%
if __name__ == "__main__":
print("\ndetection against the tolerance scale (1 = the declared tolerances):")
print(robustness(analyses, alpha=ALPHA))