Skip to content

Releases: darksim33/Pyneapple

Pyneapple v2.0.0

13 May 16:36

Choose a tag to compare

Pyneapple v2.0.0

This is a major release with breaking changes. The entire fitting architecture has been redesigned. Code written against v1.x will require updates — see the migration notes below.


Breaking Changes

  • Entire module structure replaced. pyneapple/parameters/, pyneapple/fitting/, pyneapple/utils/, and radimgarray have been removed. The new structure is Models, Solvers, and Fitters following scikit-learn estimator conventions.
  • Old fitting functions removed: fit_pixel_wise(), fit_segmentation_wise(), fit_ivim_segmented(), fit_ideal() are gone.
  • CLI redesigned: pyneapple-fitdata is replaced by pyneapple pixelwise, pyneapple segmentationwise, pyneapple ideal, pyneapple segmented.
  • TOML config format changed: [General] with a Class field is replaced by a [Fitting] section. All example configs have been updated.
  • IDEALFitter.interpolation_method removed: replaced by downsampling_method (default "block_average") and upsampling_method (default "cubic").
  • IDEALFitter.step_tol type changed from list / np.ndarray to dict[str, float] keyed by parameter name. TOML configs must update from a flat list to a [Fitting.ideal.step_tol] sub-table.
  • pygpufit moved to a separate package.
  • Minimum Python version lowered to 3.9 (was 3.12); dependency version ranges now split per Python version.

What's New

  • scikit-learn-style architectureMonoExpModel, BiExpModel, TriExpModel, NNLSModel as stateless forward models; CurveFitSolver, NNLSSolver, ConstrainedCurveFitSolver as backends; PixelWiseFitter, SegmentationWiseFitter, IDEALFitter, SegmentedFitter as high-level orchestrators.
  • FitResult public container — all fitters now populate results_ with a FitResult after fitting; exported from the top-level pyneapple package.
  • Registry-based plugin discovery via entry points for models, solvers, and fitters.
  • pyneapple.io module — unified I/O for NIfTI, b-values, TOML configs, Excel, and HDF5.
  • pyneapple.utility module — spectrum processing, plotting, and validation utilities.
  • Optional dependency groups: pip install pyneapple[excel,plotting,export]
  • SegmentedFitter for two-step model fitting workflows, now including TOML config support via fitter = "segmented".
  • IDEAL block-average downsampling_block_average_array() porting MATLAB IDEAL reference accumarray(@nanmean) behavior, dispatched via new downsampling_method / upsampling_method split.
  • New clamp_interpolated_p0 parameter on IDEALFitter (default True) — controls clamping of upsampled parameter maps to solver bounds before step-wise tolerances are derived.
  • New user guides: docs/guide/fitting-config.md (FittingConfig / load_config) and docs/guide/logging.md (configure_logging(), log levels, file sinks, PYNEAPPLE_QUIET).

Improvements & Changes

  • configure_logging() no longer attaches a console sink by default — a sink is only added when explicitly requested.
  • numpy, scipy, and nibabel dependencies split into Python-version-specific ranges for correct resolution across Python 3.9–3.12+.
  • tomli>=2.0 added as a conditional dependency for Python < 3.11 to backport tomllib.
  • Ruff target-version updated to py39.

Bug Fixes

  • ConstrainedCurveFitSolver: fraction_constraint=True now correctly raises ValueError when fit_reduced=False.
  • ConstrainedCurveFitSolver: gradient callable no longer returns None to SLSQP when model Jacobian is unavailable; falls back to finite-difference approximation.
  • CurveFitSolver: use_jacobian flag now respected in both fixed-params and unfixed branches.
  • CurveFitSolver: n_pools=None in multi-threading configuration no longer raises an error.
  • IDEALFitter: cubic-interpolated parameter maps are clamped to solver bounds before step-wise bounds are derived, preventing out-of-range initial guesses from interpolation overshoot.
  • IDEALFitter: a warning is logged and all voxels are fitted when no voxels survive the segmentation threshold at a coarse step — previously collapsed silently.
  • IDEALFitter._validate_step_tol(): error message now contains "step_tol" when dict keys don't match model.param_names.
  • get_model("nnls"): factory now accepts **kwargs and raises a descriptive ValueError for missing required arguments.
  • save_parameter_map: NNLS 4-D coefficient arrays saved correctly as 4-D NIfTI volumes.
  • hdf5._encode_key(): unhandled key types fall back to str instead of returning None and crashing the caller.
  • isinstance(value, h5py.Group | h5py.Dataset) replaced with tuple form — runtime | union in isinstance() requires Python 3.10+.
  • SegmentedFitter is now properly exported from pyneapple.fitters.
  • Stale pyneapple-<cmd> CLI references corrected to pyneapple <cmd> in all example configs and guides.
  • Various TOML example config corrections (wrong fit_s0 values, transposed dim_steps shape, fit_reducefit_reduced typo).

Migration from v1.x

The architecture change is significant. Key points:

  • Replace FitData + parameter classes with the new Fitter/Model/Solver pattern
  • Update TOML configs from [General] Class = ... to [Fitting] fitter = ...
  • Replace pyneapple-fitdata CLI calls with pyneapple <subcommand>
  • Replace from pyneapple.utils import logger with from pyneapple import configure_logging

v2.0.0-beta.2

22 Apr 14:23

Choose a tag to compare

v2.0.0-beta.2 Pre-release
Pre-release

Fixed - \SegmentedFitter\ was missing from \pyneapple.fitters\ public API — now properly exported.

v2.0.0-beta.1

01 Apr 08:14
a65fe63

Choose a tag to compare

v2.0.0-beta.1 Pre-release
Pre-release

v2.0.0-beta.1 (Pre-release)

⚠️ This is a pre-release. This major version introduces significant breaking changes to align with scikit-learn conventions.


What's New

Architecture — scikit-learn Style Restructure

The entire codebase has been refactored to follow scikit-learn conventions with a clear separation of concerns:

  • Models: Stateless, pure math forward model functions (forward, jacobian, residual)
  • Solvers: Curve fitting backends (CurveFitSolver, NNLSSolver, ConstrainedCurveFitSolver)
  • Fitters: High-level fitting orchestrators (PixelWiseFitter, SegmentationWiseFitter, IDEALFitter, SegmentedFitter)
  • Registry-based plugin discovery via entry points for models, solvers, and fitters

New I/O Module (pyneapple.io)

  • load_dwi_nifti, save_parameter_map, reconstruct_maps, save_spectrum_to_nifti
  • load_bvalues, save_bvalues
  • load_config / FittingConfig for TOML configs
  • Excel export: save_params_to_excel, save_spectrum_to_excel
  • HDF5 export with gzip compression: save_to_hdf5, load_from_hdf5, save_params_to_hdf5

New Utilities (pyneapple.utility)

  • spectrum — Spectrum processing utilities
  • plotting — Visualization helpers
  • validation — Validation helpers

New CLI Tools

pyneapple pixelwise         # Per-pixel fitting
pyneapple segmented         # Segmented fitting (two-step)
pyneapple ideal             # IDEAL iterative fitting
pyneapple segmentationwise  # ROI mean signal fitting

Optional Dependencies

pip install pyneapple[excel,plotting,export]

Breaking Changes

1. Removed Entire Module Hierarchy

Old Path Status
pyneapple/parameters/ Removed entirely
pyneapple/results/ Removed entirely
pyneapple/fitting/ Removed entirely
pyneapple/utils/ Removed entirely

2. Removed Parameter Classes

# REMOVED - No direct replacement
from pyneapple.parameters import Parameters
from pyneapple.parameters.ivim import IVIMParams
from pyneapple.parameters.ivim import IVIMSegmentedParams
from pyneapple.parameters.nnls import NNLSParams
from pyneapple.parameters.nnls import NNLSCVParams
from pyneapple.parameters.ideal import IDEALParams
from pyneapple.parameters.boundaries import BaseBoundaryDict

3. Removed Result Classes

# REMOVED - No direct replacement
from pyneapple.results import Results
from pyneapple.results.ivim import IVIMResults
from pyneapple.results.ivim import IVIMSegmentedResults
from pyneapple.results.nnls import NNLSResults
from pyneapple.results.nnls import NNLSCVResults
from pyneapple.results.types import Results
from pyneapple.results.result_dict import ResultDict

4. Removed Fitting Interface

# REMOVED - Replaced by new Fitters
from pyneapple.fitting.fitdata import FitData

# OLD API (removed)
fit_data = FitData(img, seg, "params.toml")
fit_data.fit_pixel_wise()
fit_data.fit_segmentation_wise()
fit_data.fit_ivim_segmented()
fit_data.fit_ideal()

5. Removed Utility Modules

# REMOVED
from pyneapple.utils.logger import logger
from pyneapple.utils.plotting import plot_results
from pyneapple.utils.processing import *

6. Removed External Dependency

# REMOVED - Was using radimgarray submodule
from radimgarray import RadImgArray, SegImgArray

7. TOML/JSON Parameter File Format — Complete Redesign

Old format (params_biexp.toml):

[General]
Class = "IVIMParams"          # ← Required class name
b_values = [0, 10, 50, ...]

[Model]
model = "biexp"
fit_s0 = false

[boundaries.D]
1 = [0.001, 0.0007, 0.05]    # ← Complex boundary format
2 = [0.02, 0.003, 0.3]

New format (segmentationwise_biexp.toml):

[Fitting]
fitter = "segmentationwise"

[Fitting.model]
type = "biexp"

[Fitting.solver]
type = "curvefit"
max_iter = 250

[Fitting.solver.p0]         # ← Simple initial guess
S0 = 1000.0
f1 = 0.2
D2 = 0.02

[Fitting.solver.bounds]     # ← Simple bounds
S0 = [1.0, 5000.0]
f1 = [0.01, 0.99]

8. CLI Interface Changes

# OLD
pyneapple-fitdata --params params_biexp.toml
pyneapple-fitdata --img data.nii --seg mask.nii

# NEW
pyneapple pixelwise --image data.nii --bval data.bval --config config.toml
pyneapple segmented --image data.nii --bval data.bval --config config.toml --seg mask.nii
pyneapple ideal --image data.nii --bval data.bval --config config.toml --seg mask.nii

9. Model API Changes

# OLD - Multiple model classes for different fitting modes
from pyneapple.models import NNLSModel, NNLSCVModel
from pyneapple.models.ivim import BiExpFitModel, TriExpFitModel, MonoExpFitModel

# NEW - Unified model naming
from pyneapple.models import MonoExpModel, BiExpModel, TriExpModel, NNLSModel

10. Removed Example Scripts

  • examples/ivim_fitdata_script.py
  • examples/nnls_fitdata_script.py

11. Removed Example Parameter Files

All JSON and TOML parameter files in examples/parameters/ have been replaced:

  • params_biexp.json, params_biexp.toml
  • params_biexp_ideal.json
  • params_biexp_segmented.json
  • params_biexp_s0.toml, params_biexp_t1.toml, params_biexp_t1_steam.toml
  • params_monoexp.json
  • params_nnls.json, params_nnls.toml, params_nnls_cv.json
  • params_triexp.json, params_triexp_ideal.json, params_triexp_reduced.toml

12. Removed pygpufit Module

The pygpufit integration has been moved to a separate package.


Import Changes Summary

OLD NEW
Parameters classes Models
IVIMParams, NNLSParams BiExpModel, NNLSModel, etc.
Results classes No direct replacement
FitData Fitters (PixelWiseFitter, etc.)
logger from utils configure_logging() from pyneapple
RadImgArray NIfTI via numpy arrays
params.toml (with Class field) config.toml ([Fitting] section)
fit_ivim(), fit_nnls() fitter.fit(data, model)

Migration Guide

1. Replace parameters with models

# OLD
params = IVIMParams(bvalues=bvals, ...)
results = fit_ivim(data, params)

# NEW
from pyneapple.models import BiExpModel
from pyneapple.fitters import PixelWiseFitter
from pyneapple.solvers import NNLSSolver

model = BiExpModel(bvalues=bvals, ...)
fitter = PixelWiseFitter(solver=NNLSSolver())
results = fitter.fit(data, model)

2. Replace TOML configs

  • Remove Class field
  • Restructure under [Fitting] section
  • Rename [boundaries] to [Fitting.solver.bounds]
  • Add explicit p0 section for initial guesses

3. Update imports

  • ParametersModels
  • Results → Fitter return values (numpy arrays)
  • FitDataFitters

4. Update logging

# OLD
from pyneapple.utils import logger
logger.info("message")

# NEW
from pyneapple import configure_logging
configure_logging(level="DEBUG")

Installation

pip install pyneapple==2.0.0b1

# With optional dependencies
pip install pyneapple==2.0.0b1[excel,plotting,export]

What's Changed

Full Changelog: v1.7.0...v2.0.0-beta.1

v1.7.0

19 Jan 14:45

Choose a tag to compare

Release Summary: v1.5.6 → v1.7.0

Overview

This summary covers four major releases with significant enhancements to Pyneapple's capabilities, including logger implementation, TOML support, IVIM results improvements, and comprehensive IO functionality.


📦 Version 1.7.0 (Latest) - IO Update

Major Features

  • HDF5 Support (#198, #199)

    • Complete HDF5 data storage and export functionality
    • Transform ResultDicts to Arrays before HDF5 export
    • Support for 3D and 4D data structures
    • Switched from scipy.sparse to sparse library for N-D support
    • Dict import capabilities
    • Comprehensive test suite
  • NIfTI Support

    • NIfTI helper functions for medical imaging
    • Refactored results saving for NIfTI format
    • Comprehensive test suite with preparation helpers
  • NNLS Enhancements

    • Cutoff handling and peak merging
    • Improved peak handling with IVIM T1 flag
    • Comprehensive results test suite
    • Fixed variable array length issues

Improvements

  • GPU fitter model retrieval and constraint handling (#197)
  • Expanded DataExport documentation
  • Added fit_opt parameter to track fitting type (pixel/segmentation/segmented/ideal)
  • Moved JSON and TOML operations to dedicated IO module
  • Enhanced type support and hints throughout codebase

Bug Fixes

  • Default fit_opt to empty string
  • GPU fitter constraints and imports
  • NNLS model params not passed properly
  • Shape calculation issues
  • Missing logger output

📦 Version 1.6.2 - IVIM Results Patch

Key Changes

  • IVIM Results Refactoring

    • Switched from separate S0 and f extraction to unified method
    • Fixed segmented test issues
    • Improved extraction logic
  • Core Fixes

    • Additional small fraction issue resolved
    • dimstep now always returns np.ndarray
    • Parameter class invoke error fixed
    • JSON to params_file conversion issues
  • Testing & Quality

    • seg_args tests for mean calculations
    • Updated radimgarray commit
    • Removed unused methods and imports
    • Pylance compatibility improvements

Documentation

  • Updated class descriptions
  • Fixed type hints

📦 Version 1.6.1 - TOML Parameter Support

Major Feature: TOML Support (#168)

  • TOML File Format
    • Added TOML parameter file import/export
    • Renamed params.json to params.file for format flexibility
    • TOML packages added to dependencies (tomli, tomli-w, tomlkit)

Implementation Details

  • TOML test suite
  • TOML import examples
  • TOML documentation
  • Backward compatible with JSON files

Dependencies

  • tomli ^2.0.1 for Python <3.11
  • tomli-w ^1.0.0 for Python <3.11
  • tomlkit ^0.12.0 for Python >=3.11

📦 Version 1.6.0 - Logger Implementation

Major Feature: Custom Logger (#167)

  • Loguru Integration
    • Custom logger implementation using loguru
    • Replaced print statements throughout codebase
    • File output support for logs
    • Configurable log levels

Logger Features

  • Top-level logger access
  • Option to get/set log level dynamically
  • File output redirection
  • pytest integration (log level set to ERROR for tests)
  • Logger tests added

Supporting Changes

  • Added tox.ini to pyproject.toml
  • Linux GPUFit library (Ubuntu 22.04 LTS)
  • Moved tox.ini to test directory
  • kwargs passing for GPU fitter tuning
  • More realistic kidney fitting values in JSON files

Bug Fixes

  • LOG_LEVEL variable naming
  • Removed global variables
  • Stopped unwanted file output
  • Model-related issues
  • Missing segmented S0

🔄 Cross-Version Major Changes

Models Rework (#163, #171)

Implemented across v1.6.0-v1.6.2

  • Model Class Restructuring

    • Created base fit model classes
    • Moved from wrapper pattern to direct model classes
    • Added model properties to dedicated model class
    • IVIM model loader implementation
    • Mono, Bi, and Tri exponential models
    • GPU model constructor
  • Model Improvements

    • fit_reduced, fit_S0, fit_t1 properly pass values
    • Renamed reduced to fit_reduced for clarity
    • Updated NNLSCV model
    • Refactored *_comment* to *description*
    • Added S0 model options and tests
  • Segmented Fitting

    • Reworked to use two sub-parameter classes
    • Fixed component handling improved
    • Better S0 and fraction extraction
    • Unit and integration tests added

Boundary System Rework (#178, #197)

Implemented across v1.6.1-v1.7.0

  • Individual Boundaries

    • Pixel-by-pixel boundary support (btype)
    • Individual bounds for fit functions
    • GPU fit individual boundaries
    • Boundary validity checks
  • Structure Changes

    • Reworked to altered dict structure
    • Boundary order handling
    • Default btype and individual bound returns
    • Comprehensive test suite
  • Constraint Handling

    • Fixed constrain_types for individual bounds
    • Improved constraint returns
    • Better handling of missing f and D values

Parameters Import Update (#109, #184)

Implemented in v1.6.0

  • Dynamic Parameter Handling

    • Switched from static file-based to dynamic dict-based
    • Better file structure with tables/dicts
    • Model parameters from model class directly
    • Capitalized boundary keys allowed
  • File Organization

    • Moved file fixtures to _files
    • Parameter fixtures to _parameters
    • Moved parameter files from fitting to parameters directory
    • Created dynamic parameter file creator

Documentation Improvements (#191)

Implemented in v1.6.2

  • Comprehensive Documentation

    • Detailed model descriptions
    • IVIM models documentation
    • NNLS description
    • Example TOML files for different cases
    • Fit example scripts
    • Extended example descriptions
    • Fixed equation expressions
  • Examples

    • IVIM parameters file example
    • BiExp IVIM TOML
    • NNLS fitting script
    • FitData IVIM example script

T1 Fitting Fix (#190, #193)

Implemented in v1.6.2

  • Added fit_t1_steam for models
  • Tests for new T1 fitting with fixes
  • Updated documentation with T1 STEAM option
  • Removed model from Args (no longer needed)
  • T1 fit check for export

Testing Infrastructure

Continuous improvements across all versions

  • Test Coverage Expansion

    • pytest-mock and pytest-cov added
    • Fitting tests initialized
    • Boundary tests
    • GPU fitter tests
    • NNLS results tests
    • NIfTI tests
    • HDF5 tests
    • Segmented fitting tests
  • Test Organization

    • Moved fixtures to conftest
    • Refactored mocks
    • Added pytest marks (slow, gpu, ideal)
    • Improved test structure

Python Version Support

  • Added Python 3.13 support
  • Maintained support for 3.9, 3.10, 3.11, 3.12

Code Quality Improvements

Across all versions

  • Extensive type hint additions
  • Black code formatting
  • Ruff import organization
  • Removed unused imports and methods
  • Improved docstring formats
  • Better error handling
  • Pyright configuration

🐛 Notable Bug Fixes Summary

Data Handling

  • b_values handling (array vs list)
  • Shape calculations
  • Array dimension handling
  • Segmentation key handling with int keys

Fitting

  • NNLS model params passing
  • kwargs overwriting bools
  • MonoExp equation order (exp(D1)*S0)
  • fit_s0 addition to params2
  • D1 position in first fit

Results

  • NNLS results boolean parsing
  • Variable array length for NNLS
  • Fixed component handling
  • S0 and fraction extraction

Configuration

  • JSON to params_file conversion
  • TOML import issues
  • Parameter file path resolution
  • Model selection logic

📊 Statistics

  • Total Commits: 344
  • Major Versions: 4 (v1.6.0, v1.6.1, v1.6.2, v1.7.0)
  • Pull Requests: 10+ merged
  • Major Features: 4 (Logger, TOML, IVIM Patch, IO Module)
  • Major Refactorings: 3 (Models, Boundaries, Parameters)

🎯 Breaking Changes

v1.6.0

  • Changed default parameter file handling from static to dynamic
  • Model wrapper pattern replaced with direct model classes

Notes

  • Most changes maintain backward compatibility
  • Configuration file structure enhanced but old formats supported where possible

What's Changed

Full Changelog: v1.5.6...v1.7.0

v1.5.6

21 Mar 11:50

Choose a tag to compare

Added GPUfit capabilities and reworked models to look the same across CPU and GPU fitting approaches.
The fitting procedure and json parameter files were update to support new functionality. Therefore, parameter files from v1.3.1 or older are no longer supported.
The whole package structure is streamlined to better match the used fitting approaches by introducing new classes for result handling. The multi exponential wrapper was depreciated and is no longer available in favor of explizit models to match GPU fitting. (Might be reintroduced in the future.)

What's Changed

  • v1.3.3: direct fitting by @darksim33 in #148
  • v1.4.0: Added GPU fitting with pygpufit for CUDA GPUs by @darksim33 in #150
  • v1.5.0: Full GPU integration and Model rework c092bb7
  • v1.5.1: moved IDEAL to branch #156 and remove files from main branch until ideal is working properly 186a7fd
  • v1.5.2: updated doc with new fitting and parameter instructions and detail
  • v1.5.3: fix typos, conditionals and fit_model issues 94979ca
  • v1.5.4: fix s0 and fraction related issues for ivim 10d14b1
  • v1.5.5: fix: remove reorder array since all models use the same set of parameters for ivim 2748c4d
  • v1.5.6: fix: change fit_type: default is now set in the parameters file but can be overwritten during function calls 09572ea

Full Changelog: v1.3.1...v1.5.6

v1.3.1

09 Nov 20:00
4f66a4f

Choose a tag to compare

What's Changed

Full Changelog: v1.1.1...v1.3.1

Release v1.1.1

08 Oct 14:23

Choose a tag to compare

What's Changed

Full Changelog: v1.0.0...v1.1.1

Release v1.0

29 Apr 15:29

Choose a tag to compare

First Pyneapple Release for public repo.
Added main testing and ui properties.
Fitting for IVIM and NNLS is up and Running.
IDEAL is still work in progress.

v0.7.3

17 Apr 11:17

Choose a tag to compare

v0.7.3 Pre-release
Pre-release

Version with new package structure, icons and clean directory

What's Changed

New Contributors

Full Changelog: v0.7.0...v0.7.3

v0.7.0

15 Feb 13:25

Choose a tag to compare

v0.7.0 Pre-release
Pre-release

Added IDEAL support.