-
Notifications
You must be signed in to change notification settings - Fork 0
Major overhaul: Modularize run_length_control, full docs, and deadlock fix #6
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
Major overhaul: Modularize run_length_control, full docs, and deadlock fix #6
Conversation
- Split run_length_control.py into a package with staged private modules (_accuracy.py, _convergence.py, _equilibration.py, etc.) - Unified handling for ndim=1 and ndim>1 cases in the same code path - Added private helper functions for improved design and maintainability - Introduced new unit tests (test_run_length_control.py) covering various functionalities - keep full backward compatibility at package level
…ides - Migrated from minimal README-based docs to a complete Sphinx documentation structure - Added new sections: Getting Started, Overview, Theory, Best Practices, Examples, API reference, References, Contributing, and Troubleshooting - Enabled auto-generation of module API docs using sphinx-apidoc - Improved overall structure, cross-references, and build configuration - track empty Sphinx build directories (_build, _static, _templates). These directories are required for consistent Sphinx builds across environments and are commonly kept under version control in Sphinx projects.
- Added/updated build-system requires and optional-dependencies for Sphinx and required extensions - Ensures `pip install .[docs]` correctly installs documentation build tools
Certain BLAS implementations (e.g., OpenBLAS, MKL) acquire
internal locks that can deadlock when called re-entrantly
from within an existing OpenMP thread pool, such as when
kim-convergence is used inside LAMMPS.
This commit introduces optional subprocess isolation for the
numerically intensive correlation and periodogram computations,
which are the primary sources of BLAS calls:
- Added KIM_CONV_FORCE_SUBPROC environment variable
- When set to any value, autocovariance, cross-covariance, and
modified periodogram computations are executed in isolated
subprocesses using multiprocessing with the "spawn" start method
- Subprocesses load fresh, independent BLAS libraries, eliminating
re-entrancy and preventing deadlocks
- Introduced private helpers:
- _isolate() and _isolate_perio() for spawning subprocesses
- _subproc_corr() and _subproc_perio() as subprocess targets
- Retained both FFT-based (_fft_corr) and direct (_direct_corr)
correlation paths
- Preserved all existing validation, numerical accuracy, and
behavior when the environment variable is unset (default:
direct in-process computation)
This provides a robust compatibility path for heavily multi-threaded
simulation environments without sacrificing performance in normal use.
- Standardized and cleaned up docstrings across the package for consistency and alignment with Sphinx documentation - Removed redundant/outdated references from docstrings to avoid duplication with the dedicated References section - Unified formatting, tone, and structure of public-facing docstrings and comments - Resolved numerous static analyzer warnings (type issues, etc.) - Improved overall code clarity and quality without any behavioral changes Prepares the codebase for clean CI runs and high-quality generated documentation.
0227350 to
fa48b3d
Compare
fa48b3d to
b17b03b
Compare
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
📝 WalkthroughWalkthroughReplace the single-file run_length_control with a run_length_control package of private helpers and a public core; restore and expand explicit public exports and defaults; refactor UCL, timeseries, stats, utils, and scale typing/validation; add comprehensive docs, tests, and simplify CI dependency install. Changes
Sequence Diagram(s)%%{init: {"theme":"base","themeVariables":{"actorBorder":"#334155","noteBackground":"#f8fafc","primaryColor":"#0f766e"}}}%%
sequenceDiagram
autonumber
participant User
participant Core as run_length_control()
participant Setup as _setup_algorithm
participant Equil as _equilibration_stage
participant Conv as _convergence_stage
participant UCL as UCL (MSER/N‑SKART/Heidelberger)
User->>Core: call run_length_control(get_trajectory, ...)
Core->>Setup: validate params, instantiate/configure UCL
Setup-->>Core: return ucl_obj, max_equil_step
Core->>Equil: iterative equilibration detection (MSER / IAT / batching)
Equil-->>Core: ts_data, run_length, equil_indices, equil_detected
Core->>Conv: per-variable convergence checks
Conv->>UCL: compute per-variable UCL, ESS, stats
UCL-->>Conv: return UCL, ESS, stats
Conv->>Conv: evaluate accuracy & population tests
alt converged
Conv-->>Core: convergence report
Core-->>User: return success or serialized report
else needs more data
Conv->>Equil: request extended trajectory
Equil-->>Conv: appended data
Conv->>UCL: recompute UCL
end
Estimated code review effort🎯 5 (Critical) | ⏱️ ~120 minutes Poem
Pre-merge checks and finishing touches✅ Passed checks (3 passed)
✨ Finishing touches
Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 7
Note
Due to the large number of review comments, Critical, Major severity comments were prioritized as inline comments.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (6)
kim_convergence/outlier.py (1)
74-77: Docstring parameter name mismatch.The docstring refers to
methodbut the actual parameter is namedoutlier_method.🔎 Proposed fix
Args: x (array_like, 1d): Time series data. - method (str, optional): Method to detect what are outliers in the data. + outlier_method (str, optional): Method to detect what are outliers in the data. (default: 'iqr')kim_convergence/stats/normal_dist.py (1)
120-121: Same typo: "Ars:" should be "Args:"🔎 Proposed fix
- Ars: + Args: p {float} -- Probability (must be between 0.0 and 1.0)kim_convergence/utils.py (1)
86-95: Fix condition at line 88: should checktest_size_int, nottrain_size_int.When
test_sizeis an integer andtrain_sizeisNoneor float, the conditionelif train_size_intat line 88 evaluates toFalse, leavingn_testuninitialized. This causes a failure when line 98 later tries to usen_testto compute the complement.The condition should be
elif test_size_int:to explicitly handle the case wheretest_sizeis provided as an integer:Current logic issue
if test_size_float: n_test = np.ceil(test_size * n_samples) elif train_size_int: # <-- Wrong: checks train_size_int to set n_test assert test_size is not None n_test = float(test_size)Should be:
if test_size_float: n_test = np.ceil(test_size * n_samples) elif test_size_int: # <-- Correct: checks test_size_int to set n_test n_test = float(test_size)The condition at line 94 checking
train_size_intis correct and handles the complementary case (not redundant with the float check above).kim_convergence/timeseries/utils.py (2)
268-273: Duplicate docstring parameter.The
uncorrelated_sample_indicesparameter is documented twice in the docstring (lines 268-270 and 271-273).🔎 Proposed fix
uncorrelated_sample_indices (array_like, 1d, optional): indices of uncorrelated subsamples of the time series data. (default: None) - uncorrelated_sample_indices (array_like, 1d, optional): indices - of uncorrelated subsamples of the time series data. - (default: None)
399-410: Fix off-by-one error in array allocation.The
random_samplesarray at line 399 should be allocated withindices.size - 1elements, notindices.size. Theindicesarray represents block boundaries—with N boundaries there are N-1 blocks. The loop fills positions 0 through N-3, then the final assignment fills position -1 (which is N-1), leaving position N-2 uninitialized.This is evidenced by the similar function
time_series_data_uncorrelated_block_averaged_samplesimmediately below (line 491), which correctly allocatesindices.size - 1for the same block-based operation.Additionally, edge cases where
indiceshas fewer than 2 elements will cause index errors.kim_convergence/scale.py (1)
460-476: PotentialNameErrorinStandardScale.inversewhenwith_centering=False.When
with_scaling=Trueandwith_centering=False,self.mean_2isNone, so the assignment at line 464 is skipped. This causesinverse_scaled_xto be undefined when line 465 executes.🔎 Proposed fix
if self.with_scaling_: assert isinstance(self.std_, float) x = np.asarray(x) if self.mean_2 is not None: - inverse_scaled_x = x + self.mean_2 - inverse_scaled_x *= self.std_ + inverse_scaled_x = (x + self.mean_2) * self.std_ + else: + inverse_scaled_x = x * self.std_ else: inverse_scaled_x = np.array(x, copy=True)
🟡 Minor comments (26)
kim_convergence/stats/nonnormal_test.py-302-302 (1)
302-302: Typo: "takesno" should be "takes no".🔎 Proposed fix
- "gilbrat": ContinuousDistributions["gilbrat"] + " takesno arguments.", + "gilbrat": ContinuousDistributions["gilbrat"] + " takes no arguments.",kim_convergence/stats/nonnormal_test.py-874-877 (1)
874-877: Incorrect error message: "Levene test failed" should be "Kruskal test failed".This appears to be a copy-paste error from
levene_test.🔎 Proposed fix
try: _, pvalue = kruskal(x, y) except Exception: # noqa: BLE001 # intentional catch-all - raise CRError("Levene test failed.") + raise CRError("Kruskal test failed.")kim_convergence/stats/tools.py-635-638 (1)
635-638: Preserve exception context withraise ... from.The original exception is lost when re-raising. Use exception chaining to preserve the traceback for debugging.
🔎 Proposed fix
try: result = modified_periodogram(x, fft=fft, with_mean=with_mean) - except CRError: - raise CRError("Failed to compute a modified periodogram.") + except CRError as err: + raise CRError("Failed to compute a modified periodogram.") from errtests/test_kim_convergence/test_stats_s_normal_dist.py-6-10 (1)
6-10: Preserve import exception context.Add exception chaining to preserve the original import error for debugging.
🔎 Proposed fix
try: import kim_convergence as cr -except Exception: # noqa: BLE001 # intentional catch-all - raise RuntimeError("Failed to import `kim-convergence` utility module") +except Exception as e: # noqa: BLE001 # intentional catch-all + raise RuntimeError("Failed to import `kim-convergence` utility module") from etests/test_kim_convergence/test_outlier.py-6-9 (1)
6-9: Preserve import exception context.Same as other test files - add exception chaining for debugging.
🔎 Proposed fix
try: import kim_convergence as cr -except Exception: # noqa: BLE001 # intentional catch-all - raise RuntimeError("Failed to import `kim-convergence` utility module") +except Exception as e: # noqa: BLE001 # intentional catch-all + raise RuntimeError("Failed to import `kim-convergence` utility module") from etests/test_kim_convergence/test_stats_beta_dist.py-7-10 (1)
7-10: Chain the exception to preserve debugging context.The exception is re-raised without preserving the original error context, making debugging more difficult.
🔎 Proposed fix
try: import kim_convergence as cr -except Exception: # noqa: BLE001 # intentional catch-all - raise RuntimeError("Failed to import `kim-convergence` utility module") +except Exception as err: # noqa: BLE001 # intentional catch-all + raise RuntimeError("Failed to import `kim-convergence` utility module") from errThis preserves the original exception traceback, which is valuable for diagnosing import failures.
kim_convergence/stats/normal_dist.py-30-31 (1)
30-31: Typo in docstring: "Ars:" should be "Args:"🔎 Proposed fix
- Ars: + Args: p {float} -- Probability (must be between 0.0 and 1.0)kim_convergence/run_length_control/_convergence.py-354-357 (1)
354-357: Typo in docstring: "itn" should be "int".🔎 Proposed fix
converged : bool True if all variables fully converged. - total_run_length: itn + total_run_length: int Total number of steps in the trajectory.kim_convergence/run_length_control/_setup.py-106-110 (1)
106-110: Typo: "aproximate" should be "approximate".🔎 Proposed fix
if confidence_interval_approximation_method not in ucl_methods: raise CRError( f'method "{confidence_interval_approximation_method}" to ' - "aproximate confidence interval not found. Valid methods are:" + "approximate confidence interval not found. Valid methods are:" "\n\t- " + "\n\t- ".join(ucl_methods) )tests/test_kim_convergence/test_run_length_control.py-941-979 (1)
941-979: Samemktempdeprecation issue for multiple temp files.🔎 Proposed fix
def test_dump_trajectory_and_report_to_files(self): """Test simultaneous dumping of trajectory and JSON report to separate files.""" def constant_trajectory(step: int) -> np.ndarray: return np.full(step, 77.0) - traj_file = tempfile.mktemp(suffix=".edn") - report_file = tempfile.mktemp(suffix=".json") + with tempfile.NamedTemporaryFile(suffix=".edn", delete=False) as f: + traj_file = f.name + with tempfile.NamedTemporaryFile(suffix=".json", delete=False) as f: + report_file = f.name try:tests/test_kim_convergence/test_run_length_control.py-366-406 (1)
366-406: Replace deprecatedtempfile.mktempwithNamedTemporaryFile.
mktempis deprecated due to a race condition vulnerability (CWE-377) where an attacker could create a file at the returned path before your code does. UseNamedTemporaryFile(delete=False)instead.🔎 Proposed fix
def test_dump_and_edn_on_failure(self): """When convergence fails the full trajectory must be written to the requested file.""" - tmp = tempfile.mktemp(suffix=".edn") + with tempfile.NamedTemporaryFile(suffix=".edn", delete=False) as f: + tmp = f.name # a constant trajectory def constant_trajectory(step) -> np.ndarray:doc/conf.py-67-67 (1)
67-67: Fixconf_py_pathto match actual directory structure.The
conf_py_pathis set to"/docs/"but the documentation directory is nameddoc/(singular). This will cause incorrect "Edit on GitHub" links. Change line 67 to:"conf_py_path": "/doc/",doc/modules/ucl.rst-39-52 (1)
39-52: Incorrect toctree usage.The
toctreedirective expects document names (file paths without extensions), not numbered reference links. The numbered list with:ref:links should be outside thetoctreedirective.🔎 Proposed fix
Contents -------- -.. toctree:: - :maxdepth: 2 - -1. :ref:`Available Methods <ucl-methods>` -2. :ref:`Base Class <ucl-base-class>` -3. :ref:`MSER-m Algorithm <ucl-mser-m>` -4. :ref:`MSER-m-y Algorithm <ucl-mser-m-y>` -5. :ref:`N-SKART Algorithm <ucl-n-skart>` -6. :ref:`Heidelberger-Welch Algorithm <ucl-heidelberger-welch>` -7. :ref:`Uncorrelated Samples Method <ucl-uncorrelated-samples>` -8. :ref:`Usage Examples <ucl-usage-examples>` -9. :ref:`Algorithm Selection Guide <ucl-selection-guide>` -10. :ref:`Performance Considerations <ucl-performance>` -11. :ref:`Theoretical Background <ucl-theory>` +1. :ref:`Available Methods <ucl-methods>` +2. :ref:`Base Class <ucl-base-class>` +3. :ref:`MSER-m Algorithm <ucl-mser-m>` +4. :ref:`MSER-m-y Algorithm <ucl-mser-m-y>` +5. :ref:`N-SKART Algorithm <ucl-n-skart>` +6. :ref:`Heidelberger-Welch Algorithm <ucl-heidelberger-welch>` +7. :ref:`Uncorrelated Samples Method <ucl-uncorrelated-samples>` +8. :ref:`Usage Examples <ucl-usage-examples>` +9. :ref:`Algorithm Selection Guide <ucl-selection-guide>` +10. :ref:`Performance Considerations <ucl-performance>` +11. :ref:`Theoretical Background <ucl-theory>`doc/modules/ucl.rst-86-103 (1)
86-103: Fix automodule path: remove trailing.mser_m.The path
kim_convergence.ucl.mser_m.mser_mis incorrect for Sphinx's automodule directive. The automodule directive documents modules, not individual objects within them. The correct path should bekim_convergence.ucl.mser_mto include all public members of the module (themser_mfunction,MSER_mclass, and related functions).Current incorrect usage
.. automodule:: kim_convergence.ucl.mser_m.mser_m :members: :no-index:doc/conf.py-22-26 (1)
22-26: Use proper Sphinx listener API instead of accessing internal listener list.The current approach disconnects the last listener from
doctree-readby directly accessingapp.events.listeners, which is a private API. This is fragile because it:
- Relies on numpydoc's listener being registered last
- Breaks if extension load order or Sphinx internals change
- Violates Sphinx best practices
Per Sphinx documentation, store the listener ID from
app.connect()and useapp.disconnect(listener_id)to safely remove specific listeners. If numpydoc's relabeller conflicts with your documentation build, consider conditionally connecting to the relabeller or documenting why disconnecting by position is necessary.kim_convergence/ucl/n_skart.py-577-578 (1)
577-578: Preserve exception context when re-raising.Same issue as in
mser_m_y.py- use exception chaining to preserve the traceback.except CRError: - raise CRError("Failed to get the relative_half_width_estimate.") + raise CRError("Failed to get the relative_half_width_estimate.") from Nonekim_convergence/utils.py-73-74 (1)
73-74: Bug: Wrong variable in error message.The error message references
test_sizebut should referencetrain_size.if train_size_float and (train_size <= 0 or train_size >= 1): - raise CRError(f"train_size={test_size} should be a float in the [0, 1] range.") + raise CRError(f"train_size={train_size} should be a float in the [0, 1] range.")kim_convergence/ucl/mser_m_y.py-326-327 (1)
326-327: Preserve exception context when re-raising.The current code loses the original exception's traceback. Use exception chaining to preserve context for debugging.
except CRError: - raise CRError("Failed to get the relative_half_width_estimate.") + raise CRError("Failed to get the relative_half_width_estimate.") from NoneOr to preserve the original exception:
except CRError as err: - raise CRError("Failed to get the relative_half_width_estimate.") + raise CRError("Failed to get the relative_half_width_estimate.") from errkim_convergence/timeseries/utils.py-333-333 (1)
333-333: Typo in docstring: "Retuen" → "Return".🔎 Proposed fix
- r"""Retuen random data for each block after blocking the data. + r"""Return random data for each block after blocking the data.kim_convergence/ucl/mser_m.py-344-345 (1)
344-345: Typo: "parmeters" → "parameters".🔎 Proposed fix
- # unused input parmeters in + # unused input parameters inkim_convergence/ucl/ucl_base.py-486-486 (1)
486-486: Typo in comment: "Estimat" → "Estimate".🔎 Proposed fix
- # Estimat the relative half width + # Estimate the relative half widthkim_convergence/ucl/uncorrelated_samples.py-68-69 (1)
68-69: Typo: "parmeters" → "parameters".🔎 Proposed fix
- # unused input parmeters in + # unused input parameters inkim_convergence/ucl/spectral/heidelberger_welch.py-321-322 (1)
321-322: Typo: "parmeters" → "parameters".🔎 Proposed fix
- # unused input parmeters in + # unused input parameters inkim_convergence/timeseries/utils.py-423-423 (1)
423-423: Typo in docstring: "Retuen" → "Return".🔎 Proposed fix
- """Retuen average value for each block after blocking the data. + """Return average value for each block after blocking the data.kim_convergence/timeseries/utils.py-295-298 (1)
295-298: Missing space in error message.There's a missing space between "of" and "the" in the error message concatenation.
🔎 Proposed fix
except CRError: raise CRError( - "Failed to compute the indices of uncorrelated samples of" - "the time_series_data." - ) + "Failed to compute the indices of uncorrelated samples of " + "the time_series_data." + ) from Nonekim_convergence/scale.py-144-150 (1)
144-150: Remove unusedwith_centeringandwith_scalingparameters fromminmax_scaleandmaxabs_scale.These parameters are accepted but ignored. Unlike
translate_scale,standard_scale, androbust_scale, the underlyingMinMaxScaleandMaxAbsScaleclasses don't support these options. Remove the parameters to avoid confusing the API, or implement the behavior if intentional.
🧹 Nitpick comments (39)
pyproject.toml (1)
59-67: Consider tightening the Sphinx version constraint.The constraint
sphinx>=5is quite permissive. Sphinx 5.0 was released in 2022, and the current stable version is 7.x (as of 2024). Consider specifying a more recent minimum version or a version range to ensure consistent documentation builds and avoid compatibility issues with newer sphinx extensions.🔎 Suggested version constraint
[project.optional-dependencies] doc = [ - "sphinx>=5", + "sphinx>=7.0,<9.0", "sphinx-rtd-theme", "numpydoc", "myst-parser", "sphinxcontrib-mermaid", "sphinx-design", ]doc/troubleshooting.rst (1)
84-91: Consider the implications of adding noise to constant data.The code example adds random noise to constant data when variance is below 1e-10. While this is a pragmatic workaround, it fundamentally changes the data. Consider adding a warning that:
- This approach may not be scientifically valid for all use cases
- Users should investigate why their simulation produces constant data
- The noise magnitude (1e-8) should be chosen relative to the expected physical scale
kim_convergence/stats/beta_dist.py (1)
81-86:deepcopyis unnecessary for immutable float values.
_fpmaxand_fpminare floats, which are immutable in Python. Usingdeepcopyon them adds overhead without any benefit. Simple assignment is sufficient.🔎 Proposed fix
if fabs(d) < _fpmin: - d = deepcopy(_fpmax) - h = deepcopy(_fpmax) + d = _fpmax + h = _fpmax else: d = 1.0 / d - h = deepcopy(d) + h = dThis pattern repeats throughout the function (lines 101-102, 105, 108, 125-126, 129, 132). Consider removing all
deepcopycalls on float values.kim_convergence/run_length_control/_variable_list_factory.py (1)
40-45: Consider logging or narrowing the exception scope.The bare
except Exception: passsilently swallows all errors fromnp.isfinite(). While defensive, this could mask unexpected issues. Consider either narrowing to specific exceptions (e.g.,TypeError) or adding a debug log.🔎 Proposed fix
try: if not np.isfinite(value): return None - except Exception: # Defensive: some weird types might fail + except (TypeError, ValueError): # np.isfinite may fail on non-numeric types pass return valuekim_convergence/stats/nonnormal_test.py (1)
558-559: Missing exception chaining in re-raised exceptions.When catching an exception and raising a new one, use
raise ... from err(orfrom Noneto suppress the context) to preserve the exception chain. This helps with debugging by showing the original cause.🔎 Proposed fix for ks_test
try: _, pvalue = kstest( time_series_data, cdf=population_cdf, args=args, alternative="two-sided" ) - except Exception: # noqa: BLE001 # intentional catch-all - raise CRError("Kolmogorov-Smirnov test failed.") + except Exception as err: # noqa: BLE001 # intentional catch-all + raise CRError("Kolmogorov-Smirnov test failed.") from errThis pattern should also be applied at lines 690, 695, 782, 872, and 877.
kim_convergence/stats/tools.py (1)
1-38: Well-documented module-level docstring for the new environment variable.The documentation clearly explains the purpose, performance implications, and intended use cases for
KIM_CONV_FORCE_SUBPROC. The warnings about overhead in tests and development are helpful.Minor note: Line 21 contains an en-dash (
–) instead of a hyphen-minus (-). Consider using ASCII hyphen for consistency..readthedocs.yaml (1)
1-18: RTD configuration looks well-structured.The configuration uses modern settings (Ubuntu 24.04, Python 3.11) and properly installs the package with doc dependencies. Consider enabling
fail_on_warning: trueonce documentation stabilizes to catch issues early.tests/test_kim_convergence/test_outlier.py (1)
21-27: Redundant duplicate type assertions.
self.assertIsInstance()already validates the type and fails the test if incorrect. The additionalassert isinstance()on the next line is redundant.🔎 Proposed fix (applies to all 4 occurrences)
outlier_indices = cr.outlier_test(x, outlier_method="iqr") outlier_x = x[outlier_indices] self.assertIsInstance(outlier_indices, np.ndarray) - assert isinstance(outlier_indices, np.ndarray) self.assertTrue(outlier_indices.size == 2)tests/test_kim_convergence/test_scale.py (1)
10-10: Consider using exception chaining.While the error message change is fine, the static analysis hint suggests using
raise ... from errorraise ... from Noneto distinguish import failures from other errors.🔎 Proposed improvement
try: import kim_convergence as cr -except Exception: # noqa: BLE001 # intentional catch-all - raise RuntimeError("Failed to import `kim-convergence` utility module") +except Exception as err: # noqa: BLE001 # intentional catch-all + raise RuntimeError("Failed to import `kim-convergence` utility module") from errkim_convergence/stats/__init__.py (1)
16-17: Remove unusednoqadirectives.Static analysis correctly identifies that the
# noqa: F401comments on lines 16-17 are no longer needed, as the F401 rule is not enabled in the current configuration.🔎 Proposed cleanup
kruskal_test, wilcoxon_test, -) # noqa: F401 +) from .randomness_test import randomness_test # noqa: F401Wait, let me check line 17 as well:
-) # noqa: F401 +) -from .randomness_test import randomness_test # noqa: F401 +from .randomness_test import randomness_testtests/test_kim_convergence/test_batch.py (1)
9-9: Consider using exception chaining.While the error message change is fine, the static analysis hint suggests using
raise ... from errorraise ... from Noneto distinguish import failures from other errors.🔎 Proposed improvement
try: import kim_convergence as cr -except Exception: # noqa: BLE001 # intentional catch-all - raise RuntimeError("Failed to import `kim-convergence` utility module") +except Exception as err: # noqa: BLE001 # intentional catch-all + raise RuntimeError("Failed to import `kim-convergence` utility module") from errkim_convergence/run_length_control/__init__.py (1)
1-5: LGTM! Clean package initialization.The initialization file properly:
- Provides a module docstring
- Re-exports
run_length_controlfrom the core submodule- Declares the public API via
__all__This pattern successfully transforms
run_length_controlfrom a single module into a package while maintaining backward compatibility.💡 Optional: Remove unnecessary raw string prefix
The
rprefix on line 1 is typically used for regex patterns or paths with backslashes. For a simple docstring, it's not needed:-r"""Run length control module.""" +"""Run length control module."""This is purely cosmetic and doesn't affect functionality.
tests/test_kim_convergence/test_stats_normal_test.py (1)
9-9: Consider adding exception chaining for better error context.The static analyzer suggests using
raise ... from errto preserve the original exception context, which aids debugging when the import fails.Suggested improvement
-except Exception: # noqa: BLE001 # intentional catch-all - raise RuntimeError("Failed to import `kim-convergence` utility module") +except Exception as err: # noqa: BLE001 # intentional catch-all + raise RuntimeError("Failed to import `kim-convergence` utility module") from errtests/test_kim_convergence/test_stats.py (1)
9-9: Consider adding exception chaining for better error context.Same suggestion as in
test_stats_normal_test.py- usingraise ... from errpreserves the original exception context for easier debugging.Suggested improvement
-except Exception: # noqa: BLE001 # intentional catch-all - raise RuntimeError("Failed to import `kim-convergence` utility module") +except Exception as err: # noqa: BLE001 # intentional catch-all + raise RuntimeError("Failed to import `kim-convergence` utility module") from errkim_convergence/batch.py (2)
20-20: Consider broadening the type hint fortime_series_data.The type hint
Union[np.ndarray, list[float]]restricts lists to contain onlyfloatelements, butnp.asarrayon line 74 accepts lists with any numeric type (int, float, etc.). Consider usingUnion[np.ndarray, list]for consistency with the actual runtime behavior.🔎 Proposed adjustment
- time_series_data: Union[np.ndarray, list[float]], + time_series_data: Union[np.ndarray, list],
23-23: Consider making theCallabletype hint more specific.The
Callabletype hint forfunclacks parameter and return type specifications. Consider usingCallable[[np.ndarray], np.ndarray]or similar to document the expected signature more precisely.🔎 Proposed refinement
- func: Callable = np.mean, + func: Callable[[np.ndarray], np.ndarray] = np.mean,kim_convergence/stats/t_dist.py (1)
15-15: Consider sorting__all__alphabetically.Static analysis suggests sorting the exports alphabetically for consistency:
["t_cdf", "t_cdf_ccdf", "t_interval", "t_inv_cdf"]. This improves maintainability when the list grows.🔎 Proposed sort order
-__all__ = ["t_cdf_ccdf", "t_cdf", "t_inv_cdf", "t_interval"] +__all__ = ["t_cdf", "t_cdf_ccdf", "t_interval", "t_inv_cdf"]tests/test_kim_convergence/test_stats_nonnormal_test.py (1)
6-9: Chain the exception to preserve the original traceback.The
raiseinside theexceptblock loses the original exception context. Useraise ... from errorraise ... from Noneto clarify the chain.🔎 Proposed fix
try: import kim_convergence as cr -except Exception: # noqa: BLE001 # intentional catch-all - raise RuntimeError("Failed to import `kim-convergence` utility module") +except Exception as err: # noqa: BLE001 # intentional catch-all + raise RuntimeError("Failed to import `kim-convergence` utility module") from errkim_convergence/run_length_control/_convergence.py (1)
247-251: Chain the exception to preserve the original error context.When re-raising a
CRErrorafter catching one, usefromto chain exceptions. This preserves the stack trace for debugging.🔎 Proposed fix
except CRSampleSizeError: # do not have enough data and need more return (None, 0.0, False) - except CRError: - raise CRError(f"Failed to compute the ucl for variable number = {i + 1}.") + except CRError as e: + raise CRError(f"Failed to compute the ucl for variable number = {i + 1}.") from ekim_convergence/run_length_control/_setup.py (1)
112-115: Chain the exception to preserve the original error context.🔎 Proposed fix
try: ucl_obj = ucl_methods[confidence_interval_approximation_method]() - except CRError: - raise CRError("Failed to initialize the UCL object.") + except CRError as e: + raise CRError("Failed to initialize the UCL object.") from etests/test_kim_convergence/test_run_length_control.py (1)
11-14: Chain the exception to preserve the original traceback.🔎 Proposed fix
try: import kim_convergence as cr -except Exception: # noqa: BLE001 # intentional catch-all - raise Exception("Failed to import `kim-convergence` utility module") +except Exception as err: # noqa: BLE001 # intentional catch-all + raise ImportError("Failed to import `kim-convergence` utility module") from errNote: Using
ImportErroris more semantically appropriate than genericException.kim_convergence/run_length_control/_trajectory.py (1)
49-64: Chain exceptions to preserve the original error for debugging.When the user's
get_trajectorycallback fails, chaining the original exception helps diagnose whether the issue is in the user's code or the library.🔎 Proposed fix
if isinstance(get_trajectory_args, dict) and get_trajectory_args: try: tsd = get_trajectory(run_length, get_trajectory_args) - except Exception: # noqa: BLE001 # intentional catch-all + except Exception as e: # noqa: BLE001 # intentional catch-all raise CRError( "failed to get the time-series data or do the simulation " f"for {run_length} number of steps." - ) + ) from e else: try: tsd = get_trajectory(run_length) - except Exception: # noqa: BLE001 # intentional catch-all + except Exception as e: # noqa: BLE001 # intentional catch-all raise CRError( "failed to get the time-series data or do the simulation " f"for {run_length} number of steps." - ) + ) from ekim_convergence/run_length_control/_population.py (1)
71-142: Variable indices may be inconsistent with other error messages.This module uses 0-based indices in error messages (e.g.,
"Variable {i}: ..."), while other modules in the PR use 1-based indices (e.g.,"variable number = {i + 1}"in_convergence.py). Consider using 1-based indices for consistency with user-facing messages.🔎 Example fix for one message
if mean is not None: raise CRError( - f"Variable {i}: population_mean must be None when " + f"Variable {i + 1}: population_mean must be None when " f"population_cdf='{cdf_name}' is given. Use population_loc " "and population_scale instead." )Apply similar changes to all
f"Variable {i}:"patterns in this function.kim_convergence/run_length_control/_equilibration.py (2)
303-308: Consider simplifying list copy and removing redundant type annotation.Line 307 can use
list(truncate_index)ortruncate_index.copy()instead of a list comprehension. Also, thedelstatements on lines 303-304 are unnecessary since Python's garbage collector handles this automatically.🔎 Suggested simplification
- del extra_check - del truncated_flag - # 3. Finalize primary result - equilibration_step: list[int] = [index for index in truncate_index] + equilibration_step: list[int] = list(truncate_index) equilibration_detected: bool = bool(truncated)
314-314: Redundant type annotation.The variable
methodwas already declared with a type annotation on line 236. This reassignment doesn't need the type hint.🔎 Suggested fix
- method: str = "MSER + Integrated Autocorrelation Time refinement" + method = "MSER + Integrated Autocorrelation Time refinement"kim_convergence/err.py (1)
11-33: Consider explicit frame cleanup to avoid reference cycles.The
inspect.currentframe()documentation warns that frame objects can create reference cycles. While Python's cycle detector will eventually clean them up, explicitly deleting the frame reference is recommended.🔎 Proposed fix
def _get_caller_name(offset: int = 1) -> str: r""" Return the name of the calling function, offset steps up the stack. Args: offset: How many frames to go back. Default 1 = immediate caller of this function. Returns: Function name, or "<unknown>" if cannot be determined. """ frame = inspect.currentframe() if frame is None: return "<unknown>" - # Go back 'offset + 1' because this function itself is one frame - caller_frame = frame - for _ in range(offset + 1): - caller_frame = caller_frame.f_back - if caller_frame is None: - return "<unknown>" - - code = caller_frame.f_code - return code.co_name + try: + # Go back 'offset + 1' because this function itself is one frame + caller_frame = frame + for _ in range(offset + 1): + caller_frame = caller_frame.f_back + if caller_frame is None: + return "<unknown>" + + return caller_frame.f_code.co_name + finally: + del framekim_convergence/stats/zero_rc_bounds.py (1)
94-100: Unnecessary deepcopy on primitive types.
deepcopyon immutable primitives likefloatis redundant—simple assignment would suffice. However, this may be intentional for consistency if the class is ever subclassed with mutable types.🔎 Suggested simplification (optional)
- self.small = deepcopy(small) - self.big = deepcopy(big) - self.abs_step = deepcopy(abs_step) - self.rel_step = deepcopy(rel_step) - self.step_mul = deepcopy(step_mul) - self.abs_tol = deepcopy(abs_tol) - self.rel_tol = deepcopy(rel_tol) + self.small = small + self.big = big + self.abs_step = abs_step + self.rel_step = rel_step + self.step_mul = step_mul + self.abs_tol = abs_tol + self.rel_tol = rel_tolkim_convergence/timeseries/equilibration_length.py (1)
147-152: Consider prefixing unused parameters with underscore.The comment explains these parameters are for interface compatibility. Prefixing them with
_would suppress the static analysis warnings and signal intent to future readers.🔎 Suggested fix
# unused input parmeters in Time series module # estimate_equilibration_length interface - batch_size: int = _DEFAULT_BATCH_SIZE, - scale: str = _DEFAULT_SCALE_METHOD, - with_centering: bool = _DEFAULT_WITH_CENTERING, - with_scaling: bool = _DEFAULT_WITH_SCALING, + _batch_size: int = _DEFAULT_BATCH_SIZE, + _scale: str = _DEFAULT_SCALE_METHOD, + _with_centering: bool = _DEFAULT_WITH_CENTERING, + _with_scaling: bool = _DEFAULT_WITH_SCALING,Note: There's also a typo in the comment: "parmeters" should be "parameters".
README.md (2)
59-63: Add alt text to the image for accessibility.The image in the table lacks alt text, which is important for screen readers and accessibility compliance.
<table> <tr> - <td> <img src="./doc/files/vid1_T_Eq.gif?raw=true" width="200" height="200"> </td> + <td> <img src="./doc/files/vid1_T_Eq.gif?raw=true" width="200" height="200" alt="Temperature equilibration detection animation"> </td> </tr> </table>
131-137: Consider using markdown link syntax instead of bare URLs.For consistency with markdown best practices, wrap URLs in proper link syntax.
## Contributing -Bug reports, feature requests, pull requests: -https://github.com/openkim/kim-convergence/issues +Bug reports, feature requests, pull requests: [GitHub Issues](https://github.com/openkim/kim-convergence/issues) -Guidelines: https://kim-convergence.readthedocs.io/en/latest/contributing.html +Guidelines: [Contributing Guide](https://kim-convergence.readthedocs.io/en/latest/contributing.html)kim_convergence/timeseries/statistical_inefficiency.py (1)
166-172: Unusedminimum_correlation_timeparameter.The
minimum_correlation_timeparameter is accepted but not used in this function. While this may be intentional for API consistency across SI methods, consider documenting this in the docstring or using_prefix convention.kim_convergence/__init__.py (1)
6-6: Verifynoqadirective is still needed.Static analysis indicates
F401may not be needed in the noqa directive. However,F403for the star import is still relevant.-from ._default import * # noqa: F401,F403 +from ._default import * # noqa: F403kim_convergence/timeseries/utils.py (1)
91-95: Preserve exception context withraise ... from.When re-raising a
CRErrorafter catching one, the original traceback is lost. Use exception chaining to preserve the root cause for easier debugging.🔎 Proposed fix
except CRError: raise CRError( "Failed to compute the statistical inefficiency for the " "time_series_data." - ) + ) from Nonekim_convergence/ucl/ucl_base.py (1)
292-297: Typo in comment and consider documenting unused parameters.The comment has a typo ("parmeters" → "parameters"). These parameters are passed to maintain interface consistency across UCL implementations. Consider adding a brief note in the docstring explaining why they're accepted but unused.
🔎 Proposed fix
- # unused input parmeters in + # unused input parameters inkim_convergence/run_length_control/core.py (1)
493-497: Clarify population_args wrapping logic.The wrapping of
population_argsin a tuple whennumber_of_variables == 1is correct but non-obvious. Consider adding a comment explaining why this is necessary (to ensure_make_variable_listtreats the tuple as a single element rather than a sequence to broadcast).🔎 Proposed fix
if number_of_variables == 1: + # Wrap in tuple so _make_variable_list treats args as a single element, + # not as a sequence to broadcast population_args = (population_args,)kim_convergence/ucl/mser_m.py (1)
542-544: Preserve exception context withraise ... from.🔎 Proposed fix
except CRError: - raise CRError("Failed to get the relative_half_width_estimate.") + raise CRError("Failed to get the relative_half_width_estimate.") from Nonekim_convergence/ucl/uncorrelated_samples.py (1)
410-411: Preserve exception context withraise ... from.🔎 Proposed fix
except CRError: - raise CRError("Failed to get the relative_half_width_estimate.") + raise CRError("Failed to get the relative_half_width_estimate.") from Nonekim_convergence/scale.py (1)
771-773: Unused parameterswith_centeringandwith_scalinginmaxabs_scale.Same issue as
minmax_scale- these parameters are accepted but ignored.If these parameters are kept for interface consistency, add a comment explaining they're ignored for this particular scale method, or consider raising a warning if non-default values are passed.
kim_convergence/ucl/spectral/heidelberger_welch.py (1)
776-777: Preserve exception context withraise ... from.🔎 Proposed fix
except CRError: - raise CRError("Failed to get the relative_half_width_estimate.") + raise CRError("Failed to get the relative_half_width_estimate.") from None
… github.com:openkim/kim-convergence into refactor/run-length-control-modularization-and-docs
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 7
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
kim_convergence/stats/t_dist.py (1)
3-3: Fix typo in module docstring."specilized" should be "specialized".
🔎 Proposed fix
-This module is specilized for the ``kim-convergence`` code and is not a general +This module is specialized for the ``kim-convergence`` code and is not a general
♻️ Duplicate comments (3)
kim_convergence/run_length_control/_trajectory.py (1)
39-45: Previous review issue addressed.The mutable default argument issue has been fixed. The function now correctly uses
Optional[dict] = Noneinstead of{}.kim_convergence/outlier.py (1)
120-127: Previous review issue addressed: Division by zero protection.The potential division by zero in
modified_z_scorecalculation has been fixed. Whenx_median_absolute_deviationis close to zero (all values identical), the function now correctly returnsNoneto indicate no outliers.kim_convergence/stats/tools.py (1)
292-305: Same timeout and exception chaining concerns apply to_isolate_perio.This function has the same patterns as
_isolate(). Consider adding a timeout top.join()and usingfrom errin the exception handling.
🧹 Nitpick comments (26)
README.md (1)
34-35: Minor HTML formatting issue with trailing whitespace in image tag attributes.Lines 34–35 have extra spaces before the closing quote in the height attribute:
height="200 "should beheight="200". This doesn't break rendering but is inconsistent with the other image tags on lines 25–27 and 61.🔎 Proposed fix
- <td> <img src="./doc/files/vid2_P.gif?raw=true" width="200" height="200 "> </td> - <td> <img src="./doc/files/vid2_V.gif?raw=true" width="200" height="200 "> </td> + <td> <img src="./doc/files/vid2_P.gif?raw=true" width="200" height="200"> </td> + <td> <img src="./doc/files/vid2_V.gif?raw=true" width="200" height="200"> </td>kim_convergence/stats/t_dist.py (2)
48-49: LGTM: Formatting improvements enhance readability.The multi-line function signature and consistent quote style improve code clarity.
Note: Static analysis suggests using custom exception classes for repeated error messages (TRY003), which could reduce duplication across lines 48-49 and 135-136, but this is an optional refactor.
Also applies to: 98-107, 135-136
131-131: Improve readability of numeric range formatting.The error messages format ranges without commas (e.g., "(0.0 1.0)"), which reduces readability. Consider adding commas for clarity.
🔎 Proposed fix
- raise CRError(f"p = {p} is not in the range (0.0 1.0).") + raise CRError(f"p = {p} is not in the range (0.0, 1.0).")- f"confidence level = {confidence_level} is not in the range " "(0.0 1.0)." + f"confidence level = {confidence_level} is not in the range (0.0, 1.0)."Also applies to: 232-232
kim_convergence/timeseries/geweke.py (1)
55-66: LGTM! Input validation is thorough.The validation correctly ensures valid interval ranges for the Geweke diagnostic. The error messages are clear and informative.
Optional: The static analysis hint suggests the error message at lines 57-58 could be shortened or moved to a constant, but the current implementation is readable and acceptable.
kim_convergence/stats/zero_rc_bounds.py (2)
134-311: LGTM: Error message formatting improved.The standardized error message formatting enhances consistency. The static analysis hints about TRY003 (long messages outside exception class) are purely stylistic—current approach is clear and acceptable.
Optional: Consider custom exception types (TRY003)
If these error patterns recur across the codebase, you could define specialized exception classes with structured fields instead of embedding long messages inline. However, this is a low-priority refinement.
299-301: Type ignore is necessary but could be refined.The
type: ignoreis required because the type checker cannot infer thatself.zis always initialized before reachingindex == 6. The control flow logic ensures safety, but static analysis cannot verify this.Optional: Make type safety explicit
You could add an assertion to help both the type checker and future maintainers:
elif self.index == 6: + assert self.z is not None, "ZERO_RC instance must be initialized" while True: if status == 1: - status, x, self.xlo, self.xhi = self.z.zero( # type: ignore[arg-type] + status, x, self.xlo, self.xhi = self.z.zero( status, x, fx, self.xlo, self.xhi )This documents the invariant and removes the need for
type: ignore.kim_convergence/stats/nonnormal_test.py (1)
558-559: Optional: Remove unusednoqadirectives.Ruff indicates that the
# noqa: BLE001directives on these lines are no longer necessary. The broad exception catches with chaining are acceptable here since the errors are properly re-raised with context.🔎 Cleanup suggestion
- except Exception as e: # noqa: BLE001 # intentional catch-all + except Exception as e: # intentional catch-all raise CRError("Kolmogorov-Smirnov test failed.") from eApply similar changes to Lines 689, 694, 781, 871, and 876.
Also applies to: 689-690, 694-695, 781-782, 871-872, 876-877
tests/test_kim_convergence/test_stats_beta_dist.py (1)
9-9: Remove unusednoqadirective.The static analyzer reports the
noqa: BLE001directive is unused and can be removed for cleaner code.🔎 Proposed fix
-except Exception as e: # noqa: BLE001 # intentional catch-all +except Exception as e: # intentional catch-alltests/test_kim_convergence/test_scale.py (1)
9-9: Remove unusednoqadirective.The
noqa: BLE001directive is unused and can be removed.🔎 Proposed fix
-except Exception as e: # noqa: BLE001 # intentional catch-all +except Exception as e: # intentional catch-alltests/test_kim_convergence/test_outlier.py (1)
8-8: Remove unusednoqadirective.The
noqa: BLE001directive is unused and can be removed.🔎 Proposed fix
-except Exception as e: # noqa: BLE001 # intentional catch-all +except Exception as e: # intentional catch-alltests/test_kim_convergence/test_batch.py (1)
8-8: Remove unusednoqadirective.The
noqa: BLE001directive is unused and can be removed for cleaner code.🔎 Proposed fix
-except Exception as e: # noqa: BLE001 # intentional catch-all +except Exception as e: # intentional catch-alldoc/troubleshooting.rst (1)
93-108: Add missing import in code example.The code example uses
warnings.warnbut doesn't show the necessary import statement. Consider adding it for completeness.Suggested addition
.. code-block:: python + import warnings + import numpy as np + def get_trajectory(step: int, args: dict) -> np.ndarray: """Run the simulation and return the time-series."""tests/test_kim_convergence/test_stats_nonnormal_test.py (1)
6-9: Remove unusednoqadirective.The
noqa: BLE001directive on line 8 is unused according to Ruff. The broad exception catch in test setup is unlikely to raise anything beyond ImportError, so the directive can be safely removed.Suggested fix
try: import kim_convergence as cr -except Exception as e: # noqa: BLE001 # intentional catch-all +except Exception as e: raise RuntimeError("Failed to import `kim-convergence` utility module") from ekim_convergence/run_length_control/_variable_list_factory.py (1)
78-82: Consider simplifying scalar detection logic.The dual
isinstancecheck on lines 78-79 works correctly but could potentially be simplified for clarity. However, the current implementation is defensive and handles edge cases well, so this is optional.tests/test_kim_convergence/test_stats.py (1)
6-9: Remove unusednoqadirective.Same as in
test_stats_nonnormal_test.py, thenoqa: BLE001directive on line 8 is unused and can be removed.Suggested fix
try: import kim_convergence as cr -except Exception as e: # noqa: BLE001 # intentional catch-all +except Exception as e: raise RuntimeError("Failed to import `kim-convergence` utility module") from etests/test_kim_convergence/test_run_length_control.py (2)
11-14: Remove unusednoqadirective.The
# noqa: BLE001comment is flagged as unused by static analysis. The broadExceptioncatch is intentional here for import error handling.🔎 Proposed fix
try: import kim_convergence as cr -except Exception as e: # noqa: BLE001 # intentional catch-all +except Exception as e: raise RuntimeError("Failed to import `kim-convergence` utility module") from e
647-650: RedundantsetUp()call.
setUp()is automatically invoked by unittest before each test method. The explicit call on Line 649 is unnecessary.🔎 Proposed fix
def test_equilibration_failure_raises_error(self): """Test CRError raise when equilibration is not detected within limits.""" - self.setUp() trajectory_state = {"current": 0}kim_convergence/run_length_control/_trajectory.py (1)
54-68: Consider removing unusednoqadirectives.Static analysis indicates the
# noqa: BLE001directives on Lines 56 and 64 are unused. If the linter version has changed, these can be safely removed.🔎 Proposed fix
if ( get_trajectory_args is not None and isinstance(get_trajectory_args, dict) and get_trajectory_args ): try: tsd = get_trajectory(run_length, get_trajectory_args) - except Exception as e: # noqa: BLE001 # intentional catch-all + except Exception as e: raise CRError( "failed to get the time-series data or do the simulation " f"for {run_length} number of steps." ) from e else: try: tsd = get_trajectory(run_length) - except Exception as e: # noqa: BLE001 # intentional catch-all + except Exception as e: raise CRError( "failed to get the time-series data or do the simulation " f"for {run_length} number of steps." ) from ekim_convergence/timeseries/equilibration_length.py (1)
147-152: Unused parameters added for API consistency.The parameters
batch_size,scale,with_centering, andwith_scalingare explicitly unused (as noted in the comment). Consider prefixing them with underscore (_batch_size, etc.) to suppress linter warnings while maintaining the interface, or document in the docstring that they are accepted for API consistency but ignored.🔎 Alternative: prefix with underscore
# unused input parameters in equilibration length estimation module # estimate_equilibration_length interface - batch_size: int = _DEFAULT_BATCH_SIZE, - scale: str = _DEFAULT_SCALE_METHOD, - with_centering: bool = _DEFAULT_WITH_CENTERING, - with_scaling: bool = _DEFAULT_WITH_SCALING, + _batch_size: int = _DEFAULT_BATCH_SIZE, + _scale: str = _DEFAULT_SCALE_METHOD, + _with_centering: bool = _DEFAULT_WITH_CENTERING, + _with_scaling: bool = _DEFAULT_WITH_SCALING,doc/conf.py (1)
7-19: Consider updating the fallback version or logging a warning on import failure.The hardcoded fallback
version = "0.0.2"(line 8) will be used ifkim_convergenceimport fails. This could silently produce docs with an outdated version number. Consider either keeping the fallback in sync or emitting a warning when the import fails.🔎 Optional: add warning on import failure
try: import kim_convergence release = kim_convergence.__version__ version = ".".join(release.split(".")[:2]) except ImportError: - pass + import warnings + warnings.warn("Could not import kim_convergence; using fallback version") + release = versionkim_convergence/ucl/mser_m_y.py (1)
208-209: Unnecessary assertion before return.The
assert isinstance(self.upper_confidence_limit, float)is defensive but if it ever fails, it will raiseAssertionErrorinstead of a descriptive error. Sincet_inv_cdfand the arithmetic should always produce a float, this assertion adds runtime overhead without clear benefit. Consider removing it or replacing with explicit validation if there's a real concern.🔎 Simplified return
self.upper_confidence_limit = upper * standard_error_of_mean - assert isinstance(self.upper_confidence_limit, float) - return float(self.upper_confidence_limit) + return float(self.upper_confidence_limit)kim_convergence/ucl/uncorrelated_samples.py (1)
213-214: Optional: Redundant type cast after assertion.Line 213 asserts that
self.upper_confidence_limitis already afloat, making thefloat()cast on line 214 redundant.🔎 Proposed simplification
self.upper_confidence_limit = upper * standard_error_of_mean assert isinstance(self.upper_confidence_limit, float) -return float(self.upper_confidence_limit) +return self.upper_confidence_limitkim_convergence/ucl/mser_m.py (1)
67-90: Potential bug:ignore_endcan become 0 whennumber_batches < 4.When
ignore_end is None, lines 69-70 compute:ignore_end = max(1, batch_size) ignore_end = min(ignore_end, number_batches // 4)If
number_batches < 4, thennumber_batches // 4 == 0, soignore_endbecomes 0. This triggers the check on lines 85-90, but the error message is confusing since it wasn't "automatically set" to 0—it was explicitly clamped to 0 by themin().Consider clamping the result to at least 1:
🔎 Proposed fix
if not isinstance(ignore_end, int): if ignore_end is None: ignore_end = max(1, batch_size) - ignore_end = min(ignore_end, number_batches // 4) + ignore_end = max(1, min(ignore_end, number_batches // 4)) elif isinstance(ignore_end, float):Alternatively, remove the redundant check on lines 85-90 if it can never be reached after this fix.
kim_convergence/stats/tools.py (2)
250-263: Improved subprocess handling, but consider adding a timeout top.join().The refactored approach of calling
p.join()beforeq.get_nowait()is safer than the previous blockingq.get(). However,p.join()without a timeout can still block indefinitely if the subprocess hangs (e.g., in an infinite loop or deadlock—ironically, what this feature aims to prevent).Consider adding a timeout:
🔎 Proposed fix with timeout
p.start() - p.join() # wait until subprocess terminates + p.join(timeout=300) # 5-minute timeout + if p.is_alive(): + p.terminate() + p.join(timeout=5) + raise CRError("Correlation worker timed out.") if p.exitcode != 0: # crash, kill -9, segfault, etc.
256-259: Add exception chaining for proper traceback.Static analysis correctly identifies that the
raisewithin anexceptblock should usefrom errorfrom Nonefor proper exception chaining.🔎 Proposed fix
try: result = q.get_nowait() - except Empty: # child exited without putting anything - raise CRError("Correlation worker produced no result.") + except Empty as err: # child exited without putting anything + raise CRError("Correlation worker produced no result.") from errkim_convergence/ucl/spectral/heidelberger_welch.py (1)
517-523: Some parameters marked as "unused" are actually used.The parameters
scale,with_centering, andwith_scaling(lines 325-327) are documented as unused in the interface, but they are actually used here in thebatch()call. The static analysis hint flagging them as unused is a false positive in this case.Consider removing these parameters from the "unused input parameters" comment block in the method signature.
🔎 Proposed documentation fix
fft: bool = _DEFAULT_FFT, test_size: Union[int, float, None] = _DEFAULT_TEST_SIZE, train_size: Union[int, float, None] = _DEFAULT_TRAIN_SIZE, - # unused input parameters in HeidelbergerWelch module - # _ucl_impl interface batch_size: int = _DEFAULT_BATCH_SIZE, equilibration_length_estimate: int = _DEFAULT_EQUILIBRATION_LENGTH_ESTIMATE, scale: str = _DEFAULT_SCALE_METHOD, with_centering: bool = _DEFAULT_WITH_CENTERING, with_scaling: bool = _DEFAULT_WITH_SCALING, + # unused input parameters in HeidelbergerWelch module + # _ucl_impl interface population_standard_deviation: Optional[
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (50)
README.mddoc/conf.pydoc/modules/ucl.rstdoc/troubleshooting.rstkim_convergence/batch.pykim_convergence/err.pykim_convergence/outlier.pykim_convergence/run_length_control/__init__.pykim_convergence/run_length_control/_convergence.pykim_convergence/run_length_control/_equilibration.pykim_convergence/run_length_control/_population.pykim_convergence/run_length_control/_setup.pykim_convergence/run_length_control/_trajectory.pykim_convergence/run_length_control/_variable_list_factory.pykim_convergence/run_length_control/core.pykim_convergence/scale.pykim_convergence/stats/__init__.pykim_convergence/stats/beta_dist.pykim_convergence/stats/nonnormal_test.pykim_convergence/stats/normal_dist.pykim_convergence/stats/randomness_test.pykim_convergence/stats/t_dist.pykim_convergence/stats/tools.pykim_convergence/stats/zero_rc_bounds.pykim_convergence/timeseries/equilibration_length.pykim_convergence/timeseries/geweke.pykim_convergence/timeseries/statistical_inefficiency.pykim_convergence/timeseries/utils.pykim_convergence/ucl/mser_m.pykim_convergence/ucl/mser_m_y.pykim_convergence/ucl/n_skart.pykim_convergence/ucl/spectral/heidelberger_welch.pykim_convergence/ucl/ucl_base.pykim_convergence/ucl/uncorrelated_samples.pykim_convergence/utils.pypyproject.tomltests/test_kim_convergence/test_batch.pytests/test_kim_convergence/test_outlier.pytests/test_kim_convergence/test_run_length_control.pytests/test_kim_convergence/test_scale.pytests/test_kim_convergence/test_stats.pytests/test_kim_convergence/test_stats_beta_dist.pytests/test_kim_convergence/test_stats_nonnormal_test.pytests/test_kim_convergence/test_stats_normal_test.pytests/test_kim_convergence/test_stats_s_normal_dist.pytests/test_kim_convergence/test_stats_t_dist.pytests/test_kim_convergence/test_timeseries.pytests/test_kim_convergence/test_timeseries_equilibration_length.pytests/test_kim_convergence/test_ucl.pytests/test_kim_convergence/test_ucl_mser_m.py
✅ Files skipped from review due to trivial changes (1)
- kim_convergence/stats/init.py
🧰 Additional context used
🧬 Code graph analysis (27)
tests/test_kim_convergence/test_scale.py (2)
kim_convergence/scale.py (11)
MinMaxScale(26-141)scale(82-121)scale(228-262)scale(379-448)scale(584-618)scale(708-749)inverse(123-141)inverse(264-291)inverse(450-483)inverse(620-647)inverse(751-773)kim_convergence/err.py (1)
CRError(38-60)
kim_convergence/stats/normal_dist.py (1)
kim_convergence/err.py (1)
CRError(38-60)
kim_convergence/stats/zero_rc_bounds.py (2)
kim_convergence/stats/zero_rc.py (2)
zero(97-247)ZERO_RC(52-247)kim_convergence/err.py (1)
CRError(38-60)
tests/test_kim_convergence/test_run_length_control.py (4)
kim_convergence/err.py (1)
CRError(38-60)kim_convergence/run_length_control/_variable_list_factory.py (1)
_make_variable_list(48-105)kim_convergence/run_length_control/_equilibration.py (1)
_truncated_series(135-144)kim_convergence/run_length_control/_convergence.py (1)
_equilibrated_series(163-172)
tests/test_kim_convergence/test_outlier.py (1)
kim_convergence/outlier.py (1)
outlier_test(56-132)
tests/test_kim_convergence/test_stats.py (2)
kim_convergence/stats/tools.py (6)
auto_covariance(342-388)cross_covariance(391-435)auto_correlate(438-484)cross_correlate(487-548)periodogram(632-679)int_power(707-750)kim_convergence/err.py (1)
CRError(38-60)
kim_convergence/ucl/ucl_base.py (4)
kim_convergence/err.py (1)
CRError(38-60)kim_convergence/ucl/mser_m.py (2)
estimate_equilibration_length(293-333)_ucl_impl(335-425)kim_convergence/ucl/n_skart.py (2)
estimate_equilibration_length(111-296)_ucl_impl(298-477)kim_convergence/timeseries/utils.py (2)
time_series_data_si(47-108)uncorrelated_time_series_data_sample_indices(111-160)
kim_convergence/run_length_control/core.py (6)
kim_convergence/run_length_control/_accuracy.py (1)
_check_accuracy(28-84)kim_convergence/run_length_control/_convergence.py (3)
_convergence_message(42-160)_convergence_stage(293-528)_output_convergence_report(531-583)kim_convergence/run_length_control/_population.py (1)
_validate_population_params(35-148)kim_convergence/run_length_control/_setup.py (1)
_setup_algorithm(33-123)kim_convergence/run_length_control/_variable_list_factory.py (1)
_make_variable_list(48-105)kim_convergence/ucl/ucl_base.py (10)
si(138-140)si(143-150)si(153-155)mean(188-190)mean(193-200)mean(203-205)std(208-210)std(213-220)std(223-225)relative_half_width_estimate(441-494)
kim_convergence/timeseries/geweke.py (1)
kim_convergence/err.py (1)
CRError(38-60)
kim_convergence/run_length_control/_convergence.py (5)
kim_convergence/err.py (3)
CRError(38-60)CRSampleSizeError(63-66)cr_warning(69-78)kim_convergence/ucl/ucl_base.py (16)
ucl(344-391)UCLBase(42-494)mean(188-190)mean(193-200)mean(203-205)std(208-210)std(213-220)std(223-225)si(138-140)si(143-150)si(153-155)name(59-61)name(64-71)name(74-76)set_si(157-185)set_indices(98-135)kim_convergence/run_length_control/_population.py (1)
_population_tests(151-208)kim_convergence/run_length_control/_run_length.py (1)
_get_run_length(20-35)kim_convergence/run_length_control/_trajectory.py (1)
_get_trajectory(39-93)
kim_convergence/run_length_control/__init__.py (1)
kim_convergence/run_length_control/core.py (1)
run_length_control(57-620)
kim_convergence/run_length_control/_trajectory.py (1)
kim_convergence/err.py (1)
CRError(38-60)
tests/test_kim_convergence/test_batch.py (2)
kim_convergence/err.py (1)
CRError(38-60)kim_convergence/batch.py (1)
batch(19-145)
kim_convergence/stats/tools.py (1)
kim_convergence/err.py (1)
CRError(38-60)
kim_convergence/stats/randomness_test.py (2)
kim_convergence/stats/normal_dist.py (1)
normal_interval(136-180)kim_convergence/err.py (2)
CRError(38-60)cr_check(102-157)
kim_convergence/timeseries/equilibration_length.py (2)
kim_convergence/timeseries/statistical_inefficiency.py (1)
statistical_inefficiency(36-158)kim_convergence/err.py (2)
CRError(38-60)CRSampleSizeError(63-66)
kim_convergence/ucl/uncorrelated_samples.py (3)
kim_convergence/ucl/ucl_base.py (9)
name(59-61)name(64-71)name(74-76)si(138-140)si(143-150)si(153-155)indices(79-81)indices(84-91)indices(94-96)kim_convergence/err.py (3)
CRError(38-60)CRSampleSizeError(63-66)cr_warning(69-78)kim_convergence/timeseries/utils.py (3)
time_series_data_si(47-108)uncorrelated_time_series_data_sample_indices(111-160)uncorrelated_time_series_data_samples(163-238)
kim_convergence/batch.py (1)
kim_convergence/scale.py (5)
scale(82-121)scale(228-262)scale(379-448)scale(584-618)scale(708-749)
kim_convergence/timeseries/utils.py (2)
kim_convergence/timeseries/statistical_inefficiency.py (1)
statistical_inefficiency(36-158)kim_convergence/err.py (1)
CRError(38-60)
kim_convergence/utils.py (1)
kim_convergence/err.py (1)
CRError(38-60)
kim_convergence/stats/beta_dist.py (1)
kim_convergence/err.py (1)
CRError(38-60)
kim_convergence/outlier.py (1)
kim_convergence/err.py (1)
CRError(38-60)
kim_convergence/run_length_control/_variable_list_factory.py (1)
kim_convergence/err.py (2)
CRError(38-60)cr_warning(69-78)
kim_convergence/scale.py (1)
kim_convergence/err.py (1)
CRError(38-60)
kim_convergence/stats/nonnormal_test.py (1)
kim_convergence/err.py (3)
CRError(38-60)CRSampleSizeError(63-66)cr_check(102-157)
kim_convergence/timeseries/statistical_inefficiency.py (2)
kim_convergence/stats/tools.py (3)
auto_covariance(342-388)auto_correlate(438-484)cross_correlate(487-548)kim_convergence/err.py (2)
CRError(38-60)CRSampleSizeError(63-66)
tests/test_kim_convergence/test_stats_nonnormal_test.py (2)
kim_convergence/err.py (1)
CRError(38-60)kim_convergence/stats/nonnormal_test.py (3)
check_population_cdf_args(399-446)get_distribution_stats(449-483)levene_test(564-697)
🪛 GitHub Actions: Python package
kim_convergence/batch.py
[error] 135-135: SyntaxError: f-string expression part cannot include a backslash
🪛 Ruff (0.14.10)
tests/test_kim_convergence/test_scale.py
9-9: Unused noqa directive (unused: BLE001)
Remove unused noqa directive
(RUF100)
10-10: Avoid specifying long messages outside the exception class
(TRY003)
kim_convergence/stats/normal_dist.py
20-20: __all__ is not sorted
Apply an isort-style sorting to __all__
(RUF022)
kim_convergence/stats/zero_rc_bounds.py
156-161: Avoid specifying long messages outside the exception class
(TRY003)
162-167: Avoid specifying long messages outside the exception class
(TRY003)
174-179: Avoid specifying long messages outside the exception class
(TRY003)
180-184: Avoid specifying long messages outside the exception class
(TRY003)
221-226: Avoid specifying long messages outside the exception class
(TRY003)
259-264: Avoid specifying long messages outside the exception class
(TRY003)
308-311: Avoid specifying long messages outside the exception class
(TRY003)
tests/test_kim_convergence/test_run_length_control.py
13-13: Unused noqa directive (unused: BLE001)
Remove unused noqa directive
(RUF100)
14-14: Avoid specifying long messages outside the exception class
(TRY003)
900-900: Unused function argument: step
(ARG001)
901-901: Avoid specifying long messages outside the exception class
(TRY003)
tests/test_kim_convergence/test_outlier.py
8-8: Unused noqa directive (unused: BLE001)
Remove unused noqa directive
(RUF100)
9-9: Avoid specifying long messages outside the exception class
(TRY003)
tests/test_kim_convergence/test_stats.py
8-8: Unused noqa directive (unused: BLE001)
Remove unused noqa directive
(RUF100)
9-9: Avoid specifying long messages outside the exception class
(TRY003)
kim_convergence/ucl/ucl_base.py
294-294: Unused method argument: batch_size
(ARG002)
295-295: Unused method argument: scale
(ARG002)
296-296: Unused method argument: with_centering
(ARG002)
297-297: Unused method argument: with_scaling
(ARG002)
488-491: Avoid specifying long messages outside the exception class
(TRY003)
kim_convergence/run_length_control/_setup.py
115-115: Avoid specifying long messages outside the exception class
(TRY003)
kim_convergence/timeseries/geweke.py
56-59: Avoid specifying long messages outside the exception class
(TRY003)
tests/test_kim_convergence/test_stats_beta_dist.py
9-9: Unused noqa directive (unused: BLE001)
Remove unused noqa directive
(RUF100)
10-10: Avoid specifying long messages outside the exception class
(TRY003)
kim_convergence/run_length_control/_convergence.py
251-251: Avoid specifying long messages outside the exception class
(TRY003)
272-276: Avoid specifying long messages outside the exception class
(TRY003)
467-469: Avoid specifying long messages outside the exception class
(TRY003)
556-556: Avoid specifying long messages outside the exception class
(TRY003)
559-562: Avoid specifying long messages outside the exception class
(TRY003)
kim_convergence/run_length_control/_trajectory.py
29-36: Avoid specifying long messages outside the exception class
(TRY003)
56-56: Unused noqa directive (unused: BLE001)
Remove unused noqa directive
(RUF100)
57-60: Avoid specifying long messages outside the exception class
(TRY003)
64-64: Unused noqa directive (unused: BLE001)
Remove unused noqa directive
(RUF100)
65-68: Avoid specifying long messages outside the exception class
(TRY003)
74-77: Avoid specifying long messages outside the exception class
(TRY003)
80-83: Avoid specifying long messages outside the exception class
(TRY003)
86-91: Avoid specifying long messages outside the exception class
(TRY003)
kim_convergence/ucl/mser_m_y.py
34-39: __all__ is not sorted
Apply an isort-style sorting to __all__
(RUF022)
57-57: Docstring contains ambiguous ′ (PRIME). Did you mean ``` (GRAVE ACCENT)?
(RUF002)
84-84: Unused method argument: equilibration_length_estimate
(ARG002)
85-85: Unused method argument: heidel_welch_number_points
(ARG002)
86-86: Unused method argument: fft
(ARG002)
87-87: Unused method argument: test_size
(ARG002)
88-88: Unused method argument: train_size
(ARG002)
89-89: Unused method argument: population_standard_deviation
(ARG002)
92-92: Unused method argument: si
(ARG002)
93-93: Unused method argument: minimum_correlation_time
(ARG002)
94-94: Unused method argument: uncorrelated_sample_indices
(ARG002)
97-97: Unused method argument: sample_method
(ARG002)
122-122: Avoid specifying long messages outside the exception class
(TRY003)
127-131: Avoid specifying long messages outside the exception class
(TRY003)
327-327: Avoid specifying long messages outside the exception class
(TRY003)
tests/test_kim_convergence/test_batch.py
8-8: Unused noqa directive (unused: BLE001)
Remove unused noqa directive
(RUF100)
9-9: Avoid specifying long messages outside the exception class
(TRY003)
kim_convergence/ucl/spectral/heidelberger_welch.py
37-42: __all__ is not sorted
Apply an isort-style sorting to __all__
(RUF022)
324-324: Unused method argument: equilibration_length_estimate
(ARG002)
328-328: Unused method argument: population_standard_deviation
(ARG002)
331-331: Unused method argument: si
(ARG002)
332-332: Unused method argument: minimum_correlation_time
(ARG002)
333-333: Unused method argument: uncorrelated_sample_indices
(ARG002)
336-336: Unused method argument: sample_method
(ARG002)
486-486: Avoid specifying long messages outside the exception class
(TRY003)
777-777: Avoid specifying long messages outside the exception class
(TRY003)
kim_convergence/stats/tools.py
126-126: Avoid specifying long messages outside the exception class
(TRY003)
130-130: Avoid specifying long messages outside the exception class
(TRY003)
254-254: Avoid specifying long messages outside the exception class
(TRY003)
259-259: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling
(B904)
259-259: Avoid specifying long messages outside the exception class
(TRY003)
296-296: Avoid specifying long messages outside the exception class
(TRY003)
301-301: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling
(B904)
301-301: Avoid specifying long messages outside the exception class
(TRY003)
316-316: Avoid specifying long messages outside the exception class
(TRY003)
319-319: Avoid specifying long messages outside the exception class
(TRY003)
322-325: Avoid specifying long messages outside the exception class
(TRY003)
331-331: Avoid specifying long messages outside the exception class
(TRY003)
334-337: Avoid specifying long messages outside the exception class
(TRY003)
474-474: Avoid specifying long messages outside the exception class
(TRY003)
477-477: Avoid specifying long messages outside the exception class
(TRY003)
538-538: Avoid specifying long messages outside the exception class
(TRY003)
541-541: Avoid specifying long messages outside the exception class
(TRY003)
663-663: Avoid specifying long messages outside the exception class
(TRY003)
696-696: Avoid specifying long messages outside the exception class
(TRY003)
721-721: Avoid specifying long messages outside the exception class
(TRY003)
724-724: Avoid specifying long messages outside the exception class
(TRY003)
727-727: Avoid specifying long messages outside the exception class
(TRY003)
778-778: Avoid specifying long messages outside the exception class
(TRY003)
kim_convergence/stats/randomness_test.py
50-50: Avoid specifying long messages outside the exception class
(TRY003)
61-64: Avoid specifying long messages outside the exception class
(TRY003)
kim_convergence/timeseries/equilibration_length.py
89-92: Avoid specifying long messages outside the exception class
(TRY003)
96-99: Avoid specifying long messages outside the exception class
(TRY003)
101-104: Avoid specifying long messages outside the exception class
(TRY003)
109-112: Avoid specifying long messages outside the exception class
(TRY003)
116-119: Avoid specifying long messages outside the exception class
(TRY003)
123-126: Avoid specifying long messages outside the exception class
(TRY003)
130-133: Avoid specifying long messages outside the exception class
(TRY003)
149-149: Unused function argument: batch_size
(ARG001)
150-150: Unused function argument: scale
(ARG001)
151-151: Unused function argument: with_centering
(ARG001)
152-152: Unused function argument: with_scaling
(ARG001)
191-191: Avoid specifying long messages outside the exception class
(TRY003)
205-205: Avoid specifying long messages outside the exception class
(TRY003)
211-211: Avoid specifying long messages outside the exception class
(TRY003)
216-216: Avoid specifying long messages outside the exception class
(TRY003)
kim_convergence/ucl/uncorrelated_samples.py
35-40: __all__ is not sorted
Apply an isort-style sorting to __all__
(RUF022)
70-70: Unused method argument: equilibration_length_estimate
(ARG002)
71-71: Unused method argument: heidel_welch_number_points
(ARG002)
72-72: Unused method argument: batch_size
(ARG002)
73-73: Unused method argument: scale
(ARG002)
74-74: Unused method argument: with_centering
(ARG002)
75-75: Unused method argument: with_scaling
(ARG002)
76-76: Unused method argument: test_size
(ARG002)
77-77: Unused method argument: train_size
(ARG002)
133-133: Avoid specifying long messages outside the exception class
(TRY003)
138-141: Avoid specifying long messages outside the exception class
(TRY003)
144-147: Avoid specifying long messages outside the exception class
(TRY003)
411-411: Avoid specifying long messages outside the exception class
(TRY003)
kim_convergence/run_length_control/_population.py
67-69: Avoid specifying long messages outside the exception class
(TRY003)
86-88: Avoid specifying long messages outside the exception class
(TRY003)
92-96: Avoid specifying long messages outside the exception class
(TRY003)
98-102: Avoid specifying long messages outside the exception class
(TRY003)
106-109: Avoid specifying long messages outside the exception class
(TRY003)
112-115: Avoid specifying long messages outside the exception class
(TRY003)
121-124: Avoid specifying long messages outside the exception class
(TRY003)
126-129: Avoid specifying long messages outside the exception class
(TRY003)
131-134: Avoid specifying long messages outside the exception class
(TRY003)
138-141: Avoid specifying long messages outside the exception class
(TRY003)
145-148: Avoid specifying long messages outside the exception class
(TRY003)
kim_convergence/batch.py
78-78: Avoid specifying long messages outside the exception class
(TRY003)
81-81: Avoid specifying long messages outside the exception class
(TRY003)
84-84: Avoid specifying long messages outside the exception class
(TRY003)
125-128: Avoid specifying long messages outside the exception class
(TRY003)
131-135: Avoid specifying long messages outside the exception class
(TRY003)
134-134: Cannot use an escape sequence (backslash) in f-strings on Python 3.9 (syntax was added in Python 3.12)
(invalid-syntax)
134-134: Cannot use an escape sequence (backslash) in f-strings on Python 3.9 (syntax was added in Python 3.12)
(invalid-syntax)
kim_convergence/ucl/n_skart.py
40-45: __all__ is not sorted
Apply an isort-style sorting to __all__
(RUF022)
148-148: Avoid specifying long messages outside the exception class
(TRY003)
307-307: Unused method argument: heidel_welch_number_points
(ARG002)
308-308: Unused method argument: batch_size
(ARG002)
312-312: Unused method argument: test_size
(ARG002)
313-313: Unused method argument: train_size
(ARG002)
314-314: Unused method argument: population_standard_deviation
(ARG002)
317-317: Unused method argument: si
(ARG002)
318-318: Unused method argument: minimum_correlation_time
(ARG002)
319-319: Unused method argument: uncorrelated_sample_indices
(ARG002)
322-322: Unused method argument: sample_method
(ARG002)
347-347: Avoid specifying long messages outside the exception class
(TRY003)
350-350: Avoid specifying long messages outside the exception class
(TRY003)
578-578: Avoid specifying long messages outside the exception class
(TRY003)
kim_convergence/timeseries/utils.py
18-25: __all__ is not sorted
Apply an isort-style sorting to __all__
(RUF022)
92-95: Avoid specifying long messages outside the exception class
(TRY003)
99-101: Avoid specifying long messages outside the exception class
(TRY003)
106-106: Avoid specifying long messages outside the exception class
(TRY003)
206-206: Avoid specifying long messages outside the exception class
(TRY003)
281-281: Avoid specifying long messages outside the exception class
(TRY003)
292-295: Avoid specifying long messages outside the exception class
(TRY003)
301-303: Avoid specifying long messages outside the exception class
(TRY003)
361-361: Avoid specifying long messages outside the exception class
(TRY003)
372-375: Avoid specifying long messages outside the exception class
(TRY003)
400-400: Standard pseudo-random generators are not suitable for cryptographic purposes
(S311)
450-450: Avoid specifying long messages outside the exception class
(TRY003)
461-464: Avoid specifying long messages outside the exception class
(TRY003)
kim_convergence/utils.py
40-40: Avoid specifying long messages outside the exception class
(TRY003)
45-48: Avoid specifying long messages outside the exception class
(TRY003)
54-54: Avoid specifying long messages outside the exception class
(TRY003)
57-57: Avoid specifying long messages outside the exception class
(TRY003)
59-59: Avoid specifying long messages outside the exception class
(TRY003)
72-72: Avoid specifying long messages outside the exception class
(TRY003)
92-92: Avoid specifying long messages outside the exception class
(TRY003)
97-97: Avoid specifying long messages outside the exception class
(TRY003)
102-105: Avoid specifying long messages outside the exception class
(TRY003)
107-107: Avoid specifying long messages outside the exception class
(TRY003)
109-109: Avoid specifying long messages outside the exception class
(TRY003)
kim_convergence/stats/beta_dist.py
49-49: Docstring contains ambiguous ’ (RIGHT SINGLE QUOTATION MARK). Did you mean ``` (GRAVE ACCENT)?
(RUF002)
52-52: Docstring contains ambiguous ’ (RIGHT SINGLE QUOTATION MARK). Did you mean ``` (GRAVE ACCENT)?
(RUF002)
141-144: Avoid specifying long messages outside the exception class
(TRY003)
kim_convergence/outlier.py
86-86: Avoid specifying long messages outside the exception class
(TRY003)
89-92: Avoid specifying long messages outside the exception class
(TRY003)
101-101: Avoid specifying long messages outside the exception class
(TRY003)
kim_convergence/err.py
8-8: __all__ is not sorted
Apply an isort-style sorting to __all__
(RUF022)
84-84: Avoid specifying long messages outside the exception class
(TRY003)
93-96: Avoid specifying long messages outside the exception class
(TRY003)
135-137: Avoid specifying long messages outside the exception class
(TRY003)
kim_convergence/ucl/mser_m.py
32-38: __all__ is not sorted
Apply an isort-style sorting to __all__
(RUF022)
73-76: Avoid specifying long messages outside the exception class
(TRY003)
80-83: Avoid specifying long messages outside the exception class
(TRY003)
86-90: Avoid specifying long messages outside the exception class
(TRY003)
93-96: Avoid specifying long messages outside the exception class
(TRY003)
99-102: Avoid specifying long messages outside the exception class
(TRY003)
183-183: Avoid specifying long messages outside the exception class
(TRY003)
189-192: Avoid specifying long messages outside the exception class
(TRY003)
196-196: Avoid specifying long messages outside the exception class
(TRY003)
199-199: Avoid specifying long messages outside the exception class
(TRY003)
304-304: Unused method argument: number_of_cores
(ARG002)
306-306: Unused method argument: nskip
(ARG002)
346-346: Unused method argument: equilibration_length_estimate
(ARG002)
347-347: Unused method argument: heidel_welch_number_points
(ARG002)
348-348: Unused method argument: fft
(ARG002)
349-349: Unused method argument: test_size
(ARG002)
350-350: Unused method argument: train_size
(ARG002)
351-351: Unused method argument: population_standard_deviation
(ARG002)
354-354: Unused method argument: si
(ARG002)
355-355: Unused method argument: minimum_correlation_time
(ARG002)
356-356: Unused method argument: uncorrelated_sample_indices
(ARG002)
359-359: Unused method argument: sample_method
(ARG002)
384-384: Avoid specifying long messages outside the exception class
(TRY003)
387-390: Avoid specifying long messages outside the exception class
(TRY003)
543-543: Avoid specifying long messages outside the exception class
(TRY003)
kim_convergence/run_length_control/_variable_list_factory.py
89-89: Avoid specifying long messages outside the exception class
(TRY003)
93-96: Avoid specifying long messages outside the exception class
(TRY003)
99-102: Avoid specifying long messages outside the exception class
(TRY003)
kim_convergence/scale.py
11-23: __all__ is not sorted
Apply an isort-style sorting to __all__
(RUF022)
73-73: Use explicit conversion flag
Replace with conversion flag
(RUF010)
95-95: Avoid specifying long messages outside the exception class
(TRY003)
147-147: Unused function argument: with_centering
(ARG001)
148-148: Unused function argument: with_scaling
(ARG001)
241-241: Avoid specifying long messages outside the exception class
(TRY003)
392-392: Avoid specifying long messages outside the exception class
(TRY003)
571-571: Avoid specifying long messages outside the exception class
(TRY003)
571-571: Use explicit conversion flag
Replace with conversion flag
(RUF010)
574-574: Avoid specifying long messages outside the exception class
(TRY003)
574-574: Use explicit conversion flag
Replace with conversion flag
(RUF010)
578-578: Avoid specifying long messages outside the exception class
(TRY003)
578-578: Use explicit conversion flag
Replace with conversion flag
(RUF010)
596-596: Avoid specifying long messages outside the exception class
(TRY003)
734-734: Avoid specifying long messages outside the exception class
(TRY003)
779-779: Unused function argument: with_centering
(ARG001)
780-780: Unused function argument: with_scaling
(ARG001)
kim_convergence/stats/nonnormal_test.py
17-27: __all__ is not sorted
Apply an isort-style sorting to __all__
(RUF022)
108-108: String contains ambiguous ’ (RIGHT SINGLE QUOTATION MARK). Did you mean ``` (GRAVE ACCENT)?
(RUF001)
122-122: String contains ambiguous ’ (RIGHT SINGLE QUOTATION MARK). Did you mean ``` (GRAVE ACCENT)?
(RUF001)
411-416: Avoid specifying long messages outside the exception class
(TRY003)
540-540: Avoid specifying long messages outside the exception class
(TRY003)
558-558: Unused noqa directive (unused: BLE001)
Remove unused noqa directive
(RUF100)
559-559: Avoid specifying long messages outside the exception class
(TRY003)
662-662: Avoid specifying long messages outside the exception class
(TRY003)
689-689: Unused noqa directive (unused: BLE001)
Remove unused noqa directive
(RUF100)
690-690: Avoid specifying long messages outside the exception class
(TRY003)
694-694: Unused noqa directive (unused: BLE001)
Remove unused noqa directive
(RUF100)
695-695: Avoid specifying long messages outside the exception class
(TRY003)
757-757: Avoid specifying long messages outside the exception class
(TRY003)
781-781: Unused noqa directive (unused: BLE001)
Remove unused noqa directive
(RUF100)
782-782: Avoid specifying long messages outside the exception class
(TRY003)
841-841: Avoid specifying long messages outside the exception class
(TRY003)
849-849: Avoid specifying long messages outside the exception class
(TRY003)
871-871: Unused noqa directive (unused: BLE001)
Remove unused noqa directive
(RUF100)
872-872: Avoid specifying long messages outside the exception class
(TRY003)
876-876: Unused noqa directive (unused: BLE001)
Remove unused noqa directive
(RUF100)
877-877: Avoid specifying long messages outside the exception class
(TRY003)
kim_convergence/stats/t_dist.py
131-131: Avoid specifying long messages outside the exception class
(TRY003)
134-137: Avoid specifying long messages outside the exception class
(TRY003)
kim_convergence/timeseries/statistical_inefficiency.py
26-33: __all__ is not sorted
Apply an isort-style sorting to __all__
(RUF022)
88-88: Avoid specifying long messages outside the exception class
(TRY003)
94-97: Avoid specifying long messages outside the exception class
(TRY003)
104-104: Avoid specifying long messages outside the exception class
(TRY003)
106-106: Avoid specifying long messages outside the exception class
(TRY003)
171-171: Unused function argument: minimum_correlation_time
(ARG001)
175-175: Docstring contains ambiguous ’ (RIGHT SINGLE QUOTATION MARK). Did you mean ``` (GRAVE ACCENT)?
(RUF002)
228-228: Avoid specifying long messages outside the exception class
(TRY003)
321-321: Unused function argument: minimum_correlation_time
(ARG001)
326-326: Docstring contains ambiguous ’ (RIGHT SINGLE QUOTATION MARK). Did you mean ``` (GRAVE ACCENT)?
(RUF002)
372-375: Avoid specifying long messages outside the exception class
(TRY003)
385-385: Unused function argument: minimum_correlation_time
(ARG001)
422-422: Avoid specifying long messages outside the exception class
(TRY003)
426-429: Avoid specifying long messages outside the exception class
(TRY003)
tests/test_kim_convergence/test_stats_nonnormal_test.py
8-8: Unused noqa directive (unused: BLE001)
Remove unused noqa directive
(RUF100)
9-9: Avoid specifying long messages outside the exception class
(TRY003)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
♻️ Duplicate comments (2)
kim_convergence/err.py (1)
56-56: LGTM! The__reduce__pickling bug has been fixed.The trailing comma in
(self.msg,)ensures this is a proper one-element tuple, resolving the pickling issue noted in previous reviews.kim_convergence/stats/beta_dist.py (1)
49-52: Ambiguous character in docstring persists.The docstring still uses
'(RIGHT SINGLE QUOTATION MARK, U+2019) in "Lentz's" instead of a standard ASCII apostrophe. This was flagged in a previous review and can cause issues with some documentation tools.🔎 Proposed fix
- r"""Continued fraction for incomplete beta function by modified Lentz's method. + r"""Continued fraction for incomplete beta function by modified Lentz's method. Evaluates continued fraction for incomplete beta function by modified - Lentz's method [numrec2007]_. + Lentz's method [numrec2007]_.Replace
'(U+2019) with'(U+0027) in both occurrences of "Lentz's".
🧹 Nitpick comments (8)
doc/conf.py (1)
12-21: Consider addingstacklevel=2to the warning.The dynamic version import with fallback is a solid pattern for Sphinx configuration. However, the
warnings.warncall on line 19 would benefit fromstacklevel=2to properly attribute the warning to the calling context during documentation builds, making it easier to debug import issues.🔎 Proposed improvement
- warnings.warn("Could not import kim_convergence; using fallback version") + warnings.warn("Could not import kim_convergence; using fallback version", stacklevel=2)kim_convergence/ucl/mser_m_y.py (2)
34-39: Consider sorting__all__for consistency.Static analysis suggests sorting
__all__. While not critical, sorted exports improve readability and maintainability.🔎 Proposed fix
__all__ = [ - "MSER_m_y", - "mser_m_y_ucl", "mser_m_y_ci", "mser_m_y_relative_half_width_estimate", + "mser_m_y_ucl", + "MSER_m_y", ]
55-57: Ambiguous character in docstring.Line 57 uses
′(PRIME, U+2032) in "k′" which may cause rendering issues. Consider using'(apostrophe) or describing it differently.kim_convergence/ucl/uncorrelated_samples.py (1)
35-40: Consider sorting__all__for consistency.Same optional refactor as other UCL modules.
kim_convergence/ucl/n_skart.py (1)
40-45: Consider sorting__all__for consistency.Same optional refactor as other UCL modules.
kim_convergence/ucl/spectral/heidelberger_welch.py (1)
37-42: Consider sorting__all__for consistency.Same optional refactor as other UCL modules.
kim_convergence/ucl/mser_m.py (2)
32-38: Consider sorting__all__for consistency.Same optional refactor as other UCL modules.
67-78: Potential unreachable code path.The check at lines 85-90 (
if ignore_end < 1) after theNoneandfloathandling branches cannot be reached because:
Nonebranch:ignore_end = max(1, ...)ensures >= 1floatbranch:ignore_end = max(1, int(...))ensures >= 1This code path is defensive but effectively dead code.
🔎 Proposed simplification
elif isinstance(ignore_end, float): if not 0.0 < ignore_end < 1.0: raise CRError( f"invalid ignore_end = {ignore_end}. If ignore_end input " "is a `float`, it should be in a `(0, 1)` range." ) ignore_end *= number_batches ignore_end = max(1, int(ignore_end)) else: raise CRError( f"invalid ignore_end = {ignore_end}. ignore_end is not an " "`int`, `float`, or `None`." ) - - if ignore_end < 1: - raise CRError( - "ignore_end is not given on input and it is automatically set = " - f"{ignore_end} using {data_size} number of data points and the " - f"batch size = {batch_size}.\nignore_end should be a positive `int`." - ) elif ignore_end < 1:The lines 85-90 can be removed since both
Noneandfloatbranches guaranteeignore_end >= 1.
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (32)
README.mddoc/conf.pykim_convergence/err.pykim_convergence/outlier.pykim_convergence/run_length_control/_trajectory.pykim_convergence/stats/beta_dist.pykim_convergence/stats/nonnormal_test.pykim_convergence/stats/t_dist.pykim_convergence/stats/tools.pykim_convergence/stats/zero_rc_bounds.pykim_convergence/timeseries/equilibration_length.pykim_convergence/timeseries/geweke.pykim_convergence/ucl/mser_m.pykim_convergence/ucl/mser_m_y.pykim_convergence/ucl/n_skart.pykim_convergence/ucl/spectral/heidelberger_welch.pykim_convergence/ucl/ucl_base.pykim_convergence/ucl/uncorrelated_samples.pytests/test_kim_convergence/test_batch.pytests/test_kim_convergence/test_outlier.pytests/test_kim_convergence/test_run_length_control.pytests/test_kim_convergence/test_scale.pytests/test_kim_convergence/test_stats.pytests/test_kim_convergence/test_stats_beta_dist.pytests/test_kim_convergence/test_stats_nonnormal_test.pytests/test_kim_convergence/test_stats_normal_test.pytests/test_kim_convergence/test_stats_s_normal_dist.pytests/test_kim_convergence/test_stats_t_dist.pytests/test_kim_convergence/test_timeseries.pytests/test_kim_convergence/test_timeseries_equilibration_length.pytests/test_kim_convergence/test_ucl.pytests/test_kim_convergence/test_ucl_mser_m.py
🧰 Additional context used
🧬 Code graph analysis (14)
kim_convergence/timeseries/equilibration_length.py (3)
kim_convergence/timeseries/statistical_inefficiency.py (1)
statistical_inefficiency(36-158)kim_convergence/err.py (2)
CRError(38-60)CRSampleSizeError(63-66)kim_convergence/ucl/mser_m.py (1)
_normalize_ignore_end(41-104)
kim_convergence/stats/tools.py (1)
kim_convergence/err.py (1)
CRError(38-60)
kim_convergence/ucl/spectral/heidelberger_welch.py (5)
kim_convergence/ucl/ucl_base.py (9)
ucl(342-389)UCLBase(42-492)name(59-61)name(64-71)name(74-76)_ucl_impl(315-340)si(138-140)si(143-150)si(153-155)kim_convergence/err.py (3)
CRError(38-60)CRSampleSizeError(63-66)cr_warning(69-78)kim_convergence/stats/tools.py (1)
modified_periodogram(551-629)kim_convergence/stats/t_dist.py (1)
t_inv_cdf(103-195)kim_convergence/utils.py (1)
train_test_split(114-169)
tests/test_kim_convergence/test_stats_beta_dist.py (1)
kim_convergence/stats/beta_dist.py (4)
beta(17-37)betacf(40-144)betai(147-183)betai_cdf(218-240)
kim_convergence/ucl/mser_m_y.py (5)
kim_convergence/ucl/mser_m.py (3)
mser_m(107-259)MSER_m(262-421)_ucl_impl(333-421)kim_convergence/batch.py (1)
batch(19-145)kim_convergence/err.py (2)
CRError(38-60)CRSampleSizeError(63-66)kim_convergence/stats/randomness_test.py (1)
randomness_test(15-80)kim_convergence/ucl/ucl_base.py (7)
name(59-61)name(64-71)name(74-76)_ucl_impl(315-340)si(138-140)si(143-150)si(153-155)
kim_convergence/outlier.py (1)
kim_convergence/err.py (1)
CRError(38-60)
kim_convergence/timeseries/geweke.py (1)
kim_convergence/err.py (1)
CRError(38-60)
kim_convergence/stats/nonnormal_test.py (1)
kim_convergence/err.py (3)
CRError(38-60)CRSampleSizeError(63-66)cr_check(102-157)
kim_convergence/stats/beta_dist.py (1)
kim_convergence/err.py (1)
CRError(38-60)
tests/test_kim_convergence/test_scale.py (2)
kim_convergence/scale.py (11)
MinMaxScale(26-141)scale(82-121)scale(228-262)scale(379-448)scale(584-618)scale(708-749)inverse(123-141)inverse(264-291)inverse(450-483)inverse(620-647)inverse(751-773)kim_convergence/err.py (1)
CRError(38-60)
kim_convergence/run_length_control/_trajectory.py (1)
kim_convergence/err.py (1)
CRError(38-60)
tests/test_kim_convergence/test_batch.py (2)
kim_convergence/err.py (1)
CRError(38-60)kim_convergence/batch.py (1)
batch(19-145)
tests/test_kim_convergence/test_outlier.py (1)
kim_convergence/outlier.py (1)
outlier_test(56-135)
tests/test_kim_convergence/test_stats.py (2)
kim_convergence/stats/tools.py (6)
auto_covariance(342-388)cross_covariance(391-435)auto_correlate(438-484)cross_correlate(487-548)periodogram(632-679)int_power(707-750)kim_convergence/err.py (1)
CRError(38-60)
🪛 markdownlint-cli2 (0.18.1)
README.md
34-34: Images should have alternate text (alt text)
(MD045, no-alt-text)
35-35: Images should have alternate text (alt text)
(MD045, no-alt-text)
🪛 Ruff (0.14.10)
tests/test_kim_convergence/test_stats_nonnormal_test.py
9-9: Avoid specifying long messages outside the exception class
(TRY003)
kim_convergence/timeseries/equilibration_length.py
89-92: Avoid specifying long messages outside the exception class
(TRY003)
96-99: Avoid specifying long messages outside the exception class
(TRY003)
101-104: Avoid specifying long messages outside the exception class
(TRY003)
109-112: Avoid specifying long messages outside the exception class
(TRY003)
116-119: Avoid specifying long messages outside the exception class
(TRY003)
123-126: Avoid specifying long messages outside the exception class
(TRY003)
130-133: Avoid specifying long messages outside the exception class
(TRY003)
147-147: Unused function argument: batch_size
(ARG001)
148-148: Unused function argument: scale
(ARG001)
149-149: Unused function argument: with_centering
(ARG001)
150-150: Unused function argument: with_scaling
(ARG001)
189-189: Avoid specifying long messages outside the exception class
(TRY003)
203-203: Avoid specifying long messages outside the exception class
(TRY003)
209-209: Avoid specifying long messages outside the exception class
(TRY003)
214-214: Avoid specifying long messages outside the exception class
(TRY003)
kim_convergence/stats/t_dist.py
23-23: Avoid specifying long messages outside the exception class
(TRY003)
kim_convergence/stats/tools.py
126-126: Avoid specifying long messages outside the exception class
(TRY003)
130-130: Avoid specifying long messages outside the exception class
(TRY003)
231-231: Do not catch blind exception: Exception
(BLE001)
254-254: Avoid specifying long messages outside the exception class
(TRY003)
259-259: Avoid specifying long messages outside the exception class
(TRY003)
276-276: Do not catch blind exception: Exception
(BLE001)
296-296: Avoid specifying long messages outside the exception class
(TRY003)
301-301: Avoid specifying long messages outside the exception class
(TRY003)
316-316: Avoid specifying long messages outside the exception class
(TRY003)
319-319: Avoid specifying long messages outside the exception class
(TRY003)
322-325: Avoid specifying long messages outside the exception class
(TRY003)
331-331: Avoid specifying long messages outside the exception class
(TRY003)
334-337: Avoid specifying long messages outside the exception class
(TRY003)
474-474: Avoid specifying long messages outside the exception class
(TRY003)
477-477: Avoid specifying long messages outside the exception class
(TRY003)
538-538: Avoid specifying long messages outside the exception class
(TRY003)
541-541: Avoid specifying long messages outside the exception class
(TRY003)
663-663: Avoid specifying long messages outside the exception class
(TRY003)
696-696: Avoid specifying long messages outside the exception class
(TRY003)
721-721: Avoid specifying long messages outside the exception class
(TRY003)
724-724: Avoid specifying long messages outside the exception class
(TRY003)
727-727: Avoid specifying long messages outside the exception class
(TRY003)
778-778: Avoid specifying long messages outside the exception class
(TRY003)
kim_convergence/ucl/n_skart.py
40-45: __all__ is not sorted
Apply an isort-style sorting to __all__
(RUF022)
116-116: Unused method argument: nskip
(ARG002)
119-119: Unused method argument: ignore_end
(ARG002)
120-120: Unused method argument: number_of_cores
(ARG002)
146-146: Avoid specifying long messages outside the exception class
(TRY003)
303-303: Unused method argument: heidel_welch_number_points
(ARG002)
304-304: Unused method argument: batch_size
(ARG002)
308-308: Unused method argument: test_size
(ARG002)
309-309: Unused method argument: train_size
(ARG002)
310-310: Unused method argument: population_standard_deviation
(ARG002)
313-313: Unused method argument: si
(ARG002)
314-314: Unused method argument: minimum_correlation_time
(ARG002)
315-315: Unused method argument: uncorrelated_sample_indices
(ARG002)
318-318: Unused method argument: sample_method
(ARG002)
343-343: Avoid specifying long messages outside the exception class
(TRY003)
346-346: Avoid specifying long messages outside the exception class
(TRY003)
574-574: Avoid specifying long messages outside the exception class
(TRY003)
kim_convergence/ucl/ucl_base.py
292-292: Unused method argument: batch_size
(ARG002)
293-293: Unused method argument: scale
(ARG002)
294-294: Unused method argument: with_centering
(ARG002)
295-295: Unused method argument: with_scaling
(ARG002)
486-489: Avoid specifying long messages outside the exception class
(TRY003)
kim_convergence/ucl/spectral/heidelberger_welch.py
37-42: __all__ is not sorted
Apply an isort-style sorting to __all__
(RUF022)
322-322: Unused method argument: equilibration_length_estimate
(ARG002)
326-326: Unused method argument: population_standard_deviation
(ARG002)
329-329: Unused method argument: si
(ARG002)
330-330: Unused method argument: minimum_correlation_time
(ARG002)
331-331: Unused method argument: uncorrelated_sample_indices
(ARG002)
334-334: Unused method argument: sample_method
(ARG002)
484-484: Avoid specifying long messages outside the exception class
(TRY003)
775-775: Avoid specifying long messages outside the exception class
(TRY003)
tests/test_kim_convergence/test_stats_beta_dist.py
10-10: Avoid specifying long messages outside the exception class
(TRY003)
kim_convergence/ucl/mser_m_y.py
34-39: __all__ is not sorted
Apply an isort-style sorting to __all__
(RUF022)
57-57: Docstring contains ambiguous ′ (PRIME). Did you mean ``` (GRAVE ACCENT)?
(RUF002)
82-82: Unused method argument: equilibration_length_estimate
(ARG002)
83-83: Unused method argument: heidel_welch_number_points
(ARG002)
84-84: Unused method argument: fft
(ARG002)
85-85: Unused method argument: test_size
(ARG002)
86-86: Unused method argument: train_size
(ARG002)
87-87: Unused method argument: population_standard_deviation
(ARG002)
90-90: Unused method argument: si
(ARG002)
91-91: Unused method argument: minimum_correlation_time
(ARG002)
92-92: Unused method argument: uncorrelated_sample_indices
(ARG002)
95-95: Unused method argument: sample_method
(ARG002)
120-120: Avoid specifying long messages outside the exception class
(TRY003)
125-129: Avoid specifying long messages outside the exception class
(TRY003)
325-325: Avoid specifying long messages outside the exception class
(TRY003)
tests/test_kim_convergence/test_run_length_control.py
14-14: Avoid specifying long messages outside the exception class
(TRY003)
900-900: Unused function argument: step
(ARG001)
901-901: Avoid specifying long messages outside the exception class
(TRY003)
kim_convergence/ucl/uncorrelated_samples.py
35-40: __all__ is not sorted
Apply an isort-style sorting to __all__
(RUF022)
68-68: Unused method argument: equilibration_length_estimate
(ARG002)
69-69: Unused method argument: heidel_welch_number_points
(ARG002)
70-70: Unused method argument: batch_size
(ARG002)
71-71: Unused method argument: scale
(ARG002)
72-72: Unused method argument: with_centering
(ARG002)
73-73: Unused method argument: with_scaling
(ARG002)
74-74: Unused method argument: test_size
(ARG002)
75-75: Unused method argument: train_size
(ARG002)
131-131: Avoid specifying long messages outside the exception class
(TRY003)
136-139: Avoid specifying long messages outside the exception class
(TRY003)
142-145: Avoid specifying long messages outside the exception class
(TRY003)
409-409: Avoid specifying long messages outside the exception class
(TRY003)
kim_convergence/outlier.py
86-86: Avoid specifying long messages outside the exception class
(TRY003)
89-92: Avoid specifying long messages outside the exception class
(TRY003)
101-101: Avoid specifying long messages outside the exception class
(TRY003)
kim_convergence/timeseries/geweke.py
57-60: Avoid specifying long messages outside the exception class
(TRY003)
kim_convergence/ucl/mser_m.py
32-38: __all__ is not sorted
Apply an isort-style sorting to __all__
(RUF022)
73-76: Avoid specifying long messages outside the exception class
(TRY003)
80-83: Avoid specifying long messages outside the exception class
(TRY003)
86-90: Avoid specifying long messages outside the exception class
(TRY003)
93-96: Avoid specifying long messages outside the exception class
(TRY003)
99-102: Avoid specifying long messages outside the exception class
(TRY003)
183-183: Avoid specifying long messages outside the exception class
(TRY003)
189-192: Avoid specifying long messages outside the exception class
(TRY003)
196-196: Avoid specifying long messages outside the exception class
(TRY003)
199-199: Avoid specifying long messages outside the exception class
(TRY003)
302-302: Unused method argument: number_of_cores
(ARG002)
304-304: Unused method argument: nskip
(ARG002)
342-342: Unused method argument: equilibration_length_estimate
(ARG002)
343-343: Unused method argument: heidel_welch_number_points
(ARG002)
344-344: Unused method argument: fft
(ARG002)
345-345: Unused method argument: test_size
(ARG002)
346-346: Unused method argument: train_size
(ARG002)
347-347: Unused method argument: population_standard_deviation
(ARG002)
350-350: Unused method argument: si
(ARG002)
351-351: Unused method argument: minimum_correlation_time
(ARG002)
352-352: Unused method argument: uncorrelated_sample_indices
(ARG002)
355-355: Unused method argument: sample_method
(ARG002)
380-380: Avoid specifying long messages outside the exception class
(TRY003)
383-386: Avoid specifying long messages outside the exception class
(TRY003)
539-539: Avoid specifying long messages outside the exception class
(TRY003)
kim_convergence/stats/nonnormal_test.py
17-27: __all__ is not sorted
Apply an isort-style sorting to __all__
(RUF022)
108-108: String contains ambiguous ’ (RIGHT SINGLE QUOTATION MARK). Did you mean ``` (GRAVE ACCENT)?
(RUF001)
122-122: String contains ambiguous ’ (RIGHT SINGLE QUOTATION MARK). Did you mean ``` (GRAVE ACCENT)?
(RUF001)
411-416: Avoid specifying long messages outside the exception class
(TRY003)
540-540: Avoid specifying long messages outside the exception class
(TRY003)
559-559: Avoid specifying long messages outside the exception class
(TRY003)
662-662: Avoid specifying long messages outside the exception class
(TRY003)
690-690: Avoid specifying long messages outside the exception class
(TRY003)
695-695: Avoid specifying long messages outside the exception class
(TRY003)
757-757: Avoid specifying long messages outside the exception class
(TRY003)
782-782: Avoid specifying long messages outside the exception class
(TRY003)
841-841: Avoid specifying long messages outside the exception class
(TRY003)
849-849: Avoid specifying long messages outside the exception class
(TRY003)
872-872: Avoid specifying long messages outside the exception class
(TRY003)
877-877: Avoid specifying long messages outside the exception class
(TRY003)
kim_convergence/stats/beta_dist.py
141-144: Avoid specifying long messages outside the exception class
(TRY003)
tests/test_kim_convergence/test_scale.py
10-10: Avoid specifying long messages outside the exception class
(TRY003)
doc/conf.py
19-19: No explicit stacklevel keyword argument found
Set stacklevel=2
(B028)
kim_convergence/err.py
8-8: __all__ is not sorted
Apply an isort-style sorting to __all__
(RUF022)
84-84: Avoid specifying long messages outside the exception class
(TRY003)
93-96: Avoid specifying long messages outside the exception class
(TRY003)
135-137: Avoid specifying long messages outside the exception class
(TRY003)
kim_convergence/run_length_control/_trajectory.py
29-36: Avoid specifying long messages outside the exception class
(TRY003)
57-60: Avoid specifying long messages outside the exception class
(TRY003)
65-68: Avoid specifying long messages outside the exception class
(TRY003)
74-77: Avoid specifying long messages outside the exception class
(TRY003)
80-83: Avoid specifying long messages outside the exception class
(TRY003)
86-91: Avoid specifying long messages outside the exception class
(TRY003)
kim_convergence/stats/zero_rc_bounds.py
156-161: Avoid specifying long messages outside the exception class
(TRY003)
161-161: Unused noqa directive (unused: TRY003)
Remove unused noqa directive
(RUF100)
162-167: Avoid specifying long messages outside the exception class
(TRY003)
167-167: Unused noqa directive (unused: TRY003)
Remove unused noqa directive
(RUF100)
174-179: Avoid specifying long messages outside the exception class
(TRY003)
179-179: Unused noqa directive (unused: TRY003)
Remove unused noqa directive
(RUF100)
180-184: Avoid specifying long messages outside the exception class
(TRY003)
184-184: Unused noqa directive (unused: TRY003)
Remove unused noqa directive
(RUF100)
221-226: Avoid specifying long messages outside the exception class
(TRY003)
226-226: Unused noqa directive (unused: TRY003)
Remove unused noqa directive
(RUF100)
259-264: Avoid specifying long messages outside the exception class
(TRY003)
264-264: Unused noqa directive (unused: TRY003)
Remove unused noqa directive
(RUF100)
309-312: Avoid specifying long messages outside the exception class
(TRY003)
312-312: Unused noqa directive (unused: TRY003)
Remove unused noqa directive
(RUF100)
tests/test_kim_convergence/test_batch.py
9-9: Avoid specifying long messages outside the exception class
(TRY003)
tests/test_kim_convergence/test_outlier.py
9-9: Avoid specifying long messages outside the exception class
(TRY003)
tests/test_kim_convergence/test_stats.py
9-9: Avoid specifying long messages outside the exception class
(TRY003)
🔇 Additional comments (82)
kim_convergence/timeseries/geweke.py (4)
12-14: LGTM! Function signature enhanced with type annotations.The added type hints (
x: np.ndarray, keyword-only parameters with*, and return type-> np.ndarray) improve API clarity and align with modern Python typing conventions.
15-53: Excellent docstring improvement—past review concern resolved.The rewritten NumPy-style docstring now correctly documents the return type as
np.ndarraywith shape information, resolving the previous inconsistency where the old docstring claimedlist [[]]. The added Parameters, Returns, and Notes sections with the mathematical formula significantly improve API clarity.
71-72: Good defensive programming.The dimensionality check ensures the input constraint (
x : 1D array-like) from the docstring is enforced at runtime, preventing silent failures or cryptic downstream errors.
84-86: LGTM! Explicit dtype prevents indexing issues.Adding
dtype=inttonp.linspaceensures thatstart_indicesare integers, avoiding potential type-related indexing errors.doc/conf.py (2)
7-10: LGTM! Dynamic copyright prevents documentation staleness.The use of
datetime.now().yearensures the copyright year range stays current without manual updates, andrst_epilogenables convenient|copyright|substitution throughout the documentation.
23-62: Well-structured Sphinx configuration.The streamlined extension list, comprehensive MyST features, and GitHub integration via
html_contextprovide a modern, maintainable documentation setup that aligns well with the PR's goal of delivering a full Sphinx documentation site with Read the Docs integration.README.md (3)
1-51: Excellent transformation to user-friendly landing page.The rewrite successfully transforms the README from detailed documentation into a compelling landing page that emphasizes the problem (manual simulation length estimation) and solution (automated convergence detection), with clear visual examples. This aligns perfectly with the PR objective of moving comprehensive documentation to a dedicated Sphinx site.
99-119: Clean quick-start example—past review concern resolved.The minimal example effectively demonstrates the core API with a simple fake trajectory generator and clear parameter usage. The past review concern about a misleading comment on line 118 has been addressed; the code now simply prints the result without ambiguous inline commentary.
121-140: LGTM! Clean separation between landing page and comprehensive docs.The concise linking structure effectively directs users to external documentation, issue tracking, and contributing guidelines, supporting the PR's strategy of maintaining the README as a focused entry point while deferring comprehensive content to the Sphinx documentation site.
tests/test_kim_convergence/test_scale.py (2)
9-10: LGTM! Exception chaining preserves the original traceback.The updated exception handling correctly uses
from eto preserve the exception chain, which will help with debugging import failures.
29-29: LGTM! Numeric literals are now consistently formatted.The normalization of numeric literals to explicit floats (e.g.,
10.0instead of10.,-1.0instead of-1.) improves code consistency and readability across the test suite.Also applies to: 33-33, 41-41, 46-46, 51-51, 54-54, 61-61, 63-63, 93-93, 108-108
kim_convergence/stats/zero_rc_bounds.py (2)
93-99: LGTM! Direct assignments are appropriate for primitive types.Replacing
deepcopywith direct assignments is correct here since all the attributes being assigned are primitive types (float, bool) that don't require deep copying.
161-161: These# noqa: TRY003directives are not unused. Each directive actively suppresses a legitimate TRY003 (raise-vanilla-args) violation. The code raisesCRErrorwith formatted f-string arguments (e.g.,raise CRError(f"Answer x = {x}, appears to be higher...")), which is exactly what TRY003 warns against. To remove these directives, the code would need to be refactored to pass plain arguments toCRErrorand handle message formatting inside the exception class itself. The directives serve their intended purpose and should not be removed.Likely an incorrect or invalid review comment.
kim_convergence/err.py (2)
11-36: LGTM! Caller name extraction with proper frame cleanup.The
_get_caller_namefunction correctly:
- Walks back the stack to find the caller
- Handles cases where frames are unavailable
- Properly cleans up frame references in the
finallyblock to prevent reference cycles
76-78: LGTM! Warnings now properly go to stderr.Writing warnings to
sys.stderrwith explicitflush=Truefollows best practices by:
- Keeping warnings separate from normal output
- Ensuring immediate visibility of warning messages
kim_convergence/stats/t_dist.py (2)
19-23: LGTM! Helper function centralizes bounds-checking logic.The
_raise_bounds_errorhelper reduces code duplication and ensures consistent error messages across all bounds validation in this module.
103-112: LGTM! Multi-line signatures improve readability.The reformatted function signatures are more readable and make the parameters and their default values easier to scan.
Also applies to: 198-200
kim_convergence/timeseries/equilibration_length.py (3)
58-135: LGTM! Validation logic centralized in helper function.The
_normalize_ignore_endhelper:
- Consolidates ignore_end validation and normalization
- Handles Geyer-specific lower bounds consistently
- Provides clear error messages for different failure modes
- Follows the same pattern used elsewhere in the codebase (e.g., mser_m.py)
239-246: LGTM! Proper use of joblib's parallel backend context manager.The
with parallel_backend("loky", n_jobs=number_of_cores)pattern:
- Explicitly specifies the loky backend for multiprocessing
- Properly scopes the parallel execution context
- Follows joblib best practices for configuring parallelism
147-150: Unused parameters are acceptable for API compatibility.The parameters marked as
# unused (API compatibility)are intentionally retained to maintain backward compatibility. This is a valid design choice and doesn't require changes.kim_convergence/stats/tools.py (6)
1-38: LGTM: Clear documentation of escape-hatch mechanism.The extensive documentation for
KIM_CONV_FORCE_SUBPROCis excellent. The performance warnings are appropriately stark, and the guidance to never set it during testing is clear.
235-263: LGTM: Subprocess isolation with explicit timeout trade-off.The implementation correctly addresses the previous timeout concerns by:
- Using
p.join()without timeout (with clear justification)- Checking
exitcodeto detect crashes- Using
get_nowait()to avoid blocking- Handling the
EmptyexceptionThe NO-TIMEOUT comment explicitly acknowledges the trade-off: blocking indefinitely on genuine hangs vs. not killing legitimate long-running computations. This is a reasonable design decision for scientific workloads.
280-305: LGTM: Consistent with correlation isolation.Same robust pattern as
_isolate()with the same explicit trade-offs.
308-339: LGTM: Comprehensive input validation.This helper centralizes validation logic effectively, checking dimensionality, emptiness, finiteness, and shape matching.
342-388: LGTM: Clean integration of optional subprocess isolation.The environment variable check at lines 383-386 cleanly integrates the isolation mechanism while preserving the original behavior by default. The updated signature accepting
list[float]improves usability.
231-232: Static analysis note: Intentional broad exception handling.The static analysis hint about catching blind
Exceptionat line 231 can be ignored. This is correct for subprocess workers that must catch all exceptions to pass them back through the queue for proper error reporting in the parent process.tests/test_kim_convergence/test_stats_beta_dist.py (2)
9-10: LGTM: Improved exception chaining.The addition of
from epreserves the original exception context, improving debuggability.
41-51: LGTM: Correct unpacking of tuple return.The unpacking of
betai_cdf_ccdfreturn value correctly reflects the function's tuple return type(cdf, ccdf).tests/test_kim_convergence/test_outlier.py (2)
8-9: LGTM: Improved exception chaining.Exception chaining preserves the original context for better debugging.
21-48: LGTM: Defensive type assertions added.The dual approach of
assertIsInstance(runtime check) andassert isinstance(mypy satisfaction) is good defensive programming, especially given thatoutlier_testreturnsOptional[np.ndarray].tests/test_kim_convergence/test_batch.py (2)
8-9: LGTM: Improved exception chaining.
28-163: LGTM: Formatting improvements.The multi-line formatting of function calls improves readability. The change to
np.nan(line 138) uses the standard name rather than the deprecatednp.NaNalias.tests/test_kim_convergence/test_stats.py (2)
8-9: LGTM: Improved exception chaining.
71-832: LGTM: Comprehensive formatting improvements.The multi-line array definitions, explicit float literals, and consistent assertion formatting significantly improve readability. The standardization of
-np.infusage removes version-dependent conditionals.tests/test_kim_convergence/test_stats_nonnormal_test.py (1)
1-169: LGTM! Formatting and style improvements enhance consistency.The updates to this test file—standardizing string literals to double quotes, improving exception chaining with
from e, normalizing numeric literals, and applying multiline formatting—all improve code consistency and readability without altering test logic.tests/test_kim_convergence/test_run_length_control.py (1)
1-1019: Excellent test coverage for the run_length_control module.This new test file provides comprehensive coverage of the run_length_control functionality, including:
- Validation of invalid inputs and parameter combinations
- Convergence scenarios (constant data, noisy data, multi-variable)
- Edge cases (max run length, equilibration failures, non-finite values)
- File I/O (trajectory dumps, JSON/EDN reports)
- Internal helper functions (view semantics, variable list factory)
The test structure is well-organized and thorough, with clear test names and appropriate assertions.
kim_convergence/run_length_control/_trajectory.py (1)
1-93: Well-structured trajectory acquisition module with proper validation.This private module provides robust trajectory data retrieval with comprehensive validation:
- Callable validation with clear error messages
- Proper handling of optional arguments (mutable default previously flagged has been corrected to
Optional[dict] = None)- Finite-value and shape validation
- Clear error reporting for all failure modes
The implementation is clean and the error handling is thorough.
kim_convergence/stats/nonnormal_test.py (1)
1-879: Type annotations and formatting modernized successfully.The updates to this module modernize the codebase:
- Type hints updated to Python 3.9+ style (
list[float]instead ofList[float])- String literals standardized to double quotes for consistency
- Added
castfor type safety in dynamic attribute accessThese changes align with the PR's goal of code quality improvements and modernization while preserving all functional behavior.
kim_convergence/outlier.py (1)
1-135: Division-by-zero safeguards successfully implemented.The outlier detection module has been properly hardened:
- Lines 118-120: Added check for zero standard deviation in z-score calculation, returning
Nonewhen all values are identical- Lines 126-128: Added check for zero MAD in modified z-score calculation, similarly returning
Nonefor degenerate cases- Type annotations modernized to Python 3.9+ style (
list[float],Optional[np.ndarray])These fixes address the critical division-by-zero issues flagged in previous reviews while maintaining clean error handling.
kim_convergence/stats/beta_dist.py (5)
8-14: LGTM!The
__all__export list update to double-quoted strings is consistent with the broader project style changes.
40-48: LGTM!Good refactor of the function signature to multi-line format with explicit type hints and the use of
np.finfo(np.float64).resolutionfor the default epsilon value.
69-145: LGTM!The
betacfimplementation is correct with proper handling of numerical edge cases. The updates to use explicit1.0literals and consistent formatting improve readability.
147-184: LGTM!The
betaifunction correctly implements the incomplete beta function with proper boundary checks and symmetry relation optimization.
186-240: LGTM!The
betai_cdf_ccdfandbetai_cdffunctions are straightforward wrappers with correct boundary handling.kim_convergence/ucl/mser_m_y.py (6)
73-96: Unused parameters for API compatibility are acceptable.The parameters marked as "unused (API compatibility)" maintain interface consistency with the base class
_ucl_implsignature. This is a valid design choice for polymorphic UCL method dispatch.
117-129: LGTM!Input validation is thorough with appropriate error messages for dimensionality checks and minimum sample size requirements.
148-168: LGTM!The randomness test loop with batch size inflation (factor 1.2) correctly implements the MSER-m_y algorithm's approach to finding independent batch means.
206-207: Assertion for type narrowing is appropriate.The
assert isinstance(self.upper_confidence_limit, float)serves as a type guard for mypy, andfloat()ensures a built-in float is returned rather than a numpy scalar. This is consistent with the pattern used across other UCL modules.
210-230: LGTM!The
mser_m_y_uclwrapper correctly delegates to the class instance'suclmethod.
324-325: Exception chaining preserves context.Good use of
raise ... from eto preserve the exception chain while providing a user-friendly message.kim_convergence/ucl/ucl_base.py (7)
37-39: LGTM!Single-item
__all__export is appropriate for this base class module.
49-56: LGTM!Good use of
Optionaltypes for attributes that may be unset. The trailing underscore convention for backing attributes is consistent.
247-280: Well-designed zero-variance handling.The
_handle_zero_variancemethod correctly handles constant series by:
- Setting mean to the constant value
- Setting std to 0.0
- Setting SI to N (no effective decorrelation possible)
- Setting UCL to 0.0 (no uncertainty)
This centralizes edge-case handling that was previously scattered across subclasses.
315-340: LGTM!The abstract
_ucl_implmethod withNotImplementedErrorcorrectly enforces subclass implementation. The comprehensive parameter list ensures a uniform interface across all UCL implementations.
366-389: LGTM!The
uclmethod properly chains zero-variance handling before delegating to subclass-specific computation.
434-437: Assertion may fail if_ucl_impldoesn't setself.mean.The assertion
assert isinstance(self.mean, float)assumes_ucl_implalways setsself.mean_. If a subclass implementation fails to do so, this will raiseAssertionErrorrather than a more informative error.However, since
_handle_zero_variancesetsself.mean_for constant series and returns early, and all subclass_ucl_implimplementations in this PR setself.mean, this is acceptable as a defensive check.
483-491: LGTM!The
relative_half_width_estimatecorrectly guards against division by zero when the mean is close to zero.kim_convergence/ucl/uncorrelated_samples.py (5)
42-42: LGTM!The
SAMPLING_METHODStuple provides a clear enumeration of valid sampling strategies.
53-76: Unused parameters for API compatibility are documented.The pattern of accepting but not using parameters for interface consistency is well-documented with inline comments.
176-183: Good defensive handling for small sample sizes.Warning before raising an exception for samples < 5 provides useful feedback, and the hard error at < 2 prevents undefined behavior in variance calculations.
205-212: Degrees of freedom calculation is correct.Using
uncorrelated_samples_size - 1for the t-distribution is appropriate when estimating the sample standard deviation.
408-409: Exception chaining preserves context.Consistent with the pattern used in other UCL modules.
kim_convergence/ucl/n_skart.py (7)
78-109: LGTM!Initialization correctly sets algorithm constants including the initial batch count (1280), significance level (0.2), and maximum spacer batches (10).
219-237: LGTM!The nested while loop for spacer determination correctly implements steps 3b-3d of the N-Skart algorithm, incrementing the spacer until randomness is achieved or the maximum is reached.
228-230: Verify spaced batch slicing logic.The expression
x_batch[idx::idx + 1]creates a view starting at indexidxwith strideidx + 1. For example, withidx=1, this selects indices 1, 3, 5, 7... which implements "every (d+1)-th batch starting from batch d".This matches the N-Skart algorithm's spaced batch means construction.
296-319: Unused parameters documented for API compatibility.Consistent with the base class interface pattern.
362-364: LGTM!The reinflation calculation
kp * (1.0 / 0.9)^bcorrectly reverses the 0.9 deflation applied during the randomness testing phase.
465-473: LGTM!The skewness adjustment formula and final UCL calculation correctly implement step 7 of the N-Skart algorithm with correlation and skewness corrections.
573-574: Exception chaining pattern is consistent.Good use of
raise ... from efor exception context preservation.kim_convergence/ucl/spectral/heidelberger_welch.py (8)
99-115: LGTM!Explicit
Optionaltyping for all attributes improves type safety and documents the object's state lifecycle.
144-154: Efficient caching of constants.The early return when
heidel_welch_setis true and only the confidence coefficient changes avoids redundant matrix computations. The assertions ensure type safety for the t_inv_cdf calls.
336-479: Excellent documentation added to_ucl_impl.The expanded docstring provides:
- Mathematical basis with LaTeX equations
- Algorithm description with numbered steps
- Performance characteristics (time/space complexity)
- Working code example
- Clear parameter documentation
This significantly improves the module's usability.
499-507: Good defensive handling with warning before exception.Calling
cr_warningbefore raisingCRSampleSizeErrorprovides useful feedback while still enforcing the minimum data requirement.
543-546: Type assertions ensure safe matrix operations.The assertions verify that the auxiliary matrices are properly initialized before use in
np.matmuloperations.
603-640: LGTM!The model selection based on minimum error norm (or test error when train/test split is used) correctly implements the polynomial degree selection, and the final UCL calculation uses the appropriate bias correction constants.
774-775: Exception chaining pattern is consistent.Good use of
raise ... from efor exception context preservation.
193-220: Implementation of Heidelberger-Welch bias correction constants verified.The constants C1 and C2 are correctly computed following Table 1 of Heidelberger & Welch (1981). The formulas
C1 = exp(-σ²/2)andC2 = round(2/(exp(σ²)-1))withσ² = 0.645 * (A'A)⁻¹[0,0]match expected values in the test suite (e.g., for k=50: C1 values of 0.974, 0.941, 0.894 and C2 values of 37, 16, 8 respectively for the three polynomial degrees).kim_convergence/ucl/mser_m.py (5)
41-105: Well-designed helper function forignore_endnormalization.The
_normalize_ignore_endfunction:
- Handles
Nonewith sensible defaults (min of batch_size and quarter of batches)- Handles float as fraction with validation in (0, 1)
- Validates int >= 1
- Ensures ignore_end < number_batches
This centralizes validation that was previously inline, improving maintainability.
107-259: LGTM!The
mser_mfunction correctly implements the MSER-m algorithm with proper batching, variance calculation, and truncation point detection. The use of_normalize_ignore_endimproves code clarity.
333-356: Unused parameters documented for API compatibility.Consistent with the base class interface pattern across all UCL implementations.
377-421: LGTM!The
_ucl_implmethod correctly computes the UCL using batch means, sample standard deviation, and the t-distribution critical value. The assertion and float conversion ensure type consistency.
538-539: Exception chaining pattern is consistent.Good use of
raise ... from efor exception context preservation.
…, quotes, TRY003 ignores
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 5
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
kim_convergence/ucl/n_skart.py (1)
433-471: Potential edge cases in correlation and skewness adjustments.The code could encounter numerical issues in pathological cases:
- Line 438: Division by
(1 - lag1_correlation)fails whenlag1_correlation ≈ 1.0(perfectly correlated batches).- Line 465-467: Division by
2 * betafails whenbeta ≈ 0(zero skewness).While these scenarios are rare in practice, consider adding guards or documenting the assumptions.
🔎 Suggested safeguards (optional)
# compute the correlation adjustment A <- (1 + \phi) / (1 - \phi) - correlation_adjustment = (1 + lag1_correlation) / (1 - lag1_correlation) + if abs(1 - lag1_correlation) < 1e-10: + raise CRError("Batches are perfectly correlated; cannot compute correlation adjustment.") + correlation_adjustment = (1 + lag1_correlation) / (1 - lag1_correlation)- skewness_adjustment = ((1 + 6 * beta * (upper - beta)) ** (1 / 3) - 1) / ( - 2 * beta - ) + if abs(beta) < 1e-15: + skewness_adjustment = (upper - beta) # limiting case as beta → 0 + else: + skewness_adjustment = ((1 + 6 * beta * (upper - beta)) ** (1 / 3) - 1) / ( + 2 * beta + )
🧹 Nitpick comments (6)
kim_convergence/stats/normal_dist.py (1)
170-172: Optional: Simplify string concatenation.The error message uses string concatenation that could be consolidated into a single f-string for slightly improved readability.
🔎 Proposed simplification
- raise CRError( - f"confidence level = {confidence_level} is not in the " "range (0.0 1.0)." - ) + raise CRError( + f"confidence level = {confidence_level} is not in the range (0.0 1.0)." + )kim_convergence/scale.py (2)
147-148: Consider deprecating unused parameters in a future version.The
with_centeringandwith_scalingparameters are kept for API compatibility but are ignored. While the Notes section documents this behavior, it could confuse users who expect these parameters to work.Consider adding a deprecation warning or removing these parameters in a future major version to clarify the API surface.
Also applies to: 174-179
779-780: Consider deprecating unused parameters in a future version.Similar to
minmax_scale(lines 147-148), thewith_centeringandwith_scalingparameters are kept for API compatibility but ignored. The documentation clarifies this, but consider deprecating these parameters in a future major version for API clarity.Also applies to: 793-798
kim_convergence/stats/nonnormal_test.py (2)
399-446: LGTM: Type annotations and style improvements.The updated type hints and double-quoted strings improve consistency. The membership check using a tuple at line 407 is appropriate for the small number of items.
Note: Static analysis suggests extracting the long error message (lines 411-416) into a custom exception class rather than constructing it inline. This is a style preference (Ruff TRY003) and can be deferred.
564-879: LGTM: Consistent type improvements across test functions.The type annotation updates for
levene_test,wilcoxon_test, andkruskal_testmaintain consistency. Thecast(float, pvalue)at line 786 appropriately handles scipy's type stub imprecision for thewilcoxonreturn value.Note: Static analysis flags long error messages at lines 559, 690, 695, 782, and 877 (Ruff TRY003), suggesting custom exception classes instead. This is a style preference and can be addressed in a future refactor if desired.
kim_convergence/ucl/mser_m.py (1)
41-97: Consider removing unuseddata_sizeparameter.The
data_sizeparameter is not used in the function body. If it's not needed for future validation logic, consider removing it from the signature to simplify the API.🔎 Proposed fix
def _normalize_ignore_end( ignore_end: Union[int, float, None], batch_size: int, number_batches: int, - data_size: int, ) -> int:And update the call site at line 213-215:
ignore_end = _normalize_ignore_end( - ignore_end, batch_size, number_batches, time_series_data.size + ignore_end, batch_size, number_batches )
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (19)
README.mddoc/conf.pykim_convergence/_default.pykim_convergence/err.pykim_convergence/scale.pykim_convergence/stats/beta_dist.pykim_convergence/stats/nonnormal_test.pykim_convergence/stats/normal_dist.pykim_convergence/stats/normal_test.pykim_convergence/stats/tools.pykim_convergence/timeseries/statistical_inefficiency.pykim_convergence/timeseries/utils.pykim_convergence/ucl/mser_m.pykim_convergence/ucl/mser_m_y.pykim_convergence/ucl/n_skart.pykim_convergence/ucl/spectral/__init__.pykim_convergence/ucl/spectral/heidelberger_welch.pykim_convergence/ucl/uncorrelated_samples.pykim_convergence/utils.py
🚧 Files skipped from review as they are similar to previous changes (3)
- kim_convergence/stats/normal_test.py
- kim_convergence/ucl/spectral/init.py
- kim_convergence/_default.py
🧰 Additional context used
🧬 Code graph analysis (8)
kim_convergence/ucl/n_skart.py (5)
kim_convergence/ucl/ucl_base.py (9)
UCLBase(42-492)name(59-61)name(64-71)name(74-76)si(138-140)si(143-150)si(153-155)_ucl_impl(315-340)ucl(342-389)kim_convergence/batch.py (1)
batch(19-145)kim_convergence/stats/tools.py (1)
skew(789-832)kim_convergence/stats/randomness_test.py (1)
randomness_test(15-80)kim_convergence/stats/beta_dist.py (1)
beta(17-37)
kim_convergence/stats/beta_dist.py (1)
kim_convergence/err.py (1)
CRError(38-60)
kim_convergence/timeseries/utils.py (2)
kim_convergence/timeseries/statistical_inefficiency.py (1)
statistical_inefficiency(36-158)kim_convergence/err.py (1)
CRError(38-60)
kim_convergence/utils.py (1)
kim_convergence/err.py (1)
CRError(38-60)
kim_convergence/ucl/uncorrelated_samples.py (4)
kim_convergence/ucl/ucl_base.py (6)
si(138-140)si(143-150)si(153-155)indices(79-81)indices(84-91)indices(94-96)kim_convergence/err.py (3)
CRError(38-60)CRSampleSizeError(63-66)cr_warning(69-78)kim_convergence/stats/t_dist.py (1)
t_inv_cdf(103-195)kim_convergence/timeseries/utils.py (3)
time_series_data_si(47-108)uncorrelated_time_series_data_sample_indices(111-160)uncorrelated_time_series_data_samples(163-238)
kim_convergence/scale.py (1)
kim_convergence/err.py (1)
CRError(38-60)
kim_convergence/stats/tools.py (1)
kim_convergence/err.py (1)
CRError(38-60)
kim_convergence/timeseries/statistical_inefficiency.py (2)
kim_convergence/stats/tools.py (3)
auto_covariance(342-388)auto_correlate(438-484)cross_correlate(487-548)kim_convergence/err.py (2)
CRError(38-60)CRSampleSizeError(63-66)
🪛 Ruff (0.14.10)
kim_convergence/stats/nonnormal_test.py
411-416: Avoid specifying long messages outside the exception class
(TRY003)
540-540: Avoid specifying long messages outside the exception class
(TRY003)
559-559: Avoid specifying long messages outside the exception class
(TRY003)
662-662: Avoid specifying long messages outside the exception class
(TRY003)
690-690: Avoid specifying long messages outside the exception class
(TRY003)
695-695: Avoid specifying long messages outside the exception class
(TRY003)
757-757: Avoid specifying long messages outside the exception class
(TRY003)
782-782: Avoid specifying long messages outside the exception class
(TRY003)
841-841: Avoid specifying long messages outside the exception class
(TRY003)
849-849: Avoid specifying long messages outside the exception class
(TRY003)
872-872: Avoid specifying long messages outside the exception class
(TRY003)
877-877: Avoid specifying long messages outside the exception class
(TRY003)
kim_convergence/err.py
84-84: Avoid specifying long messages outside the exception class
(TRY003)
93-96: Avoid specifying long messages outside the exception class
(TRY003)
135-137: Avoid specifying long messages outside the exception class
(TRY003)
kim_convergence/ucl/n_skart.py
116-116: Unused method argument: nskip
(ARG002)
119-119: Unused method argument: ignore_end
(ARG002)
120-120: Unused method argument: number_of_cores
(ARG002)
146-146: Avoid specifying long messages outside the exception class
(TRY003)
303-303: Unused method argument: heidel_welch_number_points
(ARG002)
304-304: Unused method argument: batch_size
(ARG002)
308-308: Unused method argument: test_size
(ARG002)
309-309: Unused method argument: train_size
(ARG002)
310-310: Unused method argument: population_standard_deviation
(ARG002)
313-313: Unused method argument: si
(ARG002)
314-314: Unused method argument: minimum_correlation_time
(ARG002)
315-315: Unused method argument: uncorrelated_sample_indices
(ARG002)
318-318: Unused method argument: sample_method
(ARG002)
343-343: Avoid specifying long messages outside the exception class
(TRY003)
346-346: Avoid specifying long messages outside the exception class
(TRY003)
574-574: Avoid specifying long messages outside the exception class
(TRY003)
kim_convergence/stats/beta_dist.py
141-144: Avoid specifying long messages outside the exception class
(TRY003)
kim_convergence/timeseries/utils.py
92-95: Avoid specifying long messages outside the exception class
(TRY003)
99-101: Avoid specifying long messages outside the exception class
(TRY003)
106-106: Avoid specifying long messages outside the exception class
(TRY003)
206-206: Avoid specifying long messages outside the exception class
(TRY003)
281-281: Avoid specifying long messages outside the exception class
(TRY003)
292-295: Avoid specifying long messages outside the exception class
(TRY003)
301-303: Avoid specifying long messages outside the exception class
(TRY003)
361-361: Avoid specifying long messages outside the exception class
(TRY003)
372-375: Avoid specifying long messages outside the exception class
(TRY003)
400-400: Standard pseudo-random generators are not suitable for cryptographic purposes
(S311)
450-450: Avoid specifying long messages outside the exception class
(TRY003)
461-464: Avoid specifying long messages outside the exception class
(TRY003)
kim_convergence/ucl/mser_m_y.py
34-39: __all__ is not sorted
Apply an isort-style sorting to __all__
(RUF022)
82-82: Unused method argument: equilibration_length_estimate
(ARG002)
83-83: Unused method argument: heidel_welch_number_points
(ARG002)
84-84: Unused method argument: fft
(ARG002)
85-85: Unused method argument: test_size
(ARG002)
86-86: Unused method argument: train_size
(ARG002)
87-87: Unused method argument: population_standard_deviation
(ARG002)
90-90: Unused method argument: si
(ARG002)
91-91: Unused method argument: minimum_correlation_time
(ARG002)
92-92: Unused method argument: uncorrelated_sample_indices
(ARG002)
95-95: Unused method argument: sample_method
(ARG002)
120-120: Avoid specifying long messages outside the exception class
(TRY003)
125-129: Avoid specifying long messages outside the exception class
(TRY003)
325-325: Avoid specifying long messages outside the exception class
(TRY003)
kim_convergence/utils.py
37-37: Avoid specifying long messages outside the exception class
(TRY003)
42-45: Avoid specifying long messages outside the exception class
(TRY003)
51-51: Avoid specifying long messages outside the exception class
(TRY003)
54-54: Avoid specifying long messages outside the exception class
(TRY003)
56-56: Avoid specifying long messages outside the exception class
(TRY003)
69-69: Avoid specifying long messages outside the exception class
(TRY003)
89-89: Avoid specifying long messages outside the exception class
(TRY003)
94-94: Avoid specifying long messages outside the exception class
(TRY003)
99-102: Avoid specifying long messages outside the exception class
(TRY003)
104-104: Avoid specifying long messages outside the exception class
(TRY003)
106-106: Avoid specifying long messages outside the exception class
(TRY003)
158-158: Avoid specifying long messages outside the exception class
(TRY003)
kim_convergence/ucl/uncorrelated_samples.py
68-68: Unused method argument: equilibration_length_estimate
(ARG002)
69-69: Unused method argument: heidel_welch_number_points
(ARG002)
70-70: Unused method argument: batch_size
(ARG002)
71-71: Unused method argument: scale
(ARG002)
72-72: Unused method argument: with_centering
(ARG002)
73-73: Unused method argument: with_scaling
(ARG002)
74-74: Unused method argument: test_size
(ARG002)
75-75: Unused method argument: train_size
(ARG002)
131-131: Avoid specifying long messages outside the exception class
(TRY003)
136-139: Avoid specifying long messages outside the exception class
(TRY003)
142-145: Avoid specifying long messages outside the exception class
(TRY003)
409-409: Avoid specifying long messages outside the exception class
(TRY003)
kim_convergence/ucl/spectral/heidelberger_welch.py
322-322: Unused method argument: equilibration_length_estimate
(ARG002)
326-326: Unused method argument: population_standard_deviation
(ARG002)
329-329: Unused method argument: si
(ARG002)
330-330: Unused method argument: minimum_correlation_time
(ARG002)
331-331: Unused method argument: uncorrelated_sample_indices
(ARG002)
334-334: Unused method argument: sample_method
(ARG002)
484-484: Avoid specifying long messages outside the exception class
(TRY003)
775-775: Avoid specifying long messages outside the exception class
(TRY003)
kim_convergence/scale.py
73-73: Use explicit conversion flag
Replace with conversion flag
(RUF010)
95-95: Avoid specifying long messages outside the exception class
(TRY003)
147-147: Unused function argument: with_centering
(ARG001)
148-148: Unused function argument: with_scaling
(ARG001)
241-241: Avoid specifying long messages outside the exception class
(TRY003)
392-392: Avoid specifying long messages outside the exception class
(TRY003)
571-571: Avoid specifying long messages outside the exception class
(TRY003)
571-571: Use explicit conversion flag
Replace with conversion flag
(RUF010)
574-574: Avoid specifying long messages outside the exception class
(TRY003)
574-574: Use explicit conversion flag
Replace with conversion flag
(RUF010)
578-578: Avoid specifying long messages outside the exception class
(TRY003)
578-578: Use explicit conversion flag
Replace with conversion flag
(RUF010)
596-596: Avoid specifying long messages outside the exception class
(TRY003)
734-734: Avoid specifying long messages outside the exception class
(TRY003)
779-779: Unused function argument: with_centering
(ARG001)
780-780: Unused function argument: with_scaling
(ARG001)
kim_convergence/ucl/mser_m.py
45-45: Unused function argument: data_size
(ARG001)
73-76: Avoid specifying long messages outside the exception class
(TRY003)
80-83: Avoid specifying long messages outside the exception class
(TRY003)
86-89: Avoid specifying long messages outside the exception class
(TRY003)
92-95: Avoid specifying long messages outside the exception class
(TRY003)
176-176: Avoid specifying long messages outside the exception class
(TRY003)
182-185: Avoid specifying long messages outside the exception class
(TRY003)
189-189: Avoid specifying long messages outside the exception class
(TRY003)
192-192: Avoid specifying long messages outside the exception class
(TRY003)
295-295: Unused method argument: number_of_cores
(ARG002)
297-297: Unused method argument: nskip
(ARG002)
335-335: Unused method argument: equilibration_length_estimate
(ARG002)
336-336: Unused method argument: heidel_welch_number_points
(ARG002)
337-337: Unused method argument: fft
(ARG002)
338-338: Unused method argument: test_size
(ARG002)
339-339: Unused method argument: train_size
(ARG002)
340-340: Unused method argument: population_standard_deviation
(ARG002)
343-343: Unused method argument: si
(ARG002)
344-344: Unused method argument: minimum_correlation_time
(ARG002)
345-345: Unused method argument: uncorrelated_sample_indices
(ARG002)
348-348: Unused method argument: sample_method
(ARG002)
373-373: Avoid specifying long messages outside the exception class
(TRY003)
376-379: Avoid specifying long messages outside the exception class
(TRY003)
532-532: Avoid specifying long messages outside the exception class
(TRY003)
kim_convergence/stats/tools.py
126-126: Avoid specifying long messages outside the exception class
(TRY003)
130-130: Avoid specifying long messages outside the exception class
(TRY003)
231-231: Do not catch blind exception: Exception
(BLE001)
254-254: Avoid specifying long messages outside the exception class
(TRY003)
259-259: Avoid specifying long messages outside the exception class
(TRY003)
276-276: Do not catch blind exception: Exception
(BLE001)
296-296: Avoid specifying long messages outside the exception class
(TRY003)
301-301: Avoid specifying long messages outside the exception class
(TRY003)
316-316: Avoid specifying long messages outside the exception class
(TRY003)
319-319: Avoid specifying long messages outside the exception class
(TRY003)
322-325: Avoid specifying long messages outside the exception class
(TRY003)
331-331: Avoid specifying long messages outside the exception class
(TRY003)
334-337: Avoid specifying long messages outside the exception class
(TRY003)
474-474: Avoid specifying long messages outside the exception class
(TRY003)
477-477: Avoid specifying long messages outside the exception class
(TRY003)
538-538: Avoid specifying long messages outside the exception class
(TRY003)
541-541: Avoid specifying long messages outside the exception class
(TRY003)
663-663: Avoid specifying long messages outside the exception class
(TRY003)
696-696: Avoid specifying long messages outside the exception class
(TRY003)
721-721: Avoid specifying long messages outside the exception class
(TRY003)
724-724: Avoid specifying long messages outside the exception class
(TRY003)
727-727: Avoid specifying long messages outside the exception class
(TRY003)
778-778: Avoid specifying long messages outside the exception class
(TRY003)
kim_convergence/timeseries/statistical_inefficiency.py
88-88: Avoid specifying long messages outside the exception class
(TRY003)
94-97: Avoid specifying long messages outside the exception class
(TRY003)
104-104: Avoid specifying long messages outside the exception class
(TRY003)
106-106: Avoid specifying long messages outside the exception class
(TRY003)
171-171: Unused function argument: minimum_correlation_time
(ARG001)
228-228: Avoid specifying long messages outside the exception class
(TRY003)
321-321: Unused function argument: minimum_correlation_time
(ARG001)
372-375: Avoid specifying long messages outside the exception class
(TRY003)
385-385: Unused function argument: minimum_correlation_time
(ARG001)
422-422: Avoid specifying long messages outside the exception class
(TRY003)
426-429: Avoid specifying long messages outside the exception class
(TRY003)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: build (windows-latest, 3.12)
🔇 Additional comments (56)
kim_convergence/stats/normal_dist.py (5)
1-14: LGTM! Documentation header improved.The module header now properly attributes the adapted code to pythonstats with appropriate copyright notice and references. The raw string format and consistent formatting enhance readability.
20-20: LGTM! Public API exports reordered.The reordering and quote style change are cosmetic improvements consistent with the broader documentation reorganization.
23-39: LGTM! Enhanced docstring with structured Args section.The addition of the Args section and updated references improve documentation clarity and consistency with modern Python docstring standards.
118-133: LGTM! Consistent docstring enhancement.The Args section addition maintains documentation consistency across the module's public API.
136-138: LGTM! Signature reformatted for readability.The multi-line signature format improves readability without any functional changes.
README.md (1)
1-140: LGTM! Previous review concerns addressed.The README restructure is clear and well-organized. The previous issues have been resolved:
- All images now include descriptive alt text (lines 25-35), improving accessibility
- The misleading comment about return type at line 118 has been removed
The Quick Start example (lines 99-119) is concise and demonstrates the core functionality effectively. The marketing-oriented approach with clear sections (Why, Challenge, Features, Installation, Quick Start) makes the package immediately accessible to new users.
kim_convergence/scale.py (5)
1-23: LGTM! Consistent import and export formatting.The addition of
Unionto typing imports supports the widened type signatures throughout the file, and the double-quoted strings in__all__provide consistent formatting.
26-142: LGTM! Type signature widening improves API flexibility.The
scale()method now accepts bothnp.ndarrayandlist, with immediate conversion tonp.ndarrayat line 92, ensuring type safety for downstream operations.
184-292: LGTM! Consistent type handling with appropriate casts.The type signature widening and
cast()calls for type checking in theinverse()method are appropriate. The casts help the type checker understand thatself.scale_andself.center_are floats at this point in the execution flow.
523-648: LGTM! Past issue correctly addressed and consistent type handling.The quantile_range type check at line 570 has been correctly fixed (as noted in past reviews), and the type signature widening with appropriate
cast()usage maintains consistency with other scale classes.
804-810: LGTM! Consistent string formatting.The
scale_methodsdictionary has been updated with double-quoted strings for consistency with the rest of the file.kim_convergence/stats/nonnormal_test.py (4)
35-396: LGTM: String literal standardization.The consistent use of double-quoted strings across all three distribution dictionaries improves codebase uniformity without altering functionality.
449-483: LGTM: Type annotations and safe cast usage.The added type hints improve clarity. The
cast(str, population_cdf)at line 476 is appropriate:check_population_cdf_args(line 470) returns early ifpopulation_cdfis None or "default", so the cast safely informs the type checker thatpopulation_cdfmust be a valid string at line 476.
486-561: LGTM: Enhanced type safety.The updated type annotations (function parameters and return type) improve API clarity. The intentional catch-all exception handling at lines 558-559 appropriately wraps scipy errors.
1-27: The project explicitly requires Python 3.9+ (perpyproject.toml:requires-python = ">=3.9"), and CI validates against Python 3.9, 3.10, 3.11, 3.12, and 3.13. Thelist[float]syntax is compatible with this requirement. The stylistic changes—double-quoted strings, reordered__all__, and modern type annotations—are all appropriate and consistent with the project's Python version constraint.kim_convergence/err.py (3)
11-35: LGTM!The stack frame walking logic is correct, with proper cleanup in the
finallyblock to prevent reference cycles.
38-60: LGTM!The caller-aware error messages and the fixed
__reduce__method (with proper tuple syntax) look correct.
102-157: LGTM!The validation logic is correct, covering all necessary branches for type and bounds checking.
kim_convergence/utils.py (2)
13-108: LGTM!The validation logic correctly handles all cases: fractional sizes, integer sizes, and None values. The assertions provide good runtime guards.
111-164: LGTM!The train/test splitting logic is correct, with proper seed handling and random permutation.
kim_convergence/ucl/n_skart.py (3)
111-294: LGTM!The equilibration length estimation logic is correct. The unused parameters (
nskip,ignore_end,number_of_cores) are appropriately marked for API compatibility.
476-492: LGTM!The wrapper correctly delegates to the base class
uclmethod.
495-575: LGTM!The wrapper functions correctly delegate to the base class methods with appropriate error handling.
kim_convergence/stats/beta_dist.py (2)
40-144: LGTM!The refactored assignments (replacing unnecessary deepcopy with direct assignment) are correct for scalar values, and the continued fraction logic is preserved.
147-183: LGTM!The numeric literal updates maintain consistency without changing the function's behavior.
kim_convergence/stats/tools.py (8)
1-38: Excellent documentation of the subprocess isolation feature.The docstring clearly explains the purpose, trade-offs, and appropriate usage of
KIM_CONV_FORCE_SUBPROC, with explicit warnings about performance overhead in tests.
177-206: LGTM!The FFT and direct correlation implementations correctly handle both auto-correlation and cross-correlation cases.
209-263: LGTM!The subprocess isolation is well-designed. The decision to use
join()without timeout (line 251) is intentional to avoid interrupting legitimate long-running operations, with properexitcodechecking andget_nowait()to prevent blocking.
266-305: LGTM!The periodogram subprocess isolation follows the same robust pattern as the correlation functions.
308-339: LGTM!The input validation comprehensively checks dimensions, size, and finite values for both arrays.
342-388: LGTM!The environment variable check correctly routes to subprocess isolation when
KIM_CONV_FORCE_SUBPROCis set, with proper fallback to direct computation.
391-435: LGTM!The cross-covariance function correctly handles edge cases (None, identity) and properly integrates subprocess isolation.
438-832: LGTM!All remaining functions correctly integrate the subprocess isolation feature where applicable, with proper type hints and validation.
kim_convergence/ucl/mser_m.py (3)
187-198: LGTM: Zero-variance handling is correct.The special case handling for constant time series is well-implemented and prevents unnecessary computation when the data has no variance.
326-414: LGTM: Internal _ucl_impl refactoring is well-structured.The introduction of
_ucl_implwith API-compatibility parameters and explicit float conversion at the return is a good design pattern for maintaining backward compatibility while allowing internal refactoring.
523-533: Approve: Error handling with proper exception chaining.The exception handling correctly preserves the error chain using
from e, providing good debugging context.kim_convergence/ucl/mser_m_y.py (3)
124-129: LGTM: Appropriate minimum sample size validation.The check for at least 10 data points is reasonable for the MSER-m-y algorithm, with a clear error message.
137-169: LGTM: Adaptive batch size selection with randomness test.The adaptive batch sizing algorithm using the von Neumann randomness test is well-implemented. The 1.2 growth factor and fallback to batch_size=10 provide reasonable defaults.
206-207: Approve: Consistent type handling pattern.The assertion and explicit float conversion follow the same pattern as the parent MSER_m class, ensuring type consistency.
kim_convergence/timeseries/utils.py (3)
30-44: LGTM: Clean error message generation helper.The helper function properly handles both singular and plural forms and provides clear, readable error messages.
396-404: LGTM: Random sampling logic is correct.The random sampling between index pairs is correctly implemented. The static analysis warning (S311) about non-cryptographic random is a false positive—this is legitimate scientific sampling, not a security-sensitive operation.
485-492: LGTM: Block averaging implementation is correct.The block averaging logic correctly computes the mean for each block defined by consecutive index pairs.
kim_convergence/ucl/spectral/heidelberger_welch.py (5)
99-115: LGTM: Proper initialization with explicit Optional types.The initialization of all Heidelberger-Welch constants with explicit
Optionaltypes improves type safety and makes the uninitialized state clear.
144-154: LGTM: Efficient constant re-initialization with proper guards.The conditional logic avoids unnecessary recalculation of constants, and the assertions properly guard against
Nonevalues fromOptionalattributes before use.
543-546: LGTM: Proper type guards before matrix operations.The assertions ensure that the matrix attributes are not
Nonebefore being used in numerical operations, preventing potential runtime errors and satisfying type checkers.
336-479: Excellent: Comprehensive documentation for complex algorithm.The extensive docstring for
_ucl_implis exemplary. It includes:
- Mathematical foundation with proper LaTeX formatting
- Step-by-step algorithm description
- Interpretation guidelines
- Working example
- Performance characteristics
This level of documentation significantly improves maintainability and user understanding of this complex spectral method.
499-507: LGTM: Good user experience with warning before error.The pattern of emitting a warning via
cr_warningbefore raisingCRSampleSizeErrorprovides good user feedback, and the assertion ensures the required attribute is initialized.kim_convergence/ucl/uncorrelated_samples.py (4)
135-145: LGTM: Appropriate minimum data requirement.The check for at least 5 data points is reasonable for statistical analysis, with a clear error message explaining the requirement.
176-183: LGTM: Excellent graduated validation approach.The graduated validation (warning at <5 samples, error at <2) is a thoughtful design that:
- Warns users about potentially insufficient data
- Allows proceeding with caution in borderline cases
- Enforces the absolute minimum (2) needed for valid degrees of freedom (df = n-1)
This provides good user experience while maintaining statistical validity.
193-203: LGTM: Correct standard error calculation for both cases.The implementation properly handles both known and unknown population standard deviation cases, correctly using
uncorrelated_samples_sizefor the standard error denominator.
211-212: Approve: Consistent type handling across UCL implementations.The assertion and explicit float conversion maintain consistency with other UCL class implementations, ensuring type safety and preventing numpy scalar issues.
kim_convergence/timeseries/statistical_inefficiency.py (5)
36-158: LGTM!The function signature and error messages have been updated for consistency. The logic remains correct.
166-313: LGTM!The function signature has been updated for consistency with modern type hints. The
minimum_correlation_timeparameter is intentionally unused for API compatibility, which is clearly documented.
531-536: LGTM!The dictionary keys have been updated to use double quotes for consistency with the rest of the codebase.
539-600: LGTM!The function has been updated consistently with modern type hints and improved string formatting. The logic remains correct.
9-9: The project'spyproject.tomlspecifiesrequires-python = ">=3.9", which supports PEP 585 built-in generic types. The change fromList[float]tolist[float]is appropriate and compatible with the project's minimum Python version requirement.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
kim_convergence/timeseries/utils.py (1)
262-263: Fix incomplete docstring.Line 263 contains incomplete text "c" after the parameter description. This should fully describe the
siparameter.🔎 Proposed fix
si (float, or str, optional): estimated statistical inefficiency. - c + (default: None)
♻️ Duplicate comments (2)
kim_convergence/timeseries/statistical_inefficiency.py (2)
364-368: Fix error message grammar and consolidate string literal.The error message has issues that were flagged in a previous review:
- String is split across two literals with implicit concatenation
- Grammar error: "do not use" should be "does not use"
- Unnecessary comma after "method"
🔎 Proposed fix
if y is not None: raise CRError( - "The split-r method, splits the x time-series data " - "and do not use y." + "The split-r method splits the x time-series data and does not use y." )
414-418: Fix error message grammar and consolidate string literal.Same issue as flagged in a previous review:
- String split with implicit concatenation
- Grammar error: "do not use" should be "does not use"
- Lowercase "the" should be capitalized for consistency
🔎 Proposed fix
if y is not None: raise CRError( - "the split-r method, splits the x time-series data " - "and do not use y." + "The split-r method splits the x time-series data and does not use y." )
🧹 Nitpick comments (7)
kim_convergence/stats/zero_rc_bounds.py (1)
162-162: Remove unusednoqadirectives.The
# noqa: TRY003comments on lines 162, 168, 180, 185, 227, 265, and 313 are flagged as unused by Ruff. These should be removed to maintain clean code hygiene.🔎 Proposed fix to remove unused noqa directives
raise CRError( f"Answer x = {x}, appears to be higher than the " f"highest search bound = {self.big}.\nIt means " "that the stepping search terminated unsuccessfully " "at the highest search bound." - ) # noqa: TRY003 + ) raise CRError( f"Answer x = {x}, appears to be lower than the lowest " f"search bound = {self.small}.\nIt means that the " "stepping search terminated unsuccessfully at the " "lowest search bound." - ) # noqa: TRY003 + )Apply similar changes to lines 180, 185, 227, 265, and 313.
Also applies to: 168-168, 180-180, 185-185, 227-227, 265-265, 313-313
kim_convergence/timeseries/statistical_inefficiency.py (1)
166-172: Unused parameter is acceptable for API compatibility.The
minimum_correlation_timeparameter is intentionally unused (as noted in the inline comment). This pattern maintains a consistent function signature across all SI methods, allowing them to be called interchangeably. Consider adding a brief note in the docstring (e.g., "Note:minimum_correlation_timeis accepted for API compatibility but not used by this method.") to make this clearer to users.kim_convergence/utils.py (1)
48-69: Good refactor: unified validation helper reduces code duplication.The
_checkhelper cleanly validates both int and float ranges. The combined check for fractional sizes summing to > 1.0 (lines 64-69) is a useful addition.One minor consideration: the
_checkfunction currently acceptsUnion[int, float]but the caller has already verifiedtest_size is not None/train_size is not None. This is fine, but if you wanted stricter typing, you could annotate_checkto not acceptNone.kim_convergence/stats/nonnormal_test.py (1)
399-446: Remove unused noqa directive.The static analysis tool correctly identifies that the
# noqa: TRY003directive on line 416 is unused. The noqa comment should be removed.🔎 Proposed fix
raise CRError( f"The {population_cdf} distribution is not supported. It should " "be the name of a distribution in:\n " "https://docs.scipy.org/doc/scipy/reference/stats.html#" "continuous-distributions" - ) # noqa: TRY003 + )kim_convergence/scale.py (1)
71-74: Consider using f-string conversion flag for cleaner formatting.Static analysis suggests using explicit conversion flags instead of
str().🔎 Proposed fix
raise CRError( "Minimum of desired feature range must be smaller than " - f"maximum. Got {str(feature_range)}" + f"maximum. Got {feature_range!s}" )This is a minor style preference and can be safely ignored.
kim_convergence/run_length_control/_convergence.py (2)
383-444: Consider caching converged variables (optional optimization).The convergence loop re-checks all variables each iteration (line 385 resets
done[i] = False), even those that have already converged. While this ensures robustness—verifying that variables remain converged as the trajectory extends—it incurs redundant UCL computations.For better performance, you could skip already-converged variables:
if done[i]: continue done[i] = FalseHowever, the current conservative approach is more robust and given the statistical nature of the computation, the overhead is likely acceptable.
251-251: Static analysis: Long error messages are appropriate here.Ruff flags these lines for long inline error messages (TRY003). However, these messages include dynamic context (variable numbers, actual values) that makes them more informative than predefined exception classes would be. The current approach appropriately prioritizes clarity and debuggability.
If you prefer to address this lint, you could extract message templates while preserving the dynamic interpolation, but the current implementation is entirely reasonable for internal convergence logic.
Also applies to: 272-276, 467-469, 556-556, 559-562
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (14)
doc/conf.pykim_convergence/run_length_control/_convergence.pykim_convergence/scale.pykim_convergence/stats/nonnormal_test.pykim_convergence/stats/normal_dist.pykim_convergence/stats/tools.pykim_convergence/stats/zero_rc_bounds.pykim_convergence/timeseries/statistical_inefficiency.pykim_convergence/timeseries/utils.pykim_convergence/ucl/mser_m.pykim_convergence/ucl/n_skart.pykim_convergence/ucl/spectral/heidelberger_welch.pykim_convergence/ucl/ucl_base.pykim_convergence/utils.py
🧰 Additional context used
🧬 Code graph analysis (6)
kim_convergence/ucl/spectral/heidelberger_welch.py (6)
kim_convergence/ucl/ucl_base.py (8)
ucl(342-389)name(59-61)name(64-71)name(74-76)_ucl_impl(315-340)si(138-140)si(143-150)si(153-155)kim_convergence/batch.py (1)
batch(19-145)kim_convergence/err.py (3)
CRError(38-60)CRSampleSizeError(63-66)cr_warning(69-78)kim_convergence/stats/tools.py (1)
modified_periodogram(551-629)kim_convergence/stats/t_dist.py (1)
t_inv_cdf(103-195)kim_convergence/utils.py (1)
train_test_split(111-164)
kim_convergence/stats/tools.py (1)
kim_convergence/err.py (1)
CRError(38-60)
kim_convergence/ucl/ucl_base.py (2)
kim_convergence/err.py (1)
CRError(38-60)kim_convergence/timeseries/utils.py (2)
time_series_data_si(47-111)uncorrelated_time_series_data_sample_indices(114-163)
kim_convergence/timeseries/statistical_inefficiency.py (2)
kim_convergence/stats/tools.py (3)
auto_covariance(342-388)auto_correlate(438-484)cross_correlate(487-548)kim_convergence/err.py (2)
CRError(38-60)CRSampleSizeError(63-66)
kim_convergence/ucl/mser_m.py (4)
kim_convergence/batch.py (1)
batch(19-145)kim_convergence/err.py (2)
CRError(38-60)CRSampleSizeError(63-66)kim_convergence/stats/t_dist.py (1)
t_inv_cdf(103-195)kim_convergence/ucl/mser_m_y.py (1)
_ucl_impl(73-207)
kim_convergence/utils.py (1)
kim_convergence/err.py (1)
CRError(38-60)
🪛 Ruff (0.14.10)
kim_convergence/run_length_control/_convergence.py
251-251: Avoid specifying long messages outside the exception class
(TRY003)
272-276: Avoid specifying long messages outside the exception class
(TRY003)
467-469: Avoid specifying long messages outside the exception class
(TRY003)
556-556: Avoid specifying long messages outside the exception class
(TRY003)
559-562: Avoid specifying long messages outside the exception class
(TRY003)
kim_convergence/ucl/spectral/heidelberger_welch.py
322-322: Unused method argument: equilibration_length_estimate
(ARG002)
326-326: Unused method argument: population_standard_deviation
(ARG002)
329-329: Unused method argument: si
(ARG002)
330-330: Unused method argument: minimum_correlation_time
(ARG002)
331-331: Unused method argument: uncorrelated_sample_indices
(ARG002)
334-334: Unused method argument: sample_method
(ARG002)
484-484: Avoid specifying long messages outside the exception class
(TRY003)
775-775: Avoid specifying long messages outside the exception class
(TRY003)
kim_convergence/stats/tools.py
126-126: Avoid specifying long messages outside the exception class
(TRY003)
130-130: Avoid specifying long messages outside the exception class
(TRY003)
231-231: Do not catch blind exception: Exception
(BLE001)
254-254: Avoid specifying long messages outside the exception class
(TRY003)
259-259: Avoid specifying long messages outside the exception class
(TRY003)
276-276: Do not catch blind exception: Exception
(BLE001)
296-296: Avoid specifying long messages outside the exception class
(TRY003)
301-301: Avoid specifying long messages outside the exception class
(TRY003)
316-316: Avoid specifying long messages outside the exception class
(TRY003)
319-319: Avoid specifying long messages outside the exception class
(TRY003)
322-325: Avoid specifying long messages outside the exception class
(TRY003)
331-331: Avoid specifying long messages outside the exception class
(TRY003)
334-337: Avoid specifying long messages outside the exception class
(TRY003)
474-474: Avoid specifying long messages outside the exception class
(TRY003)
477-477: Avoid specifying long messages outside the exception class
(TRY003)
538-538: Avoid specifying long messages outside the exception class
(TRY003)
541-541: Avoid specifying long messages outside the exception class
(TRY003)
663-663: Avoid specifying long messages outside the exception class
(TRY003)
696-696: Avoid specifying long messages outside the exception class
(TRY003)
721-721: Avoid specifying long messages outside the exception class
(TRY003)
724-724: Avoid specifying long messages outside the exception class
(TRY003)
727-727: Avoid specifying long messages outside the exception class
(TRY003)
778-778: Avoid specifying long messages outside the exception class
(TRY003)
kim_convergence/ucl/ucl_base.py
292-292: Unused method argument: batch_size
(ARG002)
293-293: Unused method argument: scale
(ARG002)
294-294: Unused method argument: with_centering
(ARG002)
295-295: Unused method argument: with_scaling
(ARG002)
486-489: Avoid specifying long messages outside the exception class
(TRY003)
kim_convergence/timeseries/statistical_inefficiency.py
88-88: Avoid specifying long messages outside the exception class
(TRY003)
94-97: Avoid specifying long messages outside the exception class
(TRY003)
104-104: Avoid specifying long messages outside the exception class
(TRY003)
106-106: Avoid specifying long messages outside the exception class
(TRY003)
171-171: Unused function argument: minimum_correlation_time
(ARG001)
228-228: Avoid specifying long messages outside the exception class
(TRY003)
321-321: Unused function argument: minimum_correlation_time
(ARG001)
373-376: Avoid specifying long messages outside the exception class
(TRY003)
386-386: Unused function argument: minimum_correlation_time
(ARG001)
424-424: Avoid specifying long messages outside the exception class
(TRY003)
428-431: Avoid specifying long messages outside the exception class
(TRY003)
kim_convergence/ucl/mser_m.py
72-75: Avoid specifying long messages outside the exception class
(TRY003)
79-82: Avoid specifying long messages outside the exception class
(TRY003)
85-88: Avoid specifying long messages outside the exception class
(TRY003)
91-94: Avoid specifying long messages outside the exception class
(TRY003)
175-175: Avoid specifying long messages outside the exception class
(TRY003)
181-184: Avoid specifying long messages outside the exception class
(TRY003)
188-188: Avoid specifying long messages outside the exception class
(TRY003)
191-191: Avoid specifying long messages outside the exception class
(TRY003)
292-292: Unused method argument: number_of_cores
(ARG002)
294-294: Unused method argument: nskip
(ARG002)
332-332: Unused method argument: equilibration_length_estimate
(ARG002)
333-333: Unused method argument: heidel_welch_number_points
(ARG002)
334-334: Unused method argument: fft
(ARG002)
335-335: Unused method argument: test_size
(ARG002)
336-336: Unused method argument: train_size
(ARG002)
337-337: Unused method argument: population_standard_deviation
(ARG002)
340-340: Unused method argument: si
(ARG002)
341-341: Unused method argument: minimum_correlation_time
(ARG002)
342-342: Unused method argument: uncorrelated_sample_indices
(ARG002)
345-345: Unused method argument: sample_method
(ARG002)
370-370: Avoid specifying long messages outside the exception class
(TRY003)
373-376: Avoid specifying long messages outside the exception class
(TRY003)
529-529: Avoid specifying long messages outside the exception class
(TRY003)
kim_convergence/stats/nonnormal_test.py
411-416: Avoid specifying long messages outside the exception class
(TRY003)
416-416: Unused noqa directive (unused: TRY003)
Remove unused noqa directive
(RUF100)
540-540: Avoid specifying long messages outside the exception class
(TRY003)
559-559: Avoid specifying long messages outside the exception class
(TRY003)
662-662: Avoid specifying long messages outside the exception class
(TRY003)
690-690: Avoid specifying long messages outside the exception class
(TRY003)
695-695: Avoid specifying long messages outside the exception class
(TRY003)
757-757: Avoid specifying long messages outside the exception class
(TRY003)
782-782: Avoid specifying long messages outside the exception class
(TRY003)
841-841: Avoid specifying long messages outside the exception class
(TRY003)
849-849: Avoid specifying long messages outside the exception class
(TRY003)
872-872: Avoid specifying long messages outside the exception class
(TRY003)
877-877: Avoid specifying long messages outside the exception class
(TRY003)
kim_convergence/timeseries/utils.py
92-95: Avoid specifying long messages outside the exception class
(TRY003)
99-102: Avoid specifying long messages outside the exception class
(TRY003)
107-109: Avoid specifying long messages outside the exception class
(TRY003)
209-209: Avoid specifying long messages outside the exception class
(TRY003)
284-284: Avoid specifying long messages outside the exception class
(TRY003)
295-298: Avoid specifying long messages outside the exception class
(TRY003)
304-306: Avoid specifying long messages outside the exception class
(TRY003)
364-364: Avoid specifying long messages outside the exception class
(TRY003)
375-378: Avoid specifying long messages outside the exception class
(TRY003)
403-403: Standard pseudo-random generators are not suitable for cryptographic purposes
(S311)
453-453: Avoid specifying long messages outside the exception class
(TRY003)
464-467: Avoid specifying long messages outside the exception class
(TRY003)
kim_convergence/scale.py
73-73: Use explicit conversion flag
Replace with conversion flag
(RUF010)
95-95: Avoid specifying long messages outside the exception class
(TRY003)
147-147: Unused function argument: with_centering
(ARG001)
148-148: Unused function argument: with_scaling
(ARG001)
241-241: Avoid specifying long messages outside the exception class
(TRY003)
392-392: Avoid specifying long messages outside the exception class
(TRY003)
468-468: Avoid specifying long messages outside the exception class
(TRY003)
479-479: Avoid specifying long messages outside the exception class
(TRY003)
481-481: Avoid specifying long messages outside the exception class
(TRY003)
574-574: Avoid specifying long messages outside the exception class
(TRY003)
574-574: Use explicit conversion flag
Replace with conversion flag
(RUF010)
577-577: Avoid specifying long messages outside the exception class
(TRY003)
577-577: Use explicit conversion flag
Replace with conversion flag
(RUF010)
581-581: Avoid specifying long messages outside the exception class
(TRY003)
581-581: Use explicit conversion flag
Replace with conversion flag
(RUF010)
599-599: Avoid specifying long messages outside the exception class
(TRY003)
737-737: Avoid specifying long messages outside the exception class
(TRY003)
782-782: Unused function argument: with_centering
(ARG001)
783-783: Unused function argument: with_scaling
(ARG001)
kim_convergence/ucl/n_skart.py
116-116: Unused method argument: nskip
(ARG002)
119-119: Unused method argument: ignore_end
(ARG002)
122-122: Unused method argument: number_of_cores
(ARG002)
148-148: Avoid specifying long messages outside the exception class
(TRY003)
305-305: Unused method argument: heidel_welch_number_points
(ARG002)
306-306: Unused method argument: batch_size
(ARG002)
310-310: Unused method argument: test_size
(ARG002)
313-313: Unused method argument: train_size
(ARG002)
316-316: Unused method argument: population_standard_deviation
(ARG002)
319-319: Unused method argument: si
(ARG002)
320-320: Unused method argument: minimum_correlation_time
(ARG002)
323-323: Unused method argument: uncorrelated_sample_indices
(ARG002)
326-326: Unused method argument: sample_method
(ARG002)
353-353: Avoid specifying long messages outside the exception class
(TRY003)
356-356: Avoid specifying long messages outside the exception class
(TRY003)
448-452: Avoid specifying long messages outside the exception class
(TRY003)
596-596: Avoid specifying long messages outside the exception class
(TRY003)
kim_convergence/utils.py
37-37: Avoid specifying long messages outside the exception class
(TRY003)
42-45: Avoid specifying long messages outside the exception class
(TRY003)
51-51: Avoid specifying long messages outside the exception class
(TRY003)
54-54: Avoid specifying long messages outside the exception class
(TRY003)
56-56: Avoid specifying long messages outside the exception class
(TRY003)
69-69: Avoid specifying long messages outside the exception class
(TRY003)
89-89: Avoid specifying long messages outside the exception class
(TRY003)
94-94: Avoid specifying long messages outside the exception class
(TRY003)
99-102: Avoid specifying long messages outside the exception class
(TRY003)
104-104: Avoid specifying long messages outside the exception class
(TRY003)
106-106: Avoid specifying long messages outside the exception class
(TRY003)
158-158: Avoid specifying long messages outside the exception class
(TRY003)
kim_convergence/stats/zero_rc_bounds.py
157-162: Avoid specifying long messages outside the exception class
(TRY003)
162-162: Unused noqa directive (unused: TRY003)
Remove unused noqa directive
(RUF100)
163-168: Avoid specifying long messages outside the exception class
(TRY003)
168-168: Unused noqa directive (unused: TRY003)
Remove unused noqa directive
(RUF100)
175-180: Avoid specifying long messages outside the exception class
(TRY003)
180-180: Unused noqa directive (unused: TRY003)
Remove unused noqa directive
(RUF100)
181-185: Avoid specifying long messages outside the exception class
(TRY003)
185-185: Unused noqa directive (unused: TRY003)
Remove unused noqa directive
(RUF100)
222-227: Avoid specifying long messages outside the exception class
(TRY003)
227-227: Unused noqa directive (unused: TRY003)
Remove unused noqa directive
(RUF100)
260-265: Avoid specifying long messages outside the exception class
(TRY003)
265-265: Unused noqa directive (unused: TRY003)
Remove unused noqa directive
(RUF100)
310-313: Avoid specifying long messages outside the exception class
(TRY003)
313-313: Unused noqa directive (unused: TRY003)
Remove unused noqa directive
(RUF100)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: build (windows-latest, 3.12)
🔇 Additional comments (59)
kim_convergence/stats/zero_rc_bounds.py (3)
47-52: LGTM!The changes to use double-quoted strings in
__all__and remove empty parentheses from the class declaration align with PEP 8 conventions and improve consistency.
55-101: LGTM!The multi-line signature formatting improves readability. The change from
deepcopyto direct assignment for the float parameters is appropriate and more efficient, as primitive float types don't require deep copying.
298-298: LGTM!The assertion provides a clear defensive check to ensure
ZERO_RChas been initialized before use, improving code robustness.kim_convergence/timeseries/statistical_inefficiency.py (4)
1-33: LGTM!The imports are well-organized, and the
__all__exports are consistent with the PR's goal of using double-quoted strings. The type annotations usinglist[float](Python 3.9+ syntax) are consistent throughout.
36-158: LGTM!The
statistical_inefficiencyfunction is well-structured with proper input validation, handling of constant time series, and correct computation of the integrated auto-correlation time. The use of explicitfloat()casts (lines 133, 142, 155) ensures numeric stability.
533-538: LGTM!The
si_methodsdictionary provides a clean lookup for all statistical inefficiency methods, enabling runtime method selection inintegrated_auto_correlation_time.
541-602: LGTM!The
integrated_auto_correlation_timefunction correctly derives τ from the statistical inefficiency using the formulaτ = (si - 1) / 2. The uniform parameter passing tosi_func(line 592) works correctly because all methods insi_methodsacceptminimum_correlation_timefor API compatibility.doc/conf.py (1)
12-24: LGTM! Previous issue resolved.The
except ImportErrorblock now correctly assigns bothreleaseandversion, addressing the concern from the previous review. The fallback values ensure the documentation build won't fail with aNameErrorif the package isn't installed.kim_convergence/ucl/mser_m.py (2)
41-96: Well-designed helper function for parameter normalization.The
_normalize_ignore_endfunction consolidates validation and normalization logic effectively:
- Handles multiple input types (
None,float,int) with clear semantics- Provides sensible defaults when
Noneis passed- Includes comprehensive error checking with appropriate exception types
- The docstring clearly explains the contract
This refactoring improves code maintainability by centralizing ignore_end handling.
323-411: Clean delegation pattern with _ucl_impl.The internal
_ucl_implmethod correctly implements the core MSER-m UCL computation:
- Proper input validation
- Correct statistical calculations (batch means, t-distribution)
- Explicit
float()conversion at return ensures type consistencyThe unused parameters marked as "API compatibility" maintain a consistent interface across UCL implementations, which is good design.
kim_convergence/ucl/ucl_base.py (2)
247-280: Excellent centralization of zero-variance handling.The
_handle_zero_variancemethod provides a clean, centralized solution for constant time series:
- Correct statistical treatment: For a constant series, SI = N → effective sample size = 1, and UCL = 0 (no uncertainty)
- Early exit pattern: Returns
Trueto signal that no further computation is needed- Comprehensive attribute setting: Properly initializes
mean_,std_,si_,indices_, andupper_confidence_limit- Robust detection: Uses
ddof=0for population std, appropriate for detecting true constantsThis refactoring eliminates duplication across UCL implementations and ensures consistent handling of edge cases.
315-389: Clean delegation pattern for subclass-specific UCL computation.The introduction of
_ucl_implas an internal hook and the updateduclmethod create a well-structured template method pattern:
- Base class (
ucl) handles zero-variance case via_handle_zero_variance- Non-constant data is delegated to subclass-specific
_ucl_impl- Subclasses override
_ucl_implto provide their algorithm-specific logicThis design improves separation of concerns and reduces code duplication across MSER-m, Heidelberger-Welch, N-SKART, and other UCL variants.
kim_convergence/ucl/spectral/heidelberger_welch.py (2)
500-507: Good practice: warning before raising exception.Emitting a warning via
cr_warningbefore raisingCRSampleSizeErrorimproves observability by ensuring the diagnostic message appears in logs even if the exception is caught upstream. This pattern helps with debugging insufficient data scenarios.
336-479: Excellent mathematical documentation.The expanded docstring for
_ucl_implprovides comprehensive documentation:
- Clear mathematical basis with spectral density formulation
- Step-by-step algorithm description
- Interpretation guidance for users
- Performance characteristics
- Working example
This level of documentation significantly improves the usability of this complex statistical method. The mathematical notation and references to Heidelberger & Welch (1981) provide strong theoretical grounding.
kim_convergence/ucl/n_skart.py (2)
447-455: Critical guard against perfect correlation.The check for near-perfect lag-one correlation (
abs(1 - lag1_correlation) < 1e-10) is essential:
- Prevents division by zero: Line 455 computes
(1 + lag1_correlation) / (1 - lag1_correlation), which would fail if the denominator is zero- Clear diagnostic: The error message explains the root cause (sampling interval too small or system hasn't moved)
- Appropriate threshold:
1e-10is a reasonable epsilon for detecting numerical equalityThis guard improves robustness for edge cases where batches are essentially identical.
482-491: Proper handling of numerical edge case.The conditional handling of
betanear zero is mathematically sound:
- Limiting case: When
beta → 0, the complex formula reduces toupper - beta- Threshold choice:
abs(beta) < 1e-15is appropriate for detecting values near machine epsilon- Prevents numerical instability: Avoids computing
(small_number)^(1/3)which can amplify rounding errorsThis implementation demonstrates careful attention to numerical stability.
kim_convergence/timeseries/utils.py (4)
30-44: LGTM! Excellent error message helper.The centralized error message generation ensures consistency and proper singular/plural handling across the module.
47-111: LGTM! Type annotations and error handling improved.The updated type hints accept both
np.ndarrayandlist[float], improving flexibility. Exception chaining provides good error context.
399-406: LGTM! Random sampling implementation is correct.The use of
randintfor statistical sampling is appropriate here. The S311 warning from static analysis is a false positive, as cryptographic randomness is not required for time series subsampling.
488-493: LGTM! Block averaging logic is correct.The implementation properly computes block averages using the uncorrelated sample indices.
kim_convergence/stats/normal_dist.py (4)
1-20: LGTM! Module header and exports are well-structured.The attribution to pythonstats and the reference formatting are appropriate. The
__all__export list is correctly ordered alphabetically.
23-115: LGTM! Standard normal inverse CDF implementation is correct.The implementation follows Wichura's AS241 algorithm correctly with proper handling of edge cases (p=0, p=1, invalid p values). The polynomial coefficients are accurately transcribed.
118-133: LGTM! Normal inverse CDF wrapper is straightforward.The location-scale transformation
s_normal_inv_cdf(p) * scale + locis mathematically correct.
136-181: LGTM! Confidence interval implementation is correct.The calculation of lower and upper bounds using
(1 - confidence_level) / 2and(1 + confidence_level) / 2correctly produces symmetric intervals around the median. The validation for confidence_level being in (0, 1) is appropriate.kim_convergence/utils.py (4)
1-10: LGTM! Module setup is clean.The imports and exports are properly organized.
13-46: LGTM! Function signature and initial validation are well-structured.The early validation for
n_samplesand the fallback todefault_test_sizewhen both sizes areNoneis correct.
71-107: LGTM! Size derivation logic is correct.The conversion from float fractions to integer counts using
ceilfor test andfloorfor train is appropriate (erring on the side of larger test set when rounding). The derived size validation ensures non-empty sets.
111-164: LGTM! train_test_split implementation is correct.The function properly delegates validation to
validate_split, handles the random state correctly, and returns train/test indices via random permutation.kim_convergence/stats/nonnormal_test.py (7)
1-27: LGTM! Module header and exports are well-organized.The public API surface is clearly defined with consistent double-quoted strings.
29-135: LGTM! Distribution dictionary is comprehensive.The ContinuousDistributions dictionary provides a complete mapping of scipy continuous distributions.
449-483: LGTM! get_distribution_stats uses appropriate type narrowing.The
cast(str, population_cdf)on line 476 is appropriate since the function returns early whenpopulation_cdfis"default"orNone(handled bycheck_population_cdf_args).
486-561: LGTM! ks_test implementation with proper exception chaining.The exception chaining (
raise CRError(...) from e) on line 559 preserves the original traceback, which is good practice.
564-697: LGTM! levene_test implementation is correct.The test properly generates samples from the specified distribution and compares variances using the median-based Levene test.
700-786: LGTM! wilcoxon_test implementation is correct.The cast on line 786 is appropriate for the pvalue which scipy returns as a float-like type.
789-879: LGTM! kruskal_test implementation is correct.The minimum sample size requirement of 5 for the chi-square approximation is appropriately enforced.
kim_convergence/stats/tools.py (13)
1-63: LGTM! Comprehensive documentation for subprocess isolation.The module docstring clearly explains the
KIM_CONV_FORCE_SUBPROCenvironment variable, its purpose (avoiding BLAS/OpenMP deadlocks), and important performance warnings. This is excellent user-facing documentation.
107-174: LGTM! FFT optimal size calculation is correct.The algorithm correctly finds the next 5-smooth number (Hamming number) for efficient FFT computation.
177-206: LGTM! FFT and direct correlation helpers are well-implemented.The
_fft_corrcorrectly uses zero-padding to optimal size and conjugate multiplication for correlation. The_direct_corrproperly uses numpy's correlate with appropriate slicing.
209-263: Previous timeout concerns have been properly addressed.The implementation now:
- Waits for the process to complete with
p.join()(no timeout, as documented)- Checks
p.exitcodeto detect crashes/segfaults- Uses
q.get_nowait()to avoid blocking on empty queue- Propagates
CRErrorinstances from the subprocessThis is a robust pattern for subprocess error handling.
266-305: LGTM! Periodogram isolation follows the same robust pattern.Consistent implementation with the correlation isolation function.
308-339: LGTM! Input validation helper is comprehensive.The
_validate_and_prepare_inputfunction properly validates:
- Dimensionality (1D only)
- Non-empty arrays
- Finite values (no NaN/Inf)
- Shape consistency between x and y
Good consolidation of repeated validation logic.
342-388: LGTM! auto_covariance with subprocess isolation support.The function correctly computes biased auto-covariance and conditionally uses subprocess isolation when
KIM_CONV_FORCE_SUBPROCis set.
391-435: LGTM! cross_covariance properly delegates to auto_covariance for self-correlation.The early returns for
y is Noneandy is xcases avoid redundant computation.
438-548: LGTM! Auto and cross correlation functions are correct.The normalization by the initial covariance (variance) for auto-correlation and by the product of standard deviations for cross-correlation is mathematically correct.
551-629: LGTM! Modified periodogram implementation supports subprocess isolation.The function correctly implements the periodogram as defined in the Heidelberger paper, with proper handling of both FFT and direct computation paths.
632-679: LGTM! Periodogram wrapper with proper Nyquist handling.The special handling for even-length data (not doubling the Nyquist frequency point) is correct.
682-786: LGTM! Summary, int_power, moment utilities are correct.The functions implement standard statistical computations with proper input validation.
789-832: LGTM! Skewness calculation with bias correction.The Fisher-Pearson coefficient calculation with optional bias correction is implemented correctly.
kim_convergence/scale.py (7)
1-23: LGTM! Module exports are properly organized.The
__all__list includes all public classes, functions, and thescale_methodsdictionary.
26-141: LGTM! MinMaxScale implementation is correct.The transformation logic correctly scales data to the specified feature range with proper validation.
144-181: API compatibility parameters are well-documented.The
with_centeringandwith_scalingparameters are intentionally unused (as documented in the Notes section) to maintain a consistent signature across all scaling helpers. This is a reasonable design choice.
184-291: LGTM! TranslateScale with proper type narrowing.The
cast(float, self.scale_)andcast(float, self.center_)on lines 281 and 289 are appropriate for type narrowing after the None check on line 274.
328-486: Previous assertion concerns have been properly addressed.The assertions have been replaced with proper runtime type checks (lines 467-468, 478-481) that raise
CRErrorwith descriptive messages. This ensures validation works even with Python's-Oflag.
526-684: Previous quantile_range logic error has been fixed.Line 573 now correctly uses
not isinstance(quantile_range, (tuple, list))instead of the previous incorrectorcondition that always evaluated toTrue.
687-813: LGTM! MaxAbsScale and scale_methods dictionary are correct.The implementation correctly scales data by the maximum absolute value. The
scale_methodsdictionary provides convenient access to all scaling functions.kim_convergence/run_length_control/_convergence.py (4)
42-160: LGTM: Clean report builder with appropriate defensive checks.The structured report generation correctly handles both single- and multi-variable scenarios. The assertions provide good defensive validation for this internal function, and the conditional flattening (lines 155-158) maintains a clean API.
163-172: LGTM: Efficient view-based slicing.The memory-shared view approach is appropriate for this use case and avoids unnecessary copies.
175-290: LGTM: Robust accuracy checking with proper guards.The distinction between relative and absolute accuracy modes is handled correctly, and the zero-mean guard (lines 269-276) appropriately prevents ill-defined relative estimates. The
final_passmode provides a clean mechanism for reporting best-available estimates when full convergence isn't achieved.
531-583: LGTM: Clean output handling with proper validation.The function correctly handles multiple output destinations and formats, with appropriate validation for both
fpandfp_formatparameters.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 4
🧹 Nitpick comments (11)
kim_convergence/stats/zero_rc_bounds.py (1)
157-168: Optional: Consider error message consolidation (low priority).Static analysis flags the inline error messages (TRY003), suggesting they could be defined as class-level constants or in a custom exception class. However, given that:
- The messages include dynamic f-string interpolation
- The current approach is readable and maintainable
- This is purely stylistic
This refactor is entirely optional and can be safely deferred or ignored.
Also applies to: 175-185, 222-227, 260-265, 310-313
kim_convergence/timeseries/equilibration_length.py (1)
58-136: Consider consolidating duplicated validation logic.The
_normalize_ignore_endhelper shares substantial validation structure with the similar function inkim_convergence/ucl/mser_m.py(None/float/int handling, range checks, error raising). While the semantics differ (data points vs batches, Geyer-specific bounds), the core validation pattern is duplicated.Consider extracting the shared validation logic into a common utility function that accepts domain-specific parameters (defaults, bounds, validators) to reduce technical debt and improve maintainability.
Optional: Address static analysis style hints (TRY003)
The static analyzer flags lines 89-92, 96-99, 101-104, 109-112, 116-119, 123-126, 130-133 for specifying long error messages outside the exception class. While not critical, you could reduce these warnings by defining custom exception classes with built-in messages or by shortening the inline messages.
kim_convergence/run_length_control/_convergence.py (5)
175-292: LGTM with optional style suggestion.The function correctly handles UCL computation, accuracy checking, and error conditions. The near-zero mean check at lines 271-278 appropriately prevents ill-defined relative accuracy calculations.
Static analysis flagged long error messages at lines 251-253 and 274-278. While informative, consider extracting these to exception class constructors or module-level constants for consistency:
🔎 Optional refactor for error messages
+# Module-level error message templates +_ERR_UCL_COMPUTATION = "Failed to compute the ucl for variable number = {var_num}." +_ERR_RELATIVE_ACCURACY_ZERO_MEAN = ( + "It is not possible to estimate the relative half width for " + "the close to zero mean = {mean}, for the variable " + "number = {var_num}. Consider using absolute_accuracy instead." +) + def _compute_ucl_and_check_accuracy( ... ) -> tuple[Optional[float], float, bool]: ... except CRError as e: - raise CRError( - f"Failed to compute the ucl for variable number = {i + 1}." - ) from e + raise CRError(_ERR_UCL_COMPUTATION.format(var_num=i + 1)) from e ... if isclose( ucl_obj.mean, 0, abs_tol=_DEFAULT_RELATIVE_HALF_WIDTH_ESTIMATE_ABS_TOL ): - raise CRError( - "It is not possible to estimate the relative half width for " - f"the close to zero mean = {ucl_obj.mean}, for the variable " - f"number = {i + 1}. Consider using absolute_accuracy instead." - ) + raise CRError(_ERR_RELATIVE_ACCURACY_ZERO_MEAN.format( + mean=ucl_obj.mean, var_num=i + 1 + ))
385-446: Consider relocating thedonereset for clarity.The
done[i] = Falsereset at line 387 executes for every variable in every convergence iteration, but it would be clearer and slightly more efficient to reset once at the start of the outerwhileloop:🔎 Suggested refactor
converged = False while not converged: + # Reset convergence flags for all variables at the start of each iteration + for i in range(number_of_variables): + done[i] = False + for i in range(number_of_variables): - done[i] = False # reset even if already converged - # slice a numpy array, the memory is shared between the slice and the original time_series_data = _equilibrated_series(tsd, ndim, equilibration_step[i], i)This makes the intent clearer: we're resetting convergence state once per convergence iteration, not once per variable check.
443-446: Document thefor-elseconstruct for clarity.The
for-elsepattern here is correct: theelseclause executes only if the loop completes without hitting thebreakat line 418 (i.e., all variables successfully computed UCL). However, this Python feature can be confusing to readers.🔎 Suggested clarification
+ # Python for-else: the else clause executes only if the loop completes + # without breaking. Here it means all variables computed UCL successfully. else: converged = all(done) if converged: break
467-521: LGTM with optional style suggestion.The error handling and final pass logic correctly handle non-convergence cases. The warning for undefined relative accuracy (lines 517-520) appropriately alerts users when the confidence interval includes zero.
Similar to earlier suggestions, the long error message at lines 469-472 could be extracted to a module-level constant:
🔎 Optional refactor
+_ERR_UCL_COMPUTATION_FAILED = ( + 'For variable number(s) {var_nums}. Failed to compute the UCL.' +) + ... failed = [str(i + 1) for i, u in enumerate(upper_confidence_limit) if u is None] if failed: - raise CRError( - f'For variable number(s) {", ".join(failed)}. Failed to ' - "compute the UCL." - ) + raise CRError(_ERR_UCL_COMPUTATION_FAILED.format(var_nums=", ".join(failed)))
534-588: LGTM with optional style suggestion.The function correctly handles validation, serialization, and output routing for the convergence report. The dual return type (
Union[str, bool]) is justified by the different usage modes.The long error messages at lines 559-561 and 564-567 could be extracted to module-level constants for consistency:
🔎 Optional refactor
+# Module-level error message templates +_ERR_FP_INVALID_STRING = 'Keyword argument `fp` is a `str` and not equal to "return".' +_ERR_FP_INVALID_TYPE = ( + "Keyword argument `fp` must be either a `str` and equal to " + '"return", or None, or an object with write(string) method.' +) +_ERR_FP_FORMAT_UNKNOWN = ( + "fp format is unknown. Valid formats are:\n\t- " + + "\n\t- ".join(("txt", "json", "edn")) +) + def _output_convergence_report( ... ): ... elif isinstance(fp, str): if fp != "return": - raise CRError( - 'Keyword argument `fp` is a `str` and not equal to "return".' - ) + raise CRError(_ERR_FP_INVALID_STRING) fp = None elif not hasattr(fp, "write"): - raise CRError( - "Keyword argument `fp` must be either a `str` and equal to " - '"return", or None, or an object with write(string) method.' - ) + raise CRError(_ERR_FP_INVALID_TYPE) if fp_format not in ("txt", "json", "edn"): - raise CRError( - "fp format is unknown. Valid formats are:\n\t- " - + "\n\t- ".join(("txt", "json", "edn")) - ) + raise CRError(_ERR_FP_FORMAT_UNKNOWN)kim_convergence/timeseries/statistical_inefficiency.py (2)
133-133: LGTM: Explicit float literals improve clarity.The use of explicit float literals (e.g.,
1.0,2.0,0.0) throughout the file makes the intent clear and ensures consistent numeric types. While Python 3's division operator already returns floats, this explicit style is beneficial for code clarity.Also applies to: 155-155, 308-308
161-163: Consider clarifying reference comment formatting.The reference comments have been reformatted. Note that line 162 contains
mcstanesswhich may be a typo or unconventional formatting. If this refers to Stan's effective sample size documentation, consider clarifying the reference or using a more standard citation format.kim_convergence/ucl/mser_m_y.py (2)
34-39: Optional: Consider sorting__all__alphabetically.Ruff suggests sorting
__all__(RUF022). While not critical, sorted exports improve discoverability.🔎 Proposed fix
__all__ = [ - "mser_m_y_ci", - "mser_m_y_relative_half_width_estimate", - "mser_m_y_ucl", "MSER_m_y", + "mser_m_y_ci", + "mser_m_y_relative_half_width_estimate", + "mser_m_y_ucl", ]
176-189: Consider documenting the fallback batch size choice.When
dependent_dataremains true after exhausting available data, the fallback tobatch_size=10is used. Consider adding a brief comment explaining why 10 was chosen as the fallback value.
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (12)
kim_convergence/run_length_control/_convergence.pykim_convergence/scale.pykim_convergence/stats/nonnormal_test.pykim_convergence/stats/zero_rc_bounds.pykim_convergence/timeseries/equilibration_length.pykim_convergence/timeseries/statistical_inefficiency.pykim_convergence/timeseries/utils.pykim_convergence/ucl/mser_m.pykim_convergence/ucl/mser_m_y.pykim_convergence/ucl/n_skart.pykim_convergence/ucl/spectral/heidelberger_welch.pykim_convergence/ucl/uncorrelated_samples.py
🧰 Additional context used
🧬 Code graph analysis (3)
kim_convergence/timeseries/equilibration_length.py (2)
kim_convergence/err.py (2)
CRError(38-60)CRSampleSizeError(63-66)kim_convergence/ucl/mser_m.py (1)
_normalize_ignore_end(41-96)
kim_convergence/ucl/uncorrelated_samples.py (2)
kim_convergence/err.py (3)
CRError(38-60)CRSampleSizeError(63-66)cr_warning(69-78)kim_convergence/stats/t_dist.py (1)
t_inv_cdf(103-195)
kim_convergence/ucl/mser_m.py (4)
kim_convergence/batch.py (1)
batch(19-145)kim_convergence/err.py (2)
CRError(38-60)CRSampleSizeError(63-66)kim_convergence/stats/t_dist.py (1)
t_inv_cdf(103-195)kim_convergence/timeseries/equilibration_length.py (2)
_normalize_ignore_end(58-135)estimate_equilibration_length(138-293)
🪛 Ruff (0.14.10)
kim_convergence/run_length_control/_convergence.py
251-253: Avoid specifying long messages outside the exception class
(TRY003)
274-278: Avoid specifying long messages outside the exception class
(TRY003)
469-472: Avoid specifying long messages outside the exception class
(TRY003)
559-561: Avoid specifying long messages outside the exception class
(TRY003)
564-567: Avoid specifying long messages outside the exception class
(TRY003)
kim_convergence/timeseries/equilibration_length.py
89-92: Avoid specifying long messages outside the exception class
(TRY003)
96-99: Avoid specifying long messages outside the exception class
(TRY003)
101-104: Avoid specifying long messages outside the exception class
(TRY003)
109-112: Avoid specifying long messages outside the exception class
(TRY003)
116-119: Avoid specifying long messages outside the exception class
(TRY003)
123-126: Avoid specifying long messages outside the exception class
(TRY003)
130-133: Avoid specifying long messages outside the exception class
(TRY003)
147-147: Unused function argument: batch_size
(ARG001)
148-148: Unused function argument: scale
(ARG001)
149-149: Unused function argument: with_centering
(ARG001)
150-150: Unused function argument: with_scaling
(ARG001)
192-192: Avoid specifying long messages outside the exception class
(TRY003)
206-206: Avoid specifying long messages outside the exception class
(TRY003)
212-212: Avoid specifying long messages outside the exception class
(TRY003)
217-217: Avoid specifying long messages outside the exception class
(TRY003)
kim_convergence/ucl/uncorrelated_samples.py
68-68: Unused method argument: equilibration_length_estimate
(ARG002)
69-69: Unused method argument: heidel_welch_number_points
(ARG002)
70-70: Unused method argument: batch_size
(ARG002)
71-71: Unused method argument: scale
(ARG002)
72-72: Unused method argument: with_centering
(ARG002)
73-73: Unused method argument: with_scaling
(ARG002)
74-74: Unused method argument: test_size
(ARG002)
75-75: Unused method argument: train_size
(ARG002)
136-136: Avoid specifying long messages outside the exception class
(TRY003)
141-144: Avoid specifying long messages outside the exception class
(TRY003)
147-150: Avoid specifying long messages outside the exception class
(TRY003)
414-414: Avoid specifying long messages outside the exception class
(TRY003)
kim_convergence/scale.py
95-95: Avoid specifying long messages outside the exception class
(TRY003)
147-147: Unused function argument: with_centering
(ARG001)
148-148: Unused function argument: with_scaling
(ARG001)
241-241: Avoid specifying long messages outside the exception class
(TRY003)
392-392: Avoid specifying long messages outside the exception class
(TRY003)
468-468: Avoid specifying long messages outside the exception class
(TRY003)
479-479: Avoid specifying long messages outside the exception class
(TRY003)
481-481: Avoid specifying long messages outside the exception class
(TRY003)
574-574: Avoid specifying long messages outside the exception class
(TRY003)
574-574: Use explicit conversion flag
Replace with conversion flag
(RUF010)
577-577: Avoid specifying long messages outside the exception class
(TRY003)
577-577: Use explicit conversion flag
Replace with conversion flag
(RUF010)
581-581: Avoid specifying long messages outside the exception class
(TRY003)
581-581: Use explicit conversion flag
Replace with conversion flag
(RUF010)
599-599: Avoid specifying long messages outside the exception class
(TRY003)
737-737: Avoid specifying long messages outside the exception class
(TRY003)
782-782: Unused function argument: with_centering
(ARG001)
783-783: Unused function argument: with_scaling
(ARG001)
kim_convergence/ucl/mser_m_y.py
34-39: __all__ is not sorted
Apply an isort-style sorting to __all__
(RUF022)
82-82: Unused method argument: equilibration_length_estimate
(ARG002)
83-83: Unused method argument: heidel_welch_number_points
(ARG002)
84-84: Unused method argument: fft
(ARG002)
85-85: Unused method argument: test_size
(ARG002)
86-86: Unused method argument: train_size
(ARG002)
87-87: Unused method argument: population_standard_deviation
(ARG002)
90-90: Unused method argument: si
(ARG002)
91-91: Unused method argument: minimum_correlation_time
(ARG002)
92-92: Unused method argument: uncorrelated_sample_indices
(ARG002)
95-95: Unused method argument: sample_method
(ARG002)
126-126: Avoid specifying long messages outside the exception class
(TRY003)
131-135: Avoid specifying long messages outside the exception class
(TRY003)
331-331: Avoid specifying long messages outside the exception class
(TRY003)
kim_convergence/timeseries/utils.py
92-95: Avoid specifying long messages outside the exception class
(TRY003)
99-102: Avoid specifying long messages outside the exception class
(TRY003)
107-109: Avoid specifying long messages outside the exception class
(TRY003)
208-208: Avoid specifying long messages outside the exception class
(TRY003)
282-282: Avoid specifying long messages outside the exception class
(TRY003)
293-296: Avoid specifying long messages outside the exception class
(TRY003)
302-304: Avoid specifying long messages outside the exception class
(TRY003)
362-362: Avoid specifying long messages outside the exception class
(TRY003)
373-376: Avoid specifying long messages outside the exception class
(TRY003)
401-401: Standard pseudo-random generators are not suitable for cryptographic purposes
(S311)
451-451: Avoid specifying long messages outside the exception class
(TRY003)
462-465: Avoid specifying long messages outside the exception class
(TRY003)
kim_convergence/ucl/spectral/heidelberger_welch.py
322-322: Unused method argument: equilibration_length_estimate
(ARG002)
326-326: Unused method argument: population_standard_deviation
(ARG002)
329-329: Unused method argument: si
(ARG002)
330-330: Unused method argument: minimum_correlation_time
(ARG002)
331-331: Unused method argument: uncorrelated_sample_indices
(ARG002)
334-334: Unused method argument: sample_method
(ARG002)
489-489: Avoid specifying long messages outside the exception class
(TRY003)
780-780: Avoid specifying long messages outside the exception class
(TRY003)
kim_convergence/ucl/mser_m.py
72-75: Avoid specifying long messages outside the exception class
(TRY003)
79-82: Avoid specifying long messages outside the exception class
(TRY003)
85-88: Avoid specifying long messages outside the exception class
(TRY003)
91-94: Avoid specifying long messages outside the exception class
(TRY003)
175-175: Avoid specifying long messages outside the exception class
(TRY003)
181-184: Avoid specifying long messages outside the exception class
(TRY003)
188-188: Avoid specifying long messages outside the exception class
(TRY003)
191-191: Avoid specifying long messages outside the exception class
(TRY003)
292-292: Unused method argument: number_of_cores
(ARG002)
294-294: Unused method argument: nskip
(ARG002)
332-332: Unused method argument: equilibration_length_estimate
(ARG002)
333-333: Unused method argument: heidel_welch_number_points
(ARG002)
334-334: Unused method argument: fft
(ARG002)
335-335: Unused method argument: test_size
(ARG002)
336-336: Unused method argument: train_size
(ARG002)
337-337: Unused method argument: population_standard_deviation
(ARG002)
340-340: Unused method argument: si
(ARG002)
341-341: Unused method argument: minimum_correlation_time
(ARG002)
342-342: Unused method argument: uncorrelated_sample_indices
(ARG002)
345-345: Unused method argument: sample_method
(ARG002)
376-376: Avoid specifying long messages outside the exception class
(TRY003)
379-382: Avoid specifying long messages outside the exception class
(TRY003)
535-535: Avoid specifying long messages outside the exception class
(TRY003)
kim_convergence/ucl/n_skart.py
116-116: Unused method argument: nskip
(ARG002)
119-119: Unused method argument: ignore_end
(ARG002)
122-122: Unused method argument: number_of_cores
(ARG002)
151-151: Avoid specifying long messages outside the exception class
(TRY003)
308-308: Unused method argument: heidel_welch_number_points
(ARG002)
309-309: Unused method argument: batch_size
(ARG002)
313-313: Unused method argument: test_size
(ARG002)
316-316: Unused method argument: train_size
(ARG002)
319-319: Unused method argument: population_standard_deviation
(ARG002)
322-322: Unused method argument: si
(ARG002)
323-323: Unused method argument: minimum_correlation_time
(ARG002)
326-326: Unused method argument: uncorrelated_sample_indices
(ARG002)
329-329: Unused method argument: sample_method
(ARG002)
361-361: Avoid specifying long messages outside the exception class
(TRY003)
364-364: Avoid specifying long messages outside the exception class
(TRY003)
456-460: Avoid specifying long messages outside the exception class
(TRY003)
604-604: Avoid specifying long messages outside the exception class
(TRY003)
kim_convergence/stats/nonnormal_test.py
406-411: Avoid specifying long messages outside the exception class
(TRY003)
535-535: Avoid specifying long messages outside the exception class
(TRY003)
554-554: Avoid specifying long messages outside the exception class
(TRY003)
657-657: Avoid specifying long messages outside the exception class
(TRY003)
685-685: Avoid specifying long messages outside the exception class
(TRY003)
690-690: Avoid specifying long messages outside the exception class
(TRY003)
752-752: Avoid specifying long messages outside the exception class
(TRY003)
777-777: Avoid specifying long messages outside the exception class
(TRY003)
836-836: Avoid specifying long messages outside the exception class
(TRY003)
844-844: Avoid specifying long messages outside the exception class
(TRY003)
867-867: Avoid specifying long messages outside the exception class
(TRY003)
872-872: Avoid specifying long messages outside the exception class
(TRY003)
kim_convergence/stats/zero_rc_bounds.py
157-162: Avoid specifying long messages outside the exception class
(TRY003)
163-168: Avoid specifying long messages outside the exception class
(TRY003)
175-180: Avoid specifying long messages outside the exception class
(TRY003)
181-185: Avoid specifying long messages outside the exception class
(TRY003)
222-227: Avoid specifying long messages outside the exception class
(TRY003)
260-265: Avoid specifying long messages outside the exception class
(TRY003)
310-313: Avoid specifying long messages outside the exception class
(TRY003)
kim_convergence/timeseries/statistical_inefficiency.py
88-88: Avoid specifying long messages outside the exception class
(TRY003)
94-97: Avoid specifying long messages outside the exception class
(TRY003)
104-104: Avoid specifying long messages outside the exception class
(TRY003)
106-106: Avoid specifying long messages outside the exception class
(TRY003)
171-171: Unused function argument: minimum_correlation_time
(ARG001)
231-231: Avoid specifying long messages outside the exception class
(TRY003)
324-324: Unused function argument: minimum_correlation_time
(ARG001)
371-373: Avoid specifying long messages outside the exception class
(TRY003)
378-381: Avoid specifying long messages outside the exception class
(TRY003)
391-391: Unused function argument: minimum_correlation_time
(ARG001)
423-425: Avoid specifying long messages outside the exception class
(TRY003)
431-431: Avoid specifying long messages outside the exception class
(TRY003)
435-438: Avoid specifying long messages outside the exception class
(TRY003)
🔇 Additional comments (51)
kim_convergence/stats/zero_rc_bounds.py (5)
47-49: LGTM! Style improvements align with Python conventions.The changes to use double quotes in
__all__and remove empty parentheses from the class declaration are good style improvements that align with PEP 8 and the broader PR's formatting standards.Also applies to: 52-52
55-65: LGTM! Improved readability with multi-line formatting.The multi-line signature with trailing comma improves readability and follows Python best practices for functions with multiple parameters.
93-99: Excellent simplification by removing unnecessary deepcopy.Replacing
deepcopy()with direct assignments for float parameters is a good optimization. Since floats are immutable in Python, deep copying adds unnecessary overhead without providing any safety benefit.
138-296: LGTM! Consistent style improvements throughout.The changes maintain the original logic while improving code quality through:
- Removing unnecessary
deepcopy()calls for float variables (immutable types)- Standardizing string formatting with double quotes
- Improving readability with multi-line expressions
All changes are stylistically consistent with the broader PR.
298-298: Excellent addition of defensive assertion.The assertion ensures
self.zis properly initialized before use in the state machine's index==6 branch. This is good defensive programming that helps catch potential logic errors in the reverse communication flow.kim_convergence/stats/nonnormal_test.py (4)
211-211: Previous issue resolved: pearson3 parameter count corrected.The value for
"pearson3"has been correctly updated to1, matching scipy's single shape parameter (skew). This addresses the critical issue identified in the previous review.
444-478: LGTM: Type hints and safe cast operation.The function signature has been enhanced with explicit type hints, and the
cast(str, population_cdf)on line 471 is safe becausecheck_population_cdf_args(line 465) validates the parameter and returns early forNoneor"default", ensuringpopulation_cdfis a valid string when reaching thegetattrcall.
553-554: LGTM: Improved exception handling with causal chains.The exception handlers now use
raise ... from eto preserve exception context, which is excellent for debugging. The intentional catch-all handlers appropriately wrap underlying library exceptions with domain-specific error types.Note: Static analysis suggests moving long messages to custom exception classes (TRY003), but this is a style preference and can be addressed later if desired.
Also applies to: 684-685, 689-690, 776-777, 866-867, 871-872
481-488: LGTM: Modernized type hints for test functions.The function signatures have been updated with modern type hints using
Union[np.ndarray, list[float]](lowercaselistper PEP 585, Python 3.9+) and explicitOptionalannotations. These improvements enhance API clarity and type safety.Also applies to: 559-566, 695-702, 784-791
kim_convergence/timeseries/equilibration_length.py (4)
10-28: LGTM! Enhanced imports support new functionality.The addition of
parallel_backendfor deadlock mitigation, enhanced type hints, and centralized default constants improves code quality and maintainability.
37-56: LGTM! Type hints and keyword arguments improve clarity.The updated signature with explicit type hints and keyword argument usage in the
si_funccall enhances code readability and reduces potential argument ordering errors.
138-220: LGTM! API extension maintains backward compatibility.The function signature extension with
batch_size,scale,with_centering, andwith_scalingparameters (marked as unused for API compatibility) is intentional and well-documented in the Note section (lines 185-188). The delegation to_normalize_ignore_endcorrectly passes thesiparameter to handle Geyer-specific bounds.The static analyzer warnings about unused arguments (ARG001) can be safely ignored given the explicit API compatibility rationale.
242-249: LGTM! Loky backend mitigates threading deadlocks.The
parallel_backend("loky", ...)wrapper around the parallelization path is an effective mitigation for BLAS/OpenMP deadlocks when this code is invoked from within multithreaded contexts (e.g., LAMMPS), as noted in the PR objectives. The consistent use of keyword arguments forsi_funccalls throughout both parallel and serial paths (lines 246, 280-281) enhances code safety.kim_convergence/timeseries/utils.py (6)
30-44: LGTM!The type annotation modernization (
List[int]→list[int]) is correct, and the error formatting logic is sound.
47-111: LGTM!The type annotation updates and error handling are correct. The use of
from ein exception chaining properly preserves the traceback.
114-162: LGTM!The type annotation updates are correct, and the previously flagged typo in the docstring has been addressed.
165-240: LGTM!The dispatcher logic correctly routes to the appropriate sampling method, and the type annotations are properly updated.
243-318: LGTM!The type annotation updates are correct, and the previously flagged spacing issue in the error message has been resolved.
321-405: LGTM!The random sampling logic is correct. Starting with
indices[0]properly handles custom index arrays. The static analysis warning aboutrandint(S311) is not applicable here since this is statistical sampling, not cryptographic use.kim_convergence/run_length_control/_convergence.py (3)
1-40: LGTM!The module documentation clearly describes the convergence phase responsibilities, and the private API surface is appropriately marked with
__all__ = [].
42-160: LGTM!The function correctly builds a structured convergence report with proper handling of single vs multi-variable cases and appropriate type conversions for serialization.
163-172: LGTM!The function correctly returns a memory-shared view of the equilibrated portion, with appropriate handling for both 1D and 2D cases.
kim_convergence/timeseries/statistical_inefficiency.py (6)
142-142: LGTM: Good use of local alias for clarity.The introduction of the
mctalias improves readability by making the minimum correlation time threshold calculation explicit and avoiding repetition.
171-171: LGTM: Unused parameter documented for API compatibility.The
minimum_correlation_timeparameter is appropriately kept for API compatibility with other statistical inefficiency methods. The inline comment and docstring note make this explicit. While Ruff flags it as unused, this is an intentional design decision for maintaining a consistent interface acrosssi_methods.Also applies to: 223-225
372-372: LGTM: Error messages corrected per previous review.The grammar issues and string concatenation problems flagged in the previous review have been successfully addressed. The error messages now use proper grammar ("does not use" instead of "do not use") and single string literals.
Also applies to: 424-424
540-545: LGTM: Consistent string literal style.The
si_methodsdictionary has been updated to use double-quoted strings consistently with the rest of the module. All function references are correctly preserved.
203-205: LGTM: Well-documented references to methodology.The docstrings properly reference the Stan implementation and Geyer's papers using Sphinx citation syntax. This provides good context for the algorithm choices.
Also applies to: 349-351
9-9: Python 3.9+ requirement is already documented.The project's
pyproject.tomlcorrectly declaresrequires-python = ">=3.9", which fully supports the PEP 585 type hint syntax (list[float]) used in this file. No action needed.kim_convergence/scale.py (2)
573-574: LGTM! Past review issue resolved.The type check for
quantile_rangehas been correctly fixed to useisinstance(quantile_range, (tuple, list)), resolving the logic error from the previous review.
467-468: LGTM! Past review issues resolved.The assertions have been correctly replaced with explicit
isinstancechecks that raiseCRErrorwith clear messages. This ensures the type guards work even when Python is run with optimization flags (-O).Also applies to: 478-481
kim_convergence/ucl/spectral/heidelberger_welch.py (6)
1-43: LGTM: Module structure and imports are well-organized.The imports are cleanly organized, and the
__all__export list correctly exposes the public API.
89-115: LGTM: Clean initialization with explicit Optional typing.The explicit
Optionaltype annotations for all attributes improve type safety and make the lazy initialization pattern clear.
144-154: LGTM: Efficient caching with proper type narrowing.The early return pattern avoids redundant computation when only the confidence coefficient changes, and the assertions properly narrow the
Optionaltypes for mypy.
312-335: Unused parameters are intentional for API compatibility.The unused parameters (
equilibration_length_estimate,population_standard_deviation,si, etc.) are correctly documented in the Note section (lines 479-483) as being accepted for API compatibility. This is a valid pattern for maintaining a consistent interface across different UCL implementations. The static analysis warnings (ARG002) can be safely ignored here.
520-546: LGTM: Batch and periodogram computation follows the standard method.The batch computation and log periodogram transformation (including the 0.27 bias correction) correctly implement the Heidelberger-Welch spectral method.
648-668: LGTM: Clean wrapper function pattern.The wrapper functions correctly delegate to the class methods and provide a consistent functional API.
kim_convergence/ucl/mser_m_y.py (3)
73-96: Unused parameters are intentional for API compatibility.The unused parameters are documented in the Note section (lines 116-121). This maintains interface consistency across UCL implementations. The static analysis warnings (ARG002) can be safely ignored.
154-174: LGTM: Adaptive batch sizing logic.The progressive increase of batch size by factor 1.2 until the randomness test passes is a reasonable approach for finding independent batch means.
210-213: LGTM: Type conversion ensures consistent return type.The
float()conversion on line 213 ensures a built-in Python float is returned rather than a numpy scalar, which is good for type consistency.kim_convergence/ucl/mser_m.py (4)
41-96: LGTM: Well-structured ignore_end normalization.The
_normalize_ignore_endhelper properly handlesNone,float, andintinputs with appropriate validation. The logic mirrors the similar function inequilibration_length.pybut is adapted for batch-based operations.
214-232: LGTM: MSER statistic computation is correct.The vectorized computation of the MSER statistic using cumulative sums and element-wise operations is efficient and follows the mathematical definition correctly.
323-346: Unused parameters follow the established API compatibility pattern.Consistent with other UCL implementations in this PR, unused parameters are documented in the Note section (lines 366-371).
404-417: LGTM: Standard UCL computation using Student's t-distribution.The computation of the upper confidence limit using the standard error of the mean and t-distribution critical value is correct.
kim_convergence/ucl/uncorrelated_samples.py (3)
179-188: LGTM: Graceful degradation with warning for small samples.The two-tier approach (warning for <5 samples, error for <2) allows computation to proceed in borderline cases while alerting users. The minimum of 2 samples is mathematically required for the t-distribution (df = n-1 >= 1).
53-76: Unused parameters follow the established API compatibility pattern.Consistent with other UCL implementations, unused parameters are documented in the Note section (lines 127-131).
214-217: LGTM: Consistent return type handling.The assertion and
float()conversion ensure type consistency across all UCL implementations.kim_convergence/ucl/n_skart.py (5)
233-242: Verify the spaced batch slicing logic.The slicing
x_batch[idx::idx + 1]starts at indexidx(number of batches per spacer) and steps byidx + 1. This implements spaced sampling, but the result at line 238 (self.kp_number_batches = spaced_x_batch.size) may not match the expected formula. Consider verifying the slicing matches the N-Skart paper's specification.
455-463: LGTM: Good defensive check for perfect correlation.The check for
abs(1 - lag1_correlation) < 1e-10prevents division by near-zero when computing the correlation adjustment. The error message helpfully suggests potential causes.
490-503: LGTM: Proper handling of skewness adjustment edge case.The limiting case
abs(beta) < 1e-15correctly handles numerical stability when skewness is near zero. The simplified formulaupper - betais the appropriate limit of the Cornish-Fisher expansion as β → 0.
111-148: Unused parameters follow the established API compatibility pattern.The parameters
nskip,ignore_end, andnumber_of_coresare documented as unused for API compatibility in the Note section (lines 145-147).
301-332: Unused parameters follow the established API compatibility pattern.Consistent with other UCL implementations, unused parameters are documented in the Note section (lines 352-356).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
🧹 Nitpick comments (9)
kim_convergence/timeseries/statistical_inefficiency.py (1)
88-88: Consider extracting error messages as class-level constants (optional).Static analysis flags multiple instances of long error messages defined inline (TRY003). While the current implementation is functional and consistent with the codebase style, extracting these as constants in the
CRErrororCRSampleSizeErrorclasses could improve maintainability and testability.This is a minor stylistic improvement and can be deferred or addressed as part of a broader error-handling refactor.
Also applies to: 94-97, 104-106, 232-232, 372-374, 379-382, 424-426, 432-432, 436-439
kim_convergence/ucl/uncorrelated_samples.py (1)
42-42: Consider removing the commented-out constant.The commented
SAMPLING_METHODSline can be removed entirely, as the constant is already defined inkim_convergence/timeseries/utils.pywhere the actual validation occurs. Based on learnings, this constant is not referenced in this module.🔎 Proposed fix
-# SAMPLING_METHODS = ("uncorrelated", "random", "block_averaged")kim_convergence/run_length_control/_convergence.py (2)
256-256: Consider replacing fragile string comparison with a method or constant.The literal string
"uncorrelated_sample"is compared directly againstucl_obj.namein two places (lines 256 and 284). This coupling is fragile—if the naming convention changes in the UCL class hierarchy, this logic will break silently.🔎 Proposed refactor options
Option 1: Add a method to UCLBase:
In
kim_convergence/ucl/ucl_base.py, add:def requires_si_computation(self) -> bool: """Return True if this UCL method requires statistical inefficiency computation.""" return self.name != "uncorrelated_sample"Then update both locations in this file:
- if ucl_obj.name != "uncorrelated_sample": + if ucl_obj.requires_si_computation(): ucl_obj.set_si(...)Option 2: Define a constant at module level:
_UCL_METHOD_UNCORRELATED_SAMPLE = "uncorrelated_sample"Then use it consistently:
- if ucl_obj.name != "uncorrelated_sample": + if ucl_obj.name != _UCL_METHOD_UNCORRELATED_SAMPLE: ucl_obj.set_si(...)Also applies to: 284-284
537-591: LGTM! Robust output handling.The function provides thorough validation of both
fpandfp_formatparameters with clear error messages. The logic correctly handles multiple output modes (return as string, write to file-like object, write to stdout) and supports all specified formats.
Optional style note: Static analysis flagged the exception messages (lines 562-564, 567-570, and earlier at 251-253, 274-278, 472-475) as potentially better placed in the exception class definition per TRY003. This is a minor style consideration and can be addressed if the project adopts stricter exception message patterns.
kim_convergence/timeseries/utils.py (3)
30-30: Broaden the type signature to eliminate# type: ignorecomments.The
bad_indicesparameter is typed aslist[int], but all call sites (lines 314, 393, 482) passnp.ndarrayvalues, requiring# type: ignore[arg-type]suppressions. Since the function body works correctly with both types (usingmap(str, bad_indices)), update the signature to accept both.🔎 Proposed fix
-def _out_of_bounds_error_str(bad_indices: list[int], size: int) -> str: +def _out_of_bounds_error_str(bad_indices: Union[np.ndarray, list[int]], size: int) -> str:This will allow you to remove the
# type: ignore[arg-type]comments at lines 314, 393, and 482.
200-201: Polish the docstring wording.Line 201 reads "time series data at uncorrelated uncorrelated_sample indices" with duplicate "uncorrelated" wording. Consider simplifying to "time series data at uncorrelated sample indices" for clarity.
🔎 Proposed fix
Returns: 1darray: uncorrelated_sample of the time series data. - time series data at uncorrelated uncorrelated_sample indices. + time series data at uncorrelated sample indices.
253-253: Polish the docstring wording.Lines 253 and 275 contain "uncorrelated uncorrelated_sample indices" with duplicate "uncorrelated" wording, similar to line 201. Consider simplifying to "uncorrelated sample indices" for consistency and clarity.
🔎 Proposed fix
- r"""Return time series data at uncorrelated uncorrelated_sample indices. + r"""Return time series data at uncorrelated sample indices.and
Returns: 1darray: uncorrelated_sample of the time series data. - time series data at uncorrelated uncorrelated_sample indices. + time series data at uncorrelated sample indices.Also applies to: 274-275
kim_convergence/ucl/mser_m_y.py (1)
116-122: Consider standard docstring section formatting.The
Note:section uses non-standard formatting for NumPy-style docstrings. Consider changingNote:toNotes(without colon) to align with standard NumPy docstring conventions.🔎 Proposed formatting adjustment
- Note: + Notes + ----- equilibration_length_estimate, heidel_welch_number_points, fft,kim_convergence/scale.py (1)
576-576: Consider consistent string formatting for error messages.For consistency with line 73 which uses
{feature_range!s}, consider using the conversion flag!sinstead of explicitstr()calls in these error messages.🔎 Suggested refactor
- if not isinstance(quantile_range, (tuple, list)): - raise CRError(f"invalid quantile range: {str(quantile_range)}.") + if not isinstance(quantile_range, (tuple, list)): + raise CRError(f"invalid quantile range: {quantile_range!s}.") if len(quantile_range) != 2: - raise CRError(f"invalid quantile range: {str(quantile_range)}.") + raise CRError(f"invalid quantile range: {quantile_range!s}.") q_min, q_max = quantile_range if not 0 <= q_min <= q_max <= 100: - raise CRError(f"invalid quantile range: {str(quantile_range)}.") + raise CRError(f"invalid quantile range: {quantile_range!s}.")Also applies to: 579-579, 583-583
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (8)
doc/references.rstkim_convergence/run_length_control/_convergence.pykim_convergence/scale.pykim_convergence/timeseries/statistical_inefficiency.pykim_convergence/timeseries/utils.pykim_convergence/ucl/mser_m_y.pykim_convergence/ucl/n_skart.pykim_convergence/ucl/uncorrelated_samples.py
🚧 Files skipped from review as they are similar to previous changes (1)
- doc/references.rst
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2026-01-04T04:00:25.216Z
Learnt from: yafshar
Repo: openkim/kim-convergence PR: 6
File: kim_convergence/ucl/n_skart.py:468-476
Timestamp: 2026-01-04T04:00:25.216Z
Learning: In kim_convergence/ucl/n_skart.py, the formula for spaced_x_batch_size (line 474-476) intentionally follows the original N-SKART paper and should not be replaced with spaced_x_batch.size, even though they may produce different values.
Applied to files:
kim_convergence/ucl/n_skart.py
🧬 Code graph analysis (5)
kim_convergence/ucl/uncorrelated_samples.py (3)
kim_convergence/ucl/ucl_base.py (11)
UCLBase(42-492)name(59-61)name(64-71)name(74-76)_ucl_impl(315-340)si(138-140)si(143-150)si(153-155)indices(79-81)indices(84-91)indices(94-96)kim_convergence/err.py (3)
CRError(38-60)CRSampleSizeError(63-66)cr_warning(69-78)kim_convergence/timeseries/utils.py (3)
time_series_data_si(47-111)uncorrelated_time_series_data_sample_indices(114-162)uncorrelated_time_series_data_samples(165-240)
kim_convergence/timeseries/utils.py (2)
kim_convergence/timeseries/statistical_inefficiency.py (1)
statistical_inefficiency(36-158)kim_convergence/err.py (1)
CRError(38-60)
kim_convergence/scale.py (1)
kim_convergence/err.py (1)
CRError(38-60)
kim_convergence/run_length_control/_convergence.py (5)
kim_convergence/err.py (3)
CRError(38-60)CRSampleSizeError(63-66)cr_warning(69-78)kim_convergence/ucl/ucl_base.py (17)
ucl(342-389)UCLBase(42-492)relative_half_width_estimate(439-492)mean(188-190)mean(193-200)mean(203-205)std(208-210)std(213-220)std(223-225)si(138-140)si(143-150)si(153-155)name(59-61)name(64-71)name(74-76)set_si(157-185)set_indices(98-135)kim_convergence/run_length_control/_population.py (1)
_population_tests(151-208)kim_convergence/run_length_control/_run_length.py (1)
_get_run_length(20-35)kim_convergence/run_length_control/_trajectory.py (1)
_get_trajectory(39-93)
kim_convergence/timeseries/statistical_inefficiency.py (2)
kim_convergence/stats/tools.py (3)
auto_covariance(342-388)auto_correlate(438-484)cross_correlate(487-548)kim_convergence/err.py (2)
CRError(38-60)CRSampleSizeError(63-66)
🪛 Ruff (0.14.10)
kim_convergence/ucl/n_skart.py
116-116: Unused method argument: nskip
(ARG002)
119-119: Unused method argument: ignore_end
(ARG002)
122-122: Unused method argument: number_of_cores
(ARG002)
151-151: Avoid specifying long messages outside the exception class
(TRY003)
308-308: Unused method argument: heidel_welch_number_points
(ARG002)
309-309: Unused method argument: batch_size
(ARG002)
313-313: Unused method argument: test_size
(ARG002)
316-316: Unused method argument: train_size
(ARG002)
319-319: Unused method argument: population_standard_deviation
(ARG002)
322-322: Unused method argument: si
(ARG002)
323-323: Unused method argument: minimum_correlation_time
(ARG002)
326-326: Unused method argument: uncorrelated_sample_indices
(ARG002)
329-329: Unused method argument: sample_method
(ARG002)
361-361: Avoid specifying long messages outside the exception class
(TRY003)
364-364: Avoid specifying long messages outside the exception class
(TRY003)
456-460: Avoid specifying long messages outside the exception class
(TRY003)
605-605: Avoid specifying long messages outside the exception class
(TRY003)
kim_convergence/ucl/uncorrelated_samples.py
68-68: Unused method argument: equilibration_length_estimate
(ARG002)
69-69: Unused method argument: heidel_welch_number_points
(ARG002)
70-70: Unused method argument: batch_size
(ARG002)
71-71: Unused method argument: scale
(ARG002)
72-72: Unused method argument: with_centering
(ARG002)
73-73: Unused method argument: with_scaling
(ARG002)
74-74: Unused method argument: test_size
(ARG002)
75-75: Unused method argument: train_size
(ARG002)
136-136: Avoid specifying long messages outside the exception class
(TRY003)
141-144: Avoid specifying long messages outside the exception class
(TRY003)
147-150: Avoid specifying long messages outside the exception class
(TRY003)
414-414: Avoid specifying long messages outside the exception class
(TRY003)
kim_convergence/ucl/mser_m_y.py
82-82: Unused method argument: equilibration_length_estimate
(ARG002)
83-83: Unused method argument: heidel_welch_number_points
(ARG002)
84-84: Unused method argument: fft
(ARG002)
85-85: Unused method argument: test_size
(ARG002)
86-86: Unused method argument: train_size
(ARG002)
87-87: Unused method argument: population_standard_deviation
(ARG002)
90-90: Unused method argument: si
(ARG002)
91-91: Unused method argument: minimum_correlation_time
(ARG002)
92-92: Unused method argument: uncorrelated_sample_indices
(ARG002)
95-95: Unused method argument: sample_method
(ARG002)
126-126: Avoid specifying long messages outside the exception class
(TRY003)
131-135: Avoid specifying long messages outside the exception class
(TRY003)
331-331: Avoid specifying long messages outside the exception class
(TRY003)
kim_convergence/timeseries/utils.py
92-95: Avoid specifying long messages outside the exception class
(TRY003)
99-102: Avoid specifying long messages outside the exception class
(TRY003)
107-109: Avoid specifying long messages outside the exception class
(TRY003)
208-208: Avoid specifying long messages outside the exception class
(TRY003)
282-282: Avoid specifying long messages outside the exception class
(TRY003)
293-296: Avoid specifying long messages outside the exception class
(TRY003)
302-304: Avoid specifying long messages outside the exception class
(TRY003)
362-362: Avoid specifying long messages outside the exception class
(TRY003)
373-376: Avoid specifying long messages outside the exception class
(TRY003)
401-401: Standard pseudo-random generators are not suitable for cryptographic purposes
(S311)
451-451: Avoid specifying long messages outside the exception class
(TRY003)
462-465: Avoid specifying long messages outside the exception class
(TRY003)
kim_convergence/scale.py
95-95: Avoid specifying long messages outside the exception class
(TRY003)
147-147: Unused function argument: with_centering
(ARG001)
148-148: Unused function argument: with_scaling
(ARG001)
241-241: Avoid specifying long messages outside the exception class
(TRY003)
392-392: Avoid specifying long messages outside the exception class
(TRY003)
468-468: Avoid specifying long messages outside the exception class
(TRY003)
481-481: Avoid specifying long messages outside the exception class
(TRY003)
483-483: Avoid specifying long messages outside the exception class
(TRY003)
576-576: Avoid specifying long messages outside the exception class
(TRY003)
576-576: Use explicit conversion flag
Replace with conversion flag
(RUF010)
579-579: Avoid specifying long messages outside the exception class
(TRY003)
579-579: Use explicit conversion flag
Replace with conversion flag
(RUF010)
583-583: Avoid specifying long messages outside the exception class
(TRY003)
583-583: Use explicit conversion flag
Replace with conversion flag
(RUF010)
601-601: Avoid specifying long messages outside the exception class
(TRY003)
739-739: Avoid specifying long messages outside the exception class
(TRY003)
784-784: Unused function argument: with_centering
(ARG001)
785-785: Unused function argument: with_scaling
(ARG001)
kim_convergence/run_length_control/_convergence.py
251-253: Avoid specifying long messages outside the exception class
(TRY003)
274-278: Avoid specifying long messages outside the exception class
(TRY003)
472-475: Avoid specifying long messages outside the exception class
(TRY003)
562-564: Avoid specifying long messages outside the exception class
(TRY003)
567-570: Avoid specifying long messages outside the exception class
(TRY003)
kim_convergence/timeseries/statistical_inefficiency.py
88-88: Avoid specifying long messages outside the exception class
(TRY003)
94-97: Avoid specifying long messages outside the exception class
(TRY003)
104-104: Avoid specifying long messages outside the exception class
(TRY003)
106-106: Avoid specifying long messages outside the exception class
(TRY003)
172-172: Unused function argument: minimum_correlation_time
(ARG001)
232-232: Avoid specifying long messages outside the exception class
(TRY003)
325-325: Unused function argument: minimum_correlation_time
(ARG001)
372-374: Avoid specifying long messages outside the exception class
(TRY003)
379-382: Avoid specifying long messages outside the exception class
(TRY003)
392-392: Unused function argument: minimum_correlation_time
(ARG001)
424-426: Avoid specifying long messages outside the exception class
(TRY003)
432-432: Avoid specifying long messages outside the exception class
(TRY003)
436-439: Avoid specifying long messages outside the exception class
(TRY003)
🔇 Additional comments (22)
kim_convergence/timeseries/statistical_inefficiency.py (1)
373-373: LGTM - Past review feedback addressed.The grammar issues in error messages flagged in previous reviews have been correctly fixed. Both messages now read properly as single, grammatically correct strings.
Also applies to: 425-425
kim_convergence/ucl/n_skart.py (2)
455-463: LGTM: Excellent guard against perfect correlation.This defensive check prevents division by zero in the correlation adjustment and provides a clear, actionable error message when batches are perfectly correlated.
491-504: LGTM: Proper handling of limiting case and type safety.The beta limiting case correctly handles numerical stability when skewness is negligible, and the explicit float casting ensures the return type is a built-in float rather than a numpy scalar.
kim_convergence/ucl/uncorrelated_samples.py (1)
53-217: LGTM: Consistent internal API pattern and type safety.The
_ucl_implmethod properly handles type hints withUnion[np.ndarray, list[float]], includes API compatibility parameters (documented in the Note section), and ensures the return value is a built-in float for downstream compatibility.kim_convergence/run_length_control/_convergence.py (4)
1-40: LGTM! Well-documented module structure.The module docstring is comprehensive and clearly explains the convergence phase responsibilities. The imports are organized appropriately, and the private module declaration (
__all__ = []) correctly signals that this is an internal implementation detail.
42-161: LGTM! Clean report generation logic.The function builds a well-structured convergence report with appropriate handling of single vs. multi-variable cases. The defensive assertions (lines 88-96) document internal invariants clearly and are appropriate for a private module.
163-172: LGTM! Efficient memory-shared view.The function correctly returns a memory-shared view of the equilibrated portion, avoiding unnecessary copies. The conditional logic appropriately handles both 1D and 2D array cases.
295-534: Convergence loop logic is comprehensive.The main convergence stage handles multiple complex scenarios correctly:
- Multi-variable coordination (all must converge)
- Trajectory extension with budget management
- Population tests integration
- Graceful handling of non-convergence with final statistics
- Clear error messages for failed UCL computations (lines 470-475)
- Appropriate warnings for ill-defined relative accuracy (lines 520-523)
The for-else pattern (lines 444-449) is correctly used and well-commented.
kim_convergence/timeseries/utils.py (6)
47-111: LGTM!The function correctly handles statistical inefficiency computation and validation. Type hints have been modernized to use
list[float], and error handling is comprehensive.
114-162: LGTM!The function correctly computes uncorrelated sample indices using the statistical inefficiency stride. The past docstring typo has been addressed.
165-199: LGTM!The dispatcher function correctly routes to the appropriate sampling method with proper validation and error handling. Type signatures have been updated consistently.
Also applies to: 202-240
243-252: LGTM!The function correctly validates inputs, computes or uses provided indices, and returns uncorrelated samples. The past error message spacing issue has been addressed, and error handling has been improved with the helper function.
Also applies to: 254-273, 276-318
321-405: LGTM!The function correctly implements random sampling from uncorrelated blocks. Line 399 correctly initializes
index_s = indices[0](past review comment addressed). The S311 static analysis warning at line 401 is a false positive—randintis appropriate for statistical sampling, not cryptographic use.
408-493: LGTM!The function correctly implements block averaging for uncorrelated samples. Line 488 now correctly initializes
index_s = indices[0], addressing the past critical review comment about incorrect block ranges when custom indices don't start at zero.kim_convergence/ucl/mser_m_y.py (4)
212-213: Type assertion and cast are intentional for type safety.The combination of
assert isinstance(...)andfloat(...)ensures both static type checking (mypy) and runtime guarantee of a built-in float rather than a NumPy scalar. This is appropriate given the return type annotation.
239-279: LGTM: Confidence interval wrapper is well-structured.The function signature, type hints, and documentation are clear and comprehensive. The implementation correctly delegates to the base class method.
282-332: LGTM: Exception handling follows best practices.The function properly wraps the base class call with exception chaining (
from e), providing clear error context. The comprehensive docstring and type hints enhance maintainability.
216-236: The base class method routing pattern is correctly implemented.UCLBase.ucl()(line 342) properly delegates toself._ucl_impl()(line 376), and the wrapper functionmser_m_y_ucl()correctly invokes this public method. The inheritance chain (MSER_m_y → MSER_m → UCLBase) is sound.kim_convergence/scale.py (4)
467-475: LGTM! Past review issues correctly addressed.The previous assertion-based type checks have been properly replaced with explicit
isinstancechecks that raiseCRErrorwith clear messages. Additionally, themean_2handling now correctly mirrors the forward transform by checkingisclosebefore adding it back (lines 470-472), fixing the asymmetry that was previously flagged.Also applies to: 480-486
575-575: LGTM! Type check logic fixed.The quantile_range type validation now correctly uses
isinstance(quantile_range, (tuple, list))instead of the previous logic error (not isinstance(..., tuple) or not isinstance(..., list)) that always evaluated toTrue. This properly accepts both tuples and lists as documented.
82-82: LGTM! Improved type flexibility.Widening the
scale()method signatures to acceptUnion[np.ndarray, list]improves API usability while maintaining the internalnp.asarray()conversion. This is a backwards-compatible enhancement that aligns with common usage patterns.Also applies to: 228-228, 379-379, 589-589, 713-713
174-178: LGTM! Clear documentation of API compatibility parameters.The Notes sections clearly document that
with_centeringandwith_scalingparameters exist solely for API compatibility and are ignored by these specific scaling methods. This prevents confusion about unused parameters while maintaining a consistent interface across all scaling helpers.Also applies to: 798-803
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (6)
kim_convergence/timeseries/geweke.py (1)
58-61: Consider extracting error messages to constants (optional).Static analysis suggests moving the long error message to a constant or exception class method to improve maintainability. While the current inline message is clear and readable, extraction would make testing and reuse easier if these messages evolve.
Example pattern:
_ERR_INVALID_INTERVALS = ( "Invalid intervals for Geweke convergence analysis: " "({first}, {last}), where {first} + {last} >= 1" ) # Then in the function: raise CRError(_ERR_INVALID_INTERVALS.format(first=first, last=last))This is purely optional—the current implementation is perfectly functional.
Based on static analysis hint TRY003.
kim_convergence/scale.py (1)
574-582: Consider using!sconversion flag for consistency.Static analysis suggests replacing
str(quantile_range)with the!sconversion specifier, which is slightly more idiomatic in f-strings.🔎 Optional fix
- if not isinstance(quantile_range, (tuple, list)): - raise CRError(f"invalid quantile range: {str(quantile_range)}.") + if not isinstance(quantile_range, (tuple, list)): + raise CRError(f"invalid quantile range: {quantile_range!s}.") if len(quantile_range) != 2: - raise CRError(f"invalid quantile range: {str(quantile_range)}.") + raise CRError(f"invalid quantile range: {quantile_range!s}.") q_min, q_max = quantile_range if not 0 <= q_min <= q_max <= 100: - raise CRError(f"invalid quantile range: {str(quantile_range)}.") + raise CRError(f"invalid quantile range: {quantile_range!s}.")kim_convergence/ucl/mser_m_y.py (1)
212-213: Remove assertion; cast alone is sufficient.The assertion on line 212 could fail if
self.upper_confidence_limitis a NumPy scalar (fromupper * standard_error_of_meanwherestandard_error_of_meancomes fromx_batch.std() / sqrt(...)). Thefloat()cast on line 213 safely handles both Python floats and NumPy scalars.🔎 Proposed fix
- self.upper_confidence_limit = upper * standard_error_of_mean - assert isinstance(self.upper_confidence_limit, float) # keeps mypy happy - return float(self.upper_confidence_limit) # ensures built-in float, not numpy scalar + self.upper_confidence_limit = float(upper * standard_error_of_mean) + return self.upper_confidence_limitkim_convergence/timeseries/utils.py (2)
396-404: Consider adding validation for minimum indices length.If a user provides
uncorrelated_sample_indiceswith fewer than 2 elements,indices.size - 1could be 0 (returning an empty array, which may be unexpected) or -1 (causingnp.empty(-1)to raise aValueError).Note: The static analysis hint about
randint(S311) is a false positive here—this is statistical subsampling, not cryptographic use.🔎 Proposed validation
+ if indices.size < 2: + raise CRError( + "uncorrelated_sample_indices must contain at least 2 elements " + "to define block boundaries." + ) + random_samples = np.empty(indices.size - 1, dtype=time_series_data.dtype)
363-383: Consider extracting common index validation logic.The index validation blocks (computing indices when None, validating dimensions, checking bounds) are nearly identical between
time_series_data_uncorrelated_random_samplesandtime_series_data_uncorrelated_block_averaged_samples. A private helper could reduce duplication.🔎 Proposed helper extraction
def _resolve_and_validate_indices( time_series_data: np.ndarray, uncorrelated_sample_indices: Union[np.ndarray, list[int], None], si: Union[str, float, int, None], fft: bool, minimum_correlation_time: Optional[int], ) -> np.ndarray: """Resolve and validate uncorrelated sample indices.""" if uncorrelated_sample_indices is None: try: indices = uncorrelated_time_series_data_sample_indices( time_series_data=time_series_data, si=si, fft=fft, minimum_correlation_time=minimum_correlation_time, ) except CRError as e: raise CRError( "Failed to compute the indices of uncorrelated samples of " "the time_series_data." ) from e else: indices = np.asarray(uncorrelated_sample_indices) if indices.ndim != 1: raise CRError( "uncorrelated_sample_indices is not an array of one-dimension." ) time_series_data_size = time_series_data.size wrong_indices = np.where(indices >= time_series_data_size) if len(wrong_indices[0]) > 0: raise CRError( _out_of_bounds_error_str( bad_indices=indices[wrong_indices], size=time_series_data_size ) ) return indicesAlso applies to: 452-472
kim_convergence/timeseries/statistical_inefficiency.py (1)
161-221: Consider adding a deprecation warning for unused parameter.The
minimum_correlation_timeparameter is retained for API compatibility but is unused by this method. While the Note documents this, users may not realize their parameter is ignored.Consider adding a runtime deprecation warning:
🔎 Suggested approach
+import warnings + def geyer_r_statistical_inefficiency( x: Union[np.ndarray, list[float]], y: Union[np.ndarray, list[float], None] = None, *, fft: bool = _DEFAULT_FFT, minimum_correlation_time: Optional[int] = _DEFAULT_MINIMUM_CORRELATION_TIME, # unused (API compatibility) ) -> float: r"""Compute the statistical inefficiency. ... """ + if minimum_correlation_time is not None and minimum_correlation_time != _DEFAULT_MINIMUM_CORRELATION_TIME: + warnings.warn( + "minimum_correlation_time is not used by geyer_r_statistical_inefficiency " + "and will be ignored. This parameter is kept for API compatibility only.", + DeprecationWarning, + stacklevel=2 + )This would alert users who explicitly pass this parameter that it's being ignored.
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (11)
doc/references.rstkim_convergence/batch.pykim_convergence/run_length_control/_convergence.pykim_convergence/run_length_control/core.pykim_convergence/scale.pykim_convergence/timeseries/geweke.pykim_convergence/timeseries/statistical_inefficiency.pykim_convergence/timeseries/utils.pykim_convergence/ucl/mser_m_y.pykim_convergence/ucl/spectral/heidelberger_welch.pykim_convergence/ucl/ucl_base.py
✅ Files skipped from review due to trivial changes (1)
- doc/references.rst
🧰 Additional context used
🧬 Code graph analysis (8)
kim_convergence/ucl/mser_m_y.py (6)
kim_convergence/ucl/mser_m.py (3)
mser_m(99-249)MSER_m(252-417)_ucl_impl(323-417)kim_convergence/batch.py (1)
batch(19-146)kim_convergence/err.py (2)
CRError(38-60)CRSampleSizeError(63-66)kim_convergence/stats/randomness_test.py (1)
randomness_test(15-80)kim_convergence/stats/t_dist.py (1)
t_inv_cdf(103-195)kim_convergence/ucl/ucl_base.py (7)
name(59-61)name(64-71)name(74-76)_ucl_impl(319-344)si(138-140)si(143-150)si(153-155)
kim_convergence/timeseries/geweke.py (1)
kim_convergence/err.py (1)
CRError(38-60)
kim_convergence/batch.py (2)
kim_convergence/err.py (1)
CRError(38-60)kim_convergence/scale.py (5)
scale(82-121)scale(227-261)scale(378-447)scale(588-622)scale(712-753)
kim_convergence/timeseries/statistical_inefficiency.py (2)
kim_convergence/stats/tools.py (3)
auto_covariance(342-388)auto_correlate(438-484)cross_correlate(487-548)kim_convergence/err.py (2)
CRError(38-60)CRSampleSizeError(63-66)
kim_convergence/run_length_control/core.py (7)
kim_convergence/run_length_control/_accuracy.py (1)
_check_accuracy(28-84)kim_convergence/run_length_control/_convergence.py (3)
_convergence_message(42-160)_convergence_stage(295-544)_output_convergence_report(547-601)kim_convergence/run_length_control/_equilibration.py (1)
_equilibration_stage(147-348)kim_convergence/run_length_control/_population.py (1)
_validate_population_params(35-148)kim_convergence/run_length_control/_setup.py (1)
_setup_algorithm(33-123)kim_convergence/run_length_control/_variable_list_factory.py (1)
_make_variable_list(48-105)kim_convergence/ucl/ucl_base.py (10)
si(138-140)si(143-150)si(153-155)mean(188-190)mean(193-200)mean(203-205)std(208-210)std(213-220)std(223-225)relative_half_width_estimate(443-496)
kim_convergence/scale.py (1)
kim_convergence/err.py (1)
CRError(38-60)
kim_convergence/timeseries/utils.py (2)
kim_convergence/timeseries/statistical_inefficiency.py (1)
statistical_inefficiency(36-158)kim_convergence/err.py (1)
CRError(38-60)
kim_convergence/ucl/spectral/heidelberger_welch.py (6)
kim_convergence/ucl/ucl_base.py (8)
ucl(346-393)name(59-61)name(64-71)name(74-76)_ucl_impl(319-344)si(138-140)si(143-150)si(153-155)kim_convergence/batch.py (1)
batch(19-146)kim_convergence/err.py (3)
CRError(38-60)CRSampleSizeError(63-66)cr_warning(69-78)kim_convergence/stats/tools.py (1)
modified_periodogram(551-629)kim_convergence/utils.py (1)
train_test_split(111-164)kim_convergence/ucl/mser_m.py (1)
_ucl_impl(323-417)
🪛 Ruff (0.14.10)
kim_convergence/ucl/mser_m_y.py
82-82: Unused method argument: equilibration_length_estimate
(ARG002)
83-83: Unused method argument: heidel_welch_number_points
(ARG002)
84-84: Unused method argument: fft
(ARG002)
85-85: Unused method argument: test_size
(ARG002)
86-86: Unused method argument: train_size
(ARG002)
87-87: Unused method argument: population_standard_deviation
(ARG002)
90-90: Unused method argument: si
(ARG002)
91-91: Unused method argument: minimum_correlation_time
(ARG002)
92-92: Unused method argument: uncorrelated_sample_indices
(ARG002)
95-95: Unused method argument: sample_method
(ARG002)
126-126: Avoid specifying long messages outside the exception class
(TRY003)
131-135: Avoid specifying long messages outside the exception class
(TRY003)
331-331: Avoid specifying long messages outside the exception class
(TRY003)
kim_convergence/timeseries/geweke.py
58-61: Avoid specifying long messages outside the exception class
(TRY003)
kim_convergence/run_length_control/_convergence.py
251-253: Avoid specifying long messages outside the exception class
(TRY003)
274-278: Avoid specifying long messages outside the exception class
(TRY003)
423-426: Avoid specifying long messages outside the exception class
(TRY003)
477-480: Avoid specifying long messages outside the exception class
(TRY003)
519-522: Avoid specifying long messages outside the exception class
(TRY003)
572-574: Avoid specifying long messages outside the exception class
(TRY003)
577-580: Avoid specifying long messages outside the exception class
(TRY003)
kim_convergence/batch.py
79-79: Avoid specifying long messages outside the exception class
(TRY003)
82-82: Avoid specifying long messages outside the exception class
(TRY003)
85-85: Avoid specifying long messages outside the exception class
(TRY003)
126-129: Avoid specifying long messages outside the exception class
(TRY003)
kim_convergence/timeseries/statistical_inefficiency.py
88-88: Avoid specifying long messages outside the exception class
(TRY003)
94-97: Avoid specifying long messages outside the exception class
(TRY003)
104-104: Avoid specifying long messages outside the exception class
(TRY003)
106-106: Avoid specifying long messages outside the exception class
(TRY003)
166-166: Unused function argument: minimum_correlation_time
(ARG001)
226-226: Avoid specifying long messages outside the exception class
(TRY003)
319-319: Unused function argument: minimum_correlation_time
(ARG001)
366-368: Avoid specifying long messages outside the exception class
(TRY003)
373-376: Avoid specifying long messages outside the exception class
(TRY003)
386-386: Unused function argument: minimum_correlation_time
(ARG001)
418-420: Avoid specifying long messages outside the exception class
(TRY003)
426-426: Avoid specifying long messages outside the exception class
(TRY003)
430-433: Avoid specifying long messages outside the exception class
(TRY003)
kim_convergence/ucl/ucl_base.py
296-296: Unused method argument: batch_size
(ARG002)
297-297: Unused method argument: scale
(ARG002)
298-298: Unused method argument: with_centering
(ARG002)
299-299: Unused method argument: with_scaling
(ARG002)
490-493: Avoid specifying long messages outside the exception class
(TRY003)
kim_convergence/scale.py
95-95: Avoid specifying long messages outside the exception class
(TRY003)
147-147: Unused function argument: with_centering
(ARG001)
148-148: Unused function argument: with_scaling
(ARG001)
240-240: Avoid specifying long messages outside the exception class
(TRY003)
391-391: Avoid specifying long messages outside the exception class
(TRY003)
467-467: Avoid specifying long messages outside the exception class
(TRY003)
480-480: Avoid specifying long messages outside the exception class
(TRY003)
482-482: Avoid specifying long messages outside the exception class
(TRY003)
575-575: Avoid specifying long messages outside the exception class
(TRY003)
575-575: Use explicit conversion flag
Replace with conversion flag
(RUF010)
578-578: Avoid specifying long messages outside the exception class
(TRY003)
578-578: Use explicit conversion flag
Replace with conversion flag
(RUF010)
582-582: Avoid specifying long messages outside the exception class
(TRY003)
582-582: Use explicit conversion flag
Replace with conversion flag
(RUF010)
600-600: Avoid specifying long messages outside the exception class
(TRY003)
738-738: Avoid specifying long messages outside the exception class
(TRY003)
783-783: Unused function argument: with_centering
(ARG001)
784-784: Unused function argument: with_scaling
(ARG001)
kim_convergence/timeseries/utils.py
94-97: Avoid specifying long messages outside the exception class
(TRY003)
101-103: Avoid specifying long messages outside the exception class
(TRY003)
108-108: Avoid specifying long messages outside the exception class
(TRY003)
207-207: Avoid specifying long messages outside the exception class
(TRY003)
281-281: Avoid specifying long messages outside the exception class
(TRY003)
292-295: Avoid specifying long messages outside the exception class
(TRY003)
301-303: Avoid specifying long messages outside the exception class
(TRY003)
361-361: Avoid specifying long messages outside the exception class
(TRY003)
372-375: Avoid specifying long messages outside the exception class
(TRY003)
400-400: Standard pseudo-random generators are not suitable for cryptographic purposes
(S311)
450-450: Avoid specifying long messages outside the exception class
(TRY003)
461-464: Avoid specifying long messages outside the exception class
(TRY003)
kim_convergence/ucl/spectral/heidelberger_welch.py
322-322: Unused method argument: equilibration_length_estimate
(ARG002)
326-326: Unused method argument: population_standard_deviation
(ARG002)
329-329: Unused method argument: si
(ARG002)
330-330: Unused method argument: minimum_correlation_time
(ARG002)
331-331: Unused method argument: uncorrelated_sample_indices
(ARG002)
334-334: Unused method argument: sample_method
(ARG002)
489-489: Avoid specifying long messages outside the exception class
(TRY003)
780-780: Avoid specifying long messages outside the exception class
(TRY003)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: build (windows-latest, 3.12)
🔇 Additional comments (60)
kim_convergence/timeseries/geweke.py (1)
12-100: Excellent refactor with improved type safety and documentation.This refactor delivers substantial improvements:
- Type annotations: Explicit parameter and return types (
-> np.ndarray) improve type safety and developer experience.- Comprehensive docstring: The NumPy-style documentation clearly describes parameters, return shape, and the mathematical formula. This properly addresses the past review feedback about return type documentation.
- Input validation: The added dimensionality check (lines 72-73) ensures
xis 1D before processing, preventing silent errors downstream.- Defensive computation: The division-by-zero guard (line 96) prevents NaN propagation when variance is zero.
- Consistent return type: The function now returns
np.array(zscores)as documented, rather than a plain list.The implementation is correct and the changes align well with modern Python best practices.
kim_convergence/scale.py (11)
1-23: LGTM!Imports and
__all__declarations are well-organized and comprehensive.
26-141: LGTM!The
MinMaxScaleclass implementation is correct with proper validation, state management, and inverse transformation logic.
144-180: LGTM!The unused
with_centeringandwith_scalingparameters are appropriately documented as API compatibility placeholders. TheNotesection clearly explains they are ignored.
183-290: LGTM!The
TranslateScaleclass correctly handles centering and scaling with proper state management. The use ofcast()for type narrowing after the state validation check is appropriate.
293-324: LGTM!Clean delegation to
TranslateScale.
327-487: LGTM!The
StandardScaleclass implementation correctly handles numerical precision issues with proper forward/inverse symmetry. The previous issues withmean_2handling and assertion-based type checks have been properly addressed withisclosechecks and explicitisinstancevalidation.
490-524: LGTM!Clean delegation to
StandardScale.
654-685: LGTM!Clean delegation to
RobustScale.
688-777: LGTM!The
MaxAbsScaleclass correctly handles the edge case where the maximum absolute value is near zero by returning a copy without scaling.
780-804: LGTM!Same appropriate API compatibility pattern as
minmax_scale, with clear documentation that the parameters are ignored.
807-813: LGTM!The
scale_methodsdictionary provides a clean mapping for programmatic access to scaling functions.kim_convergence/ucl/mser_m_y.py (5)
42-63: LGTM! Typo fixed.The class docstring is clear and well-documented. The typo "trucation" → "truncation" flagged in the previous review has been corrected.
73-122: Well-documented API compatibility parameters.The expanded signature with unused keyword-only parameters maintains API compatibility with the base
_ucl_implinterface. TheNotesection clearly documents which parameters are unused, making the design intent explicit.
216-236: LGTM!The wrapper function signature and implementation are clean. Type hints are accurate, and the delegation pattern is appropriate.
239-279: LGTM!The confidence interval wrapper is well-documented with accurate type hints and clean delegation logic.
282-332: LGTM! Error wrapping adds helpful context.The function is well-documented and correctly wraps
CRErrorexceptions with additional context while preserving the original exception chain (viafrom e). This provides clearer error messages for callers.kim_convergence/timeseries/utils.py (8)
1-16: LGTM!The imports are well-organized, and the type hints using
Union[np.ndarray, list[float]]are consistent with the broader PR refactoring goals.
18-27: LGTM!The public API exports and
SAMPLING_METHODSconstant are clearly defined.
30-46: LGTM!Nice centralization of error message formatting with proper singular/plural grammar handling.
49-110: LGTM!The function correctly handles the three input types for
si(None, str, float/int) with appropriate validation and error handling. Exception chaining withfrom eproperly preserves the stack trace.
113-161: LGTM!The docstring typo from the past review has been addressed. The logic correctly computes uncorrelated sample indices by spacing them according to the statistical inefficiency value.
164-239: LGTM!Clean dispatcher function that validates the sampling method and delegates to the appropriate specialized implementation.
242-317: LGTM!The error message spacing issue from the past review has been addressed. The function correctly handles both computed and user-provided indices with proper validation.
485-492: LGTM - past issue addressed.The
index_sinitialization withindices[0]has been correctly applied as suggested in the past review. The block averaging logic is correct.The same edge case regarding minimum indices length mentioned for the random sampling function applies here as well.
kim_convergence/ucl/ucl_base.py (7)
1-39: LGTM!Clean module structure with appropriate imports and proper encapsulation via
__all__.
42-156: LGTM!The class structure with
reset(), property accessors, and theset_indices/set_simethods is clean and well-typed.
247-280: LGTM!The zero-variance handling correctly identifies constant series and sets appropriate values: SI = N (one effective sample), UCL = 0 (no uncertainty), and a single index. The early-exit pattern is clean.
286-317: LGTM!The unused parameters (
batch_size,scale,with_centering,with_scaling) are correctly documented as API compatibility placeholders. This maintains interface consistency across UCL implementations.
319-393: LGTM!Clean template method pattern:
ucl()handles the common zero-variance case, then delegates to subclass-specific_ucl_impl(). This centralizes the constant-series logic and avoids duplication across UCL implementations.
395-441: LGTM!The
ci()method correctly computes confidence interval bounds using the UCL. The assertion at line 438 is acceptable as a programming invariant sinceucl()guaranteesself.meanis set.
443-495: LGTM!The
relative_half_width_estimate()method properly guards against division by zero-mean and provides a clear error message. The assertion at line 487 is similarly justified as a programming invariant.kim_convergence/ucl/spectral/heidelberger_welch.py (6)
1-116: LGTM!Clean class structure with proper
Optionaltyping for all configurable attributes. The initialization pattern correctly inherits fromUCLBaseand sets the method name.
117-231: LGTM!The constant setup method correctly caches computed matrices and t-distribution values, avoiding redundant computation when parameters don't change. The assertions at lines 146-148 are appropriate for type narrowing.
233-310: LGTM!The getter methods provide clean read-only access to internal state. The
unset_heidel_welch_constantsmethod properly resets all attributes.
312-484: LGTM!Excellent documentation of the mathematical basis. The unused parameters are correctly documented as API compatibility placeholders, maintaining interface consistency with other UCL implementations.
485-645: LGTM!The implementation correctly follows the Heidelberger-Welch spectral method: batching, periodogram computation, polynomial fitting with model selection, and bias-corrected variance estimation. The type assertions are appropriate since the constants are lazily initialized.
648-781: LGTM!Clean wrapper functions that allow stateless usage while optionally accepting a pre-configured instance. The addition of
train_sizeparameter maintains consistency with the internal API.kim_convergence/run_length_control/_convergence.py (7)
1-39: LGTM!Clean module structure with a comprehensive docstring. The
__all__ = []properly marks this as a private implementation module.
42-160: LGTM!The message builder correctly handles both single-variable (flattened) and multi-variable (nested) report formats. The defensive assertions at lines 88-96 are appropriate for internal consistency checks on controlled inputs.
163-172: LGTM!Efficient helper that returns a memory-shared view, avoiding unnecessary copies. Correctly handles both 1D and 2D array cases.
175-292: LGTM!Well-structured helper with proper error handling: graceful handling of insufficient sample size and context-preserving re-raise for other errors. The
final_passmode correctly computes final statistics without enforcing accuracy.
295-454: LGTM!The convergence loop correctly implements the iterative accuracy-checking algorithm. The for-else pattern at line 451 is idiomatic for detecting whether all variables succeeded.
Good work addressing the previous review feedback: the assertions at lines 422-426 are now explicit runtime checks with
CRError.
456-544: LGTM!The run extension logic, trajectory dump, and final statistics computation for non-converged runs are well-implemented. The explicit check at lines 518-522 correctly addresses the previous review feedback about using runtime checks instead of assertions.
547-600: LGTM!Clean output handling supporting multiple destinations (stdout, file object, return string) and formats (txt, json, edn). The validation is appropriate.
kim_convergence/run_length_control/core.py (5)
1-54: LGTM!Clean module structure with a clear docstring and proper encapsulation via
__all__. The imports from internal helper modules maintain good separation of concerns.
57-97: LGTM!Good work addressing the previous review feedback: the mutable default
{}has been replaced withOptional[dict] = Noneat line 59.The
# type: ignore[assignment]at line 90 is acceptable since_DEFAULT_SImay have a type that doesn't strictly matchstrin the type system.
98-457: LGTM!Comprehensive documentation with clear explanations of the callback signature requirements, parameter semantics, and practical usage examples for both single and multi-variable scenarios.
459-520: LGTM!Clean stage organization with proper parameter normalization. The special handling at lines 495-498 correctly wraps
population_argsin a tuple for single-variable cases to prevent_make_variable_listfrom treating the tuple as a sequence to broadcast. The initialization at lines 519-520 completes the mutable default fix.
522-622: LGTM!Clean orchestration of the algorithm stages with proper parameter delegation. The tuple unpacking at line 523 and 554 efficiently captures multi-value returns. The final report generation and output handling complete the pipeline correctly.
kim_convergence/batch.py (5)
19-27: LGTM: Improved type hints for function signature.The changes improve type precision with
Callable[..., np.ndarray]for thefuncparameter. The less specificlisttype (vsList[float]) is acceptable sincetime_series_datais immediately converted to a numpy array at line 75.
75-91: LGTM: Consistent error message formatting.The validation logic is preserved while standardizing error messages to use double-quoted strings, aligning with the project's style guidelines.
112-122: LGTM: Explicit keyword arguments improve clarity.The refactor to use explicit
axis=anddtype=keyword arguments enhances readability while maintaining backward compatibility through theTypeErrorfallback for functions that don't acceptdtype.
131-136: LGTM: Scale validation with proper f-string syntax.The error message correctly uses string concatenation to avoid embedding backslashes in f-string expressions, which was a previous issue that has been resolved.
140-144: LGTM: Improved formatting with explicit keyword arguments.The multi-line formatting with explicit keyword parameters enhances readability and clarity.
kim_convergence/timeseries/statistical_inefficiency.py (5)
36-158: LGTM: Improved numerical clarity and consistent error messages.The changes enhance numerical stability and code clarity through:
- Explicit float literals (1.0, 0.0) in array construction
- Clear naming with
mctvariable for the minimum correlation time threshold- Explicit float type conversions
- Consistent double-quoted error messages
365-368: LGTM: Clear error message for unsupported parameter.The error message correctly explains that the split-r method splits the x time-series data and doesn't use y. The grammar issue from the previous review has been properly addressed.
480-523: LGTM: Explicit float literals improve numerical consistency.The use of explicit
2.0float literals in arithmetic operations (lines 480, 495, 500, 522) ensures consistent floating-point calculations and avoids potential integer division issues in older code paths.
535-604: LGTM: Consistent formatting and clear error messages.The
si_methodsdictionary andintegrated_auto_correlation_timefunction follow the same style improvements seen throughout the file: double-quoted strings, updated type hints, and clear error messages.
170-171: The citations[geyer1992],[geyer2011], and[mcstan]are already properly defined indoc/references.rstwith complete reference details. Sphinx will resolve these references correctly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
kim_convergence/scale.py (1)
58-65: Docstring example contains errors.Two issues in this example block:
- Line 60:
print(x)references an undefined variable; should beprint(scaled_x).- Line 63:
mms.inverse(scaled_x)uses themmsinstance that was fit on[-1., 3.], butscaled_xwas produced byminmax_scale([-1., 3., 100.]). The inverse would use incorrect scale factors.🔎 Proposed fix
>>> data = [-1., 3., 100.] - >>> scaled_x = minmax_scale(data) - >>> print(x) + >>> mms = MinMaxScale() + >>> scaled_x = mms.scale(data) + >>> print(scaled_x) [0. 0.03960396 1.] >>> x = mms.inverse(scaled_x) >>> print(x) [ -1. 3. 100.]
🧹 Nitpick comments (4)
kim_convergence/timeseries/utils.py (1)
242-280: Consider validating for negative indices.The validation checks for indices >=
time_series_data_size, but doesn't check for negative indices. While NumPy allows negative indexing, in the context of block boundaries for random/block-averaged sampling, negative indices could lead to unexpected behavior (e.g.,randint(index_s, index_e - 1)with negative values).🔎 Proposed fix to also validate negative indices
time_series_data_size = time_series_data.size - wrong_indices = np.where(indices >= time_series_data_size) + wrong_indices = np.where( + (indices < 0) | (indices >= time_series_data_size) + ) if len(wrong_indices[0]) > 0: raise CRError( _out_of_bounds_error_str( bad_indices=indices[wrong_indices], size=time_series_data_size ) )kim_convergence/scale.py (3)
144-180: LGTM - unused parameters are intentional.The
with_centeringandwith_scalingparameters are documented as existing for API signature compatibility. Consider prefixing them with_(e.g.,_with_centering) to silence linter warnings while preserving the public signature, though this is optional.
588-606: Docstring format and content inconsistency.This docstring uses NumPy-style format (
Parameters/Returns) while the rest of the file uses Google-style (Args/Returns). Additionally, the docstring referencesX : array-like, shape [n_samples, n_features]but the method only accepts 1D arrays and raisesCRErrorfor multi-dimensional input.🔎 Proposed fix
def scale(self, x: Union[np.ndarray, list]) -> np.ndarray: - r"""Compute the median and quantiles to be used for scaling. + r"""Standardize a dataset using median and quantile range. - Parameters - ---------- - X : array-like, shape [n_samples, n_features] - The data used to compute the median and quantiles - used for later scaling along the features axis. + Args: + x (array_like, 1d): The data to center and scale. + + Returns: + 1darray: Scaled dataset. + """
712-733: Docstring appears copied without adaptation.The docstring references:
X : array-like, shape [n_samples, n_features]— but method only accepts 1D arraysy : None— parameter doesn't exist in the method signature:meth:\fit`— this class has nofit` method- Returns
self : object— but the method returnsnp.ndarray🔎 Proposed fix
def scale(self, x: Union[np.ndarray, list]) -> np.ndarray: - r""" - Online computation of max absolute value of X for later scaling. - - All of X is processed as a single batch. This is intended for cases - when :meth:`fit` is not feasible due to very large number of - `n_samples` or because X is read from a continuous stream. - - Parameters - ---------- - X : {array-like, sparse matrix}, shape [n_samples, n_features] - The data used to compute the mean and standard deviation - used for later scaling along the features axis. - - y : None - Ignored. - - Returns - ------- - self : object - Transformer instance. + r"""Scale dataset by its maximum absolute value. + Args: + x (array_like, 1d): Time series data. + + Returns: + 1darray: Scaled dataset in the [-1, 1] range. + """
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
kim_convergence/scale.pykim_convergence/timeseries/utils.py
🧰 Additional context used
🧬 Code graph analysis (2)
kim_convergence/timeseries/utils.py (2)
kim_convergence/timeseries/statistical_inefficiency.py (1)
statistical_inefficiency(36-158)kim_convergence/err.py (1)
CRError(38-60)
kim_convergence/scale.py (1)
kim_convergence/err.py (1)
CRError(38-60)
🪛 Ruff (0.14.10)
kim_convergence/timeseries/utils.py
94-97: Avoid specifying long messages outside the exception class
(TRY003)
101-103: Avoid specifying long messages outside the exception class
(TRY003)
108-108: Avoid specifying long messages outside the exception class
(TRY003)
207-207: Avoid specifying long messages outside the exception class
(TRY003)
259-262: Avoid specifying long messages outside the exception class
(TRY003)
266-268: Avoid specifying long messages outside the exception class
(TRY003)
322-322: Avoid specifying long messages outside the exception class
(TRY003)
378-378: Avoid specifying long messages outside the exception class
(TRY003)
389-392: Avoid specifying long messages outside the exception class
(TRY003)
398-398: Standard pseudo-random generators are not suitable for cryptographic purposes
(S311)
448-448: Avoid specifying long messages outside the exception class
(TRY003)
459-462: Avoid specifying long messages outside the exception class
(TRY003)
kim_convergence/scale.py
95-95: Avoid specifying long messages outside the exception class
(TRY003)
147-147: Unused function argument: with_centering
(ARG001)
148-148: Unused function argument: with_scaling
(ARG001)
240-240: Avoid specifying long messages outside the exception class
(TRY003)
391-391: Avoid specifying long messages outside the exception class
(TRY003)
467-467: Avoid specifying long messages outside the exception class
(TRY003)
480-480: Avoid specifying long messages outside the exception class
(TRY003)
482-482: Avoid specifying long messages outside the exception class
(TRY003)
575-575: Avoid specifying long messages outside the exception class
(TRY003)
578-578: Avoid specifying long messages outside the exception class
(TRY003)
582-582: Avoid specifying long messages outside the exception class
(TRY003)
600-600: Avoid specifying long messages outside the exception class
(TRY003)
738-738: Avoid specifying long messages outside the exception class
(TRY003)
783-783: Unused function argument: with_centering
(ARG001)
784-784: Unused function argument: with_scaling
(ARG001)
🔇 Additional comments (14)
kim_convergence/timeseries/utils.py (8)
1-27: LGTM!The module setup, imports, and exports are well-organized. The consolidation of default imports from
kim_convergence._defaultimproves maintainability, and the__all__exports are properly defined.
30-46: LGTM!The helper function correctly handles singular/plural grammar for error messages and provides clear, informative output for debugging out-of-bounds index issues.
49-110: LGTM!The function properly handles all input types (None, str, float, int), validates method names against the registry, and chains exceptions with context for debugging. The error messages are appropriately descriptive.
113-161: LGTM!The index computation logic correctly generates uncorrelated sample indices by spacing them at intervals of the statistical inefficiency value. The use of
ceil()ensures proper block boundaries, and the filtering ensures all indices are within valid bounds.
164-239: LGTM!The dispatcher function properly validates the sampling method and routes to the appropriate implementation. The control flow is clean with early returns for
uncorrelatedandrandommethods, withblock_averagedas the implicit final case.
283-334: LGTM!The function cleanly delegates index resolution to the new helper and performs straightforward array indexing to extract samples. The input validation and implementation are correct.
337-402: LGTM!The random sampling implementation correctly iterates through blocks and extracts a random sample from each. The use of
random.randintis appropriate here since this is statistical sampling, not cryptographic—the static analysis warning (S311) is a false positive for this use case.
405-471: LGTM!The block averaging implementation is correct. The past review's fix for initializing
index_s = indices[0]has been properly applied, ensuring correct block boundaries when custom indices are provided.kim_convergence/scale.py (6)
1-23: LGTM!The imports are appropriate for the type annotations used throughout the file, and
__all__properly exports the public API surface.
183-290: LGTM!The
TranslateScaleclass correctly handles centering and scaling operations. The use ofcast()for type narrowing after None checks is appropriate, and the inverse method's guard condition properly ensuresscale()was called first.
465-487: Properly addressed prior review feedback.The inverse transformation now correctly:
- Uses runtime
isinstancechecks instead of assertions (lines 466-467, 479-482)- Applies the
isclose()check formean_2(lines 469-471) to mirror the forward pass behaviorThe forward/inverse symmetry is now correct.
574-575: Properly addressed prior review feedback.The type check for
quantile_rangenow correctly usesisinstance(quantile_range, (tuple, list)), fixing the logic error from the previous review.
780-804: LGTM!Same pattern as
minmax_scale— the unused parameters are documented as existing for API compatibility across all scaling helpers.
807-813: LGTM!The
scale_methodsdictionary provides a clean runtime lookup for all scaling functions, enabling dynamic dispatch by method name.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (1)
doc/api.rst (1)
60-96: Verify heading level consistency for documentation structure.The RST heading underlines appear inconsistent in length. While RST allows flexible heading markers, maintaining consistent underline lengths for the same heading level improves readability and reduces confusion.
For example:
- Line 33:
batchuses 5 tildes (~~~~~)- Line 64:
minmax_scaleuses 12 tildes (~~~~~~~~~~~~)Both appear to be at the same structural level (subsections under "Utility Functions"). Consider standardizing the underline lengths to match the text width or use a consistent length for each heading level.
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
doc/api.rstkim_convergence/scale.py
🧰 Additional context used
🧬 Code graph analysis (1)
kim_convergence/scale.py (1)
kim_convergence/err.py (1)
CRError(38-60)
🪛 Ruff (0.14.10)
kim_convergence/scale.py
97-97: Avoid specifying long messages outside the exception class
(TRY003)
149-149: Unused function argument: with_centering
(ARG001)
150-150: Unused function argument: with_scaling
(ARG001)
240-240: Avoid specifying long messages outside the exception class
(TRY003)
391-391: Avoid specifying long messages outside the exception class
(TRY003)
467-467: Avoid specifying long messages outside the exception class
(TRY003)
480-480: Avoid specifying long messages outside the exception class
(TRY003)
482-482: Avoid specifying long messages outside the exception class
(TRY003)
575-575: Avoid specifying long messages outside the exception class
(TRY003)
578-578: Avoid specifying long messages outside the exception class
(TRY003)
582-582: Avoid specifying long messages outside the exception class
(TRY003)
601-601: Avoid specifying long messages outside the exception class
(TRY003)
731-731: Avoid specifying long messages outside the exception class
(TRY003)
776-776: Unused function argument: with_centering
(ARG001)
777-777: Unused function argument: with_scaling
(ARG001)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: build (windows-latest, 3.11)
🔇 Additional comments (8)
kim_convergence/scale.py (8)
5-5: LGTM: Type imports and public API declarations.The addition of
castandUnionfrom typing enables better type narrowing throughout the module. The__all__list is now consistently formatted with double-quoted strings and alphabetically ordered.Also applies to: 11-23
26-180: LGTM: MinMaxScale implementation with API compatibility parameters.The class and wrapper function are well-implemented. The unused parameters
with_centeringandwith_scaling(lines 149-150) are intentionally included for API compatibility with other scaling methods, as documented in the Note at lines 175-177.
183-324: LGTM: TranslateScale with proper type narrowing.The use of
cast(float, ...)at lines 280 and 288 appropriately narrows types in the inverse transformation, enabling type checkers to verify the arithmetic operations.
327-524: LGTM: StandardScale with properly fixed inverse transformation.The previous issues have been correctly addressed:
- Assertions replaced with explicit
isinstancechecks (lines 466-467, 479-482) that provide clear error messages- The
mean_2handling in the inverse transformation (lines 469-471) now correctly checksisclosebefore adding it back, maintaining symmetry with the forward pass at lines 444-445
527-686: LGTM: RobustScale with corrected type validation.The critical issue with
quantile_rangetype checking has been properly fixed at lines 574-575. The condition now correctly accepts both tuples and lists usingisinstance(quantile_range, (tuple, list))instead of the previous always-True logic error.
689-795: LGTM: MaxAbsScale with API compatibility parameters.Consistent with
minmax_scale, the unused parameterswith_centeringandwith_scaling(lines 776-777) are intentionally included for API compatibility, as documented at lines 790-792.
798-804: LGTM: Scale methods registry.The
scale_methodsdictionary has been updated with consistent double-quoted string literals while preserving all functional mappings.
97-97: Static analysis hints (TRY003) are false positives for this context.The Ruff warnings about "long messages outside the exception class" (TRY003) are style suggestions rather than correctness issues. The current approach of inline error messages is appropriate here because:
- Each error is highly contextual and specific to the validation point
- The messages include dynamic values (e.g.,
{quantile_range!s})- Extracting them to class attributes would reduce clarity and increase maintenance burden
Also applies to: 240-240, 391-391, 467-467, 480-480, 482-482, 575-575, 578-578, 582-582, 601-601, 731-731
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
kim_convergence/stats/zero_rc_bounds.py (1)
55-99: Good refactoring: removed unnecessary deepcopy for primitives.The constructor has been improved in two ways:
- Multiline signature enhances readability
- Lines 92-98 now use direct assignment instead of
deepcopy()for float primitivesSince Python floats are immutable,
deepcopy()was unnecessary overhead. This change improves performance without affecting behavior.
🧹 Nitpick comments (5)
kim_convergence/stats/zero_rc_bounds.py (1)
127-179: Optional: Consider extracting error messages to exception classes.The static analyzer flags the detailed error messages (TRY003). While the current messages are informative and helpful, you could optionally extract them into custom exception classes if you want to follow stricter exception handling patterns.
However, the current approach provides excellent diagnostic information inline, which aids debugging. This is a stylistic preference rather than a functional issue.
Also applies to: 216-221, 254-259, 304-307
kim_convergence/stats/beta_dist.py (1)
141-144: Optional: Consider extracting error messages to exception classes.Static analysis suggests moving the formatted error message to a dedicated exception class or module-level constant to comply with TRY003. This is a style preference rather than a functional issue and can be deferred.
kim_convergence/stats/tools.py (1)
231-231: Optional: Broad exception handling is acceptable here.Static analysis flags catching
Exception, but this is intentional and appropriate for subprocess communication where any error must be serialized and propagated through the queue. The patternexcept Exception as e: q.put(CRError(str(e)))ensures the parent process receives error information regardless of the exception type.Also applies to: 276-276
kim_convergence/stats/nonnormal_test.py (1)
405-410: Optional: Consider extracting error messages for TRY003 compliance.Static analysis suggests avoiding inline formatted error messages in exception constructors. While this is a style preference that doesn't affect functionality, extracting messages to constants or exception subclasses could improve maintainability. This can be addressed in a future refactoring pass.
Also applies to: 532-532, 551-551, 653-653, 681-681, 686-686, 747-747, 772-772, 829-829, 837-837, 860-860, 865-865
kim_convergence/ucl/spectral/heidelberger_welch.py (1)
488-647: LGTM: Correct implementation with improved error handling.The addition of
cr_warning(line 513) before raisingCRSampleSizeErroris valuable for diagnostics. The runtime assertions throughout (lines 506, 550-553, 645) are necessary for mypy type narrowing.The method is lengthy (~335 lines including signature and docstring), but this is justified by the comprehensive documentation and the cohesive algorithm implementation. The train/test split logic (lines 556-609) is appropriately conditional and correctly implements model selection.
💡 Optional refactor: Extract polynomial fitting logic
If desired, the polynomial fitting logic (lines 556-609) could be extracted into a private helper method to reduce method length:
def _fit_polynomials_with_split( self, avg_period_lg, ind_train, ind_test ) -> tuple[float, float, float]: """Fit polynomials and return test errors.""" # ... polynomial fitting logic ... return eps1, eps2, eps3However, the current implementation is clear and maintainable as-is.
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (38)
doc/api.rstdoc/getting_started.rstdoc/modules/run_length_control.rstdoc/modules/stats.rstdoc/modules/ucl.rstdoc/theory.rstdoc/troubleshooting.rstkim_convergence/batch.pykim_convergence/err.pykim_convergence/outlier.pykim_convergence/run_length_control/_accuracy.pykim_convergence/run_length_control/_convergence.pykim_convergence/run_length_control/_equilibration.pykim_convergence/run_length_control/_population.pykim_convergence/run_length_control/_setup.pykim_convergence/run_length_control/_variable_list_factory.pykim_convergence/run_length_control/core.pykim_convergence/scale.pykim_convergence/stats/beta_dist.pykim_convergence/stats/nonnormal_test.pykim_convergence/stats/normal_dist.pykim_convergence/stats/normal_test.pykim_convergence/stats/randomness_test.pykim_convergence/stats/t_dist.pykim_convergence/stats/tools.pykim_convergence/stats/zero_rc.pykim_convergence/stats/zero_rc_bounds.pykim_convergence/timeseries/equilibration_length.pykim_convergence/timeseries/geweke.pykim_convergence/timeseries/statistical_inefficiency.pykim_convergence/timeseries/utils.pykim_convergence/ucl/mser_m.pykim_convergence/ucl/mser_m_y.pykim_convergence/ucl/n_skart.pykim_convergence/ucl/spectral/heidelberger_welch.pykim_convergence/ucl/ucl_base.pykim_convergence/ucl/uncorrelated_samples.pykim_convergence/utils.py
✅ Files skipped from review due to trivial changes (1)
- doc/api.rst
🚧 Files skipped from review as they are similar to previous changes (2)
- doc/modules/stats.rst
- doc/getting_started.rst
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2026-01-04T04:00:25.216Z
Learnt from: yafshar
Repo: openkim/kim-convergence PR: 6
File: kim_convergence/ucl/n_skart.py:468-476
Timestamp: 2026-01-04T04:00:25.216Z
Learning: In kim_convergence/ucl/n_skart.py, the formula for spaced_x_batch_size (line 474-476) intentionally follows the original N-SKART paper and should not be replaced with spaced_x_batch.size, even though they may produce different values.
Applied to files:
kim_convergence/ucl/n_skart.py
🧬 Code graph analysis (16)
kim_convergence/run_length_control/_setup.py (3)
kim_convergence/err.py (3)
CRError(40-62)cr_check(104-161)cr_warning(71-80)kim_convergence/ucl/ucl_base.py (5)
ucl(339-386)UCLBase(42-489)name(59-61)name(64-71)name(74-76)kim_convergence/run_length_control/_trajectory.py (1)
_check_get_trajectory(27-36)
kim_convergence/timeseries/statistical_inefficiency.py (2)
kim_convergence/stats/tools.py (3)
auto_covariance(342-389)auto_correlate(439-485)cross_correlate(488-549)kim_convergence/err.py (2)
CRError(40-62)CRSampleSizeError(65-68)
kim_convergence/ucl/n_skart.py (5)
kim_convergence/ucl/ucl_base.py (10)
name(59-61)name(64-71)name(74-76)si(136-138)si(141-147)si(150-152)_ucl_impl(312-337)ucl(339-386)ci(388-434)relative_half_width_estimate(436-489)kim_convergence/err.py (3)
CRError(40-62)CRSampleSizeError(65-68)cr_warning(71-80)kim_convergence/stats/tools.py (1)
skew(796-839)kim_convergence/stats/randomness_test.py (1)
randomness_test(15-80)kim_convergence/stats/beta_dist.py (1)
beta(17-37)
kim_convergence/utils.py (1)
kim_convergence/err.py (1)
CRError(40-62)
kim_convergence/run_length_control/core.py (7)
kim_convergence/run_length_control/_accuracy.py (1)
_check_accuracy(28-83)kim_convergence/run_length_control/_convergence.py (3)
_convergence_message(42-158)_convergence_stage(296-554)_output_convergence_report(557-608)kim_convergence/run_length_control/_equilibration.py (1)
_equilibration_stage(147-344)kim_convergence/run_length_control/_population.py (1)
_validate_population_params(35-146)kim_convergence/run_length_control/_setup.py (1)
_setup_algorithm(33-119)kim_convergence/run_length_control/_variable_list_factory.py (1)
_make_variable_list(48-103)kim_convergence/ucl/ucl_base.py (10)
si(136-138)si(141-147)si(150-152)mean(184-186)mean(189-195)mean(198-200)std(203-205)std(208-214)std(217-219)relative_half_width_estimate(436-489)
kim_convergence/stats/normal_dist.py (1)
kim_convergence/err.py (1)
CRError(40-62)
kim_convergence/outlier.py (1)
kim_convergence/err.py (1)
CRError(40-62)
kim_convergence/stats/zero_rc_bounds.py (2)
kim_convergence/stats/zero_rc.py (1)
zero(96-241)kim_convergence/err.py (1)
CRError(40-62)
kim_convergence/batch.py (2)
kim_convergence/err.py (1)
CRError(40-62)kim_convergence/scale.py (5)
scale(83-122)scale(226-260)scale(376-445)scale(585-620)scale(709-742)
kim_convergence/timeseries/geweke.py (1)
kim_convergence/err.py (1)
CRError(40-62)
kim_convergence/stats/nonnormal_test.py (1)
kim_convergence/err.py (3)
CRError(40-62)CRSampleSizeError(65-68)cr_check(104-161)
kim_convergence/stats/beta_dist.py (1)
kim_convergence/err.py (1)
CRError(40-62)
kim_convergence/timeseries/utils.py (2)
kim_convergence/timeseries/statistical_inefficiency.py (1)
statistical_inefficiency(36-157)kim_convergence/err.py (1)
CRError(40-62)
kim_convergence/run_length_control/_accuracy.py (1)
kim_convergence/err.py (2)
CRError(40-62)cr_check(104-161)
kim_convergence/run_length_control/_population.py (3)
kim_convergence/err.py (1)
CRError(40-62)kim_convergence/stats/nonnormal_test.py (2)
check_population_cdf_args(394-440)levene_test(556-688)kim_convergence/stats/normal_test.py (2)
chi_square_test(62-103)t_test(21-59)
kim_convergence/run_length_control/_variable_list_factory.py (1)
kim_convergence/err.py (2)
CRError(40-62)cr_warning(71-80)
🪛 Ruff (0.14.10)
kim_convergence/run_length_control/_setup.py
111-111: Avoid specifying long messages outside the exception class
(TRY003)
kim_convergence/stats/t_dist.py
23-23: Avoid specifying long messages outside the exception class
(TRY003)
kim_convergence/timeseries/statistical_inefficiency.py
87-87: Avoid specifying long messages outside the exception class
(TRY003)
93-96: Avoid specifying long messages outside the exception class
(TRY003)
103-103: Avoid specifying long messages outside the exception class
(TRY003)
105-105: Avoid specifying long messages outside the exception class
(TRY003)
165-165: Unused function argument: minimum_correlation_time
(ARG001)
226-226: Avoid specifying long messages outside the exception class
(TRY003)
319-319: Unused function argument: minimum_correlation_time
(ARG001)
367-369: Avoid specifying long messages outside the exception class
(TRY003)
374-377: Avoid specifying long messages outside the exception class
(TRY003)
387-387: Unused function argument: minimum_correlation_time
(ARG001)
420-422: Avoid specifying long messages outside the exception class
(TRY003)
428-428: Avoid specifying long messages outside the exception class
(TRY003)
432-435: Avoid specifying long messages outside the exception class
(TRY003)
kim_convergence/run_length_control/_convergence.py
252-254: Avoid specifying long messages outside the exception class
(TRY003)
275-279: Avoid specifying long messages outside the exception class
(TRY003)
433-436: Avoid specifying long messages outside the exception class
(TRY003)
487-490: Avoid specifying long messages outside the exception class
(TRY003)
529-532: Avoid specifying long messages outside the exception class
(TRY003)
579-581: Avoid specifying long messages outside the exception class
(TRY003)
584-587: Avoid specifying long messages outside the exception class
(TRY003)
kim_convergence/ucl/n_skart.py
114-114: Unused method argument: nskip
(ARG002)
117-117: Unused method argument: ignore_end
(ARG002)
120-120: Unused method argument: number_of_cores
(ARG002)
150-150: Avoid specifying long messages outside the exception class
(TRY003)
307-307: Unused method argument: heidel_welch_number_points
(ARG002)
308-308: Unused method argument: batch_size
(ARG002)
312-312: Unused method argument: test_size
(ARG002)
315-315: Unused method argument: train_size
(ARG002)
318-318: Unused method argument: population_standard_deviation
(ARG002)
321-321: Unused method argument: si
(ARG002)
322-322: Unused method argument: minimum_correlation_time
(ARG002)
325-325: Unused method argument: uncorrelated_sample_indices
(ARG002)
328-328: Unused method argument: sample_method
(ARG002)
360-360: Avoid specifying long messages outside the exception class
(TRY003)
363-363: Avoid specifying long messages outside the exception class
(TRY003)
455-459: Avoid specifying long messages outside the exception class
(TRY003)
603-603: Avoid specifying long messages outside the exception class
(TRY003)
kim_convergence/err.py
86-86: Avoid specifying long messages outside the exception class
(TRY003)
95-98: Avoid specifying long messages outside the exception class
(TRY003)
139-141: Avoid specifying long messages outside the exception class
(TRY003)
kim_convergence/ucl/mser_m.py
69-72: Avoid specifying long messages outside the exception class
(TRY003)
76-79: Avoid specifying long messages outside the exception class
(TRY003)
82-85: Avoid specifying long messages outside the exception class
(TRY003)
88-91: Avoid specifying long messages outside the exception class
(TRY003)
172-172: Avoid specifying long messages outside the exception class
(TRY003)
178-181: Avoid specifying long messages outside the exception class
(TRY003)
185-185: Avoid specifying long messages outside the exception class
(TRY003)
188-188: Avoid specifying long messages outside the exception class
(TRY003)
288-288: Unused method argument: number_of_cores
(ARG002)
290-290: Unused method argument: nskip
(ARG002)
328-328: Unused method argument: equilibration_length_estimate
(ARG002)
329-329: Unused method argument: heidel_welch_number_points
(ARG002)
330-330: Unused method argument: fft
(ARG002)
331-331: Unused method argument: test_size
(ARG002)
332-332: Unused method argument: train_size
(ARG002)
333-333: Unused method argument: population_standard_deviation
(ARG002)
336-336: Unused method argument: si
(ARG002)
337-337: Unused method argument: minimum_correlation_time
(ARG002)
338-338: Unused method argument: uncorrelated_sample_indices
(ARG002)
341-341: Unused method argument: sample_method
(ARG002)
373-373: Avoid specifying long messages outside the exception class
(TRY003)
376-379: Avoid specifying long messages outside the exception class
(TRY003)
532-532: Avoid specifying long messages outside the exception class
(TRY003)
kim_convergence/utils.py
41-41: Avoid specifying long messages outside the exception class
(TRY003)
46-49: Avoid specifying long messages outside the exception class
(TRY003)
55-55: Avoid specifying long messages outside the exception class
(TRY003)
58-58: Avoid specifying long messages outside the exception class
(TRY003)
60-60: Avoid specifying long messages outside the exception class
(TRY003)
73-73: Avoid specifying long messages outside the exception class
(TRY003)
93-93: Avoid specifying long messages outside the exception class
(TRY003)
98-98: Avoid specifying long messages outside the exception class
(TRY003)
103-106: Avoid specifying long messages outside the exception class
(TRY003)
108-108: Avoid specifying long messages outside the exception class
(TRY003)
110-110: Avoid specifying long messages outside the exception class
(TRY003)
kim_convergence/outlier.py
86-86: Avoid specifying long messages outside the exception class
(TRY003)
89-92: Avoid specifying long messages outside the exception class
(TRY003)
101-101: Avoid specifying long messages outside the exception class
(TRY003)
kim_convergence/timeseries/equilibration_length.py
86-89: Avoid specifying long messages outside the exception class
(TRY003)
93-96: Avoid specifying long messages outside the exception class
(TRY003)
98-101: Avoid specifying long messages outside the exception class
(TRY003)
106-109: Avoid specifying long messages outside the exception class
(TRY003)
113-116: Avoid specifying long messages outside the exception class
(TRY003)
120-123: Avoid specifying long messages outside the exception class
(TRY003)
127-130: Avoid specifying long messages outside the exception class
(TRY003)
144-144: Unused function argument: batch_size
(ARG001)
145-145: Unused function argument: scale
(ARG001)
146-146: Unused function argument: with_centering
(ARG001)
147-147: Unused function argument: with_scaling
(ARG001)
188-188: Avoid specifying long messages outside the exception class
(TRY003)
202-202: Avoid specifying long messages outside the exception class
(TRY003)
208-208: Avoid specifying long messages outside the exception class
(TRY003)
213-213: Avoid specifying long messages outside the exception class
(TRY003)
kim_convergence/stats/zero_rc_bounds.py
127-130: Avoid specifying long messages outside the exception class
(TRY003)
151-156: Avoid specifying long messages outside the exception class
(TRY003)
157-162: Avoid specifying long messages outside the exception class
(TRY003)
169-174: Avoid specifying long messages outside the exception class
(TRY003)
175-179: Avoid specifying long messages outside the exception class
(TRY003)
216-221: Avoid specifying long messages outside the exception class
(TRY003)
254-259: Avoid specifying long messages outside the exception class
(TRY003)
304-307: Avoid specifying long messages outside the exception class
(TRY003)
kim_convergence/ucl/mser_m_y.py
82-82: Unused method argument: equilibration_length_estimate
(ARG002)
83-83: Unused method argument: heidel_welch_number_points
(ARG002)
84-84: Unused method argument: fft
(ARG002)
85-85: Unused method argument: test_size
(ARG002)
86-86: Unused method argument: train_size
(ARG002)
87-87: Unused method argument: population_standard_deviation
(ARG002)
90-90: Unused method argument: si
(ARG002)
91-91: Unused method argument: minimum_correlation_time
(ARG002)
92-92: Unused method argument: uncorrelated_sample_indices
(ARG002)
95-95: Unused method argument: sample_method
(ARG002)
127-127: Avoid specifying long messages outside the exception class
(TRY003)
132-136: Avoid specifying long messages outside the exception class
(TRY003)
332-332: Avoid specifying long messages outside the exception class
(TRY003)
kim_convergence/batch.py
78-78: Avoid specifying long messages outside the exception class
(TRY003)
81-81: Avoid specifying long messages outside the exception class
(TRY003)
84-84: Avoid specifying long messages outside the exception class
(TRY003)
125-128: Avoid specifying long messages outside the exception class
(TRY003)
kim_convergence/timeseries/geweke.py
49-52: Avoid specifying long messages outside the exception class
(TRY003)
kim_convergence/ucl/ucl_base.py
289-289: Unused method argument: batch_size
(ARG002)
290-290: Unused method argument: scale
(ARG002)
291-291: Unused method argument: with_centering
(ARG002)
292-292: Unused method argument: with_scaling
(ARG002)
483-486: Avoid specifying long messages outside the exception class
(TRY003)
kim_convergence/stats/tools.py
126-126: Avoid specifying long messages outside the exception class
(TRY003)
130-130: Avoid specifying long messages outside the exception class
(TRY003)
231-231: Do not catch blind exception: Exception
(BLE001)
254-254: Avoid specifying long messages outside the exception class
(TRY003)
259-259: Avoid specifying long messages outside the exception class
(TRY003)
276-276: Do not catch blind exception: Exception
(BLE001)
296-296: Avoid specifying long messages outside the exception class
(TRY003)
301-301: Avoid specifying long messages outside the exception class
(TRY003)
316-316: Avoid specifying long messages outside the exception class
(TRY003)
319-319: Avoid specifying long messages outside the exception class
(TRY003)
322-325: Avoid specifying long messages outside the exception class
(TRY003)
331-331: Avoid specifying long messages outside the exception class
(TRY003)
334-337: Avoid specifying long messages outside the exception class
(TRY003)
475-475: Avoid specifying long messages outside the exception class
(TRY003)
478-478: Avoid specifying long messages outside the exception class
(TRY003)
539-539: Avoid specifying long messages outside the exception class
(TRY003)
542-542: Avoid specifying long messages outside the exception class
(TRY003)
665-665: Avoid specifying long messages outside the exception class
(TRY003)
703-703: Avoid specifying long messages outside the exception class
(TRY003)
728-728: Avoid specifying long messages outside the exception class
(TRY003)
731-731: Avoid specifying long messages outside the exception class
(TRY003)
734-734: Avoid specifying long messages outside the exception class
(TRY003)
785-785: Avoid specifying long messages outside the exception class
(TRY003)
kim_convergence/scale.py
96-96: Avoid specifying long messages outside the exception class
(TRY003)
135-138: Avoid specifying long messages outside the exception class
(TRY003)
148-148: Unused function argument: with_centering
(ARG001)
149-149: Unused function argument: with_scaling
(ARG001)
239-239: Avoid specifying long messages outside the exception class
(TRY003)
273-276: Avoid specifying long messages outside the exception class
(TRY003)
389-389: Avoid specifying long messages outside the exception class
(TRY003)
458-461: Avoid specifying long messages outside the exception class
(TRY003)
465-465: Avoid specifying long messages outside the exception class
(TRY003)
478-478: Avoid specifying long messages outside the exception class
(TRY003)
480-480: Avoid specifying long messages outside the exception class
(TRY003)
572-572: Avoid specifying long messages outside the exception class
(TRY003)
575-575: Avoid specifying long messages outside the exception class
(TRY003)
579-579: Avoid specifying long messages outside the exception class
(TRY003)
598-598: Avoid specifying long messages outside the exception class
(TRY003)
633-636: Avoid specifying long messages outside the exception class
(TRY003)
727-727: Avoid specifying long messages outside the exception class
(TRY003)
772-772: Unused function argument: with_centering
(ARG001)
773-773: Unused function argument: with_scaling
(ARG001)
kim_convergence/stats/nonnormal_test.py
405-410: Avoid specifying long messages outside the exception class
(TRY003)
532-532: Avoid specifying long messages outside the exception class
(TRY003)
551-551: Avoid specifying long messages outside the exception class
(TRY003)
653-653: Avoid specifying long messages outside the exception class
(TRY003)
681-681: Avoid specifying long messages outside the exception class
(TRY003)
686-686: Avoid specifying long messages outside the exception class
(TRY003)
747-747: Avoid specifying long messages outside the exception class
(TRY003)
772-772: Avoid specifying long messages outside the exception class
(TRY003)
829-829: Avoid specifying long messages outside the exception class
(TRY003)
837-837: Avoid specifying long messages outside the exception class
(TRY003)
860-860: Avoid specifying long messages outside the exception class
(TRY003)
865-865: Avoid specifying long messages outside the exception class
(TRY003)
kim_convergence/ucl/uncorrelated_samples.py
68-68: Unused method argument: equilibration_length_estimate
(ARG002)
69-69: Unused method argument: heidel_welch_number_points
(ARG002)
70-70: Unused method argument: batch_size
(ARG002)
71-71: Unused method argument: scale
(ARG002)
72-72: Unused method argument: with_centering
(ARG002)
73-73: Unused method argument: with_scaling
(ARG002)
74-74: Unused method argument: test_size
(ARG002)
75-75: Unused method argument: train_size
(ARG002)
136-136: Avoid specifying long messages outside the exception class
(TRY003)
141-144: Avoid specifying long messages outside the exception class
(TRY003)
147-150: Avoid specifying long messages outside the exception class
(TRY003)
413-413: Avoid specifying long messages outside the exception class
(TRY003)
kim_convergence/stats/beta_dist.py
141-144: Avoid specifying long messages outside the exception class
(TRY003)
kim_convergence/ucl/spectral/heidelberger_welch.py
322-322: Unused method argument: equilibration_length_estimate
(ARG002)
326-326: Unused method argument: population_standard_deviation
(ARG002)
329-329: Unused method argument: si
(ARG002)
330-330: Unused method argument: minimum_correlation_time
(ARG002)
331-331: Unused method argument: uncorrelated_sample_indices
(ARG002)
334-334: Unused method argument: sample_method
(ARG002)
491-491: Avoid specifying long messages outside the exception class
(TRY003)
781-781: Avoid specifying long messages outside the exception class
(TRY003)
kim_convergence/timeseries/utils.py
94-97: Avoid specifying long messages outside the exception class
(TRY003)
101-103: Avoid specifying long messages outside the exception class
(TRY003)
108-108: Avoid specifying long messages outside the exception class
(TRY003)
207-207: Avoid specifying long messages outside the exception class
(TRY003)
259-262: Avoid specifying long messages outside the exception class
(TRY003)
266-268: Avoid specifying long messages outside the exception class
(TRY003)
322-322: Avoid specifying long messages outside the exception class
(TRY003)
378-378: Avoid specifying long messages outside the exception class
(TRY003)
389-392: Avoid specifying long messages outside the exception class
(TRY003)
398-398: Standard pseudo-random generators are not suitable for cryptographic purposes
(S311)
447-447: Avoid specifying long messages outside the exception class
(TRY003)
458-461: Avoid specifying long messages outside the exception class
(TRY003)
kim_convergence/run_length_control/_accuracy.py
47-47: Avoid specifying long messages outside the exception class
(TRY003)
49-49: Avoid specifying long messages outside the exception class
(TRY003)
57-60: Avoid specifying long messages outside the exception class
(TRY003)
72-75: Avoid specifying long messages outside the exception class
(TRY003)
80-83: Avoid specifying long messages outside the exception class
(TRY003)
kim_convergence/run_length_control/_population.py
65-67: Avoid specifying long messages outside the exception class
(TRY003)
84-86: Avoid specifying long messages outside the exception class
(TRY003)
90-94: Avoid specifying long messages outside the exception class
(TRY003)
96-100: Avoid specifying long messages outside the exception class
(TRY003)
104-107: Avoid specifying long messages outside the exception class
(TRY003)
110-113: Avoid specifying long messages outside the exception class
(TRY003)
119-122: Avoid specifying long messages outside the exception class
(TRY003)
124-127: Avoid specifying long messages outside the exception class
(TRY003)
129-132: Avoid specifying long messages outside the exception class
(TRY003)
136-139: Avoid specifying long messages outside the exception class
(TRY003)
143-146: Avoid specifying long messages outside the exception class
(TRY003)
kim_convergence/run_length_control/_variable_list_factory.py
87-87: Avoid specifying long messages outside the exception class
(TRY003)
91-94: Avoid specifying long messages outside the exception class
(TRY003)
97-100: Avoid specifying long messages outside the exception class
(TRY003)
kim_convergence/stats/randomness_test.py
50-50: Avoid specifying long messages outside the exception class
(TRY003)
61-64: Avoid specifying long messages outside the exception class
(TRY003)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: build (windows-latest, 3.13)
- GitHub Check: build (windows-latest, 3.9)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🧹 Nitpick comments (2)
kim_convergence/timeseries/utils.py (1)
242-286: Excellent centralized validation with monotonically increasing check.The refactoring effectively consolidates index resolution and validation. The monotonically increasing check at line 270 addresses the prior review suggestion.
One optional consideration: negative indices from user input would pass validation but wrap around in numpy. If you want to reject these explicitly for time series semantics:
🔎 Optional: add negative index validation
if indices.size > 1 and (indices[:-1] >= indices[1:]).any(): raise CRError( "uncorrelated_sample_indices must be monotonically increasing " "(sorted in time order)." ) + if (indices < 0).any(): + raise CRError( + "uncorrelated_sample_indices must contain non-negative indices." + ) + time_series_data_size = time_series_data.sizekim_convergence/run_length_control/_convergence.py (1)
86-94: Replace assertions with explicit runtime checks.The defensive input validation uses
assertstatements which are removed when Python runs with-O(optimize) flag. If the function is called with invalid inputs in production, this will result in obscureAttributeErrororIndexErrorexceptions instead of clear validation errors.🔎 Proposed fix
- assert isinstance(eq_step, list) and len(eq_step) == number_of_variables - assert isinstance(rel_acc, list) and len(rel_acc) == number_of_variables - assert isinstance(abs_acc, list) and len(abs_acc) == number_of_variables - assert isinstance(rel_hw, list) and len(rel_hw) == number_of_variables - assert isinstance(mean, list) and len(mean) == number_of_variables - assert isinstance(ucl, list) and len(ucl) == number_of_variables - assert isinstance(std, list) and len(std) == number_of_variables - assert isinstance(ess, list) and len(ess) == number_of_variables - assert isinstance(rau, list) and len(rau) == number_of_variables + # Validate input arrays + for name, arr in [ + ("equilibration_step", eq_step), + ("relative_accuracy", rel_acc), + ("absolute_accuracy", abs_acc), + ("relative_half_width_estimate", rel_hw), + ("time_series_data_mean", mean), + ("upper_confidence_limit", ucl), + ("time_series_data_std", std), + ("effective_sample_size", ess), + ("relative_accuracy_undefined", rau), + ]: + if not isinstance(arr, list) or len(arr) != number_of_variables: + raise CRError( + f"{name} must be a list of length {number_of_variables}" + )
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
kim_convergence/run_length_control/_convergence.pykim_convergence/timeseries/utils.py
🧰 Additional context used
🧬 Code graph analysis (1)
kim_convergence/timeseries/utils.py (1)
kim_convergence/err.py (1)
CRError(40-62)
🪛 Ruff (0.14.10)
kim_convergence/run_length_control/_convergence.py
252-254: Avoid specifying long messages outside the exception class
(TRY003)
275-279: Avoid specifying long messages outside the exception class
(TRY003)
433-436: Avoid specifying long messages outside the exception class
(TRY003)
487-490: Avoid specifying long messages outside the exception class
(TRY003)
529-532: Avoid specifying long messages outside the exception class
(TRY003)
583-585: Avoid specifying long messages outside the exception class
(TRY003)
588-591: Avoid specifying long messages outside the exception class
(TRY003)
kim_convergence/timeseries/utils.py
94-97: Avoid specifying long messages outside the exception class
(TRY003)
101-103: Avoid specifying long messages outside the exception class
(TRY003)
108-108: Avoid specifying long messages outside the exception class
(TRY003)
207-207: Avoid specifying long messages outside the exception class
(TRY003)
259-262: Avoid specifying long messages outside the exception class
(TRY003)
266-268: Avoid specifying long messages outside the exception class
(TRY003)
271-274: Avoid specifying long messages outside the exception class
(TRY003)
329-329: Avoid specifying long messages outside the exception class
(TRY003)
386-386: Avoid specifying long messages outside the exception class
(TRY003)
397-400: Avoid specifying long messages outside the exception class
(TRY003)
406-406: Standard pseudo-random generators are not suitable for cryptographic purposes
(S311)
456-456: Avoid specifying long messages outside the exception class
(TRY003)
467-470: Avoid specifying long messages outside the exception class
(TRY003)
🔇 Additional comments (12)
kim_convergence/timeseries/utils.py (8)
1-28: Well-organized imports and exports.The module structure is clean with proper separation of concerns. The
__all__list accurately reflects the public API surface.
30-46: Clean helper for consistent error messaging.Good approach to centralize error message formatting with proper singular/plural handling.
49-110: Correct SI computation logic with proper validation.The function correctly handles all input types (None, str, float, int) with appropriate validation and error chaining.
113-161: Correct implementation of uncorrelated index computation.The algorithm properly spaces indices by the statistical inefficiency and ensures all returned indices are within bounds.
164-239: Clean dispatcher pattern for sampling methods.The routing logic is clear with proper validation and early returns.
289-341: Clean implementation using centralized validation.The function properly validates input, resolves indices, and extracts samples.
344-410: Correct random sampling implementation.The block-based random sampling logic is sound. The
index_s = indices[0]initialization correctly handles custom indices that may not start at zero.Regarding the static analysis hint (S311) about
randint: This is a false positive—the standard library random module is appropriate for statistical sampling; cryptographic-grade randomness is not required here.
413-479: Correct block averaging with proper index initialization.The
index_s = indices[0]initialization (line 474) correctly addresses the prior review feedback. Block averaging logic is sound.kim_convergence/run_length_control/_convergence.py (4)
1-39: LGTM!The module docstring clearly describes the convergence stage responsibilities, and all imports are appropriate for the functionality implemented.
161-170: LGTM!The function correctly returns a memory-shared view of the equilibrated portion, with proper handling for both single-variable (1D) and multi-variable (2D) cases.
296-554: LGTM! Past issues properly addressed.The convergence stage logic is comprehensive and correct. The previous issues with
assertstatements forucl_obj.sivalidation (flagged in past reviews) have been properly fixed with explicit runtime checks at lines 432-436 and 528-532, providing clear error messages when statistical inefficiency is not computed.
557-612: LGTM! Format handling correctly documented.The report serialization logic is clear and correct. The previous concern about
txtformat handling (flagged in past reviews) has been properly addressed with a NOTE in the docstring (lines 575-577) explaining thattxtformat uses EDN encoding as the default plain-text representation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
🧹 Nitpick comments (2)
kim_convergence/timeseries/utils.py (1)
94-97: Optional: Consider custom exception types for repeated validation errors.Static analysis flags multiple instances where long error messages are constructed inline (TRY003). While the current approach with
CRErroris functional and clear, you could consider defining specialized exception types if these patterns recur across the codebase:class InvalidIndicesError(CRError): """Raised when uncorrelated_sample_indices validation fails.""" passHowever, given that:
- The existing
CRErrorpattern is established across the codebase- The messages are clear and context-specific
- This would require broader refactoring beyond this file
This refactor can be safely deferred.
Also applies to: 259-262, 266-268, 271-274, 277-279
kim_convergence/run_length_control/_convergence.py (1)
564-617: LGTM! Clean serialization with proper validation.The function correctly:
- Validates
fpaccepts None, "return", or file-like objects- Validates
fp_formatis one of "txt", "json", or "edn"- Handles both return mode (string) and write mode (boolean)
- Uses EDN serialization for "txt" format as clarified in previous review discussion
The Ruff TRY003 warnings (long exception messages) are style preferences that can optionally be addressed by moving messages into custom exception classes, but this is not critical.
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
kim_convergence/run_length_control/_convergence.pykim_convergence/timeseries/utils.py
🧰 Additional context used
🧬 Code graph analysis (2)
kim_convergence/run_length_control/_convergence.py (5)
kim_convergence/err.py (3)
CRError(40-62)CRSampleSizeError(65-68)cr_warning(71-80)kim_convergence/ucl/ucl_base.py (18)
ucl(339-386)UCLBase(42-489)relative_half_width_estimate(436-489)mean(184-186)mean(189-195)mean(198-200)std(203-205)std(208-214)std(217-219)name(59-61)name(64-71)name(74-76)si(136-138)si(141-147)si(150-152)requires_si_computation(275-277)set_si(154-181)set_indices(97-133)kim_convergence/run_length_control/_population.py (1)
_population_tests(149-206)kim_convergence/run_length_control/_run_length.py (1)
_get_run_length(20-35)kim_convergence/run_length_control/_trajectory.py (1)
_get_trajectory(39-93)
kim_convergence/timeseries/utils.py (1)
kim_convergence/err.py (1)
CRError(40-62)
🪛 Ruff (0.14.10)
kim_convergence/run_length_control/_convergence.py
98-98: Avoid specifying long messages outside the exception class
(TRY003)
257-259: Avoid specifying long messages outside the exception class
(TRY003)
277-277: Avoid specifying long messages outside the exception class
(TRY003)
283-287: Avoid specifying long messages outside the exception class
(TRY003)
441-444: Avoid specifying long messages outside the exception class
(TRY003)
495-497: Avoid specifying long messages outside the exception class
(TRY003)
536-539: Avoid specifying long messages outside the exception class
(TRY003)
590-590: Avoid specifying long messages outside the exception class
(TRY003)
593-596: Avoid specifying long messages outside the exception class
(TRY003)
kim_convergence/timeseries/utils.py
94-97: Avoid specifying long messages outside the exception class
(TRY003)
101-103: Avoid specifying long messages outside the exception class
(TRY003)
108-108: Avoid specifying long messages outside the exception class
(TRY003)
207-207: Avoid specifying long messages outside the exception class
(TRY003)
259-262: Avoid specifying long messages outside the exception class
(TRY003)
266-268: Avoid specifying long messages outside the exception class
(TRY003)
271-274: Avoid specifying long messages outside the exception class
(TRY003)
277-279: Avoid specifying long messages outside the exception class
(TRY003)
334-334: Avoid specifying long messages outside the exception class
(TRY003)
391-391: Avoid specifying long messages outside the exception class
(TRY003)
402-405: Avoid specifying long messages outside the exception class
(TRY003)
411-411: Standard pseudo-random generators are not suitable for cryptographic purposes
(S311)
461-461: Avoid specifying long messages outside the exception class
(TRY003)
472-475: Avoid specifying long messages outside the exception class
(TRY003)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: build (windows-latest, 3.11)
- GitHub Check: build (windows-latest, 3.12)
🔇 Additional comments (14)
kim_convergence/timeseries/utils.py (8)
1-27: LGTM! Clean import modernization and consistent styling.The imports are well-organized, and the shift to centralized defaults from
kim_convergence._defaultimproves maintainability. The consistent use of double-quoted strings in__all__andSAMPLING_METHODSaligns with the broader PR refactoring.
30-46: LGTM! Flexible signature and clear error messaging.The updated signature accepts both
np.ndarrayandlist[int], providing flexibility for callers. The singular/plural handling in the error message is well-implemented.
113-161: LGTM! Correct implementation of uncorrelated index computation.The function correctly computes indices at
si-spaced intervals and filters them to stay within bounds. The docstring fix from previous reviews is confirmed.
164-240: LGTM! Clean dispatcher with sensible defaults.The function serves as a clean dispatcher to the three specialized sampling methods. The explicit default of
"uncorrelated"(line 204) improves clarity over the previousNone-handling approach.
242-291: Excellent refactoring! Centralized validation eliminates duplication.The introduction of
_resolve_and_validate_indicesis a significant improvement that consolidates index validation logic previously duplicated across three sampling functions. The validation is comprehensive and covers:
- Auto-computation when indices are
None- Dimensionality check (1D array)
- Monotonicity enforcement (sorted in time order)
- Non-negativity check
- Bounds validation against time series size
This centralization improves maintainability and ensures consistent behavior across all sampling methods.
294-346: LGTM! Simplified using centralized validation.The refactoring to use
_resolve_and_validate_indiceseliminates local validation logic and improves maintainability. The docstring now explicitly documents the monotonicity requirement (lines 322-323), which is helpful for users providing custom indices.
349-415: LGTM! Correct block-based random sampling.The refactoring successfully integrates the centralized validator and the critical fix from previous reviews (line 409:
index_s = indices[0]) is confirmed. The function correctly samples one random value from each block defined by consecutive index pairs.The static analysis warning (S311) about
randinton line 411 is a false positive—this is statistical sampling, not cryptographic random number generation, so the standard library'srandintis appropriate.
418-484: LGTM! Correct block averaging implementation.The refactoring successfully integrates the centralized validator and correctly initializes
index_s = indices[0](line 479), ensuring proper block boundaries when custom indices don't start at zero. The block averaging logic usingnp.meanis clean and correct.kim_convergence/run_length_control/_convergence.py (6)
1-40: LGTM! Clear module documentation and appropriate imports.The module docstring provides comprehensive context for the convergence phase, and the import structure correctly reflects the module's dependencies on sibling private modules and core components.
42-162: LGTM! Robust report generation with proper validation.The function correctly validates all input arrays and handles both single-variable (flattened) and multi-variable (nested) report formats. The type casting is safe given the preceding None checks.
165-174: LGTM! Efficient memory-shared view extraction.The dimensionality-aware slicing correctly returns equilibrated data while maintaining memory sharing with the original array.
177-301: LGTM! Comprehensive UCL computation with proper error handling.The function correctly addresses the previous critical issue by replacing assert statements with explicit runtime checks (lines 276-277). The logic properly handles:
- Insufficient sample size via CRSampleSizeError
- Final-pass mode for reporting best estimates
- Both relative and absolute accuracy criteria
- Near-zero mean detection with helpful guidance
304-472: LGTM! Robust convergence loop with proper safeguards.The main convergence loop correctly addresses the previous critical issue with explicit runtime checks (lines 440-444). The algorithm properly:
- Resets convergence flags each iteration
- Breaks early if any variable lacks sufficient data
- Uses the for-else pattern to distinguish insufficient data from convergence checks
- Requires all variables to pass their criteria
502-550: LGTM! Proper final statistics computation for non-converged runs.The non-converged case correctly:
- Addresses the previous critical issue with explicit
sicheck (lines 535-539)- Computes final UCL in final_pass mode for reporting
- Detects when confidence intervals include zero (lines 543-546)
- Warns users that relative accuracy is ill-defined in that case
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (1)
kim_convergence/run_length_control/_convergence.py (1)
86-98: Validation logic is correct and thorough.The input validation correctly checks that all arrays are lists with the expected length. This ensures consistency before building the convergence report.
Optional: Extract error messages to reduce TRY003 warnings
Static analysis suggests extracting long error messages into custom exception classes or module-level constants. This is a minor style improvement:
# At module level _VALIDATION_ERROR_MSG = "{name} must be a list of length {expected}" # In function if not isinstance(arr, list) or len(arr) != number_of_variables: raise CRError(_VALIDATION_ERROR_MSG.format(name=name, expected=number_of_variables))This pattern can be applied to other long error messages throughout the file (lines 257-259, 277, 283-287, 441-444, 495-498, 537-540, 591, 594-597).
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
kim_convergence/run_length_control/_convergence.pykim_convergence/timeseries/utils.py
🧰 Additional context used
🪛 Ruff (0.14.10)
kim_convergence/run_length_control/_convergence.py
98-98: Avoid specifying long messages outside the exception class
(TRY003)
257-259: Avoid specifying long messages outside the exception class
(TRY003)
277-277: Avoid specifying long messages outside the exception class
(TRY003)
283-287: Avoid specifying long messages outside the exception class
(TRY003)
441-444: Avoid specifying long messages outside the exception class
(TRY003)
495-498: Avoid specifying long messages outside the exception class
(TRY003)
537-540: Avoid specifying long messages outside the exception class
(TRY003)
591-591: Avoid specifying long messages outside the exception class
(TRY003)
594-597: Avoid specifying long messages outside the exception class
(TRY003)
kim_convergence/timeseries/utils.py
94-97: Avoid specifying long messages outside the exception class
(TRY003)
101-104: Avoid specifying long messages outside the exception class
(TRY003)
109-109: Avoid specifying long messages outside the exception class
(TRY003)
208-208: Avoid specifying long messages outside the exception class
(TRY003)
260-263: Avoid specifying long messages outside the exception class
(TRY003)
267-269: Avoid specifying long messages outside the exception class
(TRY003)
272-275: Avoid specifying long messages outside the exception class
(TRY003)
278-280: Avoid specifying long messages outside the exception class
(TRY003)
335-335: Avoid specifying long messages outside the exception class
(TRY003)
392-392: Avoid specifying long messages outside the exception class
(TRY003)
403-406: Avoid specifying long messages outside the exception class
(TRY003)
412-412: Standard pseudo-random generators are not suitable for cryptographic purposes
(S311)
462-462: Avoid specifying long messages outside the exception class
(TRY003)
473-476: Avoid specifying long messages outside the exception class
(TRY003)
🔇 Additional comments (14)
kim_convergence/run_length_control/_convergence.py (5)
165-174: LGTM! Clean helper function.The conditional indexing correctly handles both single-variable and multi-variable cases, and properly returns a memory-shared view as documented.
276-287: Excellent fix! Explicit runtime checks replace assertions.The previous review flagged the use of
assertstatements for type narrowing. This has been properly addressed with explicit runtime checks that:
- Provide clear error messages with context (variable number)
- Work correctly even when Python runs with
-Ooptimization flag- Narrow types for mypy after the check
This pattern is consistently applied throughout the function and in
_convergence_stage.Based on past review comments, this addresses the critical issue identified in previous reviews.
440-446: Proper runtime check for statistical inefficiency.Consistent with the fix at lines 276-287, this explicit check ensures
ucl_obj.siis computed before using it for the effective sample size calculation. The pattern is correctly applied in both the main convergence loop and the final-pass logic (lines 536-542).
403-472: Well-structured convergence loop with proper exit conditions.The loop correctly:
- Resets convergence flags at the start of each iteration (lines 405-406)
- Breaks early if any variable lacks sufficient data (line 437)
- Uses Python's for-else idiom to detect successful UCL computation for all variables (lines 467-469)
- Requires all variables to pass their criteria before declaring convergence (line 470)
The logic is sound and handles all edge cases appropriately.
583-618: Output handling is correct with clear documentation.The function properly handles all three formats ("txt", "json", "edn") with appropriate validation. The docstring note (lines 583-585) clarifies that "txt" format uses EDN encoding, addressing the concern from previous reviews.
The logic correctly:
- Validates
fpas None, "return", or a file-like object- Validates
fp_formatagainst allowed values- Returns serialized string when
fp="return"- Writes to the provided file-like object otherwise
Based on past review comments, the "txt" format behavior has been clarified and documented as intended.
kim_convergence/timeseries/utils.py (9)
1-28: LGTM: Clean organizational improvements.The module-level changes improve maintainability:
- Centralized default constants from
_defaultmodule- Consistent double-quoted string literals
- Well-organized
__all__exports
30-46: LGTM: Type annotations updated consistently.The signature change to
Union[np.ndarray, list[int]]aligns with the module's modernized type hints and maintains backward compatibility.
49-111: LGTM: API improvements and past issues resolved.The function now uses:
- Keyword-only arguments for safer API
- Modernized type hints (
list[float]instead ofList)- Centralized default constants
The grammatical error flagged in past reviews ("equal one" → "equal to one") has been correctly fixed on lines 102-103.
114-162: LGTM: Consistent API modernization.The function follows the same API improvements as
time_series_data_si. The docstring typo flagged in past reviews has been correctly fixed (lines 123-125).
165-240: LGTM: Dispatcher function modernized consistently.The routing logic remains clear and correct, with modernized type hints and keyword-only parameters matching the updated API surface of the sampling functions it delegates to.
243-292: Excellent refactoring: centralized validation eliminates duplication.This new helper function is a significant improvement that addresses past review feedback. It consolidates index resolution and validation logic that was previously scattered across three sampling functions.
Key validations implemented:
- Auto-computation when
uncorrelated_sample_indices=None- Dimensionality check (must be 1D)
- Monotonicity enforcement (line 271-275) — addresses past review suggestion
- Non-negativity check (line 277-280)
- Bounds validation with clear error messages (line 284-291)
This reduces maintenance burden and ensures consistent behavior across all sampling methods.
295-347: LGTM: Streamlined with centralized validation.The function is now cleaner, delegating validation to
_resolve_and_validate_indices. The docstring improvement (lines 323-324) explicitly documents the monotonicity requirement, making the API contract clearer.
350-416: LGTM: Past index initialization issue resolved.The function correctly addresses the past review comment by initializing
index_s = indices[0]on line 410 (previously incorrectly used0). This ensures proper block boundaries when customuncorrelated_sample_indicesdon't start at zero.The centralized validation and explicit docstring requirements (lines 380-381) further improve robustness.
419-485: LGTM: Past index initialization issue resolved.The function correctly addresses the past review comment by initializing
index_s = indices[0]on line 480 (previously incorrectly used0). This ensures proper block boundaries when customuncorrelated_sample_indicesdon't start at zero.The centralized validation and explicit docstring requirements (lines 450-451) further improve robustness.
Major overhaul: Modularization run_length_control, full Sphinx documentation, deadlock fix, and code-base polish
Description
This PR delivers a comprehensive set of improvements to
kim-convergence, significantly enhancing maintainability, usability, documentation, and compatibility with multi-threaded simulation environments like LAMMPS.Type of Change
Related Issues
Changes
Major Changes
run_length_controlmodule with new unit testsKIM_CONV_FORCE_SUBPROC)Detailed List
run_length_control.pyinto a sub-package with staged private modules and unified 1D/multi-D handlingrun_length_controlsphinx-apidoc, moved assets, updatedpyproject.tomlfor docs building, added.readthedocs.yamlKIM_CONV_FORCE_SUBPROCenv var with subprocess isolation for correlation/periodogram to prevent deadlocks in LAMMPS + OpenMPMotivation & Context
These changes modernize the package: easier maintenance through modular design, professional documentation for users and contributors, reliable operation inside heavily threaded simulation codes, and a clean, consistent code-base ready for future development.
Testing
make htmlindoc/)Manual verification:
KIM_CONV_FORCE_SUBPROCis setDocumentation
Checklist
Additional Notes
This PR represents a major step forward in package maturity and readiness for broader adoption within the OpenKIM ecosystem.
Summary by CodeRabbit
New Features
Documentation
Improvements
Tests / Chores
✏️ Tip: You can customize this high-level summary in your review settings.