Skip to content

Fix pySPFM notebook: switch to Schaefer atlas, fix memory and path issues#73

Open
eurunuela wants to merge 1 commit intoME-ICA:mainfrom
eurunuela:update-pyspfm-api
Open

Fix pySPFM notebook: switch to Schaefer atlas, fix memory and path issues#73
eurunuela wants to merge 1 commit intoME-ICA:mainfrom
eurunuela:update-pyspfm-api

Conversation

@eurunuela
Copy link
Copy Markdown
Contributor

Summary

  • Switches the pySPFM deconvolution notebook from voxel-wise processing (~218k voxels) to parcel-wise processing using the Schaefer 1000-parcel atlas, making the notebook runnable on a laptop without running out of memory
  • Fixes ../DATA../data (case-sensitive path, was silently broken on Linux/CI)
  • Removes the dead n_jobs=-1 argument (pySPFM v2.0.1 hardcoded scheduler="synchronous" — a fix has been opened upstream at Wire n_jobs to Dask threaded scheduler in all voxel-wise solvers Paradigm-Free-Mapping/pySPFM#152)
  • Includes executed .ipynb output so the book build can use the cache

Why parcel-wise?

Running pySPFM voxel-wise on the full brain mask builds a Dask graph with ~218k delayed objects, holds all results in memory simultaneously, then allocates ~2.6 GB each for the fitted signal and residuals. On a 16 GB machine already under memory pressure this reliably kills the Jupyter kernel.

Using NiftiLabelsMasker with the Schaefer 1000-parcel atlas reduces the input matrix from (1815, 218485) to (1815, 1000) — ~14 MB vs ~1.6 GB. The full multi-echo deconvolution workflow is still demonstrated across the whole brain.

Test plan

  • Notebook executes locally without kernel dying (jupyter execute content/05_3dMEPFM.ipynb)
  • All four output files written: out_activity.nii.gz, out_lambda.npy, out_fitted.npy, out_residuals.npy
  • jb build . passes in CI

🤖 Generated with Claude Code

Copilot AI review requested due to automatic review settings April 27, 2026 20:08
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Updates the pySPFM deconvolution tutorial to run in a parcel-wise workflow (Schaefer 1000 atlas) to reduce memory usage, fixes a case-sensitive data path, and adds an .ipynb version of the notebook for builds/caching.

Changes:

  • Switch notebook deconvolution from voxel-wise to parcel-wise using NiftiLabelsMasker + Schaefer 2018 (1000 ROIs).
  • Update ../DATA to ../data for Linux/CI compatibility.
  • Add content/05_3dMEPFM.ipynb counterpart to the existing MyST/Jupytext .md notebook.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 7 comments.

File Description
content/05_3dMEPFM.md Refactors the workflow to Schaefer-parcel time series and uses SparseDeconvolution; updates data path and output-writing logic.
content/05_3dMEPFM.ipynb Adds an .ipynb version of the same tutorial content for execution/build purposes.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread content/05_3dMEPFM.ipynb
Comment thread content/05_3dMEPFM.md
Comment thread content/05_3dMEPFM.md
Comment thread content/05_3dMEPFM.ipynb
Comment thread content/05_3dMEPFM.ipynb Outdated
Comment thread content/05_3dMEPFM.ipynb Outdated
Comment thread content/05_3dMEPFM.md Outdated
- Replace voxel-wise NiftiMasker with NiftiLabelsMasker + Schaefer 1000-parcel
  atlas, reducing input matrix from ~218k voxels to 1000 parcels (feasible on
  a laptop without OOM)
- Fix data path: ../DATA → ../data (case-sensitive on Linux/CI)
- Remove n_jobs=-1 (pySPFM v2.0 removed that parameter)
- Remove unused mask_file and confounds_file variables
- Remove unused hrf_matrix assignment
- Save parcel-wise activity as out_activity.npy instead of a large 4D NIfTI;
  add a compact mean-abs summary image (out_activity_mean.nii.gz) for
  lightweight voxel-space visualization

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@handwerkerd
Copy link
Copy Markdown
Member

I'm seeing two possibly related issues:

  1. The new atlas is being downloaded to the top of my user directory tree (i.e. /Users/handwerkerd/nilearn_data) and not a gitignored directory in this repo. This might cause problems in some systems & is a bit annoying.
  2. The script crashed on build during the third cell (maybe due to issues with the file path). This also seems like a file path issue.
---------------------------------------------------------------------------
IndexError                                Traceback (most recent call last)
Cell In[3], line 15
     11     labels_img=atlas.maps,
     12     resampling_target='data',
     13     standardize=False,
     14 )
---> 15 masker.fit(data_files[0])
     16 
     17 # Load each echo and extract parcel-averaged timeseries, then concatenate
     18 # along the time axis to form the multi-echo input matrix.

IndexError: list index out of range

@eurunuela
Copy link
Copy Markdown
Contributor Author

I'm working on improving the notebook regardless. This is still not ready to be merged.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants