Skip to content

Add PaCMAP dimensionality reduction (closes #173) - #193

Merged
aronwalsh merged 3 commits into
WMD-group:mainfrom
ali-elite:add-pacmap-reducer
Aug 9, 2026
Merged

aronwalsh merged 3 commits into
WMD-group:mainfrom
ali-elite:add-pacmap-reducer

Conversation

@ali-elite

@ali-elite ali-elite commented Jun 16, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds PaCMAP (Pairwise Controlled Manifold Approximation and Projection) as a dimensionality-reduction option, alongside the existing PCA / t-SNE / UMAP reducers. Closes #173.

Changes

  • EmbeddingBase.calculate_pacmap(n_components=2, standardise=True, init="pca", **kwargs) in _base.py, following the same standardise-then-project pattern as calculate_pca / calculate_tsne / calculate_umap. **kwargs are forwarded to the PaCMAP constructor; init is forwarded to PaCMAP.fit_transform (PaCMAP exposes initialisation there rather than on the constructor), defaulting to "pca".
  • dimension_plotter(..., reducer="pacmap") support in plotter.py, with the docstring updated to list the available reducers.
  • pacmap>=0.7.0 added to project dependencies in pyproject.toml.
  • Tests: test_PaCMAP in test_core.py (return type, (n_elements, 2) shape, and determinism under a fixed random_state), and a reducer="pacmap" assertion added to the dimension_plotter dispatch test in test_plotter.py.

Testing

  • Full test suite: 62 passed.
  • ruff (v0.15.2) check + format: clean. codespell: clean.

I followed the convention of not committing a baseline image for the plotter test (matching the commented-out UMAP image test), instead asserting the dispatch returns a plt.Axes. Happy to adjust the API surface (e.g. exposing init differently) or add a tutorial-notebook example if you'd prefer.

Summary by CodeRabbit

  • New Features

    • Added PaCMAP as a supported dimensionality reduction method for embeddings
    • Users can now reduce embedding dimensions using PaCMAP with customizable parameters
  • Tests

    • Added tests validating PaCMAP functionality and deterministic behavior
    • Added tests for visualization using PaCMAP as a reducer

Add a `calculate_pacmap` method to `EmbeddingBase` and a "pacmap" option
to `dimension_plotter`, mirroring the existing PCA/t-SNE/UMAP reducers.
Adds `pacmap` as a dependency and unit tests for the new reducer.

Closes WMD-group#173
Copilot AI review requested due to automatic review settings June 16, 2026 22:42
@coderabbitai

coderabbitai Bot commented Jun 16, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@aronwalsh, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 33 minutes

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 01c077c9-9c3f-49b8-a1df-f503e83662bd

📥 Commits

Reviewing files that changed from the base of the PR and between 0b782f3 and 3c5ddde.

📒 Files selected for processing (8)
  • .github/workflows/ci.yml
  • .github/workflows/docs.yml
  • .github/workflows/python-publish.yml
  • pyproject.toml
  • src/elementembeddings/_base.py
  • src/elementembeddings/plotter.py
  • tests/test_core.py
  • tests/test_plotter.py
📝 Walkthrough

Walkthrough

Adds PaCMAP as a fourth dimensionality reduction option. The pacmap>=0.7.0 package is added as a dependency, EmbeddingBase gains a calculate_pacmap method mirroring existing projection methods, dimension_plotter is extended to dispatch to it, and tests cover shape, type, determinism, and plot output.

Changes

PaCMAP Dimensionality Reduction

Layer / File(s) Summary
Dependency and calculate_pacmap implementation
pyproject.toml, src/elementembeddings/_base.py
pacmap>=0.7.0 added to project dependencies. PaCMAP imported into _base.py and EmbeddingBase.calculate_pacmap(n_components, standardise, init, **kwargs) implemented, standardising embeddings when requested and calling PaCMAP(...).fit_transform(...).
Plotter wiring for PaCMAP reducer
src/elementembeddings/plotter.py
dimension_plotter docstring updated to list "pacmap" as a valid reducer value; an elif reducer == "pacmap" branch added to compute reduced coordinates via embedding.calculate_pacmap(...).
Core and plotter tests
src/elementembeddings/tests/test_core.py, src/elementembeddings/tests/test_plotter.py
test_PaCMAP asserts output is a NumPy array of shape (len(element_list), 2) and is deterministic with a fixed random_state. test_dimension_2d_plotter extended to verify dimension_plotter with reducer="pacmap" returns a matplotlib.axes.Axes.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐇 Hippity-hop through dimensions anew,
PaCMAP unfolds every embedding in view!
Four reducers now dance in the plotter's delight,
Standardise, transform, and the shapes come out right.
A bunny approved it — the coords look just right! ✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: adding PaCMAP dimensionality reduction and closing issue #173.
Description check ✅ Passed The description covers the main changes, testing results, and dependencies added, though it deviates from the repository template structure.
Linked Issues check ✅ Passed The PR successfully implements PaCMAP as a dimensionality-reduction option as requested in issue #173, with complete integration across the codebase and test coverage.
Out of Scope Changes check ✅ Passed All changes are directly related to implementing PaCMAP support; no unrelated or out-of-scope modifications are present.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

Adds PaCMAP dimensionality reduction support to the embeddings API and plotting utilities, along with tests and dependency updates.

Changes:

  • Introduce calculate_pacmap() on embeddings (PaCMAP projection).
  • Add "pacmap" as an option to dimension_plotter().
  • Add unit tests for PaCMAP in core and plotter tests; add pacmap dependency.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
src/elementembeddings/_base.py Adds calculate_pacmap() implementation backed by pacmap.PaCMAP.
src/elementembeddings/plotter.py Extends dimension_plotter() to accept reducer="pacmap".
src/elementembeddings/tests/test_core.py Adds deterministic(ish) PaCMAP tests for shape and reproducibility.
src/elementembeddings/tests/test_plotter.py Adds plotter test case for the PaCMAP reducer option.
pyproject.toml Adds pacmap to required dependencies.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread tests/test_core.py
Comment on lines +476 to +486
def test_PaCMAP(self):
"""Test the PaCMAP function."""
pacmap_params = {"random_state": 42}
assert isinstance(self.test_matscholar.calculate_pacmap(), np.ndarray)
assert self.test_matscholar.calculate_pacmap().shape == (
len(self.test_matscholar.element_list),
2,
)
pacmap1 = self.test_matscholar.calculate_pacmap(**pacmap_params)
pacmap2 = self.test_matscholar.calculate_pacmap(**pacmap_params)
assert (pacmap1 == pacmap2).all()

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Kept exact equality to match the existing test_PCA / test_tSNE / test_UMAP determinism checks, which all assert (x == y).all(). I verified PaCMAP is bit-reproducible within a process under a fixed random_state (same kNN backend, two calls → identical arrays), so the exact check is stable here. Happy to switch all four reducer tests to np.testing.assert_allclose together if you'd prefer a tolerance-based convention.

Comment on lines +285 to +289
warnings.warn(
"""It is recommended to scale the embeddings
before projecting with PaCMAP.
To do so, set `standardise=True`.""",
)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The warning mirrors the wording and triple-quoted format of the existing calculate_pca / calculate_tsne / calculate_umap warnings verbatim, so I kept it identical for consistency. On stacklevel: B028 is in the ignore list in pyproject.toml and none of the sibling warnings set it, so adding it only here would be inconsistent. Happy to do a repo-wide stacklevel=2 pass (and drop the B028 ignore) as a separate cleanup if you'd prefer.

Comment on lines +261 to +267
def calculate_pacmap(
self,
n_components: int = 2,
standardise: bool = True,
init: str = "pca",
**kwargs,
):

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Left off for consistency with the sibling reducers — calculate_pca / calculate_tsne / calculate_umap are also unannotated. Glad to add -> np.ndarray across all four reducer methods if you'd like them annotated together.

Comment on lines +112 to +113
reducer (str): The dimensionality reduction algorithm to use. One of
"umap", "tsne", "pca" or "pacmap", by default "umap"

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in 6089661 — the dispatch ValueError now includes the invalid value and lists the accepted reducers ('umap', 'tsne', 'pca', 'pacmap'). On the docstring: the accepted-values continuation line is indented to match the existing convention in this function's docstring (e.g. the reducer_params description wraps at the same level), so I kept it consistent with the surrounding args.

Comment thread src/elementembeddings/plotter.py Outdated
Comment on lines 133 to 134
msg = "Unrecognised reducer."
raise ValueError(msg)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in 6089661 — the dispatch ValueError now names the invalid value and the accepted reducers (including pacmap).

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/elementembeddings/_base.py`:
- Around line 285-289: The warnings.warn() call for the PaCMAP scaling
recommendation is missing the stacklevel parameter, which causes the warning to
point to the library internals instead of the caller's code location. Add the
stacklevel parameter to the warnings.warn() call that contains the message about
standardising embeddings before projecting with PaCMAP. Set stacklevel to an
appropriate value (typically 2) so that the warning appears to originate from
the caller's code rather than from within the library itself.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 0616cd87-f5ea-46aa-b168-85c31e9dbba1

📥 Commits

Reviewing files that changed from the base of the PR and between f20c012 and 0b782f3.

📒 Files selected for processing (5)
  • pyproject.toml
  • src/elementembeddings/_base.py
  • src/elementembeddings/plotter.py
  • src/elementembeddings/tests/test_core.py
  • src/elementembeddings/tests/test_plotter.py

Comment thread src/elementembeddings/_base.py
ali-elite and others added 2 commits June 17, 2026 00:51
List the accepted reducer names (including pacmap) and include the
invalid value in the ValueError, per PR review feedback.
Resolves the rename of src/elementembeddings/tests/ to tests/: the new
PaCMAP tests are carried over into tests/test_core.py and
tests/test_plotter.py.
@aronwalsh

Copy link
Copy Markdown
Member

Thanks for this @ali-elite. Will get it merged now

@aronwalsh
aronwalsh merged commit bbd46c7 into WMD-group:main Aug 9, 2026
15 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add PaCMAP

3 participants