What’s New in Revision 1.0.0rc1

These are the changes in SpectroChemPy-1.0.0rc1. See Release notes for a full changelog, including other versions of SpectroChemPy.

New Features

  • Added differentiate, a discoverable public interface for smoothed numerical derivatives. It delegates to the existing Savitzky-Golay implementation and is available as both scp.differentiate(dataset) and dataset.differentiate(). The derivative order must be a positive integer no greater than the fitted polynomial order.

  • read_srs now exposes the OMNIC Collected series timestamp of SRS series through the standard acquisition_date dataset property (same convention as read_spa), and the Y coordinate of dated series gains a per-spectrum absolute datetime label column derived in full precision from the native series fields as Collected + timedelta(minutes=time_min + i * step). The numeric relative time axis and the spectrum-name labels are unchanged. Series without a valid native anchor (GC variants, reprocessed RapidScan files) leave acquisition_date unset and keep the names-only Y labels. (#1617)

Bug Fixes

  • Preserved the complete human-readable history when functional preprocessing operations are applied in place. The existing entries and the new transformer event are now retained without duplicating timestamps.

  • Corrected download_nist_ir so its NIST download event actually replaces the generic JCAMP import event while retaining subsequent reader history entries.

  • Corrected the SRS series meta.collection_length: it was the series first time (+1002, in minutes) incorrectly converted to seconds; it now equals the OMNIC “Total collection time”, i.e. the series last time (+1006, in minutes) converted to seconds. The time axis is unchanged and is still anchored at the series first time. Also fixed a resource leak in read_srs: the file handle opened by the reader is now closed on every exit path, including the early None returns and raised errors, instead of only on the success path. (#1613)

Breaking Changes

  • Removed the long-deprecated simps alias; use simpson instead.

  • Removed the long-deprecated force_stack compatibility behavior from concatenate; use stack directly.

Deprecations

  • Preferences.all() now emits the policy-compliant deprecation warning that starts its compatibility period in 1.0. Use Preferences.list_all() instead; no premature removal version is promised.

Developer

MAINT: Defined the SpectroChemPy 1.0 stability boundary in the public documentation: the package-wide experimental claim is removed and the status of each public feature (stable, experimental or deprecated) is now stated explicitly, so that behaviour kept in 1.0 is clearly committed.

MAINT: Aligned the six official plugins (carroucell, hypercomplex, iris, nmr, perkinelmer, tensor) and the plugin template on a single core compatibility contract spectrochempy>=0.12,<2 in both pyproject.toml and recipe.yaml. This admits the 1.0.0 release candidates (1.0.0rcN) and all 1.x final releases while excluding the next major (2.x). Rewrote .github/workflows/scripts/check_plugin_core_compatibility.py on top of packaging (correct PEP 440 semantics, including pre-releases) and made the gating scope explicit: the six official plugins are blocking, Cantera and the plugin template are informational only and never block a release. Added unit tests for the rewritten checker.

CI: Restored the publication of official plugins ([tool.spectrochempy] official-plugin = true) on Conda, which was silently skipped by the release workflow, and added a recovery workflow to republish plugin versions that are missing on spectrocat/main together with a consistency check between GitHub releases, PyPI and Conda. (#1611)

CI: Fixed the plugin Conda release validation: the discovered-plugins matrix (a JSON payload) was interpolated into shell scripts, whose parser stripped every inner double quote and made the “Verify plugin in discovered matrix” guard and the recipe-extraction step fail (or false-negative) on every plugin release. The matrix is now transported through an environment variable and validated by structured JSON parsing in conda_publish.py (matrix-contains / matrix-recipe). Also added the missing Conda recipe for spectrochempy-perkinelmer and made the repair workflow take a bare X.Y.Z version (tag derived and verified) with a closed plugin list; tags without a recipe are now recoverable from the canonical master recipe with a deterministic version injection and a core bound aligned with the tag pyproject (recipe_origin=master-fallback).

MAINT: Added .github/workflows/scripts/validate_release_artifacts.py, a standalone validator for release artifacts (Python wheel + sdist and Conda packages) that checks metadata consistency, archive safety, signature compatibility, installability and smoke-tests, including an exact check of the installed distribution version, plus its unit tests and the .github/workflows/validate_release_artifacts.yml workflow. Complete Python validation requires twine. It never publishes anything or requires secrets. This first milestone validates locally rebuilt artifacts but does not yet retain them between jobs or gate the independent publication workflow; artifact upload is deferred to a later PR.

CI: Added .github/workflows/scripts/release_version.py, a single source of truth for release-candidate semantics built on packaging.version.Version (accepts only canonical X.Y.Z or X.Y.ZrcN, derives tag name, GitHub prerelease flag, release-note filename, documentation version and next development version), and wired it into the release workflows. The release candidate input is now validated in prepare_new_release.yml; publish_draft_new_release.yml derives the prerelease flag and tag from the helper instead of hardcoding prerelease: false; update_version_and_release_notes.py preserves the rcN suffix in CITATION.cff, Zenodo metadata and the release-note index; build_package.yml/validate_release_artifacts.yml compute the next development version from the helper; docs/make.py, docs/conf.py and versions.js build release-candidate documentation as root/latest and keep archives stable-only; build_docs_archived_versions.yml skips RC tags. Included the focused script tests and the documented RC release procedure.

CI: Removed the URL substring matching reported by CodeQL (py/incomplete-url-substring-sanitization) in the conda_publish.py tests: test doubles and URL assertions now compare the exact hostname parsed with urllib.parse.urlparse instead of checking "host" in url.