Version 2.0.0 - #3
Conversation
There was a problem hiding this comment.
Pull request overview
This pull request implements version 2.0.0, a major release with breaking API changes to the STR feature construction logic. The core change refactors how repeat-unit information is included in mutation features by splitting the ru parameter into two independent controls: ru_length (boolean flag) and ru (content mode: None/"class"/"ru").
Changes:
- Refactored STR feature construction to use separate
ru_lengthandruparameters, removing combined modes - Updated repeat-unit classification: renamed "AT_rich"/"non_AT_rich" to "AT_only"/"GC_only"/"mixed"
- Improved exposure plot label placement and readability for multi-group visualizations
- Added comprehensive NumPy-style docstrings across nmf and extract_tally modules
- Added Sphinx documentation infrastructure with RTD theme and GitHub Pages deployment
- Updated all tests, CLI, and examples to use the new API
Reviewed changes
Copilot reviewed 26 out of 27 changed files in this pull request and generated 9 comments.
Show a summary per file
| File | Description |
|---|---|
| src/str_mut_signatures/init.py | Updated version to 2.0.0 |
| src/str_mut_signatures/cli.py | Updated CLI arguments to support new ru_length/ru parameter split |
| src/str_mut_signatures/extract_tally/tally.py | Core refactoring: split ru into ru_length + ru, renamed motif_is_at_rich to motif_base_class |
| src/str_mut_signatures/extract_tally/*.py | Added comprehensive NumPy-style docstrings |
| src/str_mut_signatures/nmf/*.py | Added comprehensive NumPy-style docstrings and improved plotting |
| tests/test_tally.py | Updated all tests for new API, added GC_only tests |
| tests/integration/test_pipeline.py | Updated integration tests to use new API |
| tests/cli/test_cli_commands.py | Updated CLI tests and version check to 2.0.0 |
| tox.ini | Added gh-actions configuration and py312 testenv for coverage |
| .github/workflows/ci.yml | Added codecov upload step (has indentation bug) |
| .github/workflows/docs.yml | New workflow for Sphinx documentation deployment |
| docs/* | New Sphinx documentation structure |
| README.rst | Updated examples and documentation for new API |
| CHANGELOG.md | Added 2.0.0 release notes |
| pyproject.toml | Added duplicate documentation dependencies |
| setup.py | Updated development status to Beta |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| # Upload coverage | ||
| - name: Upload coverage to Codecov | ||
| if: matrix.python-version == '3.12' | ||
| uses: codecov/codecov-action@v5 | ||
| with: | ||
| files: coverage.xml | ||
| fail_ci_if_error: true | ||
| token: ${{ secrets.CODECOV_TOKEN }} No newline at end of file |
There was a problem hiding this comment.
The indentation for the coverage upload step is incorrect. This step should be at the same level as "Test with tox", not nested under it. The current indentation will cause this step to be ignored by the workflow parser.
| cmap: str = "tab20", | ||
| s: float = 30.0, | ||
| ) -> tuple[pd.DataFrame, np.ndarray, plt.Axes]: | ||
| """ | ||
| Run PCA on an NMF result (typically exposures) and plot PC1 vs PC2. | ||
|
|
||
| This is the main entry point: | ||
| - extracts a samples x features matrix from `result` | ||
| (by default `result.exposures`), | ||
| - computes PCA, | ||
| - color samples by NMFResult.groups | ||
| - returns PCA coordinates, variance explained, cluster labels and axes. | ||
| This is the main entry point for PCA visualization: | ||
|
|
||
| - Extract a samples × features matrix from ``result`` (by default | ||
| ``result.exposures``). | ||
| - Compute PCA coordinates. | ||
| - Color samples by ``result.groups``. | ||
| - Plot the first two principal components. | ||
|
|
||
| Parameters | ||
| ---------- | ||
| result : NMFResult | ||
| Output of `run_nmf`. Must have `.exposures` as a pandas DataFrame, | ||
| unless a `matrix` is explicitly passed. | ||
|
|
||
| matrix : pandas.DataFrame or None, default None | ||
| Optional matrix to use instead of `result.exposures`. | ||
| Must be samples x features. If None, uses `result.exposures`. | ||
|
|
||
| n_components : int, default 2 | ||
| Output of :func:`run_nmf`. Must provide ``.exposures`` as a | ||
| :class:`pandas.DataFrame` unless ``matrix`` is explicitly provided. | ||
| matrix : pandas.DataFrame or None, optional | ||
| Optional matrix to use instead of ``result.exposures``. | ||
| Must be samples × features. If ``None``, uses ``result.exposures``. | ||
| n_components : int, optional | ||
| Number of principal components to compute. Must be >= 2. | ||
|
|
||
| ax : matplotlib.axes.Axes or None, default None | ||
| Existing axes to plot on. If None, a new figure/axes is created. | ||
|
|
||
| title : str or None, default None | ||
| Plot title. If None, a default title is generated. | ||
|
|
||
| alpha : float, default 0.8 | ||
| Point transparency. | ||
|
|
||
| s : float, default 30.0 | ||
| Point size. | ||
| Default is 2. | ||
| ax : matplotlib.axes.Axes or None, optional | ||
| Existing axes to plot on. If ``None``, a new figure and axes are created. | ||
| title : str or None, optional | ||
| Plot title. If ``None``, a default title is generated. | ||
| alpha : float, optional | ||
| Point transparency. Default is 0.8. | ||
| s : float, optional | ||
| Point size. Default is 30.0. | ||
|
|
||
| Returns | ||
| ------- | ||
| coords : pandas.DataFrame | ||
| PCA coordinates (PC1, PC2, ...). | ||
|
|
||
| explained_variance_ratio_ : np.ndarray | ||
| Fraction of variance explained by each component. | ||
|
|
||
| PCA coordinates for each sample (``PC1``, ``PC2``, ...), indexed by sample. | ||
| explained_variance_ratio_ : numpy.ndarray | ||
| Fraction of variance explained by each principal component. | ||
| ax : matplotlib.axes.Axes | ||
| Axes with the PCA scatter plot. | ||
| Axes containing the PCA scatter plot. | ||
|
|
||
| Raises | ||
| ------ | ||
| ValueError | ||
| If ``n_components < 2`` or if the chosen matrix is empty or non-numeric. | ||
| """ |
There was a problem hiding this comment.
Missing cmap parameter documentation. The cmap parameter was added to the function signature at line 130 but is not documented in the Parameters section of the docstring.
| str_mut_signatures extract \ | ||
| --vcf-dir data/vcfs \ | ||
| --out-matrix counts_len.tsv \ | ||
| --ru-len \ |
There was a problem hiding this comment.
The help text shows '--ru-len' but the actual argument name is '--ru-length'. This inconsistency between the example and the actual CLI flag could confuse users. The argument name at line 131 is 'ru-length', not 'ru-len'.
| --ru-len \ | |
| --ru-length \ |
| "watchdog>=3.0.0", | ||
| "sphinx", | ||
| "sphinx-rtd-theme", | ||
| "myst-parser", | ||
| "sphinx-argparse" |
There was a problem hiding this comment.
Duplicate dependencies in dev extras. Lines 53-56 duplicate sphinx, sphinx-rtd-theme, myst-parser, and sphinx-argparse which are already listed in lines 49-50. This duplication is unnecessary and could lead to maintenance issues.
| "watchdog>=3.0.0", | |
| "sphinx", | |
| "sphinx-rtd-theme", | |
| "myst-parser", | |
| "sphinx-argparse" | |
| "watchdog>=3.0.0" |
| --vcf-dir data/vcfs/ \ | ||
| --out-matrix counts_raw.tsv \ | ||
| --ru length \ | ||
| --ru-len \ |
There was a problem hiding this comment.
Inconsistent CLI flag name in the README example. Line 181 shows '--ru-len' but the actual CLI argument defined in cli.py line 131 is '--ru-length'. This should be '--ru-length' to match the actual implementation.
| --ru-len \ | |
| --ru-length \ |
| matrix = build_mutation_matrix( | ||
| mutations, | ||
| ru="length", | ||
| ru_length="length", |
There was a problem hiding this comment.
The parameter name value should be "ru_length" not "ru_length="length"". Line 111 shows incorrect syntax where you're assigning the string "length" to ru_length when it should be a boolean True.
| ru_length="length", | |
| ru_length=True, |
| # ru_length: | ||
| # include repeat-unit length (LEN{len(motif)}) |
There was a problem hiding this comment.
There's a typo in the comment. 'ru_length:' should be followed by a proper description on the same line, but instead it's on line 99 with no description. The comment structure is inconsistent with the 'ru:' comment block below it.
| # ru_length: | |
| # include repeat-unit length (LEN{len(motif)}) | |
| # ru_length: include repeat-unit length (LEN{len(motif)}) |
| "'ru' (full motif sequence), or 'AT' (AT-rich vs non-AT-rich). " | ||
| "Default: length" | ||
| "How to include repeat-unit content in feature labels: " | ||
| "'class' (base class AT/GC/MX) or " |
There was a problem hiding this comment.
The help text abbreviates 'mixed' as 'MX', but the actual output uses the full word 'mixed' according to the code in tally.py and test_tally.py. This inconsistency between the help text and actual behavior could confuse users.
| "'class' (base class AT/GC/MX) or " | |
| "'class' (base class AT/GC/mixed) or " |
Welcome to Codecov 🎉Once you merge this PR into your default branch, you're all set! Codecov will compare coverage reports and display results in all future pull requests. Thanks for integrating Codecov - We've got you covered ☂️ |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 26 out of 27 changed files in this pull request and generated 4 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| "--ru", | ||
| "length", |
There was a problem hiding this comment.
This test is using the deprecated --ru length parameter which no longer exists in version 2.0.0. The parameter should be updated to use --ru-length instead (without a value, since it's a flag), or the test should be updated to use --ru-length and optionally --ru class or --ru ru.
| "--ru", | ||
| "length", |
There was a problem hiding this comment.
This test is using the deprecated --ru length parameter which no longer exists in version 2.0.0. The parameter should be updated to use --ru-length instead (without a value, since it's a flag), or the test should be updated to use --ru-length and optionally --ru class or --ru ru.
| colors = cmap(norm(plot_df["group"])) | ||
| # ---- continuous coloring ---- | ||
| cmap_name = cmap if cmap is not None else "viridis" | ||
| # ---- continuous coloring ---- |
There was a problem hiding this comment.
The comment "# ---- continuous coloring ----" is duplicated on consecutive lines. One of these should be removed.
| # ---- continuous coloring ---- |
| :param mutations_data: DataFrame containing mutation data. | ||
| :type mutations_data: pandas.DataFrame | ||
| :param output_csv: Path to the output CSV file. | ||
| :type output_csv: str or pathlib.Path |
There was a problem hiding this comment.
This function uses Sphinx-style docstring format (:param:, :type:), which is inconsistent with the NumPy-style docstrings used throughout the rest of the codebase. For consistency, consider converting this to NumPy-style format with Parameters and Returns sections.
| :param mutations_data: DataFrame containing mutation data. | |
| :type mutations_data: pandas.DataFrame | |
| :param output_csv: Path to the output CSV file. | |
| :type output_csv: str or pathlib.Path | |
| Parameters | |
| ---------- | |
| mutations_data : pandas.DataFrame | |
| DataFrame containing mutation data. | |
| output_csv : str or pathlib.Path | |
| Path to the output CSV file. |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 26 out of 27 changed files in this pull request and generated 5 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| ax.text( | ||
| x[i], ylim[1], str(group_labels[i]), ha="center", va="bottom", fontsize="x-small" | ||
| x_start, | ||
| 1.06, # a bit higher than 1.02 to avoid title/legend collisions | ||
| str(group_labels[s]), | ||
| ha="left", # start text at x_start | ||
| va="bottom", | ||
| rotation=30, | ||
| fontsize="x-small", | ||
| transform=ax.get_xaxis_transform(), # x in data, y in axes coords | ||
| clip_on=False, | ||
| ) |
There was a problem hiding this comment.
The group label placement logic has been improved. The horizontal alignment is set to "left" (line 499) with rotation=30 (line 501), which may cause labels to extend beyond the plot area for groups on the right side. Consider using "center" alignment for better visual balance, especially when n_groups == 1 where the text is placed at x[s] rather than the midpoint.
|
|
||
| # -- Options for HTML output ------------------------------------------------- | ||
| # https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output | ||
| html_static_path = ['_static'] |
There was a problem hiding this comment.
The html_static_path is set to ['_static'], but this directory may not exist. If the _static directory doesn't exist when Sphinx runs, it will generate a warning. Consider either creating the directory or removing this line if no static files are needed.
| @@ -2,7 +2,6 @@ name: Python package | |||
|
|
|||
| on: | |||
| - push | |||
There was a problem hiding this comment.
The CI workflow has been modified to trigger only on push events (removed pull_request). This means that pull requests will not trigger CI builds unless there's a push to the PR branch. Consider keeping the pull_request trigger to ensure CI runs on all PRs.
| - push | |
| push: | |
| pull_request: |
| "sphinx", | ||
| "sphinx-rtd-theme", | ||
| "myst-parser", | ||
| "sphinx-argparse" |
There was a problem hiding this comment.
Sphinx and documentation dependencies have been added to the dev optional dependencies without version constraints (lines 52-55). This could lead to compatibility issues if breaking changes are introduced in these packages. Consider adding minimum version constraints, especially for sphinx (e.g., sphinx>=7.0.0) to ensure consistency.
| "sphinx", | |
| "sphinx-rtd-theme", | |
| "myst-parser", | |
| "sphinx-argparse" | |
| "sphinx>=7.0.0", | |
| "sphinx-rtd-theme>=1.3.0", | |
| "myst-parser>=2.0.0", | |
| "sphinx-argparse>=0.4.0" |
| python = | ||
| 3.12: py312 |
There was a problem hiding this comment.
The [gh-actions] section only maps Python 3.12, but the GitHub Actions workflow matrix includes Python versions 3.8-3.13. This means tox-gh-actions won't automatically select the correct environment for Python versions other than 3.12. Either complete the mapping for all versions or remove the [gh-actions] section to rely on tox's default environment selection.
| python = | |
| 3.12: py312 | |
| python = | |
| 3.8: py38 | |
| 3.9: py39 | |
| 3.10: py310 | |
| 3.11: py311 | |
| 3.12: py312 | |
| 3.13: py313 |
[2.0.0] - 2026-01-20
Changed
Updated STR feature construction logic:
Repeat unit length is now controlled by a single flag (
ru_length).Repeat unit content is optional and can be specified as either:
ru="class"(base composition: AT_only / GC_only / mixed)ru="ru"(full repeat unit sequence).If
ruis not specified, repeat unit content is not included in features.Removed old combined
rumodes (length,AT) in favor of a clearer, modular design.Improved
Documentation