OHIF Viewer 数据源(Data Source)完全指南:从 Naturalized DICOM JSON 到自定义数据源实现
【免费下载链接】ViewersOHIF zero-footprint DICOM viewer and oncology specific Lesion Tracker, plus shared extension packages项目地址: https://gitcode.com/GitHub_Trending/vi/Viewers
导读
本文围绕 OHIF Viewer 的 Data Source 机制展开,从 OHIF 内部统一使用的 naturalized DICOM JSON 元数据格式讲起,系统梳理内置的dicomweb、dicomjson、dicomwebproxy、merge等常用数据源及其配置方式,并深入讲解如何基于IWebApiDataSource与 Data Source Module 编写自定义数据源,将任何私有后端(甚至非 DICOM 数据)映射到 OHIF 原生格式。读完本文,你将掌握数据源模块的注册方式、DICOMweb 服务的本地搭建与配置参数、以及通过 ExtensionManager 动态添加/更新数据源的实际能力。
OHIF 的数据基石:Naturalized DICOM JSON
OHIF 内部元数据的数据结构遵循naturalized DICOM JSON格式,这是一种由dcmjs项目开创的表示法。其核心思路是:将传统 DICOM 元数据头中的Tag(如(0020,000D))替换为 DICOM Keyword(如StudyInstanceUID),并将 Sequences 以数组形式组织,从而获得易于开发、代码语义清晰的 JSON 结构。
相比原始 DICOM 的十六进制 Tag 与嵌套元素,naturalized 格式带来两点直接收益:
- 可读性:开发者在代码中直接书写
StudyInstanceUID、SeriesInstanceUID、Modality等人类可读字段,无需查阅 DICOM 标准字典翻译 Tag; - 可扩展性:JSON 天然适合前后端交换与序列化,也为自定义数据源的映射提供了统一目标格式。
在仓库中,这一格式贯穿全链路:dcmjs的DicomMetaDictionary.naturalizeDataset/denaturalizeDataset被 DicomWebDataSource/index.ts 直接引用,用于将服务端返回的 DICOM 数据在 naturalized 与 denaturalized 两种形态间转换;而platform/core/src/classes中的 MetadataProvider 与services/DicomMetadataStore则负责承载这些 naturalized 元数据,供 DisplaySet 构建、挂片协议(Hanging Protocol)与视口渲染消费。
OHIF 提供的内置数据源总览
OHIF 已经为最常见的几种数据接入场景提供了开箱即用的数据源实现,官方文档(introduction.md)中明确列出的包括:
| 数据源 | 名称标识 | 适用场景 |
|---|---|---|
| DICOMweb | dicomweb | 对接遵循 DICOMweb 标准的 PACS / 影像归档(QIDO-RS / WADO-RS / STOW-RS) |
| DICOM JSON | dicomjson | 通过一个指向 JSON 文件的 URL 直接启动查看器,JSON 内含研究/序列/实例元数据与 DICOM 文件地址 |
| DICOMweb Proxy | dicomwebproxy | 通过一个返回 DICOMweb 配置的 JSON URL,动态构造数据源并代理后续请求 |
| Static DICOMweb | 基于dicomweb+staticWado | 服务由static-wado预先生成的静态 DICOMweb 文件,追求极致加载性能 |
| Merge | merge | 在 series 级别合并多个数据源的结果 |
其中dicomweb与dicomjson由 default 扩展在getDataSourcesModule中注册,源码形态如下(getDataSourcesModule.js):
import { createDicomWebApi } from './DicomWebDataSource/index'; import { createDicomJSONApi } from './DicomJSONDataSource/index'; function getDataSourcesModule() { return [ { name: 'dicomweb', type: 'webApi', createDataSource: createDicomWebApi, }, { name: 'dicomjson', type: 'jsonApi', createDataSource: createDicomJSONApi, }, ]; }从这段代码可以看到 Data Source Module 的标准注册契约:每个数据源包含name(唯一标识)、type(webApi/local/other等)与createDataSource(工厂函数,接收dataSourceConfig并返回数据源实例)。
编写自定义数据源:基于 IWebApiDataSource
如果你的数据源是自定义的、或持有非标准格式的数据,完全可以自行编写一个数据源,把数据映射到 OHIF 原生格式。数据甚至不需要是 DICOM,只要你能将私有数据映射到正确格式即可。官方文档明确给出自定义数据源的标准写法(data-source.md):
const getDataSourcesModule = () => [ { name: 'exampleDataSource', type: 'webApi', // 'webApi' | 'local' | 'other' createDataSource: dataSourceConfig => { return IWebApiDataSource.create(/* */); }, }, ];这里的IWebApiDataSource.create来自@ohif/core,是一个工厂函数,用于创建"通过 HTTP 拉取数据"的 Web API 数据源。其接口定义位于 platform/core/src/DataSources/IWebApiDataSource.js,核心入参如下:
function create({ initialize, query, retrieve, store, reject, parseRouteParams, deleteStudyMetadataPromise, getImageIdsForDisplaySet, getImageIdsForInstance, }) { /* */ }值得注意的设计点是:一个数据源实现可以为"读"和"写"分别定义不同的底层来源,并且该工厂会为缺失的方法注入默认实现(例如默认的store.dicom会抛出 "not implemented" 错误,默认getConfig返回{ dicomUploadEnabled: false })。
必须实现的核心 API 端点
参考dicomweb数据源实现(DicomWebDataSource/index.ts),自定义数据源需要重点实现以下端点:
| 端点 | 作用 | 说明 |
|---|---|---|
initialize | 数据源初始化 | 在mode.tsx中数据源首次创建时调用,用于设置配置。例如dicomweb借此从 URL 中提取StudyInstanceUID并设为活动研究;dicomjson则用浏览器 URL 拉取数据并存入缓存 |
query.studies.search | 研究查询 | 左侧研究面板用于拉取同一 MRN 的既往研究(All标签页),Worklist 中用于列出服务端全部研究 |
query.series.search | 序列查询 | 在 Worklist 展开某个研究时,拉取该研究的序列信息 |
retrieve.bulkDataURI | 大数据块检索 | 用于在视口中渲染 RTSTRUCT(放疗结构集)。它是一个包含enabled属性及数据源特定选项的对象 |
retrieve.series.metadata | 序列元数据检索 | 最关键端点,用于拉取序列级元数据,支撑挂片 DisplaySet 的构建与创建 |
store.dicom | 数据回存 | 仅当需要回存功能时实现,用于把数据写入后端;不需要可跳过 |
对应到源码:qido.js实现了mapParams、search(QIDO 查询)与processResults;retrieveStudyMetadata.js实现了retrieveStudyMetadata与deleteStudyMetadataPromise;retrieveBulkData.ts实现了 bulk data 检索;dcm4cheeReject.js实现 reject(仅 DCM4CHEE 等支持 reject 的服务)。
Static WADO 客户端
当数据源配置中设置了staticWado: true时,OHIF 会假定研究查询返回的是研究的超集(静态列表),并使用 StaticWadoClient 在客户端手动执行搜索:它解释查询参数并应用到已返回的响应上。该特性对某些"可查询但不支持按特定字段查询"的 DICOMweb 后端非常有用,但前提是研究列表规模不能太大,否则客户端侧筛选开销过高。
DicomMetadataStore:数据源与元数据的汇合点
OHIF-v3 将研究元数据集中存放在DicomMetadataStore(位于platform/core/src/services/DicomMetadataStore)中,它是存储与获取 Study / Series / Instance 三级元数据的中央位置。你的自定义数据源可以通过DicomMetadataStore写入或读取元数据,与视图渲染层解耦。该 Store 还提供了addInstances、addSeries、addStudy及订阅变更等 API,配合 IWebApiDataSource.js 顶部的注释可以看到,OHIF 有意将DicomMetadataStore设计为数据源注入元数据的统一入口,未来可进一步解除数据源对@ohif/core的硬依赖。
在模块之外添加 / 更新数据源
除在扩展模块中静态注册外,数据源还可以在运行时通过ExtensionManager动态管理。
使用 addDataSource 添加
ExtensionManager.addDataSource允许在模块之外添加数据源。下面的示例(data-source.md)为 Google Cloud Healthcare API 添加一个新的 DICOMweb 数据源并将其设为活动数据源:
extensionManager.addDataSource({ namespace: '@ohif/extension-default.dataSourcesModule.dicomweb', sourceName: 'google', configuration: { friendlyName: 'dcmjs DICOMWeb Server', name: 'GCP', wadoUriRoot: 'https://healthcare.googleapis.com/v1/projects/ohif-cloud-healthcare/locations/us-east4/datasets/ohif-qa-dataset/dicomStores/ohif-qa-2/dicomWeb', qidoRoot: 'https://healthcare.googleapis.com/v1/projects/ohif-cloud-healthcare/locations/us-east4/datasets/ohif-qa-dataset/dicomStores/ohif-qa-2/dicomWeb', wadoRoot: 'https://healthcare.googleapis.com/v1/projects/ohif-cloud-healthcare/locations/us-east4/datasets/ohif-qa-dataset/dicomStores/ohif-qa-2/dicomWeb', qidoSupportsIncludeField: true, imageRendering: 'wadors', thumbnailRendering: 'wadors', enableStudyLazyLoad: true, supportsFuzzyMatching: true, supportsWildcard: false, dicomUploadEnabled: true, omitQuotationForMultipartRequest: true, }, {activate:true} });使用 updateDataSourceConfiguration 更新
ExtensionManager.updateDataSourceConfiguration则用于更新已有数据源的配置。下面的示例(data-source.md)把名为dicomweb的数据源更新为指向 Google Cloud Healthcare:
extensionManager.updateDataSourceConfiguration( "dicomweb", { name: 'GCP', wadoUriRoot: 'https://healthcare.googleapis.com/v1/projects/ohif-cloud-healthcare/locations/us-east4/datasets/ohif-qa-dataset/dicomStores/ohif-qa-2/dicomWeb', qidoRoot: 'https://healthcare.googleapis.com/v1/projects/ohif-cloud-healthcare/locations/us-east4/datasets/ohif-qa-dataset/dicomStores/ohif-qa-2/dicomWeb', wadoRoot: 'https://healthcare.googleapis.com/v1/projects/ohif-cloud-healthcare/locations/us-east4/datasets/ohif-qa-dataset/dicomStores/ohif-qa-2/dicomWeb', qidoSupportsIncludeField: true, imageRendering: 'wadors', thumbnailRendering: 'wadors', enableStudyLazyLoad: true, supportsFuzzyMatching: true, supportsWildcard: false, dicomUploadEnabled: true, omitQuotationForMultipartRequest: true, }, );addDataSource中的sourceName与配置对象的name字段共同标识数据源实例,是后续updateDataSourceConfiguration等操作引用的句柄。
Merge 数据源
内置的merge数据源用于合并多个数据源的结果,目前仅支持在 series 级别合并:来自数据源 A 和数据源 B 的序列会被归入同一个研究下;若同一序列在两个数据源中都存在,则先到达者生效,其余冲突序列被忽略。这在"衍生数据存储在不同服务器"的场景中尤为实用——例如从一个数据源检索标注(annotation)序列、从另一个数据源检索图像数据。
配置示例(data-source.md):
window.config = { ... dataSources: [ { sourceName: 'merge', namespace: '@ohif/extension-default.dataSourcesModule.merge', configuration: { name: 'merge', friendlyName: 'Merge dicomweb-1 and dicomweb-2 data at the series level', seriesMerge: { dataSourceNames: ['dicomweb-1', 'dicomweb-2'], defaultDataSourceName: 'dicomweb-1' }, }, }, { sourceName: 'dicomweb-1', ... }, { sourceName: 'dicomweb-2', ... }, ], };其中defaultDataSourceName定义了"出问题时回退到哪台服务器"。
DICOMweb 数据源:本地服务搭建与配置
在所有数据源中,遵循 [DICOMweb] 规范的数据源最容易配置。官方教程(dicom-web.md)给出的三步法为:① 选择并安装一个影像归档(Image Archive);② 上传数据(例如用 DCMTK 的 storescu 或归档的 Web 界面);③ 保持服务运行。
本地 DICOM 服务器选型
常用的开源 DICOM 影像归档如下:
| 归档 | 安装方式 |
|---|---|
| DCM4CHEE Archive 5.x | Docker |
| Orthanc | Docker |
| DICOMcloud(仅 DICOMweb) | 源码运行 |
| OsiriX(仅 macOS) | 桌面客户端 |
| Horos(仅 macOS) | 桌面客户端 |
下面重点介绍 Orthanc 与 DCM4CHEE 两种。
运行 Orthanc
前提是已安装 Docker(可先运行docker --version确认;若使用 Docker Toolbox,需要把platform/app/package.json中的PROXY_DOMAIN改为http://192.168.99.100:8042或 docker-machine ip 输出值,这是 Webpack 代理请求所用的地址)。
启动并上传数据:
# 启动 Orthanc(窗口保持打开期间持续运行) yarn run orthanc:up上传首个研究:在浏览器打开 Orthanc Web 界面http://localhost:8042/ui/app/index.html#/,左侧即上传按钮,可直接拖放 DICOM 文件。该命令运行的docker-compose.yml位于platform/app/.recipes/Nginx-Orthanc。
随后配置 Web 应用连接 Orthanc——在仓库根目录新开终端:
# 若尚未开启 yarn workspaces yarn config set workspaces-experimental true # 恢复依赖 yarn install --frozen-lockfile # 使用本地 orthanc 配置启动开发模式 yarn run dev:orthancyarn run dev:orthanc实际执行的是platform/app下package.json中的脚本:
cross-env NODE_ENV=development PROXY_TARGET=/dicom-web PROXY_DOMAIN=http://localhost:8042 APP_CONFIG=config/docker-nginx-orthanc.js webpack-dev-server --config .webpack/webpack.pwa.js -w其中:
PROXY_TARGET=/dicom-web与PROXY_DOMAIN=http://localhost:8042告诉开发服务器把请求代理到 Orthanc,从而绕开跨域(CORS)问题;APP_CONFIG=config/docker-nginx-orthanc.js指定加载到window.config的配置文件。
DICOMweb 数据源配置详解
默认配置位于platform/app/public/config/default.js,其dataSources结构如下(dicom-web.md):
window.config = { routerBasename: null, extensions: [], modes: [], showStudyList: true, dataSources: [ { namespace: '@ohif/extension-default.dataSourcesModule.dicomweb', sourceName: 'dicomweb', configuration: { friendlyName: 'dcmjs DICOMWeb Server', name: 'DCM4CHEE', wadoUriRoot: 'https://server.dcmjs.org/dcm4chee-arc/aets/DCM4CHEE/wado', qidoRoot: 'https://server.dcmjs.org/dcm4chee-arc/aets/DCM4CHEE/rs', wadoRoot: 'https://server.dcmjs.org/dcm4chee-arc/aets/DCM4CHEE/rs', qidoSupportsIncludeField: true, supportsReject: true, imageRendering: 'wadors', thumbnailRendering: 'wadors', enableStudyLazyLoad: true, supportsFuzzyMatching: true, supportsWildcard: true, }, }, ], defaultDataSourceName: 'dicomweb', };这些配置项在源码类型定义中均有对应(DicomWebDataSource/index.ts):
| 配置项 | 类型/默认 | 说明 |
|---|---|---|
qidoRoot/wadoRoot | string | QIDO-RS 与 WADO-RS 的 Base URL |
stowRoot | string | STOW-RS 地址,缺省回退到wadoRoot |
wadoUri | string | WADO-URI 地址 |
qidoSupportsIncludeField | boolean | QIDO 是否支持includefield请求额外字段 |
imageRendering/thumbnailRendering | wadors等 | 图像/缩略图渲染方式 |
supportsReject | boolean | 服务端是否支持 reject 调用(如 DCM4CHEE) |
singlepart | boolean | string | 以单部分(single part)响应的 payload 类型,逗号分隔,可选pdf、video、bulkdata、thumbnail、image |
supportsFuzzyMatching | boolean | 是否支持模糊匹配 |
supportsWildcard | boolean | 是否支持通配符 |
supportsNativeDICOMModel | boolean | 是否支持原生 DICOM 模型 |
enableStudyLazyLoad | boolean | 是否启用研究懒加载 |
dicomUploadEnabled | boolean | 是否允许上传 DICOM 到该数据源(true时 Worklist 页面显示上传入口) |
omitQuotationForMultipartRequest | boolean | multipart 请求是否省略引号 |
staticWado | boolean | 是否启用 Static WADO 客户端 |
bulkDataURI 配置
bulkDataURI决定数据源如何利用 bulkdata 端点检索那些"最初未包含在服务端响应中"的元数据,适合体量大、应单独请求获取的元数据。当 bulkdata URI 是相对路径而非绝对路径时,用relativeResolution指定相对解析基准,可取studies或series。默认值(未配置时自动补全):
bulkDataURI: { enabled: true, relativeResolution: 'series', },其余可选属性(DicomWebDataSource/index.ts):
transform:接收字符串并返回更新后的字符串,用于替换路径片段;startsWith/prefixWith:先移除标准前缀、再添加可选前缀,主要用于反向代理或 URL 命名变更;relativeResolution:针对错误的 bulkdata 路径,将其解析为 studies 级。
各 payload 的单部分(singlepart)差异
对于 DICOM 视频与 PDF:实测发现Orthanc 以 multipart 交付,而 DCM4CHEE 以 single part 交付。因此需要查阅你所用数据源的 DICOM 一致性声明(conformance statement)来确定其 payload 交付方式,再决定singlepart是否包含pdf、video。
启用 DICOM 上传
除了dicomUploadEnabled: true,还需要在配置中加入上传组件定制(dicom-web.md):
customizationService: { dicomUploadComponent: '@ohif/extension-cornerstone.customizationModule.cornerstoneDicomUploadComponent', },运行 DCM4CHEE
dcm4che 是一套用 Java 实现 DICOM 标准的开源医疗保健企业应用集合;dcm4chee(多一个 e)是其中的 Image Manager / Image Archive 项目,提供存储、检索等能力。其完整安装步骤见官方 Wiki("Run minimum set of archive services on a single host"),不在本文教程范围内。官方文档以视频形式给出了使用本地 DCM4CHEE 运行 OHIF Viewer 的步骤概览。
DICOM JSON 数据源:用 JSON 文件直接启动查看器
你可以通过一个指向 JSON 文件的 URL 直接启动 OHIF Viewer,该 JSON 包含 DICOMweb 服务器地址以及研究/序列/实例 UID 列表与元数据。示例:
https://viewer.ohif.org/viewer/dicomjson?url=https://ohif-dicom-json-example.s3.amazonaws.com/LIDC-IDRI-0001.json
url查询参数指向 JSON 文件的位置(上面示例文件由 OHIF 团队生成并存放于 S3,仅用于演示)。
JSON 文件结构
JSON 启动文件按study 级 → series 级 → instance 级三层组织元数据。以下基于 LIDC-IDRI-0001 案例(dicom-json.md):
{ "studies": [ { "StudyInstanceUID": "1.3.6.1.4.1.14519.5.2.1.6279.6001.298806137288633453246975630178", "StudyDate": "20000101", "StudyTime": "", "PatientName": "", "PatientID": "LIDC-IDRI-0001", "AccessionNumber": "", "PatientAge": "", "PatientSex": "", "series": [ { "SeriesInstanceUID": "1.3.6.1.4.1.14519.5.2.1.6279.6001.179049373636438705059720603192", "SeriesNumber": 3000566, "Modality": "CT", "SliceThickness": 2.5, "instances": [ { "metadata": { "Columns": 512, "Rows": 512, "InstanceNumber": 1, "SOPClassUID": "1.2.840.10008.5.1.4.1.1.2", "PhotometricInterpretation": "MONOCHROME2", "BitsAllocated": 16, "BitsStored": 16, "PixelRepresentation": 1, "SamplesPerPixel": 1, "PixelSpacing": [0.703125, 0.703125], "HighBit": 15, "ImageOrientationPatient": [1, 0, 0, 0, 1, 0], "ImagePositionPatient": [-166, -171.699997, -10], "FrameOfReferenceUID": "1.3.6.1.4.1.14519.5.2.1.6279.6001.229925374658226729607867499499", "ImageType": ["ORIGINAL", "PRIMARY", "AXIAL"], "Modality": "CT", "SOPInstanceUID": "1.3.6.1.4.1.14519.5.2.1.6279.6001.262721256650280657946440242654", "SeriesInstanceUID": "1.3.6.1.4.1.14519.5.2.1.6279.6001.179049373636438705059720603192", "StudyInstanceUID": "1.3.6.1.4.1.14519.5.2.1.6279.6001.298806137288633453246975630178", "WindowCenter": -600, "WindowWidth": 1600, "SeriesDate": "20000101" }, "url": "dicomweb:https://ohif-dicom-json-example.s3.amazonaws.com/LIDC-IDRI-0001/01-01-2000-30178/3000566.000000-03192/1-001.dcm" } ], "NumInstances": 133, "Modalities": "CT" } ] } ] }关键点:instance 级同时存储metadata与url——前者是 naturalized DICOM JSON 元数据,后者是 DICOM 文件在服务器上的dicomweb:前缀地址。这个 JSON 正是 OHIF naturalized 格式的最佳写照:全部使用 Keyword 命名、Sequences 为数组。
用脚本生成 JSON 文件
仓库提供了从托管端点生成 JSON 文件的脚本(.scripts/dicom-json-generator.js):
node .scripts/dicom-json-generator.js '/path/to/study/folder' 'url/to/dicom/server/folder' 'json/output/file.json'某些模态需要额外元数据才能正常渲染。关于 OHIF Viewer 正常工作所需的最低元数据清单,见 FAQ 技术说明;生成脚本会自动补齐这些字段,例如为 SR(结构化报告)添加 CodeSequence,以便查看器正确显示测量结果。
本地 Demo
将 JSON 文件与 DICOM 文件目录放入public文件夹后,文件由本地服务器提供,于是 JSON 的 URL 为http://localhost:3000/LIDC-IDRI-0001.json,DICOM 文件为dicomweb:http://localhost:3000/LIDC-IDRI-0001/01-01-2000-30178/3000566.000000-03192/1-001.dcm。随后:
yarn install yarn dev在浏览器打开http://localhost:3000/viewer/dicomjson?url=http://localhost:3000/LIDC-IDRI-0001.json即可看到查看器。
两个实操注意点:
- URL 编码:
url参数本身若含查询参数,必须整体 URL 编码。例如http://localhost:3000/viewer/dicomjson?url=http://localhost:3000/LIDC-IDRI-0001.json?key0=val0&key1=val1应写成...?key0=val0%26key1=val1(&编码为%26); - 托管 404 兜底:部分托管商不会把 404 自动回退到
index.html(例如 Netlify 支持、Azure 不支持),这会导致带具体路径的 URL 访问时出现 404。本地同样如此——http-server不处理该问题,而serve包(npx serve ./dist -c ../public/serve.json)可以解决。
DICOMweb Proxy 数据源:动态构造 DICOMweb
你可以用一个返回 JSON 文件的 URL 启动 OHIF Viewer,该 JSON 内含 DICOMweb 配置。DICOMweb Proxy 会据此构造一个 DICOMweb 数据源,并把后续的元数据与图像请求全部代理给它。用法与 DICOM JSON 类似:
https://viewer.ohif.org/viewer/dicomwebproxy?url=https://ohif-dicom-json-example.s3.amazonaws.com/dicomweb.json
URL 返回的 JSON 需包含servers对象,其中dicomWeb是配置数组(dicom-web-proxy.md):
{ "servers": { "dicomWeb": [ { "name": "DCM4CHEE", "wadoUriRoot": "https://server.dcmjs.org/dcm4chee-arc/aets/DCM4CHEE/wado", "qidoRoot": "https://server.dcmjs.org/dcm4chee-arc/aets/DCM4CHEE/rs", "wadoRoot": "https://server.dcmjs.org/dcm4chee-arc/aets/DCM4CHEE/rs", "qidoSupportsIncludeField": true, "supportsReject": true, "imageRendering": "wadors", "thumbnailRendering": "wadors", "enableStudyLazyLoad": true, "supportsFuzzyMatching": true, "supportsWildcard": true } ] } }Proxy 只使用dicomWeb配置数组的第一项来构造数据源,因此配置结构需严格遵循上述形态。
Static DICOMweb:为极致性能生成静态文件
对于追求极致加载性能的部署,可以使用static-wado项目把 DICOM 文件预处理并压缩成静态 DICOMweb 文件,将服务时间压缩到"磁盘读取 + HTTP 流写出"的最低限度。它包含两个组件:
static-wado-creator:把原始 DICOM 文件转换为符合 DICOMweb 的目录结构;static-wado-webserver:专门服务上述静态文件的最小 Web 服务器。
安装与生成
git clone https://github.com/RadicalImaging/Static-DICOMWeb cd Static-DICOMWeb yarn install把 DICOM 文件整理到一个目录(如/Users/alireza/dicom/test-static-script/ACRIN-CT),然后转换:
node packages/static-wado-creator/bin/mkdicomweb.js '/Users/alireza/dicom/test-static-script/ACRIN-CT' -o '/Users/alireza/dicom/test-static-script/output'其中前一个路径替换为你的 DICOM 目录,-o后替换为期望的输出目录。
服务静态文件
node packages/static-wado-webserver/bin/dicomwebserver.mjs -p 3001 -o /Users/alireza/dicom/test-static-script/output-p 3001指定监听端口,-o指定生成的 DICOMweb 目录。
让 OHIF 使用静态数据
以开发模式启动,使用预置的local_static.js配置:
yarn dev:static该配置指向qidoRoot: 'http://localhost:3001/dicomweb'与wadoRoot: 'http://localhost:3001/dicomweb',与static-wado-webserver默认端口 3001 匹配。若更改了服务器的端口或输出目录,必须同步更新local_static.js中的qidoRoot/wadoRoot,否则 OHIF Viewer 无法访问数据。
数据源配置 UI:让数据源可"可视化配置"
OHIF 为数据源提供了一套通用配置机制,尤其适合拥有多个共享层级路径结构的数据源的组织。典型场景:一个组织在 Google Cloud Healthcare 下有多个 DICOM 存储,各自按 project → location → dataset → dicomStore 组织。通过在一个 OHIF 扩展中实现BaseDataSourceConfigurationAPI与BaseDataSourceConfigurationAPIItem两个接口(类型定义见platform/core/src/types/DataSourceConfigurationAPI.ts),数据源即可经由通用 UI 完成配置。
BaseDataSourceConfigurationAPIItem 接口
每个(路径)条目对应一个该接口的实例,至少暴露两个属性:
| 属性 | 说明 |
|---|---|
id | 唯一标识条目的字符串 |
name | 人类可读的名称 |
条目在路径层级中的位置信息不在接口内,但可在任何具体实现类中补充。例如 Google Cloud Healthcare 的实现GoogleCloudDataSourceConfigurationAPIItem(GoogleCloudDataSourceConfigurationAPI.ts)就额外增加了itemType(projects / locations / datasets / dicomStores)与url。
BaseDataSourceConfigurationAPI 接口
该接口的实现是整个配置过程的核心,提供若干方法,基于通过setCurrentItem设置的各类BaseDataSourceConfigurationAPIItem逐步构建数据源路径。构造函数应接受配置数据源所需的一切参数,其中必须包含数据源名称字符串;由于ExtensionManager本身拥有配置/更新数据源的 API,它通常也是构造函数参数之一。
| 方法 | 职责 |
|---|---|
getItemLabels | 返回各可配置项的 i18n 标签(查找键)。如 Google 实现返回['Project', 'Location', 'Data set', 'DICOM store']。系统还会基于每个标签派生四类翻译串:No {itemLabel} available(无可用项)、Select {itemLabel}(引导选择)、Error fetching {itemLabel} list(拉取出错,通常伴随错误信息)、Search {itemLabel} list(列表过滤占位符) |
initialize | 初始化云服务 API,并返回可用于开始配置数据源的顶层子项。如 Google 实现会先请求当前登录账号的顶层 projects 列表 |
setCurrentItem | 设置传入的当前路径项,并返回其可继续选择的子项。当设置到数据源路径的最后一个可配置项时,返回空列表并把活动数据源配置为所选路径。如 Google 实现中,设置 dataset 时查询并返回其下全部 DICOM store;设置 dicomStore 时则更新关联的 OHIF 数据源指向该存储 |
getConfiguredItems | 获取当前已配置的条目列表,其长度必须等于getItemLabels的结果长度,且按索引与标签一一对应 |
通过 Customization Module 创建
通用 UI(DataSourceConfigurationComponent)借助 OHIF UI 定制服务实例化BaseDataSourceConfigurationAPI。UI 可配置的数据源需要在 OHIF 配置文件的configuration中提供configurationAPI字段,其值即提供工厂方法的定制模块 id:
dataSources: [ { namespace: '@ohif/extension-default.dataSourcesModule.dicomweb', sourceName: 'google-dicomweb', configuration: { name: 'GCP', wadoUriRoot: 'https://healthcare.googleapis.com/v1/projects/ohif-cloud-healthcare/locations/us-east4/...', ... configurationAPI: 'ohif.dataSourceConfigurationAPI.google', ... }, }, ]'ohif.dataSourceConfigurationAPI.google'定制模块由 default 扩展的getCustomizationModule提供。注意其工厂方法名必须为factory,且只接收一个参数——数据源名称,构造函数则按需传入具体配置 API 类所需的一切:
export default function getCustomizationModule({ servicesManager, extensionManager, }) { return [ { name: 'default', value: [ { // 用于创建 Google Cloud Healthcare BaseDataSourceConfigurationAPI 实例的工厂 id: 'ohif.dataSourceConfigurationAPI.google', factory: (dataSourceName: string) => new GoogleCloudDataSourceConfigurationAPI( dataSourceName, servicesManager, extensionManager ), }, ], }, ]; }总结:如何选择你的数据源
综合本文内容,可以按以下思路选型:
- 标准 DICOMweb 后端(PACS、云影像平台)→ 使用
dicomweb,在 配置指南 中维护dataSources数组; - 只有静态 JSON 元数据 + 散落 DICOM 文件→ 使用
dicomjson,URL 直启查看器; - 动态获取 DICOMweb 配置→ 使用
dicomwebproxy; - 衍生数据分布在多台服务器→ 使用
merge在 series 级合并; - 追求加载性能→ 使用
static-wado预生成静态文件并配staticWado; - 私有后端 / 非 DICOM 数据→ 基于
IWebApiDataSource.create实现自定义数据源,实现initialize、query、retrieve、store等端点,并通过DicomMetadataStore汇入元数据;需要可视化配置时再实现BaseDataSourceConfigurationAPI接入通用配置 UI。
无论选择哪种方式,所有数据最终都会被映射为 naturalized DICOM JSON 并汇入DicomMetadataStore——这正是 OHIF 数据源机制"一处统一、处处复用"的设计精髓。
【免费下载链接】ViewersOHIF zero-footprint DICOM viewer and oncology specific Lesion Tracker, plus shared extension packages项目地址: https://gitcode.com/GitHub_Trending/vi/Viewers
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考