Release v0.8.2#138
Merged
Merged
Conversation
Signed-off-by: Andrew Mitchell <a.j.mitchell@ucl.ac.uk>
- Add CircE package availability checking and version validation - Integrate CircE package into R session initialization and management - Update package installation to handle GitHub-hosted CircE package - Modify session getter to return CircE package instance - Update tests to verify CircE package checking functionality
- Implement BFGS algorithm wrapper for circe package - Add model type enumeration and constraints handling - Update rpy2 dependency to include [all] extras - Export EQUAL_ANGLES from survey_utils module
Add CircEResult dataclass and bfgs wrapper function to public API, with improved type validation and result extraction from R circe package.
…d update imports Signed-off-by: Andrew Mitchell <a.j.mitchell@ucl.ac.uk>
Signed-off-by: Andrew Mitchell <a.j.mitchell@ucl.ac.uk>
Signed-off-by: Andrew Mitchell <a.j.mitchell@ucl.ac.uk>
Signed-off-by: Andrew Mitchell <a.j.mitchell@ucl.ac.uk>
Signed-off-by: Andrew Mitchell <a.j.mitchell@ucl.ac.uk>
Signed-off-by: Andrew Mitchell <a.j.mitchell@ucl.ac.uk>
Signed-off-by: Andrew Mitchell <a.j.mitchell@ucl.ac.uk>
Signed-off-by: Andrew Mitchell <a.j.mitchell@ucl.ac.uk>
Signed-off-by: Andrew Mitchell <a.j.mitchell@ucl.ac.uk>
Signed-off-by: Andrew Mitchell <a.j.mitchell@ucl.ac.uk>
…e121 Mitchell acoustics/issue121
refactor: remove RTHORR package integration and related checks
#127) * fix: remove global rpy2 converters, fix n bug, and lazy R session init - Replace deprecated numpy2ri.activate()/pandas2ri.activate() with explicit context managers throughout _rsn_wrapper.py, resolving issue #111 - Add _r2np() helper for consistent R→numpy conversion via context manager - Fix correctness bug: bfgs() now requires explicit n (sample count) parameter instead of silently using data_cor.shape[0] (which returned 8 — the variable count — not the participant count), causing incorrect chi-square and RMSEA statistics - Update CircE.compute_bfgs_fit() and SATP.run() to pass the correct n - Remove module-level get_r_session() calls from _circe_wrapper.py and _rsn_wrapper.py; session is now acquired lazily inside each function - Remove _raw_bfgs_fit: ro.ListVector from CircE dataclass to avoid keeping live R objects in long-lived Python dataclasses - Remove unused ro import and ConfigDict from circe.py Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: use scipy for chi2 p-value and restore ConfigDict in CircE Replace stats_package.pchisq() with scipy.chi2.sf() in extract_bfgs_fit() to avoid the rpy2 py2rpy conversion failure: pandas2ri.converter produces pandas Series from rpy2py, which cannot be passed back to R outside the context. scipy.chi2.sf(x, df) == 1 - pchisq(x, df) by definition. Also restore ConfigDict(arbitrary_types_allowed=True) on the CircE dataclass, required for the polar_angles: pd.DataFrame | None field. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: remove R object storage from MultiSkewNorm and tighten bfgs() context MultiSkewNorm.fit() was storing the rpy2 RS4 selm_model object as an instance attribute, creating a persistent reference into R's heap that can outlive the R session. Since cp and dp are extracted immediately after fitting, the R object is no longer needed. Sampling now always goes through the dp (Direct Parameters) branch, which constructs the required R vectors on the fly. Also extend the converter context in bfgs() to include the as_matrix() call, keeping all DataFrame→R operations within the same context boundary. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * refactor: lazy-load R modules and improve optional-dep handling soundscapy/__init__.py - Replace unconditional try/except imports of spi/satp with module-level __getattr__ + __dir__ (PEP 562). R now only starts when the user first accesses sspy.satp, sspy.spi, sspy.SATP, sspy.MultiSkewNorm, etc. - Use importlib.import_module() for dynamic sub-module loading. - __dir__ exposes all lazy names to dir() and IDE autocomplete. _r_wrapper.py - Add RSession NamedTuple return type for get_r_session(). Callers now use r.sn / r.base / r.circe instead of fragile positional unpacking. - Add _ver() helper for tuple-based version comparison, fixing a lexicographic bug where "1.10" < "1.2" was True (affected CircE and sn version checks). - Rename copy-paste error _raise_sn_check_error -> _raise_circe_check_error inside check_circe_package(). - Remove stale comment about imports "not used in the code". _circe_wrapper.py / _rsn_wrapper.py - Update all get_r_session() call sites to use RSession named fields. - Move base.as_matrix() call back outside the pandas2ri converter context to prevent its R-matrix return value being auto-converted to numpy. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * test: update MSN tests to reflect removal of selm_model attribute Remove `selm_model` assertions from test_init and three fit tests (test_fit_with_dataframe, test_fit_with_numpy_array, test_fit_with_x_y) since the R RS4 object is no longer stored on the instance. Update test_sample_not_fitted_or_defined error message match to reflect the new message raised by MultiSkewNorm.sample() rather than the old message from the underlying _rsn_wrapper.py sample_msn() function. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: correct p-value df, clean up r_wrapper, add CircE integration tests - Fix p-value calculation in extract_bfgs_fit() to use model df ('d') not null model df ('dfnull'); p was ~0.95 instead of the correct ~0.041 - Fix circe.py CircE.df field to map from 'd' not 'dfnull' - Remove dead 'R not found' error paths from check_r_availability() (R is always already running by the time the function is called) - Rename shutdown_r_session() -> reset_r_session() to accurately reflect that only Python package references are cleared; R process stays alive - Update test_r_wrapper.py and test_MSN.py for the above changes - Replace stale test_cp2dp skip with a dp→cp→dp2cp round-trip test - Add test/satp/test_circe.py: integration tests for bfgs() and extract_bfgs_fit() verified against the vocational interests example from CircE.BFGS.Rd (exact reference values from the R package), plus structural tests for CircE.compute_bfgs_fit() and SATP pipeline Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * refactor: improve public API, install prompt, and warning placement - Strip r_wrapper.__all__ to empty: it is an internal implementation package; user-facing names live in soundscapy.spi / soundscapy.satp - Replace AUTO_INSTALL_R_PACKAGES=True with _confirm_install_r_packages(): checks SOUNDSCAPY_AUTO_INSTALL_R env var first (CI/script opt-in), then prompts interactively when stdin is a TTY, otherwise does nothing - Move experimental UserWarning from module-level into SATP.__init__ and MultiSkewNorm.__init__ so stacklevel=2 points at the user's call site and Python's default filter deduplicates per call location - Remove now-unused `import warnings` from satp/__init__ and spi/__init__ - Add spi_score to _SPI_ATTRS so sspy.spi_score works via lazy loading - Add comment in _r_wrapper.py and _rsn_wrapper.py explaining that R starts unconditionally when rpy2 is imported Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: polar_angles key name, type comparison, scalar normalisation, PKG_SRC ordering - circe.py from_bfgs(): fix model_type comparison — was comparing a ModelType dataclass against CircModelE enum members (always False); must compare model_type.name against the enum - circe.py from_bfgs(): fix key name — R returns 'polar.angles' (dot), not 'polar_angles' (underscore); polar_angles was always None for every model - _circe_wrapper.py extract_bfgs_fit(): normalise all shape-(1,) numpy arrays to Python scalars so callers never need .item() and numpy >= 1.25 DeprecationWarnings are eliminated - _r_wrapper.py: move PKG_SRC definition above _confirm_install_r_packages() which references it, fixing forward-reference style issue - test_circe.py: add polar_angles tests for free-angle and constrained models; update .item() calls that are now redundant after scalar normalisation Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * refactor: remove unused calc_cp and calc_dp from _rsn_wrapper Both functions are dead code — no call site exists in src, tests, or docs. MultiSkewNorm.fit() calls selm() + extract_cp() + extract_dp() separately to share the single fitted model object; calc_cp/dp would call selm() twice, doubling R computation for the most common use case. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: clean up r_wrapper error handling, fix DataFrame mutation bug, improve docs and test coverage - Remove redundant `from rpy2 import robjects` re-imports in check_sn_package, check_circe_package, and initialize_r_session (module-level import already covers these) - Replace fragile `if "sn" in str(e)` / `if "CircE" in str(e)` string-matching with canonical `except ImportError: raise` / `except Exception as e:` split - Fix MultiSkewNorm.fit() mutating the caller's DataFrame in-place via data.columns=["x","y"]; now copies before renaming - Fix stale MultiSkewNorm class docstring: ks2ds→ks2d2s, spi→spi_score, add sample_mtsn - Expand msn.py module docstring to document standalone public functions - Replace vague TODO in DirectParams.from_cp warning with specific message - Remove dead test_initialize_r_session_fails (always skipped, assertions referenced non-existent error strings) - Add _ver() unit tests covering lexicographic comparison correctness - Add sample_mtsn() tests: shape, bounds enforcement, sample_data storage, unfitted error - Add from_params() branch coverage: DirectParams, CentredParams, CP kwargs, no-args error - Add test_fit_does_not_mutate_input_dataframe regression test - Replace TODO comments in ks2d2s/spi_score tests with concrete range assertions - Add test_soundscapy_satp_module and test_satp_import_error to test_basic.py for symmetric SATP coverage alongside existing SPI tests - Remove commented-out dead assertions in test_soundscapy_spi_module Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: address three code-review issues in PR #127 - Regression test for DataFrame mutation was vacuous (MOCK_DF already has ["x","y"] columns); use ["ISOPleasant","ISOEventful"] so a reintroduced bug would be visible - Fix PKG_SRC.CIRCE assertion to use .value (str(enum) yields "PKG_SRC.CIRCE", not the underlying install-path string) - from_params(xi=..., omega=..., alpha=...) was leaving instance.cp=None; add CentredParams.from_dp() call after setting instance.dp - Add test_from_params_with_xi_omega_alpha_kwargs_sets_cp to cover the fixed branch Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * style: fix ruff lint and format issues in changed modules - r_wrapper/__init__.py: add noqa F401 on re-export imports - _r_wrapper.py: noqa N801 (PKG_SRC), noqa BLE001 (exception wrappers), restructure try/except/else to satisfy TRY300 - msn.py: shorten over-long comment (E501) - test_MSN.py: rename df→input_df (PD901), shorten docstring (E501), add match= to pytest.raises (PT011) - test_circe.py: use [*PAQ_IDS, ...] unpacking (RUF005), inline rename for RET504, shorten assertion messages (E501), fix docstring (D205) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: address code-review issues (correctness, masking, CI packages) **CIRCUMPLEX model equal_ang was wrong (correctness bug)** The four CircE models form a 2×2 grid of {equal, free} × {angles, comms}. EQUAL_COM should have *free* angles (equal_ang=False), and CIRCUMPLEX should have *both* constrained (equal_ang=True, equal_com=True). The previous sets had them swapped, so CIRCUMPLEX and EQUAL_COM were producing identical CircE_BFGS calls. Confirmed by the polar_angles tests. **ImportError masking in check_r_availability** _raise_r_version_too_old_error raises ImportError, which was caught by the bare `except Exception` and re-wrapped with "Error querying R version", swallowing the informative "R version X is too old" message. Added `except ImportError: raise` before the generic handler. **R version float formula replaced with _ver() tuple comparison** `major + minor/10` fails for multi-digit minor versions and is inconsistent with the _ver() utility added for exactly this purpose. Now uses `paste(major, minor, sep='.')` → _ver() comparison. **Double-ipsatize guard** ipsatize() had an _ipsatized flag but never checked it. A second call would KeyError because groupby.transform drops the `participant` column. Added an early return with a warning. **numpy import moved to module level in _circe_wrapper.py** **DESCRIPTION: add CircE GitHub remote for CI** setup-r-dependencies installs packages from DESCRIPTION. Only `sn` was listed; `CircE` (from GitHub) was missing, causing the py311-r CI job to fail with PackageNotInstalledError. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: add CircE GitHub dependency via usethis Use usethis::use_dev_package() to add CircE to DESCRIPTION in the canonical R format: Imports field with version pin (>= 1.1) plus a Remotes entry pointing to MitchellAcoustics/CircE-R on GitHub. r-lib/actions/setup-r-dependencies reads this via pak, which fetches the GitHub repo DESCRIPTION to resolve the package name → source mapping. No workflow changes needed; this is the standard R approach for non-CRAN dependencies. Also reverts the erroneous extra-packages workflow addition from the previous commit. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: use pak-required Package=user/repo syntax for CircE GitHub remote pak/pkgdepends cannot auto-map a package name to a repository when they differ (CircE package vs CircE-R repo). The explicit `CircE=MitchellAcoustics/CircE-R` syntax in the Remotes field tells pak which GitHub repo satisfies the `CircE (>= 1.1)` Imports dependency, fixing the CI failure in setup-r-dependencies. Also removes the commented-out (dead) Rscript lines from the py-r tox environment. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: add explicit R package install to py-r tox env and fix CircE pak syntax setup-r-dependencies installs R packages into a library that rpy2 cannot see from within the tox virtualenv. The explicit `Rscript -e "if(!require(...)) { pak::... }"` pattern in commands_pre is the reliable workaround (same pattern py-all already uses successfully). Changes: - py-r: add Rscript install steps for sn and CircE (was missing entirely) - py-all, py-tutorials: update CircE pak ref to explicit Package=user/repo syntax (`CircE=MitchellAcoustics/CircE-R`) required when the package name differs from the repo name Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * style: clean up tox.ini comments and remove redundant header - Remove redundant `# tox.ini` file header - Unify R install comment across py-r, py-all, py-tutorials to accurately describe both packages being installed (sn and CircE) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: address six code-review issues in R wrapper and tox config - _r_wrapper.py: add missing single-quotes around PKG_SRC.CIRCE.value in three CircE error-message f-strings (produced invalid R syntax) - _r_wrapper.py: remove dead 'tvtnorm' from install_r_packages() default list and update stale docstring - _r_wrapper.py: reset _sn_checked/_circe_checked in reset_r_session() and update docstring to accurately describe re-verification behaviour - _rsn_wrapper.py: add max_iter=100_000 guard to sample_mtsn() rejection loop; raises RuntimeError with a clear message instead of hanging forever when the distribution has negligible mass inside [a, b] - circe.py: change self.data annotation from pandera DataFrame to pd.DataFrame since ipsatize() overwrites it with an unvalidated result - tox.ini: replace pak::local_install_deps() with pak::pkg_install('sn') for direct, reliable sn installation; add quietly=TRUE to both require() guards Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: code-review round 2 — sentinel bug, type fixes, rename CircE.df→d - sample_mtsn: replace sentinel-row + np.append loop with list accumulation + np.vstack; add max_iter guard against infinite loops - REQUIRED_R_VERSION: change from float 3.6 to str "3.6" to avoid str(4.10) == "4.1" pitfall with future two-digit minor versions - reset_r_session: reset _sn_checked/_circe_checked flags so next call re-verifies package availability from scratch - test_r_wrapper: remove unreachable SPI_DEPS branching; tests already gated by optional_deps("r") so both branches always run with R present - msn.py: remove ks2d() from module docstring — no such top-level fn - CircE.df → CircE.d to match raw R output key; update from_bfgs(), test_circe.py (4 refs), and scratch/circe_test.py integration script Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * refactor: consolidate 9 module globals into RSession dataclass Replace the nine scattered module-level globals (_r_checked, _sn_checked, _circe_checked, _r_session, _sn_package, _circe_package, _stats_package, _base_package, _session_active) with a single @DataClass RSession instance (_state). Key changes: - RSession promoted from NamedTuple return type to mutable @DataClass state container, adding active/r_checked/sn_checked/circe_checked fields and an is_ready property - _state = RSession() is the sole module-level state; functions mutate its attributes directly — no global declarations needed (mutating an object attribute does not rebind the module-level name) - reset_r_session() becomes: global _state; _state = RSession() — atomically clears all state including check flags, making it impossible to forget a field (fixes the _r_checked omission found in code review) - get_r_session() validation collapses to: if not _state.is_ready - initialize_r_session() error path calls reset_r_session() for clean retry - is_session_active() needs no global declaration - Module docstring updated to explain the _state singleton pattern Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: Andrew Mitchell <andrew.mitchell.research@gmail.com> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
…iner Implements the top-priority recommendations from the SATP circumplex validation analysis review: - fix: SATPSchema now raises SchemaErrors by default instead of silently dropping invalid rows (drop_invalid_rows=False); fit_circe gains an errors='raise'|'warn' parameter for opt-in lenient behaviour - fix: fit_circe uses grand-mean centering (1 scalar/participant) matching the published SATP R analysis; column-wise centering (8 scalars/participant) was the previous incorrect default, causing SRMR values ~0.005 higher than canonical R values - feat: add soundscapy.surveys.ipsatize(method='grand_mean'|'column_wise'| 'row_wise') — unified ipsatization entry point living in core surveys/ module (no R dependency); person_center() becomes a thin wrapper with a deprecation note - feat: fit_circe returns CircEResults instead of a bare DataFrame; provides .table (DataFrame), .for_model(CircModelE), ._repr_html_(), and len(); CircE dataclass instances are preserved with all typed attributes - test: new TestIpsatize in test/surveys/ (core, no R); new CircEResults tests; existing test_circe.py updated for new return type Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- fix(ipsatize): use np.nanmean() for grand-mean centering so participants with partial NaN data get a valid grand mean from available values, rather than the whole participant being silently wiped when any NaN is present - fix(fit_circe): use .loc[~index.isin()] instead of .drop(index=) in the errors='warn' path to correctly handle duplicate DataFrame indices; report accurate remaining row count; wrap second validate() call to prevent unhandled SchemaErrors leaking from the warn path - docs: clarify models=[] returns CircEResults not a DataFrame; disambiguate 'the default' in person_center deprecation note Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replaces marker-based optional test filtering with import-based skipping to match runtime behavior. Adds slim-install guard coverage and helper-unit tests to prevent eager optional imports. Aligns local and CI tasks so matrix jobs exercise the same test entry points.
Explains the new gate-and-deferral model and clarifies how contributors add optional features safely. Updates workflow guidance to reflect current tooling and task structure. Captures the full developer-experience improvements in release notes.
Improves version-task flexibility and ensures publish flows refresh generated environment artifacts. Updates environment constraints for compatibility and removes redundant runtime variables. Cleans up obsolete packaging metadata while advancing development versioning.
Removes outdated lint suppressions and adopts the standard library typing import where available. Stabilizes logging tests by restoring logger state after debug assertions. Keeps incidental quality fixes separate from larger behavior changes for easier review.
Switches local IDE environment and package manager defaults to the project-managed workflow. Reduces setup drift for contributors working in the shared development environment.
Both branches added dev dependencies; combined types-tqdm (our branch) and jupyter-repo2docker (dev branch) in feature.dev.dependencies. Kept our improved test tasks and pixi.lock. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…oading (#137) refactor: standardize optional dependency handling with SPEC 1 lazy loading
…bump Consolidates the v0.8.0rc1..v0.8.0rc10 + v0.8.2.dev1 pre-release line into a single shipping release. Reorganises CHANGELOG.md (and the docs mirror) to lead with breaking changes, adds a dedicated upgrade-from-0.7 guide, adds a release announcement to docs/news.md, wires the migration page into the zensical nav, refreshes the README disclaimer, and bumps pyproject.toml from 0.8.2.dev1 to 0.8.2. No code changes — release prep only. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Contributor
There was a problem hiding this comment.
Pull request overview
Release PR that merges dev into main for Soundscapy v0.8.2, consolidating the long prerelease line into a single stable release. It updates packaging/tooling (Pixi + uv, Zensical docs), adds/ships embedded CircE R scripts, and standardizes optional-dependency gating + lazy loading.
Changes:
- Finalize release packaging/tooling: version bump to
0.8.2, Pixi task matrix, uv build backend, CI workflow updates, and Zensical docs config/nav. - Adopt SPEC 1-style lazy loading + standardized optional-dependency gates (
_optional.py) with slim-install tests. - Documentation + changelog + migration materials refreshed for the 0.7 → 0.8 upgrade path; tests reorganized to use
pytest.importorskipper optional subtree.
Reviewed changes
Copilot reviewed 129 out of 149 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
| zensical.toml | New Zensical site configuration + nav for migrated docs. |
| tox.ini | Updates tox envs (docs via Zensical; spi→r extras rename). |
| test/test_sspylogging.py | Ensures logging is cleaned up after enabling debug in tests. |
| test/test_slim_install.py | Adds slim-install tests verifying lazy import + gate error messages. |
| test/test_optional_helper.py | Unit tests for the new optional-deps helper. |
| test/test_basic.py | Updates basic import tests to use pytest.importorskip for optional deps. |
| test/surveys/test_survey_utils.py | Test refactors (naming/style + minor assertion modernizations). |
| test/spi/test_r_wrapper.py | Updates R wrapper tests and adds pure-Python _ver tests. |
| test/spi/conftest.py | Skips SPI test tree unless rpy2 is installed. |
| test/satp/conftest.py | Skips SATP test tree unless rpy2 is installed. |
| test/satp/init.py | Declares SATP test package (enables per-tree behavior). |
| test/plotting/test_plotting_deprecated.py | Adjusts deprecated plotting tests (typing ignores, warning matching). |
| test/plotting/test_plot_functions.py | Plot function tests updates (incl. RNG handling change). |
| test/generate_baselines.py | Baseline generation script cleanup (Path/logging, RNG call). |
| test/databases/test_satp.py | Updates SATP dataset load test to new import path. |
| test/databases/test_isd.py | Test refactors + regex match tweak + type checks modernization. |
| test/audio/test_metrics.py | Migrates unittest-style assertions to pytest asserts. |
| test/audio/test_binaural.py | Uses default_rng for deterministic arrays; tightens error match. |
| test/audio/test_audio_analysis.py | Uses Path.open, improves assertion formatting, tightens error match. |
| test/audio/test_analysis_settings.py | Uses Path.open and simplifies channel assertions. |
| test/audio/conftest.py | Skips audio test tree unless audio extras are installed. |
| src/soundscapy/surveys/survey_utils.py | Adds a Pandera DataFrameModel schema for PAQ frames + docstring cleanup. |
| src/soundscapy/surveys/init.py | Re-exports ipsatize from surveys processing. |
| src/soundscapy/sspylogging.py | Docstring formatting tweaks for logging helpers. |
| src/soundscapy/spi/ks2d.py | Docstring formatting tweaks. |
| src/soundscapy/spi/init.pyi | Adds PEP 561 stub for lazy-loaded SPI exports. |
| src/soundscapy/spi/init.py | Switches SPI to gate + lazy loading via stub. |
| src/soundscapy/satp/init.pyi | Adds PEP 561 stub for lazy-loaded SATP exports. |
| src/soundscapy/satp/init.py | Adds SATP gate + lazy loading via stub. |
| src/soundscapy/r_wrapper/r_circe/residual.CircE.R | Bundles embedded CircE R scripts. |
| src/soundscapy/r_wrapper/r_circe/CircE.Plot.R | Bundles embedded CircE R scripts. |
| src/soundscapy/r_wrapper/r_circe/char.assign.R | Bundles embedded CircE R scripts. |
| src/soundscapy/r_wrapper/r_circe/bound.assign.R | Bundles embedded CircE R scripts. |
| src/soundscapy/r_wrapper/_rsn_wrapper.py | Refactors skew-normal wrapper conversion + adds max_iter guard for truncated sampling. |
| src/soundscapy/r_wrapper/_circe_wrapper.py | Adds CircE BFGS wrapper + fit-stat extraction in Python. |
| src/soundscapy/r_wrapper/init.py | Adds r_wrapper gate + controlled internal exports. |
| src/soundscapy/plotting/plot_context.py | Docstring formatting tweaks. |
| src/soundscapy/plotting/likert.py | Docstring improvements + removes unnecessary type: ignore on apply; adds stacked_likert docstring. |
| src/soundscapy/plotting/layers.py | Docstring formatting tweaks + minor comment formatting. |
| src/soundscapy/plotting/backends_deprecated.py | Tightens ruff ignore list. |
| src/soundscapy/databases/satp.py | Adds SATPVersion enum + version normalization + updated examples. |
| src/soundscapy/databases/isd.py | Docstring and parameter docs improvements. |
| src/soundscapy/audio/parallel_processing.py | Docstring cleanup, error handling lint suppression, and main-guard script tweaks. |
| src/soundscapy/audio/audio_analysis.py | Docstring cleanup + removes PERF noqa from broad exception block. |
| src/soundscapy/audio/analysis_settings.py | Docstring cleanup + corrects “Parameters”→“Attributes” wording for models. |
| src/soundscapy/audio/init.pyi | Adds PEP 561 stub for lazy-loaded audio exports. |
| src/soundscapy/audio/init.py | Switches audio to gate + lazy loading via stub. |
| src/soundscapy/_optional.py | New helper for consistent optional-dependency ImportErrors without side effects. |
| src/soundscapy/init.pyi | Adds PEP 561 stub driving top-level lazy re-exports. |
| src/soundscapy/init.py | Adds SPEC 1 lazy loading + switches __version__ to package metadata + reorganizes exports. |
| scripts/update-environment-yml.py | Adds script to sync exported conda env pip spec with pyproject version. |
| README.md | Updates upgrade messaging + adds [r] extra installation guidance. |
| pyproject.toml | Release version bump, uv build backend config, new deps, extras rename spi→r, and ruff/pytest config updates. |
| pixi.toml | New Pixi workspace + feature envs + tasks for lint/tests/docs/build/publish. |
| mkdocs.yml | Removes mkdocs configuration (docs migrated to Zensical). |
| examples/updated_config.yaml | Adds/updates example audio config file. |
| examples/example_settings.yaml | Adds example settings YAML for audio analysis. |
| examples/1_Understanding_Soundscape_Analysis.ipynb | Updates tutorial notebook content/metadata. |
| examples/.gitignore | Ignores Quarto/Zensical tutorial render artifacts. |
| environment.yml | Adds exported conda environment definition for R+audio installs. |
| docs/tutorials/.gitignore | Ignores rendered tutorial outputs directory. |
| docs/stylesheets/extra.css | Tweaks theme CSS (grid width, minor formatting). |
| docs/reference/surveys.md | Reworks reference page structure for mkdocstrings under Zensical. |
| docs/reference/spi/msn.md | Removes standalone msn reference page (consolidated). |
| docs/reference/spi.md | Reworks SPI reference layout (separate sections). |
| docs/reference/soundscapy.md | Adds top-level soundscapy API reference page. |
| docs/reference/satp.md | Adds SATP reference page. |
| docs/reference/plotting/plot_functions.md | Renames heading + adds mkdocstrings options. |
| docs/reference/plotting/plot_context.md | Renames heading + adds mkdocstrings options. |
| docs/reference/plotting/param_models.md | Cleans up page + mkdocstrings options. |
| docs/reference/plotting/likert.md | Simplifies heading + mkdocstrings options. |
| docs/reference/plotting/layers.md | Simplifies heading + mkdocstrings options. |
| docs/reference/plotting/iso_plot.md | Renames heading + mkdocstrings options. |
| docs/reference/plotting/index.md | Adds plotting index page for Zensical nav. |
| docs/reference/plotting/defaults.md | Renames heading + mkdocstrings options. |
| docs/reference/plotting.md | Removes old aggregated plotting reference page. |
| docs/reference/internals/utilities.md | Adds developer reference page for internal utilities. |
| docs/reference/internals/r-internals.md | Adds developer reference page for R wrappers. |
| docs/reference/internals/plotting-internals.md | Adds developer reference page for plotting internals. |
| docs/reference/internals/logging.md | Adds developer reference page for logging helpers. |
| docs/reference/internals/index.md | Adds developer reference landing page. |
| docs/reference/index.md | Adds API reference landing page + curated module links. |
| docs/reference/databases.md | Reworks databases reference page for Zensical + mkdocstrings. |
| docs/reference/audio/parallel_processing.md | Adds per-module audio reference page. |
| docs/reference/audio/metrics.md | Adds per-module audio reference page. |
| docs/reference/audio/index.md | Adds audio reference index page + structure. |
| docs/reference/audio/binaural.md | Adds per-module audio reference page. |
| docs/reference/audio/audio_analysis.md | Adds per-module audio reference page. |
| docs/reference/audio.md | Removes old aggregated audio reference page. |
| docs/reference/api.md | Removes old “core API” reference page. |
| docs/news.md | Adds v0.8.2 release announcement + embedded CircE runtime note. |
| docs/migration-0.7-to-0.8.md | Adds 0.7→0.8.2 migration guide. |
| docs/license.md | Updates license include/snippet syntax for new docs toolchain. |
| docs/javascripts/mathjax.js | Updates MathJax handling for annotation components. |
| docs/index.md | Updates landing page messaging + adds [r] extra guidance. |
| docs/CHANGELOG.md | Reworks docs changelog with 0.8.2 release structure and details. |
| DESCRIPTION | Removes obsolete R DESCRIPTION file. |
| CHANGELOG.md | Reworks root changelog with 0.8.2 release structure and details. |
| .vscode/settings.json | Adds VS Code settings aligned with Pixi workflow and tooling. |
| .readthedocs.yaml | Switches RTD build to Zensical output copy. |
| .pre-commit-config.yaml | Updates pre-commit hooks (tabs, prettier, optional pyrefly stub). |
| .markdownlint.yaml | Disables MD046 rule. |
| .gitignore | Updates ignores (pixi envs, conda build outputs, editor configs). |
| .github/workflows/test.yml | Migrates CI tests from tox/uv to Pixi task matrix across OSes. |
| .github/workflows/test-conda-install.yml | Adds workflow to build and locally install conda package via Pixi. |
| .github/workflows/linting.yml | Switches lint workflow to Pixi + Prek action. |
| .github/workflows/docs.yml | Migrates docs workflow to Pixi + Zensical; adds Pages deploy job. |
| .gitattributes | Marks pixi.lock as binary/linguist-generated to avoid merge conflicts. |
| .envrc | Adds direnv setup for Pixi and local publish credentials (from local files). |
| .devcontainer/Dockerfile | Adds devcontainer base with Pixi installed. |
| .devcontainer/devcontainer.json | Adds devcontainer config for Pixi-driven development. |
| .devcontainer/devcontainer-lock.json | Pins devcontainer feature versions. |
Comments suppressed due to low confidence (1)
pyproject.toml:99
- Pytest is no longer configured with an
optional_deps(...)marker (see[tool.pytest.ini_options].markers), but many tests intest/spi/andtest/satp/still use@pytest.mark.optional_deps(...). This will emitPytestUnknownMarkWarning(and can fail under stricter warning settings). Either re-add the marker declaration here, or remove/replace the marker usage now that per-directoryconftest.pyusespytest.importorskip.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Agent-Logs-Url: https://github.com/MitchellAcoustics/Soundscapy/sessions/739e517d-1701-4f3b-9b7d-dcbe307344a9 Co-authored-by: MitchellAcoustics <22335636+MitchellAcoustics@users.noreply.github.com>
Agent-Logs-Url: https://github.com/MitchellAcoustics/Soundscapy/sessions/739e517d-1701-4f3b-9b7d-dcbe307344a9 Co-authored-by: MitchellAcoustics <22335636+MitchellAcoustics@users.noreply.github.com>
tox.ini is fully superseded by pixi tasks and workflows — CI has used pixi exclusively since PR #134. Three dead tox references in pyproject.toml are cleaned up alongside the deletion (coverage paths, tomlsort overrides). The @pytest.mark.optional_deps marker was never registered in pyproject.toml and did nothing: per-directory conftest.py files already gate test/satp/ and test/spi/ via pytest.importorskip("rpy2") at collection time. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
test.yml: remove workflow_run chain (redundant since push/pull_request both trigger directly), scope push to main only to prevent double runs when pushing to a PR branch, remove broken workflow_call outputs block (referenced github.event.inputs which was never declared). docs.yml: remove same broken workflow_call outputs block. linting.yml: add branch scoping (was firing on every push to every branch in the repo); scope to push/main + pull_request/main,dev. test-conda-install.yml: align pixi version with other workflows (v0.67.2 → v0.68.0, setup-pixi v0.9.4 → v0.9.5). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Delete tag-release.yml and test-tag-release.yml (tag-first approach).
Add release.yml which triggers on push to main and:
- Skips if version has a pre-release suffix (.dev, rc, a, b)
- Skips if the git tag already exists (idempotent; handles manual publish)
- Otherwise: runs tests + docs, builds, publishes to PyPI via OIDC,
creates the git tag, and creates the GitHub release
If PyPI rejects a duplicate upload (version published manually without a
tag), the publish step fails and prints the git tag command needed to
reconcile the state.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Allows manually re-triggering the release if a push-triggered run fails and the follow-up fix commit is paths-ignored (e.g. a markdown-only change). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Pins OIDC token issuance to the pypi GitHub environment, which is restricted to deployments from main. PyPI's Trusted Publisher will reject tokens issued outside this environment. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
environment.yml is a derived file from pixi.toml and pyproject.toml. It now updates automatically on main whenever either source changes, completely decoupled from the release process. release.yml is simplified: no git commits, no contents:write until the final tag step. build, publish-conda, tests-pass, and docs-pass all run in parallel after check, with only publish-pypi waiting on build + tests + docs before PyPI upload. Also adds uv >= 0.9 to [package.build-dependencies] in pixi.toml so pixi has uv available during pixi publish (conda build step). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR brings
devtomainfor the v0.8.2 release. It consolidates the entirev0.8.0rc1..v0.8.0rc10+v0.8.2.dev1pre-release line into a single shipping version. The last user-facing stable on PyPI wasv0.7.8, so most users are upgrading across a much larger gap than the version number suggests.Summary of what dev adds since main (v0.8.0rc10)
User-visible code
fit_circe,ipsatize,CircE/CircEResults,CircModelE,SATPVersionenum,normalize_polar_angles,person_center. Schema validation now raises by default; passerrors="warn"for the older permissive behaviour. Default ipsatize method is nowgrand_mean(matches the published R reference).rpy2; CircE no longer needs to be installed from GitHub.Project tooling
pixi run versionwrapsuv version; no setuptools-scm.pytest.importorskip; new slim-installtest-import-tripwiretask; matrix envstest/test-audio/test-r/test-all.zensical.tomlreplacesmkdocs.yml.lazy_loader.attach_stubdriven by__init__.pyi; level-2 insideaudio,spi,satp. New_optional.pyhelper standardises ImportError messages. PEP 561 stubs let mypy/pyright/IDEs resolvefrom soundscapy.audio import Binaural.Release prep included in this PR
pyproject.tomlversion0.8.2.dev1 → 0.8.2.CHANGELOG.mdanddocs/CHANGELOG.mdto lead with breaking changes under a single0.8.2heading.docs/news.mdrelease announcement.docs/migration-0.7-to-0.8.mdupgrade guide; wired intozensical.tomlnav.README.mddisclaimer + upgrade signpost.For the user-facing upgrade story (CircumplexPlot → ISOPlot, Plotly removal,
[r]extras, fit_circe/ipsatize default changes), see docs/migration-0.7-to-0.8.md.Test plan
test.ymlCI matrix passes on this PRtest-conda-install.ymlpassestest-import-tripwireconfirmsimport soundscapypulls no optional depsv0.8.2,tag-release.ymlbuilds wheel + sdist, publishes to PyPI, creates GitHub releasepip install soundscapy==0.8.2andpip install "soundscapy[audio]==0.8.2"smoke tests pass via the existing retry-install steps intag-release.yml🤖 Generated with Claude Code