You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
FEAT: Implement <dj_zarr> Custom Type Adaptor #1263
Scientific research, particularly in fields like neuroscience and imaging, generates massive n-dimensional arrays that are too large to be stored efficiently in traditional blob fields. The Zarr format is an industry standard for storing chunked, compressed array data, enabling parallel I/O and efficient partial access (slicing). Without native support for Zarr, users are forced to manage these datasets manually by storing file paths, which disconnects the data from the DataJoint pipeline and forfeits all the benefits of integrated data management and integrity checks.
Requirements
A successful implementation of this improvement should provide a built-in Custom Type Adaptor for handling Zarr arrays, leveraging the object type for external storage. This implementation must adhere to the DataJoint 2.0 Specification.
The core requirements are:
Create a dj.CustomType Adaptor:
A new class must be implemented that inherits from dj.CustomType as a plugin
Implement the Standard Interface:
The type_name property must return the string <dj_zarr>.
The stored_type property must return the object.
The put method must accept a Zarr-compatible array object (e.g., a NumPy array) and write it to the configured external object store as a Zarr dataset.
The get method must read the Zarr dataset from the external store and return it as a lazy-loading Zarr array object.
Default Registration:
The <dj_zarr> adaptor should be registered by default with the DataJoint client, making it available out-of-the-box.
Justification
Providing native support for Zarr arrays via a type adaptor will be a transformative feature for DataJoint. It will enable the seamless management of petabyte-scale array data in a format that is optimized for high-performance, parallel computing and cloud environments. This directly addresses the needs of modern data-intensive science and solidifies DataJoint's position as a cutting-edge platform for scientific data management.
+1 this from my side! I am working a lot with zarr nowadays.
I particularly like the idea of using some kind of lazy loading, i.e. that there is a zarr object saved in the cloud (as external object in dj) that can be indexed from downstream processes in the pipeline without loading the whole zarr array to disk first - i.e. using zarr's indexability from within datajoint if that makes sense.
The DataJoint 2.0 Codec system provides the infrastructure to implement <zarr> support. Here's how it would work:
Codec Implementation
classZarrCodec(dj.Codec):
""" Store NumPy arrays as Zarr datasets in external object storage. Usage: data : <zarr@store> # Store as Zarr in named store data : <zarr@> # Store as Zarr in default store """name="zarr"defget_dtype(self, is_external: bool) ->str:
# Zarr is always external (uses object storage)return"<object>"defencode(self, value, *, key=None, store_name=None):
"""Write array to Zarr format in object storage."""importzarrimportnumpyasnp# Convert to numpy if neededifnotisinstance(value, np.ndarray):
value=np.asarray(value)
# Write to temporary Zarr, then upload# The <object> codec handles the actual storagereturn {"_zarr": True, "shape": value.shape, "dtype": str(value.dtype)}
defdecode(self, stored, *, key=None):
"""Return lazy-loading Zarr array from object storage."""importzarr# Return zarr.Array backed by fsspec for lazy loading# This enables slicing without loading entire arrayreturnzarr.open(stored["path"], mode="r")
Key Features
Lazy Loading: Returns zarr.Array object, not loaded data. Users can slice efficiently:
arr= (MyTable&key).fetch1("data") # Returns zarr.Arraychunk=arr[100:200, :, :] # Only loads this slice from cloud
Chunked Storage: Zarr's chunking enables parallel writes and partial reads
Implementation Options
Option A: Built-in codec (in datajoint.builtin_codecs)
Available out-of-box
Adds zarr as optional dependency
Option B: Plugin package (datajoint-zarr)
Separate install: pip install datajoint-zarr
Auto-registers via entry points
Keeps core datajoint lightweight
Given @dimitri-yatsenko's comment about implementing as a separate project, Option B seems preferred. The entry point system in DataJoint 2.0 supports this:
# In datajoint-zarr/pyproject.toml
[project.entry-points."datajoint.codecs"]
zarr = "datajoint_zarr:ZarrCodec"
This allows <zarr@store> to work automatically once datajoint-zarr is installed.
Activity
github-actions commentedon Oct 3, 2025
This issue is stale because it has been open for 45 days with no activity.
dimitri-yatsenko commentedon Dec 22, 2025
This will be implemented as a separate project and tested for integration here.
horsto commentedon Jan 8, 2026
+1 this from my side! I am working a lot with zarr nowadays.
I particularly like the idea of using some kind of lazy loading, i.e. that there is a zarr object saved in the cloud (as external object in dj) that can be indexed from downstream processes in the pipeline without loading the whole zarr array to disk first - i.e. using zarr's indexability from within datajoint if that makes sense.
dimitri-yatsenko commentedon Jan 8, 2026
Implementation Plan for DataJoint 2.0
The DataJoint 2.0 Codec system provides the infrastructure to implement
<zarr>support. Here's how it would work:Codec Implementation
Key Features
Lazy Loading: Returns
zarr.Arrayobject, not loaded data. Users can slice efficiently:Cloud-Native: Uses
<object@store>for storage, leveraging fsspec backends (S3, GCS, Azure)Chunked Storage: Zarr's chunking enables parallel writes and partial reads
Implementation Options
Option A: Built-in codec (in
datajoint.builtin_codecs)Option B: Plugin package (
datajoint-zarr)pip install datajoint-zarrGiven @dimitri-yatsenko's comment about implementing as a separate project, Option B seems preferred. The entry point system in DataJoint 2.0 supports this:
This allows
<zarr@store>to work automatically oncedatajoint-zarris installed.dimitri-yatsenko commentedon Jan 9, 2026
Implemented in DataJoint 2.0
Zarr support is implemented via the
<object>storage type:Implementation:
The
<object>type provides native Zarr support through fsspec:Features:
zarr.open()See
src/datajoint/objectref.pyfor the ObjectRef implementation with fsmap support.