Skip to content

Conversation

@MiquelSendra
Copy link
Contributor

@MiquelSendra MiquelSendra commented Jan 13, 2026

This PR is basically the changes you made on my computer this evening to fix the Python ≥3.11 / AnnData ≥0.10 issue where sc3D converted .raw to an AnnData object after subsetting. You found that this pattern can lead to .raw/.obs misalignment and trigger crash a crash in newer AnnData versions because the .obs for .raw are taken from the Anndata original object and that creates a mismatch.

I ran the codeS1 notebook (bioprotocols paper) with this updated code and the main workflow now runs correctly through the registration steps. However, SpatialOmicArray.save_anndata() still fails when saving the registered AnnData. The error is the same as it happened in loading. takes 5min and then same error, happens during save-time operations (copy/obsm assignment/raw handling), and needs a separate fix.
ValueError: could not convert integer scalar
Screenshot 2026-01-13 at 23 08 44

Tested

  • Python 3.13
  • sc3D 2.0.0
  • AnnData 0.12.7 (newest)
  • CodeS1 from the Bio-protocol paper run successfully up to the save step; the remaining issue is only in method save_anndata in sc3D.py/

I am leaving this PR open to track the raw-handling fix and will follow up with a patch for save_anndata.

@leoguignard
Copy link
Member

Can you try to remove the .copy from line #1809? It's not necessary here.

@MiquelSendra
Copy link
Contributor Author

MiquelSendra commented Jan 14, 2026

In the end, the fix for save_anndata was to avoid AnnData.copy() entirely on views.

When self.anndata is a view, calling .copy() (or implicitly making AnnData create a copy when setting .obsm) triggers a SciPy sparse advanced-indexing path (arrayXarray) that crashes in Python ≥3.11 / newer SciPy (ValueError: could not convert integer scalar).

The solution was to materialize a real AnnData directly from the parent (_adata_ref) using name-based indexers for obs/var, then safely add obsm["X_spatial_registered"] and write. Not the cleanest solution, because it rebuilding the AnnData from its separate components, but it works.

Additionally, save_anndata now restores a full .raw (aligned by cells) from the parent AnnData so that non-HVG genes remain accessible. This keeps the napari sc3D viewer fully functional without modifying the viewer code.

With these changes, CodeS1 now runs end-to-end (including saving and 3D differential expression) on Python 3.13 / AnnData 0.12.7, and the saved object works OK in the napari sc3D viewer.

Copy link
Member

@leoguignard leoguignard left a comment

Choose a reason for hiding this comment

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

Didn't realize the tests aren't passing

@MiquelSendra
Copy link
Contributor Author

Right.. I did not run pytest locally, my bad. The version with the modifications you did yesterday also fail. The original sc3D does not fail, so it must be something that we changed on the .raw treatment.

Fails at > em.smooth_data()
ValueError: Data matrix has wrong shape (120, 27535), need to be (120, 4).

Because the changes we made in smooth_data() make it smooth the raw/full gene matrix but then assigning it into the filtered/HVG matrix (.X). The shapes no longer match? I guess we should check, If .raw exists and contains the “full genes”, smooth into .raw and optionally also update .X only if .X is the same gene set. Otherwise smooth into .X. I have to have a look at the test data..

Also, maybe we should separate the test function into multiple test functions, because there might be something else failing down below and we cannot see it.

@leoguignard leoguignard merged commit c403156 into GuignardLab:main Jan 15, 2026
9 of 10 checks passed
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.

2 participants