跳转到主要内容

未提供项目描述

项目描述

LINDI - 链接数据接口

latest-release tests codecov

LINDI是一种云友好的文件格式和Python库,专为管理科学数据设计,特别是用于管理“没有边界的神经数据”(NWB)数据集。它提供了对HDF5Zarr的替代方案,同时保持与两者的兼容性,并提供针对链接到云中存储的远程数据集(例如DANDI存档中的数据集)的特性。LINDI的独特结构和功能使其特别适合在云环境中高效地访问和管理数据。

什么是LINDI文件?

LINDI文件是用于存储科学数据的云友好格式,旨在与HDF5和Zarr兼容,同时提供独特的优势。它有三种类型,它们是相同底层数据的表示:JSON/text格式(.lindi.json)、二进制格式(.lindi.tar)和目录格式(.lindi.d)。

在JSON格式中,分层组结构、属性和小型数据集存储在JSON结构中,而对较大数据块的外部文件的引用(灵感来自kerchunk)。这种格式可读性良好,易于检查和编辑。

二进制格式是一个包含JSON文件(lindi.json)以及由JSON文件引用的可选内部数据块(外部块)的.tar文件。此格式可用于创建新的NWB文件,该文件基于现有NWB文件而无需重复,并添加新的数据对象(见下文)。

目录格式与.tar格式类似,但将lindi.json和二进制块存储在目录中,而不是.tar文件中。

主要用例是什么?

LINDI文件在以下场景中特别有用:

在DANDI上的高效NWB文件表示:LINDI JSON文件可以表示存储在DANDI存档(或其他远程系统)上的NWB文件。通过下载一个压缩的JSON文件,可以一次性检索整个组结构,从而方便高效地加载NWB文件。例如,Neurosift利用预生成的LINDI JSON文件来简化从DANDI加载NWB文件的过程(示例)。

创建修订版NWB文件:LINDI允许创建修订版NWB文件,向现有NWB文件添加新的数据对象,而无需复制整个文件。这是通过生成一个引用原始NWB文件并包含作为内部数据块存储的附加数据对象的二进制或目录LINDI文件来实现的。这种方法通过减少冗余并建立NWB文件之间的依赖关系来节省存储空间。

为什么不使用Zarr?

当比较LINDI和Zarr时,应注意的是,LINDI文件实际上是有效的Zarr存档,可以通过Zarr API访问。事实上,LINDI文件是Zarr存储的特殊类型,允许对块进行外部链接(参见kerchunk)和用于表示NWB的HDF5功能的特殊约定,这些功能Zarr本身不支持。

传统的Zarr目录存储有一些局限性。首先,Zarr存档通常由数万个单独的文件组成,使得管理起来很麻烦。相比之下,LINDI采用类似于HDF5的单文件方法,提高了可管理性,同时保持了云友好性。另一个局限性(如前所述)是缺乏像LINDI那样的机制来引用外部数据集中的数据块。最后,Zarr本身不支持NWB使用的一些特性,如复合数据类型和引用。这些特性都由HDF5和LINDI支持。

为什么不使用HDF5?

HDF5不适合云环境,因为访问远程HDF5文件通常需要在下载更大的数据块之前,通过大量小请求来检索元数据。LINDI通过将整个组结构存储在单个JSON文件中来解决这个问题,该文件可以一次性下载。此外,HDF5缺乏内置的引用外部数据集中数据块的机制。此外,HDF5不支持Zarr和LINDI都有的自定义Python编解码器。

tar格式真的云友好吗?

使用LINDI时是的。有关详细信息,请参阅docs/tar.md

安装

pip install --upgrade lindi

或从源安装

cd lindi
pip install -e .

使用方法

创建和读取LINDI文件

最简单的方法是像使用HDF5一样使用它。

import lindi

# Create a new lindi.json file
with lindi.LindiH5pyFile.from_lindi_file('example.lindi.json', mode='w') as f:
    f.attrs['attr1'] = 'value1'
    f.attrs['attr2'] = 7
    ds = f.create_dataset('dataset1', shape=(10,), dtype='f')
    ds[...] = 12

# Later read the file
with lindi.LindiH5pyFile.from_lindi_file('example.lindi.json', mode='r') as f:
    print(f.attrs['attr1'])
    print(f.attrs['attr2'])
    print(f['dataset1'][...])

您可以通过查看example.lindi.json文件来了解数据是如何存储的。如果您熟悉内部Zarr格式,您将识别出.group和.zarray文件以及数据块的布局。这是一个示例,展示了表示存储在DANDI上的NWB文件的LINDI JSON文件。

由于上述数据集非常小,它可以合理地全部放入JSON文件中。对于存储更大的数组(通常情况),最好使用二进制或目录格式。

import numpy as np
import lindi

# Create a new lindi binary file
with lindi.LindiH5pyFile.from_lindi_file('example.lindi.tar', mode='w') as f:
    f.attrs['attr1'] = 'value1'
    f.attrs['attr2'] = 7
    ds = f.create_dataset('dataset1', shape=(1000, 1000), dtype='f')
    ds[...] = np.random.rand(1000, 1000)

# Later read the file
with lindi.LindiH5pyFile.from_lindi_file('example.lindi.tar', mode='r') as f:
    print(f.attrs['attr1'])
    print(f.attrs['attr2'])
    print(f['dataset1'][...])

从DANDI加载远程NWB文件

使用LINDI,很容易从DANDI加载存储的NWB文件。以下示例演示了如何从DANDI加载NWB文件,使用pynwb库查看它,并将其保存为相对较小的.lindi.json文件。然后可以直接读取LINDI JSON文件以访问NWB文件。

import json
import pynwb
import lindi

# Define the URL for a remote NWB file
h5_url = "https://api.dandiarchive.org/api/assets/11f512ba-5bcf-4230-a8cb-dc8d36db38cb/download/"

# Load as LINDI and view using pynwb
f = lindi.LindiH5pyFile.from_hdf5_file(h5_url)
with pynwb.NWBHDF5IO(file=f, mode="r") as io:
    nwbfile = io.read()
    print('NWB via LINDI')
    print(nwbfile)

    print('Electrode group at shank0:')
    print(nwbfile.electrode_groups["shank0"])  # type: ignore

    print('Electrode group at index 0:')
    print(nwbfile.electrodes.group[0])  # type: ignore

# Save as LINDI JSON
f.write_lindi_file('example.nwb.lindi.json')
f.close()

# Later, read directly from the LINDI JSON file
g = lindi.LindiH5pyFile.from_lindi_file('example.nwb.lindi.json')
with pynwb.NWBHDF5IO(file=g, mode="r") as io:
    nwbfile = io.read()
    print('')
    print('NWB from LINDI JSON:')
    print(nwbfile)

    print('Electrode group at shank0:')
    print(nwbfile.electrode_groups["shank0"])  # type: ignore

    print('Electrode group at index 0:')
    print(nwbfile.electrodes.group[0])  # type: ignore

修改NWB文件

LINDI的主要用途之一是创建修改后的NWB文件,该文件向现有NWB文件添加新的数据对象,而无需复制整个文件。这是通过生成一个引用原始NWB文件并包含作为内部数据块存储的附加数据对象的二进制或目录LINDI文件来实现的。

import numpy as np
import pynwb
from pynwb.file import TimeSeries
import lindi

# Load the remote NWB file from DANDI
h5_url = "https://api.dandiarchive.org/api/assets/11f512ba-5bcf-4230-a8cb-dc8d36db38cb/download/"
f = lindi.LindiH5pyFile.from_hdf5_file(h5_url)

# Write to a local .lindi.tar file
f.write_lindi_file('example.nwb.lindi.tar')
f.close()

# Open with pynwb and add new data
g = lindi.LindiH5pyFile.from_lindi_file('example.nwb.lindi.tar', mode='r+')
with pynwb.NWBHDF5IO(file=g, mode="a") as io:
    nwbfile = io.read()
    timeseries_test = TimeSeries(
        name="test",
        data=np.array([1, 2, 3, 4, 5, 4, 3, 2, 1]),
        rate=1.,
        unit='s'
    )
    ts = nwbfile.processing['behavior'].add(timeseries_test)  # type: ignore
    io.write(nwbfile)  # type: ignore

# Later on, you can read the file again
h = lindi.LindiH5pyFile.from_lindi_file('example.nwb.lindi.tar')
with pynwb.NWBHDF5IO(file=h, mode="r") as io:
    nwbfile = io.read()
    test_timeseries = nwbfile.processing['behavior']['test']  # type: ignore
    print(test_timeseries)

注意

本项目受到了kerchunkhdmf-zarr的启发。

对于开发者

LINDI使用的特殊Zarr注释

许可证

请参阅LICENSE

项目详情


下载文件

下载适用于您平台的文件。如果您不确定选择哪个,请了解更多关于安装包的信息。

源分布

lindi-0.4.2.tar.gz (57.8 kB 查看哈希)

上传时间

构建分布

lindi-0.4.2-py3-none-any.whl (68.3 kB 查看哈希)

上传时间 Python 3

由以下支持

AWS AWS 云计算和安全赞助商 Datadog Datadog 监控 Fastly Fastly CDN Google Google 下载分析 Microsoft Microsoft PSF 赞助商 Pingdom Pingdom 监控 Sentry Sentry 错误记录 StatusPage StatusPage 状态页面