Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,7 @@ docs/generated
docs/gallery_scripts
docs/_build
.DS_Store
venv/
.venv/
_build/
tmpclaude-c0db-cwd
13 changes: 13 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,19 @@ pyOpenMS-Viz is a Python library that provides a simple interface for extending
| PeakMap 3D | x, y, z | peakmap (plot3d=True) | ✓ | | ✓ |


### Note on Polars DataFrames
`pyopenms_viz` can work with [Polars](https://pola.rs/) DataFrames by internally converting them to pandas, often via an Arrow-backed representation where possible. This conversion may involve data copies depending on data types and configuration, and plotting is ultimately delegated to the pandas-based plotting backends. Due to API differences, you must use the `.ms_plot()` namespace instead of `.plot()` when working with Polars.

**Pandas:**
```python
df_pandas.plot(kind="spectrum", x="m/z", y="intensity", backend="ms_plotly")
```

**Polars:**
```python
df_polars.ms_plot(kind="spectrum", x="m/z", y="intensity", backend="ms_plotly")
```

## (Recommended) Pip Installation

The recommended way of installing pyopenms_viz is through the Python Package Index (PyPI). We recommend installing pyopenms_viz in its own virtual environment using Anaconda to avoid packaging conflicts.
Expand Down
34 changes: 34 additions & 0 deletions docs/Getting Started.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -3227,6 +3227,40 @@
" x_kind='chromatogram', # specify on x marginal axis to plot as a chromatogram rather than a spectrum \n",
" grid=False) "
]
},
{
"cell_type": "markdown",
"id": "4b971b57",
"metadata": {},
"source": [
"Using Polars DataFrames\n",
"\n",
"pyopenms_viz is deeply optimized for Pandas. While you can use Polars for high-speed data manipulation, downstream plotting libraries often force silent C-API memory materialization when handling PyArrow extension arrays.\n",
"\n",
"To maintain a strictly native, memory-safe footprint for large datasets, the recommended approach is to process your data in Polars, and then explicitly convert it to Pandas before calling the .ms_plot accessor."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "12fa9e5a",
"metadata": {},
"outputs": [],
"source": [
"import polars as pl\n",
"\n",
"# Convert the existing 'spectrum_df' to Polars\n",
"df_polars = pl.from_pandas(spectrum_df)\n",
"\n",
"# ... perform your high-speed Polars operations here ...\n",
"\n",
"# Explicitly convert back to Pandas for memory-safe rendering\n",
"df_safe = df_polars.to_pandas()\n",
"\n",
"# Plot using the native pyopenms_viz plotting method\n",
"# (Using the 'mz' and 'intensity' columns from this notebook)\n",
"df_safe.plot(kind='spectrum', x='mz', y='intensity', backend='ms_bokeh')"
]
}
],
"metadata": {
Expand Down
3 changes: 2 additions & 1 deletion docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -312,7 +312,8 @@ def bokeh_scraper(block, block_vars, gallery_conf, **kwargs):
"binder": {
"org": "OpenMS",
"repo": "pyopenms_viz",
"branch": "gh_pages",
# Use the source branch for Binder launches; gh_pages is a deploy artifact branch.
"branch": "main",
"binderhub_url": "https://notebooks.gesis.org/binder",
"dependencies": "./requirements.txt",
},
Expand Down
2 changes: 1 addition & 1 deletion pyopenms_viz/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"""
init
"""

from . import _polars_accessor # Import for side effects: registers pandas accessors. noqa: F401
Comment thread
Sanjith1013 marked this conversation as resolved.

Copilot AI Mar 26, 2026

Copy link

Choose a reason for hiding this comment

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

The inline suppression is unlikely to be recognized by common linters because it uses noqa: inside a longer comment rather than # noqa: F401 at the end of the line. Also, this import registers a Polars namespace accessor (not a pandas accessor), so the comment is misleading. Suggest updating the comment and placing a proper # noqa: F401 marker at the end of the line (or removing it if F401 is not enforced).

Suggested change
from . import _polars_accessor # Import for side effects: registers pandas accessors. noqa: F401
from . import _polars_accessor # Import for side effects: registers Polars namespace accessor. # noqa: F401

Copilot uses AI. Check for mistakes.
from pandas.plotting._core import PlotAccessor
from pandas.core.frame import DataFrame
from typing import Any
Expand Down
30 changes: 30 additions & 0 deletions pyopenms_viz/_polars_accessor.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
"""
Polars namespace extension for pyopenms_viz.
"""
try:
import polars as pl
POLARS_AVAILABLE = True
except ImportError:
POLARS_AVAILABLE = False

if POLARS_AVAILABLE:
@pl.api.register_dataframe_namespace("ms_plot")
class PolarsPlotAccessor:
def __init__(self, df: pl.DataFrame):
self._df = df

def __call__(self, *args, **kwargs):
try:
# 1. Safety Catch: Use Arrow-backed arrays with a clear error fallback
pandas_df = self._df.to_pandas(use_pyarrow_extension_array=True)
Comment on lines +18 to +19

Copilot AI Mar 12, 2026

Copy link

Choose a reason for hiding this comment

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

to_pandas(use_pyarrow_extension_array=True) produces Arrow extension dtypes in pandas. Downstream code in this repo uses x.dtype.kind (e.g., numeric-vs-categorical branching), which can raise on extension dtypes and break plotting for Polars inputs. Consider omitting use_pyarrow_extension_array=True by default (or normalizing dtypes after conversion) unless the core pipeline is updated to use pandas.api.types checks instead of dtype.kind.

Suggested change
# 1. Safety Catch: Use Arrow-backed arrays with a clear error fallback
pandas_df = self._df.to_pandas(use_pyarrow_extension_array=True)
# 1. Safety Catch: Convert to a pandas DataFrame using default dtypes
pandas_df = self._df.to_pandas()

Copilot uses AI. Check for mistakes.
except (ImportError, ModuleNotFoundError) as exc:
Comment on lines +10 to +20

Copilot AI Mar 12, 2026

Copy link

Choose a reason for hiding this comment

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

New Polars plotting entrypoint is introduced here, but there are no tests covering that the ms_plot namespace is registered and that calling it produces the same output as the pandas path (including respecting pd.options.plotting.backend and/or backend='ms_*'). Adding a small pytest covering the conversion + delegation behavior would prevent regressions.

Copilot uses AI. Check for mistakes.
raise ImportError(
"Converting a Polars DataFrame to pandas failed because required "
"optional dependencies are missing. Please install 'pyarrow':\n"
" pip install pyarrow"
) from exc
Comment thread
Sanjith1013 marked this conversation as resolved.

# 2. Delegate to pandas' plotting API.
# This lets pandas resolve ms_* backends via entry points and respect
# the global `pd.options.plotting.backend` setting.
return pandas_df.plot(*args, **kwargs)
6 changes: 6 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,8 @@ plotly==5.24.1
# via pyopenms_viz (pyproject.toml)
pluggy==1.6.0
# via pytest
polars==1.38.1

prompt-toolkit==3.0.52
# via ipython
psutil==7.2.2
Expand All @@ -185,6 +187,8 @@ ptyprocess==0.7.0
# via pexpect
pure-eval==0.2.3
# via stack-data
pyarrow==23.0.1
# via polars
pycparser==3.0
# via cffi
pydata-sphinx-theme==0.16.1
Expand Down Expand Up @@ -215,6 +219,7 @@ pytz==2025.2
# via pandas
pyyaml==6.0.3
# via bokeh

pyzmq==27.1.0
# via
# ipykernel
Expand Down Expand Up @@ -307,3 +312,4 @@ webencodings==0.5.1
# tinycss2
xyzservices==2025.11.0
# via bokeh

Loading
Loading