elbow_helper package
Submodules
- elbow_helper.api module
- elbow_helper.bootstrap module
- elbow_helper.candidates module
- elbow_helper.cli_argparse module
- elbow_helper.cli_click module
- elbow_helper.clustering module
- elbow_helper.config module
- Author
RobustKneeConfigRobustKneeConfig.bootstrap_replicatesRobustKneeConfig.boundary_marginRobustKneeConfig.cluster_toleranceRobustKneeConfig.cv_foldsRobustKneeConfig.max_bootstrap_median_shiftRobustKneeConfig.max_ci90_widthRobustKneeConfig.max_cluster_madRobustKneeConfig.max_direction_violation_rateRobustKneeConfig.max_neighbor_shiftRobustKneeConfig.max_null_p_valueRobustKneeConfig.max_secondary_cluster_rateRobustKneeConfig.min_bic_improvementRobustKneeConfig.min_bootstrap_detection_rateRobustKneeConfig.min_consecutive_scalesRobustKneeConfig.min_cv_improvementRobustKneeConfig.min_dominance_ratioRobustKneeConfig.min_noise_prominence_ratioRobustKneeConfig.min_primary_cluster_rateRobustKneeConfig.min_prominenceRobustKneeConfig.min_samplesRobustKneeConfig.min_sensitivity_supportRobustKneeConfig.min_side_pointsRobustKneeConfig.min_slope_contrastRobustKneeConfig.min_spearman_absRobustKneeConfig.null_replicatesRobustKneeConfig.random_seedRobustKneeConfig.secondary_support_fracRobustKneeConfig.sensitivity_fractionsRobustKneeConfig.slope_left_windowRobustKneeConfig.slope_right_windowRobustKneeConfig.smoothing_fractionsRobustKneeConfig.with_()
RobustKneesConfig
- elbow_helper.locator module
- elbow_helper.mcp_server module
- elbow_helper.metrics module
- elbow_helper.multi_criteria module
- elbow_helper.multi_fwer module
- elbow_helper.multi_pipeline module
- elbow_helper.multi_segmentation module
- elbow_helper.null_test module
- elbow_helper.numerics module
- elbow_helper.pipeline module
- elbow_helper.plotting module
- elbow_helper.preprocessing module
- elbow_helper.search module
- elbow_helper.segmented module
- elbow_helper.smoothing module
- elbow_helper.types module
- Author
BootstrapEvidenceBootstrapEvidence.passesBootstrapEvidence.detection_rateBootstrapEvidence.ci90BootstrapEvidence.ci90_widthBootstrapEvidence.primary_cluster_rateBootstrapEvidence.secondary_cluster_rateBootstrapEvidence.median_shiftBootstrapEvidence.kneesBootstrapEvidence.reasonBootstrapEvidence.ci90BootstrapEvidence.ci90_widthBootstrapEvidence.detection_rateBootstrapEvidence.kneesBootstrapEvidence.median_shiftBootstrapEvidence.passesBootstrapEvidence.primary_cluster_rateBootstrapEvidence.reasonBootstrapEvidence.secondary_cluster_rate
CandidateClusterCandidateCluster.median_kneeCandidateCluster.madCandidateCluster.membersCandidateCluster.n_windowsCandidateCluster.consecutive_scalesCandidateCluster.sensitivity_supportCandidateCluster.neighbor_shiftCandidateCluster.supportCandidateCluster.support_fracCandidateCluster.median_prominenceCandidateCluster.median_noise_prominence_ratioCandidateCluster.persistentCandidateCluster.stable_windowCandidateCluster.consecutive_scalesCandidateCluster.madCandidateCluster.median_kneeCandidateCluster.median_noise_prominence_ratioCandidateCluster.median_prominenceCandidateCluster.membersCandidateCluster.n_windowsCandidateCluster.neighbor_shiftCandidateCluster.persistentCandidateCluster.sensitivity_supportCandidateCluster.stable_windowCandidateCluster.supportCandidateCluster.support_frac
ClearKneeClearKnee.knee_xClearKnee.knee_x_normClearKnee.knee_indexClearKnee.ci90ClearKnee.detection_rateClearKnee.prominenceClearKnee.slope_contrastClearKnee.bic_improvementClearKnee.null_p_valueClearKnee.bic_improvementClearKnee.ci90ClearKnee.detection_rateClearKnee.knee_indexClearKnee.knee_xClearKnee.knee_x_normClearKnee.null_p_valueClearKnee.prominenceClearKnee.sensitivityClearKnee.slope_contrastClearKnee.smoothing_window
InvalidKneesKneeCandidateKneeCandidate.knee_x_normKneeCandidate.knee_indexKneeCandidate.windowKneeCandidate.sensitivityKneeCandidate.prominenceKneeCandidate.local_noiseKneeCandidate.noise_prominence_ratioKneeCandidate.boundary_distanceKneeCandidate.rejectedKneeCandidate.boundary_distanceKneeCandidate.knee_indexKneeCandidate.knee_x_normKneeCandidate.local_noiseKneeCandidate.noise_prominence_ratioKneeCandidate.prominenceKneeCandidate.rejectedKneeCandidate.sensitivityKneeCandidate.window
KneeEstimateKneeResultKneesMultiKneeResultNoClearKneeNullEvidencePreparedCurvePreparedCurve.nPreparedCurve.spearmanPreparedCurve.violation_ratePreparedCurve.curvePreparedCurve.denormalize_x()PreparedCurve.directionPreparedCurve.nPreparedCurve.spearmanPreparedCurve.violation_ratePreparedCurve.x_hiPreparedCurve.x_loPreparedCurve.x_normPreparedCurve.y_hiPreparedCurve.y_loPreparedCurve.y_scaled
ReasonReason.ALL_CANDIDATES_WEAKReason.BOOTSTRAP_MULTIMODALReason.BOOTSTRAP_UNSTABLEReason.BOUNDARY_KNEEReason.CLEAR_KNEEReason.INCOMPATIBLE_GLOBAL_SHAPEReason.INSUFFICIENT_DATAReason.INTERNAL_NUMERICAL_FAILUREReason.INVALID_INPUTReason.KNEES_FOUNDReason.MULTIPLE_PLAUSIBLE_KNEESReason.NO_KNEE_CANDIDATESReason.NO_PERSISTENT_CLUSTERReason.NULL_NOT_REJECTEDReason.SEGMENTED_MODEL_NOT_BETTERReason.WEAK_SLOPE_CHANGEReason.ZERO_RANGE
SegmentEvidenceSegmentEvidence.passesSegmentEvidence.slope_contrastSegmentEvidence.bic_improvementSegmentEvidence.cv_improvementSegmentEvidence.reasonSegmentEvidence.bic_improvementSegmentEvidence.cv_improvementSegmentEvidence.m_leftSegmentEvidence.m_rightSegmentEvidence.passesSegmentEvidence.reasonSegmentEvidence.slope_contrast
Module contents
elbow-helper — noise-robust knee/elbow detection.
A conservative wrapper around a from-scratch, NumPy-only difference-curve locator. Point-estimate knee detectors propose where plausible knees are; this package decides whether any candidate is strong, unique, persistent, reproducible and unlikely under a no-knee model and otherwise abstains explicitly.
Public API
robust_knee(x, y=None, curve=None, direction=None, config=None) ->
ClearKnee | NoClearKnee. y may be omitted (x is then
the y-values alone, against an implicit 0, 1, ..., n-1); curve and
direction are inferred from the data when omitted. robust_elbow(x,
y=None, config=None) is the convex-decreasing convenience.
RobustKneeConfig holds every threshold. KneeLocator is the
from-scratch locator, usable standalone.
robust_knees(x, y=None, config=None) (plural) -> Knees |
InvalidKnees: how many knees, if any, a curve genuinely has, via
dynamic-program search and a Bonferroni-gated modified-BIC criterion (see
ELBOW-en.tex and research/multiknee/RESULTS.md). RobustKneesConfig
holds its settings.
- class elbow_helper.ClearKnee(reason, diagnostics=<factory>, knee_x=0.0, knee_x_norm=0.0, knee_index=0, ci90=(0.0, 0.0), detection_rate=0.0, smoothing_window=1, sensitivity=1.0, prominence=0.0, slope_contrast=0.0, bic_improvement=0.0, null_p_value=1.0)[source]
Bases:
KneeResultA knee accepted by every stage of the pipeline, with uncertainty.
- Parameters:
- smoothing_window, sensitivity
The scale-space setting that produced the winning candidate.
- class elbow_helper.InvalidKnees(reason, diagnostics=<factory>)[source]
Bases:
MultiKneeResultPreprocessing failed: the input could not be searched at all.
- class elbow_helper.KneeEstimate(x, x_norm, index, slope_left, slope_right, fwer_p_value=None)[source]
Bases:
objectOne accepted breakpoint from
elbow_helper.robust_knees().Segments are independent (discontinuous) OLS lines, not the continuous broken-line model
ClearKneeuses;slope_left/slope_rightare each segment’s own fitted slope, in data units and need not agree at the breakpoint.- Parameters:
- slope_left, slope_right
Each neighbouring segment’s own fitted slope, data units.
- Type:
- class elbow_helper.KneeLocator(x, y, S=1.0, curve='concave', direction='increasing', interp_method='interp1d', online=False, polynomial_degree=7)[source]
Bases:
objectLocate the point of maximum curvature (knee/elbow) of a curve.
A NumPy-only implementation of the difference-curve locator, exposing the public surface used by this package:
knee,norm_knee,all_knees,all_norm_knees,x_difference/y_differenceand the extrema indices.- Parameters:
x (array-like) – Input coordinates, equal length.
xmust be strictly increasing.y (array-like) – Input coordinates, equal length.
xmust be strictly increasing.S (float, optional) – Sensitivity; larger values are more conservative. Default
1.0.curve (str, optional) –
"concave"to detect knees,"convex"to detect elbows.direction (str, optional) –
"increasing"or"decreasing".interp_method (str, optional) –
"interp1d"(identity fit) or"polynomial"(numpy.polyfit).online (bool, optional) – If
True, keep correcting the knee while traversing; ifFalse, return the first knee found. DefaultFalse.polynomial_degree (int, optional) – Degree used when
interp_method="polynomial". Default7.
- property all_elbows
Alias for
all_knees, for callers who think in “elbows”.
- property all_norm_elbows
Alias for
all_norm_knees, for callers who think in “elbows”.
- property elbow
Alias for
knee, for callers who think in “elbows”.
- property norm_elbow
Alias for
norm_knee, for callers who think in “elbows”.
- static transform_y(y, direction, curve)[source]
Orient
yto a concave, increasing frame (elbows become knees).- Parameters:
- Returns:
y, flipped and/or mirrored so the concave-increasing bump logic infind_knee()applies unchanged.- Return type:
numpy.ndarray
- class elbow_helper.KneeResult(reason, diagnostics=<factory>)[source]
Bases:
objectBase class for the tagged union returned by
robust_knee().- property is_clear: bool
TrueforClearKnee,FalseforNoClearKnee.
- class elbow_helper.Knees(reason, diagnostics=<factory>, knees=<factory>)[source]
Bases:
MultiKneeResultA valid multi-knee result: zero or more accepted breakpoints.
Unlike
NoClearKnee, an emptykneeslist here is not an abstention: it is the pipeline’s confident conclusion that the data has no real breakpoint, having survived the same search and false-positive gates a nonempty result would have to survive.- Parameters:
reason (str)
diagnostics (Dict)
knees (List[KneeEstimate])
- knees: List[KneeEstimate]
- class elbow_helper.MultiKneeResult(reason, diagnostics=<factory>)[source]
Bases:
objectBase class for the tagged union returned by
elbow_helper.robust_knees().- property is_valid: bool
TrueforKnees,FalseforInvalidKnees.
- class elbow_helper.NoClearKnee(reason, diagnostics=<factory>)[source]
Bases:
KneeResultAn explicit abstention: no knee is strong enough to report.
- class elbow_helper.Reason[source]
Bases:
objectStable, machine-readable abstention (and status) reason codes.
- ALL_CANDIDATES_WEAK = 'ALL_CANDIDATES_WEAK'
- BOOTSTRAP_MULTIMODAL = 'BOOTSTRAP_MULTIMODAL'
- BOOTSTRAP_UNSTABLE = 'BOOTSTRAP_UNSTABLE'
- BOUNDARY_KNEE = 'BOUNDARY_KNEE'
- CLEAR_KNEE = 'CLEAR_KNEE'
- INCOMPATIBLE_GLOBAL_SHAPE = 'INCOMPATIBLE_GLOBAL_SHAPE'
- INSUFFICIENT_DATA = 'INSUFFICIENT_DATA'
- INTERNAL_NUMERICAL_FAILURE = 'INTERNAL_NUMERICAL_FAILURE'
- INVALID_INPUT = 'INVALID_INPUT'
- KNEES_FOUND = 'KNEES_FOUND'
- MULTIPLE_PLAUSIBLE_KNEES = 'MULTIPLE_PLAUSIBLE_KNEES'
- NO_KNEE_CANDIDATES = 'NO_KNEE_CANDIDATES'
- NO_PERSISTENT_CLUSTER = 'NO_PERSISTENT_CLUSTER'
- NULL_NOT_REJECTED = 'NULL_NOT_REJECTED'
- SEGMENTED_MODEL_NOT_BETTER = 'SEGMENTED_MODEL_NOT_BETTER'
- WEAK_SLOPE_CHANGE = 'WEAK_SLOPE_CHANGE'
- ZERO_RANGE = 'ZERO_RANGE'
- class elbow_helper.RobustKneeConfig(min_samples=20, smoothing_fractions=(0.0, 0.02, 0.03, 0.05, 0.08, 0.12, 0.18, 0.25), sensitivity_fractions=(0.0, 0.01, 0.02, 0.05), min_spearman_abs=0.6, max_direction_violation_rate=0.25, boundary_margin=0.1, min_side_points=5, min_prominence=0.05, min_noise_prominence_ratio=4.0, cluster_tolerance=0.06, min_consecutive_scales=3, min_sensitivity_support=0.7, max_cluster_mad=0.03, max_neighbor_shift=0.07, secondary_support_frac=0.3, min_dominance_ratio=2.0, slope_left_window=(0.15, 0.03), slope_right_window=(0.03, 0.15), min_slope_contrast=0.3, min_cv_improvement=0.1, min_bic_improvement=10.0, cv_folds=5, bootstrap_replicates=100, min_bootstrap_detection_rate=0.9, max_ci90_width=0.1, min_primary_cluster_rate=0.8, max_secondary_cluster_rate=0.15, max_bootstrap_median_shift=0.03, null_replicates=200, max_null_p_value=0.01, random_seed=None)[source]
Bases:
objectImmutable bundle of thresholds and search settings.
Use
with_()to derive a tweaked copy (the dataclass is frozen).- Parameters:
min_samples (int)
min_spearman_abs (float)
max_direction_violation_rate (float)
boundary_margin (float)
min_side_points (int)
min_prominence (float)
min_noise_prominence_ratio (float)
cluster_tolerance (float)
min_consecutive_scales (int)
min_sensitivity_support (float)
max_cluster_mad (float)
max_neighbor_shift (float)
secondary_support_frac (float)
min_dominance_ratio (float)
min_slope_contrast (float)
min_cv_improvement (float)
min_bic_improvement (float)
cv_folds (int)
bootstrap_replicates (int)
min_bootstrap_detection_rate (float)
max_ci90_width (float)
min_primary_cluster_rate (float)
max_secondary_cluster_rate (float)
max_bootstrap_median_shift (float)
null_replicates (int)
max_null_p_value (float)
random_seed (int | None)
- class elbow_helper.RobustKneesConfig(min_samples=20, k_max=4, min_seg_fraction=0.08, fwer_alpha=0.05, fwer_permutations=200, require_fwer_confirmation=True, random_seed=None)[source]
Bases:
objectImmutable settings for
elbow_helper.robust_knees()(plural).The multi-knee search ships the combination validated in
research/multiknee/RESULTS.md: dynamic-program search, the subtractive-sign modified BIC as the selection criterion, and a Bonferroni-gated sequential permutation test layered on top by default, matching this package’s design priority of minimising false-positive knees. Usewith_()to derive a tweaked copy.- Parameters:
- elbow_helper.robust_elbow(x, y=None, config=None)[source]
Convenience wrapper for the classic convex-decreasing elbow.
Equivalent to
robust_knee()withcurve="convex"anddirection="decreasing", the k-means inertia / scree-plot case.ymay be omitted, as inrobust_knee().- Parameters:
config (RobustKneeConfig | None)
- Return type:
- elbow_helper.robust_knee(x, y=None, curve=None, direction=None, config=None)[source]
Detect a knee conservatively or abstain with a reason.
- Parameters:
x (array-like) – The curve:
x[i]maps toy[i].xneed not be sorted or unique; preprocessing handles cleaning, sorting, deduplication and normalization.ymay be omitted, in which casexis taken to be the sequence of y-values alone and the implicit x-axis0, 1, ..., n-1is used.y (array-like) – The curve:
x[i]maps toy[i].xneed not be sorted or unique; preprocessing handles cleaning, sorting, deduplication and normalization.ymay be omitted, in which casexis taken to be the sequence of y-values alone and the implicit x-axis0, 1, ..., n-1is used.curve (str, optional) –
"concave"(knees) or"convex"(elbows). If omitted, inferred from the data: a curve lying above the chord connecting its endpoints is concave, below is convex.direction (str, optional) –
"increasing"or"decreasing". If omitted, inferred from the sign of the trend betweenxandy.config (RobustKneeConfig, optional) – Thresholds and replicate counts. Defaults to
RobustKneeConfig.
- Returns:
A
ClearKnee(with location, 90% interval and diagnostics) or aNoClearKnee(with a reason code and diagnostics).- Return type:
- elbow_helper.robust_knees(x, y=None, config=None)[source]
Detect zero or more knees, with the same abstain-rather-than-guess discipline.
Unlike
robust_knee(), an empty result is not an abstention: it is the pipeline’s confident conclusion that the data has no real breakpoint, having survived the same search and false-positive gates a nonempty result would have to survive. Only preprocessing failures (bad input, too little data, zero range) returnInvalidKnees.- Parameters:
x (array-like) – The curve:
x[i]maps toy[i].ymay be omitted, in which casexis taken to be the y-values alone against an implicit0, 1, ..., n-1, as inrobust_knee(). Nocurveordirectionis needed: segments may alternate slope sign freely.y (array-like) – The curve:
x[i]maps toy[i].ymay be omitted, in which casexis taken to be the y-values alone against an implicit0, 1, ..., n-1, as inrobust_knee(). Nocurveordirectionis needed: segments may alternate slope sign freely.config (RobustKneesConfig, optional) – Search size, false-positive-control settings. Defaults to
RobustKneesConfig.
- Returns:
A
Knees(with zero or moreKneeEstimate, and diagnostics from every stage) or anInvalidKnees(with a reason code, for unusable input only).- Return type: