
OMERO 数据访问、层级遍历与安全传输规划scientific-agent-skills omero-integration 技能实战指南【免费下载链接】scientific-agent-skillsTurn any AI agent into an AI Scientist. The #1 Agent Skills library for science, used by 190,000 scientists worldwide. 165 ready-to-use validated skills plus 100 scientific databases covering biology, chemistry, medicine, and drug discovery. Compatible with Cursor, Claude Code, Codex, Pi, Antigravity, and the open Agent Skills standard.项目地址: https://gitcode.com/GitHub_Trending/cl/scientific-agent-skills本篇技术指南围绕scientific-agent-skills仓库中 omero-integration 技能的数据访问参考文档 data_access.md 展开系统讲解如何使用 OMERO.py / BlitzGateway 与 OMERO CLI 进行有界读取bounded reads与显式作用域的导入/导出explicit import/export scopes包括对象层级模型、按 ID 读取、分页限流、组/所有者过滤、容器遍历、筛选数据、Fileset 下载与传输规划。读完本文你将掌握一套可直接复制的安全访问显微镜数据模式既能高效查询 OMERO 中的图像与元数据又能避免把无界请求变成跨组全量导出同时学会用仓库内置的inventory.py、plan_transfer.py等本地安全助手在真正连接服务器之前完成 dry-run 规划。开始之前建议先阅读 connection.md 掌握连接、会话与传输安全的基础知识。对象层级OMERO 数据组织的容器路径OMERO 将生物影像数据组织为若干固定的容器层级常见路径如下Project - Dataset - Image Screen - Plate - Well - WellSample - Image Image - Pixels - Channel Image - Fileset - OriginalFile(s)一个关键事实是链接link是模型对象且可能多对多many-to-many。不要假设一张图像只属于一个 Dataset也不要假设一个 Dataset 只属于一个 Project。正确做法是遍历服务器返回的链接links而不是根据命名约定自行合成父路径——后者在权限隔离或数据被重新组织时会直接失效。OME 官方文档中常见的 BlitzGateway 对象名包括Project、Dataset、ImageScreen、Plate、PlateAcquisition、WellRoi、ShapeExperimenter、ExperimenterGroupOriginalFile、FilesetAnnotation及其具体子类型仓库内置的盘点助手 inventory.py 将对象类型收窄为一个明确的白名单OBJECT_TYPES见 inventory.py#L25-L34Project、Dataset、Image、Screen、Plate、Well、Fileset、OriginalFile。如果你的自动化流程只处理这些类型直接复用该白名单即可避免对任意对象名的假设。重要提示对象名支持object-name support不等于权限permission。调用getObject()返回None可能意味着对象不存在也可能意味着对象存在但你无权访问。因此后续所有示例都会把None视为统一的不可访问信号并抛出明确的错误。按 ID 获取单个对象显式 ID 优先只要可能优先使用显式 ID 而非名称或路径来定位对象image_id 123 image conn.getObject(Image, image_id) if image is None: raise LookupError(Image was not found or is not accessible) print(image.getId()) print(image.getSizeX(), image.getSizeY())注意除非请求的输出明确要求包含名称、描述、所有者名或采集元数据否则不要打印这些信息。它们是潜在的敏感元数据详见下文图像元数据小节。对于多个显式 ID使用getObjects()并传入 ID 列表respect_orderTrue可保持请求顺序requested_ids [101, 102, 103] for image in conn.getObjects( Image, requested_ids, respect_orderTrue, ): print(image.getId())务必保持输入列表有界bounded并在返回后检查是否有不可访问的 ID 被静默省略——getObjects()只返回可访问的对象不会为每个不可访问 ID 报错。有界分页永远不要裸写 list(conn.getObjects(...))getObjects()返回的是生成器generator单纯list(...)会一次性拉取全部结果在大型数据库中等于隐式全量导出。参考文档给出了同时约束**总上限overall cap与页大小page size**的iter_bounded生成器def iter_bounded(conn, object_type, *, limit100, page_size25): if not 1 limit 1000: raise ValueError(limit must be between 1 and 1000) if not 1 page_size min(limit, 200): raise ValueError(page_size must be between 1 and min(limit, 200)) emitted 0 offset 0 while emitted limit: size min(page_size, limit - emitted) page list( conn.getObjects( object_type, opts{ limit: size, offset: offset, order_by: obj.id, }, ) ) if not page: return for obj in page: yield obj emitted 1 if len(page) size: return offset len(page)这条模式的工程含义在仓库源码中得到了一一印证边界硬约束iter_bounded校验1 limit 1000与1 page_size 200而 inventory.py#L232-L241 在main()中同样用bounded_int()定义于 omero_common.py#L367-L380强制--limit介于 1~1000、--page-size介于 1~200且page_size不得超过limit。两端约束一致说明这是该技能所有远程操作共享的安全基线。分页请求参数真实请求使用opts{limit: ..., offset: ..., order_by: obj.id}与 inventory.py#L172-L183 的collect_inventory()完全同构。按obj.id排序保证 offset 分页在稳定数据集上可复现。测试验证tests/omero-integration/test_scripts.py 的InventoryTests.test_inventory_pages_and_redacts_names用伪造连接验证了 limit5、page_size2 时会产生offset序列[0, 2, 4]并确认返回limit_reachedTrue、名称全部脱敏。这证明分页与脱敏行为是被测试锁定的契约。两点补充提醒不要写list(conn.getObjects(...))而不加服务器端 limit/offset。如果另一个进程在 offset 分页期间修改了行结果可能发生位移新增/删除行会导致后续页错位为可审计性建议记录提取时间extraction time与所选组selected group。仓库中的take_bounded()omero_common.py#L258-L264实际路径为 omero_common.py提供另一种惰性上限工具它最多物化limit个元素并额外探测一个元素来判断是否被截断适用于listChildren()、listAnnotations()这类不支持服务端分页的懒加载迭代器。使用内置 inventory 助手参考文档捆绑的库存助手实现了 cap1000、page cap200 的安全约定且默认 dry-run 不连接服务器python -B scripts/inventory.py \ --object-type Image \ --limit 50 \ --page-size 25 # 审查 dry-run JSON 后显式连接执行 python -B scripts/inventory.py \ --object-type Image \ --limit 50 \ --page-size 25 \ --execute \ --output ./image-inventory.json除非显式指定--include-names否则名称一律脱敏输出中为name_redacted: True见 inventory.py#L126-L132。对Image类型还会输出dimensionsx/y/z/c/t与pixels_type对OriginalFile则输出size_bytes与mimetype见 inventory.py#L140-L154。--output指定的 JSON 文件通过 omero_common.py 的 atomic_write_json 原子写入文件权限为0600、拒绝写入 symlink、默认拒绝覆盖已有文件这些行为同样被 test_scripts.py 的 OutputTests 覆盖。组与所有者过滤器单组优先跨组必须单独审批OMERO 的权限模型以组group为边界。优先将连接限定在一个已选组group_id 42 conn.SERVICE_OPTS.setOmeroGroup(str(group_id)) for project in conn.getObjects( Project, opts{limit: 20, offset: 0, order_by: obj.id}, ): print(project.getId())setOmeroGroup会修改后续所有服务调用的组上下文详见 connection.md 的 Group Context 一节如需临时切换应记录原组并在写操作前恢复。过滤器可以进一步收窄查询——同时限定所有者与组owner_id conn.getUser().getId() projects conn.getObjects( Project, opts{ owner: owner_id, group: group_id, limit: 20, offset: 0, order_by: obj.id, }, )跨组上下文-1必须单独获得批准并配合硬性 limit 使用。绝不可以在对象没找到时回退到-1——那会让一次本应失败的单组查询静默变成跨组搜索从而放大数据暴露面。在仓库实现中两个远程助手 inventory.py 与 export_image_metadata.py 都只接受正整数--group-id并在输出中显式标记cross_group: False从参数层面就拒绝-1。遍历容器懒加载子节点 显式上限向下遍历downward traversal会惰性加载lazily load子节点。每个层级都要设置独立上限绝不做无界遍历project conn.getObject(Project, project_id) if project is None: raise LookupError(Project unavailable) dataset_limit 10 for dataset_index, dataset in enumerate(project.listChildren()): if dataset_index dataset_limit: break print(dataset.getId()) image_limit 25 for image_index, image in enumerate(dataset.listChildren()): if image_index image_limit: break print(image.getId())countChildren()可以帮助规划上限例如先获取数量再决定分页策略但不能替代上限本身——计数可能在检索之前就发生变化。对于已知 Dataset 下的图像这一常见场景优先使用服务器端过滤器而非遍历全部子节点images conn.getObjects( Image, opts{ dataset: dataset_id, limit: 50, offset: 0, order_by: obj.id, }, )这种写法把过滤下推到服务端客户端只拿到受限的一页比拉取整个 Dataset 再在本地过滤安全且高效得多。筛选数据Plate/Well 的逐层有界遍历高内涵筛选high-content screening数据规模巨大必须对每个层级都设置边界plate conn.getObject(Plate, plate_id) if plate is None: raise LookupError(Plate unavailable) for well_index, well in enumerate(plate.listChildren()): if well_index 96: break print(well.getId()) field_count min(well.countWellSample(), 10) for field_index in range(field_count): image well.getImage(field_index) if image is not None: print(image.getId())这里用min(well.countWellSample(), 10)限制每个 Well 最多取 10 个视野field避免 96 孔板 × 大量视野的组合爆炸。Well 的行/列位置与视野数量field counts可以揭示实验设计信息仅当请求明确要求时才输出它们——它们同样属于可识别的元数据。图像元数据读取维度不触碰像素数据基本维度dimensions的读取不会检索像素平面pixel planes因此可以作为低成本、低风险的盘点手段summary { id: image.getId(), size_x: image.getSizeX(), size_y: image.getSizeY(), size_z: image.getSizeZ(), size_c: image.getSizeC(), size_t: image.getSizeT(), pixels_type: image.getPixelsType(), }物理尺寸physical size可能缺失读取时务必判空size_x image.getPixelSizeX(unitsTrue) if size_x is not None: print(size_x.getValue(), size_x.getSymbol())敏感元数据脱敏是默认策略。名称、描述、采集日期、所有者名、组名、通道标签channel labels都属于潜在敏感元数据在大范围报告中应默认脱敏redact。这一点在源码层面体现为inventory.py#L126-L132名称默认不读入输出只写name_redacted: Trueexport_image_metadata.py 的annotation_record()与shape_record()注解值、文件名称、ROI 标签默认均以*_redacted标记代替且RedactionTests.test_annotation_value_and_filename_not_read_when_redactedtest_scripts.py#L263-L277甚至验证了被脱敏的注解值根本不会被调用读取value_read保持False——脱敏不是读了再藏而是不读也不传。omero_common.py 的 json_safe 对字符串长度、集合长度、嵌套深度进行逐层截断确保即使不小心碰到了异常值输出 JSON 也不会膨胀或泄露超长原文。Fileset 与原始文件下载前先估算作用域一个 fileset 聚合了导入时的原始文件original files可能对应多张图像。下载前应先检查其元数据fileset image.getFileset() if fileset is not None: print(fileset.getId())下载一个Image或Fileset可能一次性取回多个原始文件及其目录结构。先估算规模绝不要因为方便就对整个容器发起下载。当前 CLI 支持的三种显式下载作用域# 单个 OriginalFile omero download OriginalFile:123 ./explicit-local-file # 与单张图像关联的原始文件 omero download Image:123 ./explicit-empty-directory # 单个 fileset 中的原始文件 omero download Fileset:456 ./explicit-empty-directory安全约定通过已经提示登录的 CLI 会话认证即先omero login交互式输入不要在可复用命令文本中加入-w、--password或-k参数——会话密钥等同于 bearer 凭据拒绝 symlink 目标与碰撞collision输出目录必须是已存在的普通目录不能是指向其他位置的符号链接绝不要直接从不可信的远端文件名推导本地路径防止路径穿越path traversal。导入规划与导入scan-first 两步法OMERO 导入器支持不连接运行中的服务器做文件扫描omero import -f ./explicit-input omero import --depth 4 -f ./explicit-directory-f会列出将被导入的文件、按 fileset 分组然后退出。这是正确的第一步它不是远程导入。--depth控制目录扫描深度防止误扫出深层目录中大量无关文件。仓库捆绑的本地规划器plan_transfer.py更加保守——完全不调用 OMERO只做纯本地的文件系统扫描与命令提案python -B scripts/plan_transfer.py import \ --target Dataset:id:42 \ --max-files 100 \ ./explicit-input从 plan_transfer.py 的实现看import子命令的可调边界包括--max-paths默认 25上限 100显式顶层路径数量上限--max-files默认 100上限 10000发现的所有普通文件总数上限--scan-depth默认 4上限 20目录递归深度上限。扫描逻辑scan_import_path()plan_transfer.py#L140-L211只统计元数据、绝不读取文件内容、followlinksFalse跳过 symlink一旦文件数超过--max-files立即报错。目标格式被正则严格约束为Dataset:id:正整数或Screen:id:正整数见 plan_transfer.py#L22-L23。测试 test_scripts.py#L280-L339 验证了生成的命令绝不包含--password、-w、-k且commands_executed恒为False。规划审查通过、完成交互式omero login后真正的有作用域导入是omero import -T Dataset:id:42 ./explicit-input-T指定导入目标容器。几个必须牢记的注意事项目标必须在当前会话组内——目标组错误会在导入时才暴露务必先omero group list/omero sessions group id确认导入需要兼容的 importer Java 库将OMERODIR指向匹配的已解压服务器发行版普通 BlitzGateway 远程客户端则不需要服务器目录树详见 connection.md--parallel-fileset与--parallel-upload官方标记为实验性过高的并发值可能让客户端崩溃或让服务器无响应--report --upload会把损坏的源文件与日志发送给 OME 团队未经明确授权绝不可使用可能泄露未发表数据in-place 导入会改变仓库假设repository assumptions属于管理员工作流不是常规客户端优化。OME-TIFF 与 XML 导出区分导出与下载原始文件官方文档支持的omero export命令目前支持两种格式omero export --file ./image-123.ome.tiff Image:123 omero export --file ./image-123.ome.xml --type XML Image:123这不同于下载原始文件两者语义必须区分export把 OMERO 图像序列化为 OME-TIFF或把元数据导出为 XML属于派生产物download取回与 OriginalFile、FileAnnotation、Image 或 Fileset 关联的原始文件。Dataset 级迭代目前只是实验性导出模式默认不要用它做大规模导出。请显式规划图像 ID 列表python -B scripts/plan_transfer.py export \ --format ome-tiff \ --output-dir ./reviewed-output \ Image:123 Image:124plan_transfer.py export子命令的契约plan_transfer.py#L296-L364选择器必须是Image:正整数重复选择器直接报错--format只允许ome-tiff或xml对应文档化的两种导出格式--max-images默认 25、上限 100输出目录必须已存在、非 symlink对每个图像生成目标文件名image-id.ome.tiff/image-id.ome.xml并预先检测collision目标已存在或为 symlink只要存在碰撞ready_for_remote_export_review即为False阻止进入远程执行阶段。规划器本身不连接、不导出。请在运行每一条建议命令前审查文件碰撞、图像数量、可用存储空间bytes 估算。测试 test_scripts.py#L309-L322 用预先存在的image-5.ome.xml验证了碰撞检测确实生效。传输检查清单任何导入/导出/下载前必须确认参考文档在末尾给出了八项强制检查清单这是整个技能安全模型的可执行浓缩版确认当前会话组omero sessions group id或conn.SERVICE_OPTS.setOmeroGroup确认显式源路径或对象 ID——杜绝通配、杜绝目录级全量限制文件/对象数量与目录扫描深度对应--max-files、--scan-depth、--limit、--page-size区分派生的 OME-TIFF/XML 导出与原始文件下载——两者作用域和产物完全不同估算字节量并审查数据共享授权——OMERO 中可能含有未发表图像、标识符、注解与原始文件使用专用的已存在输出目录且无 symlink/碰撞绝不使用凭据参数-w、--password、-k未经单独同意不上传诊断信息或损坏文件对应--report --upload禁令。这套清单与 SKILL.md 中定义的Operating Contract一脉相承所有远程助手默认 dry-run、凭据只从命名的OMERO_*环境变量读取、每个列表/页/像素平面都必须有界、所有写操作必须有精确审查过的目标。结语把安全有界变成 OMERO 自动化的默认值data_access.md参考文档的价值不在于罗列 API而在于确立了一套可执行的边界纪律层级遍历要有上限、分页要有 cap、查询要限定组与所有者、下载/导入/导出要先规划后执行、敏感元数据默认脱敏。这些纪律在仓库源码inventory.py、plan_transfer.py、export_image_metadata.py、omero_common.py与测试test_scripts.py中层层落地。实际使用该技能时建议的工作流是先用plan_transfer.py或inventory.py --dry-run规划作用域 → 交互式omero login或设置OMERO_SESSION_KEY→ 显式指定对象 ID、组、上限后--execute→ 全程在finally中关闭连接与所有有状态服务。这样既拿到了显微镜数据的结构化访问能力也把误触大规模导出的风险降到了最低。【免费下载链接】scientific-agent-skillsTurn any AI agent into an AI Scientist. The #1 Agent Skills library for science, used by 190,000 scientists worldwide. 165 ready-to-use validated skills plus 100 scientific databases covering biology, chemistry, medicine, and drug discovery. Compatible with Cursor, Claude Code, Codex, Pi, Antigravity, and the open Agent Skills standard.项目地址: https://gitcode.com/GitHub_Trending/cl/scientific-agent-skills创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考