Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
cdd4f74
refactor: use py_require instead of manual library installation
jorainer Jul 2, 2025
323d1d6
ci: remove forced installation of reticulate on macOS
jorainer Jul 2, 2025
68bed8e
ci: create a virtual env for macOS
jorainer Jul 2, 2025
faaac10
ci: create full virtualenv for macOS
jorainer Jul 2, 2025
ed4f98b
ci: next try to fix macOS GHA
jorainer Jul 3, 2025
661c1f7
ci: use RETICULATE_PYTHON_ENV on macOS
jorainer Jul 3, 2025
05f30db
ci: set RETICULATE_PYTHON_ENV to .Rprofile for macOS
jorainer Jul 3, 2025
9d639a6
docs: add labels to vignette code chunks
jorainer Jul 4, 2025
31c7833
docs: update/fix installation instructions
jorainer Jul 4, 2025
2422daf
refactor: force immediate loading of Python libraries
jorainer Jul 7, 2025
8dfc12e
refactor: replace msdata by MsDataHub
jorainer Jul 9, 2025
47ba84d
fix: add tryCatch to Python loading to print config
jorainer Jul 9, 2025
c9c77ab
fix: update NAMESPACE
jorainer Jul 9, 2025
ff51dbf
Change required Python version to 3.12
jorainer Jul 16, 2025
99baf1c
Print environment variables on failure
jorainer Jul 16, 2025
a55006a
tests: add tolerance to spectrum_utils rtime comparison
jorainer Aug 18, 2025
fb0139f
Require numpy >= 2.2.0
jorainer Aug 18, 2025
99428d7
ci: remove manual macOS config
jorainer Aug 19, 2025
b7ea816
ci: drop python installation on macOS
jorainer Aug 19, 2025
1f492e1
ci: install python from source in macOS
jorainer Aug 19, 2025
ff8cea4
refactor: fix unit test and update documentation
jorainer Aug 20, 2025
47f3f38
tests: add unit tests for package loading
jorainer Aug 21, 2025
eb65380
docs: add/expand installation instructions
jorainer Aug 22, 2025
8100454
docs: complete installation and troubleshooting
jorainer Aug 22, 2025
93b4fe6
Merge remote-tracking branch 'origin/main' into py_require
jorainer Aug 22, 2025
6096093
Remove links to BioC release
jorainer Aug 25, 2025
8a8c9b2
Address Marilyn's comments
jorainer Aug 26, 2025
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
6 changes: 2 additions & 4 deletions .github/workflows/check-bioc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,8 @@ jobs:
- name: Install macOS system dependencies part 1
if: matrix.config.os == 'macOS-latest'
run: |
brew install netcdf python pyenv
brew install netcdf
brew install --build-from-source python
shell: bash {0}

## Install R dependencies using R-lib
Expand Down Expand Up @@ -142,9 +143,6 @@ jobs:
- name: Install macOS system dependencies
if: matrix.config.os == 'macOS-latest'
run: |
install.packages("reticulate")
library(reticulate)
reticulate::install_python(version = "3.13:latest")
shell: Rscript {0}

- name: Install Windows system dependencies
Expand Down
10 changes: 5 additions & 5 deletions DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Package: SpectriPy
Title: Enhancing Cross-Language Mass Spectrometry Data Analysis with R and Python
Version: 0.99.5
Version: 0.99.11
Description: The SpectriPy package allows integration of Python-based MS
analysis code with the Spectra package. Spectra objects can be converted
into Python MS data structures. In addition, SpectriPy integrates
Expand Down Expand Up @@ -52,8 +52,8 @@ Authors@R: c(person(given = "Michael", family = "Witting",
comment = c(ORCID = "0009-0007-5429-6846"))
)
Depends:
R (>= 4.1.0),
reticulate
R (>= 4.4.0),
reticulate (>= 1.42.0)
Imports:
Spectra (>= 1.17.7),
IRanges,
Expand All @@ -65,7 +65,7 @@ Suggests:
testthat,
quarto,
MsBackendMgf,
msdata,
MsDataHub,
mzR,
knitr,
BiocStyle
Expand All @@ -75,7 +75,7 @@ URL: https://github.com/RforMassSpectrometry/SpectriPy
biocViews: Infrastructure, Metabolomics, MassSpectrometry, Proteomics
Encoding: UTF-8
SystemRequirements:
python (>= 3.10),
python (>= 3.12),
pandoc,
quarto
VignetteBuilder: quarto
Expand Down
11 changes: 3 additions & 8 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -32,27 +32,22 @@ importFrom(methods,"slot<-")
importFrom(methods,as)
importFrom(methods,is)
importFrom(methods,new)
importFrom(reticulate,conda_create)
importFrom(reticulate,conda_list)
importFrom(reticulate,import)
importFrom(reticulate,iterate)
importFrom(reticulate,np_array)
importFrom(reticulate,py)
importFrom(reticulate,py_available)
importFrom(reticulate,py_config)
importFrom(reticulate,py_del_attr)
importFrom(reticulate,py_dict)
importFrom(reticulate,py_eval)
importFrom(reticulate,py_get_attr)
importFrom(reticulate,py_has_attr)
importFrom(reticulate,py_install)
importFrom(reticulate,py_module_available)
importFrom(reticulate,py_require)
importFrom(reticulate,py_run_string)
importFrom(reticulate,py_set_attr)
importFrom(reticulate,py_to_r)
importFrom(reticulate,r_to_py)
importFrom(reticulate,use_condaenv)
importFrom(reticulate,use_virtualenv)
importFrom(reticulate,virtualenv_create)
importFrom(reticulate,virtualenv_exists)
importMethodsFrom(ProtGenerics,acquisitionNum)
importMethodsFrom(ProtGenerics,backendInitialize)
importMethodsFrom(ProtGenerics,centroided)
Expand Down
30 changes: 30 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,37 @@
# SpectriPy 0.99

## Changes in 0.99.11

- Add unit tests for package startup messages.
- Remove debug startup messages.
- Complete and clean installation and configuration documentation.

## Changes in 0.99.10

- Update installation and Python configuration settings.
- Check environment variables on package loading.

## Changes in 0.99.9

- Add tolerance for comparison of retention time with *spectrum_utils*.
- Require numpy version >= 2.2.0.

## Changes in 0.99.8

- Verbose startup messages and require Python 3.12.

## Changes in 0.99.7

- Replace the *msdata* package with *MsDataHub*.

## Changes in 0.99.6

- Set `delay_load = FALSE` in `import()` calls during package loading

## Changes in 0.99.5

- Replace Python library installation *via* virtualenv or conda with
`py_require()` from *reticulate* version > 1.41.0.
- Add support for parameter `data` to `backendInitialize()`: this enables to
change the backend from a `Spectra` object to `MsBackendPy` using the
`setBackend()` method.
Expand Down
1 change: 1 addition & 0 deletions R/MsBackendPython.R
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,7 @@
#' ## from matchms.importing import load_from_mgf
#' ## s_p = list(load_from_mgf(r.fl))
#' library(Spectra)
#' library(SpectriPy)
#' library(MsBackendMgf)
#'
#' fl <- system.file("extdata", "mgf", "test.mgf", package = "SpectriPy")
Expand Down
156 changes: 70 additions & 86 deletions R/zzz.R
Original file line number Diff line number Diff line change
Expand Up @@ -4,103 +4,87 @@ matchms_similarity <- NULL
matchms_filtering <- NULL
spectrum_utils <- NULL

.PY_PKGS <- c(matchms = "matchms==0.30.0",
spectrum_utils = "spectrum_utils==0.3.2",
numpy = "numpy==2.0.2")
.PY_PKGS <- c(matchms = "matchms>=0.30",
spectrum_utils = "spectrum_utils>=0.3.2",
numpy = "numpy>=2.2.0")

#' @importFrom reticulate import use_virtualenv use_condaenv
#'
#' @importFrom reticulate py_install virtualenv_exists virtualenv_create
#'
#' @importFrom reticulate conda_list conda_create
#' @importFrom reticulate py_require py_available
.onLoad <- function(libname, pkgname) {
if (!.spectripy_use_system()) {
if (.spectripy_use_conda()) .initialize_conda()
else .initialize_virtualenv()
}
.initialize_libraries2(TRUE, FALSE, asNamespace(pkgname))
.check_environment()
py_require(packages = .PY_PKGS, python_version = ">=3.12")
.initialize_libraries2(FALSE, FALSE, asNamespace(pkgname))
}

#' Load all required Python libraries and assign it to package-internal
#' variables
#'
#' @noRd
.initialize_libraries2 <- function(delay_load = TRUE, convert = FALSE,
envir = new.env()) {
assign("matchms", import("matchms", delay_load = delay_load,
convert = convert), envir = envir)
assign("matchms_similarity",
import("matchms.similarity", delay_load = delay_load,
convert = convert), envir = envir)
assign("matchms_filtering",
import("matchms.filtering", delay_load = delay_load,
convert = convert), envir = envir)
assign("spectrum_utils",
import("spectrum_utils", delay_load = delay_load,
convert = convert), envir = envir)
.check_environment <- function() {
## Check for old setup
if (.is_spectripy_use_system())
warning("Ignoring environment variable 'SPECTRIPY_USE_SYSTEM'. ",
"Please use 'RETICULATE_PYTHON' or 'RETICULATE_PYTHON_ENV'",
" instead.")
if (.is_spectripy_use_conda())
warning("Environment variable 'SPECTRIPY_USE_CONDA' is no longer ",
"supported. Please see the package vignette for updated ",
"Python setup options.")
se <- .spectripy_env()
if (length(se) && se != "")
warning("Environment variable 'SPECTRIPY_ENV' is no longer ",
"supported. Please use 'RETICULATE_PYTHON_ENV' instead. See ",
"the package vignette for updated Python setup options.")
## Potentially interfering global settings
if ((res <- Sys.getenv("RETICULATE_PYTHON")) != "")
packageStartupMessage("Using Python defined by 'RETICULATE_PYTHON': ",
res)
if ((res <- Sys.getenv("RETICULATE_PYTHON_ENV")) != "")
packageStartupMessage("Using Python environment defined by ",
"'RETICULATE_PYTHON_ENV': ", res)
}

#' Initialize the conda environment creating it if not already present
#'
#' @noRd
.initialize_conda <- function(envname = .spectripy_env()) {
if (!(envname %in% conda_list()$name)) {
packageStartupMessage("Creating conda environment '", envname, "'")
conda_create(envname)
}
packageStartupMessage("Using conda environment '", envname, "'")
use_condaenv(envname, required = TRUE)
.py_check_install(pkgs = .PY_PKGS[c("matchms", "spectrum_utils")],
envname = envname, use_conda = TRUE)
.is_spectripy_use_system <- function() {
res <- getOption("spectripy.use_system", default = NULL)
if (!length(res))
res <- Sys.getenv("SPECTRIPY_USE_SYSTEM")
grepl("1|yes|true", res, ignore.case = TRUE)
}

#' Initialize the Python virtualenv if not already present
#'
#' @noRd
.initialize_virtualenv <- function(envname = .spectripy_env()) {
if (!virtualenv_exists(envname)) {
packageStartupMessage("Creating virtual environment '", envname, "'")
virtualenv_create(envname, packages = FALSE)
}
packageStartupMessage("Using virtual environment '", envname, "'")
use_virtualenv(envname, required = TRUE)
.py_check_install(pkgs = .PY_PKGS[c("matchms", "spectrum_utils")],
envname = envname, use_conda = FALSE)
.is_spectripy_use_conda <- function() {
res <- getOption("spectripy.use_conda", default = NULL)
if (!length(res))
res <- Sys.getenv("SPECTRIPY_USE_CONDA")
grepl("1|yes|true", res, ignore.case = TRUE)
}

.spectripy_env <- function() {
getOption(
"spectripy.env", Sys.getenv("SPECTRIPY_ENV", unset = "r-spectripy"))
if(length(res <- getOption("spectripy.env", default = NULL)))
return(res)
Sys.getenv("SPECTRIPY_ENV")
}

.spectripy_use_conda <- function() {
as.logical(getOption(
"spectripy.use_conda",
Sys.getenv("SPECTRIPY_USE_CONDA", unset = "FALSE")))
}

.spectripy_use_system <- function() {
as.logical(getOption(
"spectripy.use_system",
Sys.getenv("SPECTRIPY_USE_SYSTEM", unset = "FALSE")))
}

#' @importFrom reticulate py_module_available py_install
.py_check_install <- function(pkgs, envname = .spectripy_env(),
use_conda = .spectripy_use_conda()) {
any_install <- FALSE
for (pkg in pkgs) {
if (!py_module_available(sub("(>|=).*$", "", pkg))) {
any_install <- TRUE
packageStartupMessage("Installing required library '", pkg,"'")
if (use_conda)
py_install(pkg, envname = envname, method = "conda",
pip = FALSE, channel = c("bioconda", "conda-forge"))
else py_install(pkg, envname = envname, method = "virtualenv",
channel = c("bioconda", "conda-forge"))
}
}
if (any_install)
packageStartupMessage("\nPlease restart R to load the freshly ",
"installed packages.\n")
#' Load all required Python libraries and assign it to package-internal
#' variables
#'
#' @importFrom reticulate import py_config
#'
#' @noRd
.initialize_libraries2 <- function(delay_load = TRUE, convert = FALSE,
envir = new.env()) {
if (!reticulate::py_available(initialize = TRUE))
stop("Unable to initialize the Python environment", call. = FALSE)
tryCatch({
assign("matchms", import("matchms", delay_load = delay_load,
convert = convert), envir = envir)
assign("matchms_similarity",
import("matchms.similarity", delay_load = delay_load,
convert = convert), envir = envir)
assign("matchms_filtering",
import("matchms.filtering", delay_load = delay_load,
convert = convert), envir = envir)
assign("spectrum_utils",
import("spectrum_utils", delay_load = delay_load,
convert = convert), envir = envir)
}, error = function(e) {
stop("Failed to initialize Python environment and libraries!\n",
"Original message: ", e, "\nPython configuration:\n",
print(py_config()), "\nEnvironmental variables:\n",
print(Sys.getenv()))
})
}
65 changes: 29 additions & 36 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
[![codecov](https://codecov.io/gh/rformassspectrometry/SpectriPy/branch/main/graph/badge.svg?token=638UZM0DXP)](https://codecov.io/gh/rformassspectrometry/SpectriPy)
[![license](https://img.shields.io/badge/license-Artistic--2.0-brightgreen.svg)](https://opensource.org/licenses/Artistic-2.0)
[![DOI](https://joss.theoj.org/papers/10.21105/joss.08070/status.svg)](https://doi.org/10.21105/joss.08070)
[![Ranking by downloads](http://bioconductor.org/shields/downloads/release/SpectriPy.svg)](https://bioconductor.org/packages/stats/bioc/SpectriPy/)
[![build devel](http://bioconductor.org/shields/build/devel/bioc/SpectriPy.svg)](https://bioconductor.org/checkResults/devel/bioc-LATEST/SpectriPy/)

![SpectriPy_logo](man/figures/logo_100.png)

Expand All @@ -28,49 +30,40 @@ If you use *SpectriPy* in your research, please cite:
[![DOI](https://joss.theoj.org/papers/10.21105/joss.08070/status.svg)](https://doi.org/10.21105/joss.08070)



# Installation

Detailed installation instructions can be found in the [installation and
configuration](https://rformassspectrometry.github.io/SpectriPy/articles/detailed-installation-configuration.html)
vignette. More advanced instructions and Python configuration, e.g. to use
*miniconda*-based instead of the default *virtualenv*-based setup can be found
in the [Startup and Python
configuration](https://rformassspectrometry.github.io/SpectriPy/articles/SpectriPy.html#sec-python)
section of the main vignette.

TLDR:

- Prerequisites: R >= 4.4.0.
- System requirement: *reticulate* (i.e., setup Python environment if not
already available)
*SpectriPy* needs Python (version >= 3.12) to be installed on the system. All
necessary Python libraries (listed below) are automatically installed by the
[*reticulate*](https://rstudio.github.io/reticulate) R package. *SpectriPy*'s
Python library management uses the
[`py_require()`](https://rstudio.github.io/reticulate/reference/py_require.html)
function introduced in *reticulate* version 1.41 and should hence work on most
system without problems. To install *SpectriPy*:

```r
#' R session:

install.packages("reticulate")
reticulate::install_miniconda()
install.packages("BiocManager")
BiocManager("SpectriPy")
```

- Package requirements: Bioconductor's *BiocManager*, *remotes*

```r
#' R session:
In addition it is possible to install the Python libraries manually (e.g., for
the system Python version) and specify the version of Python (or of the local
*virtualenv* or *conda* environment) using the `RETICULATE_PYTHON` or
`RETICULATE_PYTHON_ENV` environment variables. If any of these environment
variables are defined, all Python libraries listed below **must** be installed,
since *SpectriPy* (respectively *reticulate*) will not try to install them
automatically. The required Python libraries with the suggested and tested
versions are:

- [*matchms*](https://github.com/matchms) 0.30.0
- [*spectrum_utils*](https://github.com/bittremieux-lab/spectrum_utils) 0.3.2
- *numpy* 2.2.0

See also sections [*Startup and Python
configuration*](https://rformassspectrometry.github.io/SpectriPy/articles/detailed-installation-configuration.html#sec-python)
for more details or [*Fixing package installation or loading
problems*](https://rformassspectrometry.github.io/SpectriPy/articles/detailed-installation-configuration.html#sec-fix)
if installation or loading fails.

if (!require("BiocManager", quietly = TRUE))
install.packages("BiocManager")
BiocManager::install(version = "3.20")

install.packages("remotes")
```

- Package: *SpectriPy*

```r
#' R session:

BiocManager::install("RforMassSpectrometry/SpectriPy")
```

# Documentation for users

Expand Down
Loading
Loading