') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); })(); restore option to compress raster by melonora · Pull Request #944 · scverse/spatialdata · GitHub
Skip to content

restore option to compress raster - #944

Merged
melonora merged 18 commits into
scverse:mainfrom
melonora:restore_storage_options
May 21, 2026
Merged

restore option to compress raster#944
melonora merged 18 commits into
scverse:mainfrom
melonora:restore_storage_options

Conversation

@melonora

@melonoramelonora commented Jun 10, 2025

Copy link
Copy Markdown
Collaborator

closes#37

This PR adds the capability back of using either lz4 or zstd compression at various compression levels. It is exposed through a compressor argument in write and write_element that takes as value a dict with key being the compression name and the value being the compression level. By default if compression is specified bytes will be reordered for more efficient compression SHUFFLE in blosc.

@melonora

Copy link
Copy Markdown
CollaboratorAuthor

perhaps still some refactoring to clean up the code a bit, but first want opinions on the exposed parameter.

@melonoramelonora mentioned this pull request Jun 10, 2025
@codecov

codecovBot commented Jun 10, 2025

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 76.00000% with 12 lines in your changes missing coverage. Please review.
✅ Project coverage is 92.44%. Comparing base (06e6981) to head (eea7a7f).
⚠️ Report is 20 commits behind head on main.

Files with missing linesPatch %Lines
src/spatialdata/_io/io_raster.py71.05%11 Missing ⚠️
src/spatialdata/_io/_utils.py90.00%1 Missing ⚠️
Additional details and impacted files
@@ Coverage Diff @@## main #944 +/- ##
==========================================
- Coverage 92.55% 92.44% -0.11% 
==========================================
Files 51 51 Lines 7763 7811 +48 ==========================================
+ Hits 7185 7221 +36 - Misses 578 590 +12 
Files with missing linesCoverage Δ
src/spatialdata/_core/spatialdata.py93.86% <100.00%> (+<0.01%)⬆️
src/spatialdata/_io/_utils.py86.66% <90.00%> (+0.13%)⬆️
src/spatialdata/_io/io_raster.py89.25% <71.05%> (-3.97%)⬇️
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@LucaMarconato

LucaMarconato commented Jan 4, 2026

Copy link
Copy Markdown
Member

Thanks @melonora, I picked this up and merged the conflicts arising after the Zarr v3 support.

The tests currently fail mainly due to the disconnect between the new format options and dask, but it should be straightforward to make the PR green again after https://github.com/ome/ome-zarr-py/pull/510/changes is merged.

@LucaMarconato

Copy link
Copy Markdown
Member

Sharding support has been added to ome-zarr-py ome/ome-zarr-py#534 and is being added to spatialdata via #1106.

LucaMarconatoand others added 3 commits May 12, 2026 17:39
Use "compressors" (plural) with native zarr v3 codec objects (ZstdCodec,
BloscCodec) in storage_options, which ome-zarr-py >= 0.16.0 + dask >= 2026.3.0
correctly forwards to zarr_array_kwargs. Bump minimum deps accordingly and fix
test assertions for lz4 (.clevel) vs zstd (.level) and the s0 array path.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@LucaMarconato

Copy link
Copy Markdown
Member

@melonora I merged the latest main and bumped the min ome-zarr and dask versions to be aligned with the sharding PR. Now the tests pass.

Can you please do a review of the changes? If you also think it's ok, feel free to merge (before the sharding PR).

Comment threadtests/io/test_readwrite.py
Comment threadsrc/spatialdata/_io/io_raster.py
Comment threadsrc/spatialdata/_io/_utils.py Outdated
Comment threadsrc/spatialdata/_io/io_raster.py Outdated
if zarr_format == 2:
from numcodecs import Blosc as BloscV2

assert BloscV2.SHUFFLE == 1

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

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

Why this assert if you hardcode shuffle to be 1 in any case?

@melonora
melonora enabled auto-merge (squash) May 21, 2026 18:46
@melonora
melonora disabled auto-merge May 21, 2026 18:46
@melonora
melonora merged commit 68dade6 into scverse:mainMay 21, 2026
9 checks passed
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Re-enable compression

2 participants

@melonora@LucaMarconato