DICOM To FHIR ImagingStudy ⇒ Node.JS

Posted on Mon, Mar 7, 2022 FHIR DICOM

所需知識

使用工具

程式語言

DICOM 架構

這邊使用TCIA,編號0522c0001的部分檔案做範例,點我下載

首先快速了解DICOM檔案的架構。

1個病人有多個Study(報告),Study內有多個Series(部位),Series當中有多個Instance(影像實例)。

以JSON來看大概會長這樣

{
    "study": {
        "series" : [
            {
                "instance": [

                ]
            }
        ]
    }
}

如果太過抽象,可以透過DICOM Viewer開啟提供的範例檔。

這裡使用Weasis開啟其中一個資料中所有的檔案。

DICOM欄位資訊

我們可以透過Weasis上的按鈕,來查看DICOM的欄位資訊,打開後請記得切換到All DICOM attributes

圖中可以看到我們常用的病人名稱欄位,由以下幾項組成:

補充: DICOM PS3.6 2021e - Data Dictionary 5 ConventionsA Data Element Tag is represented as (gggg,eeee), where gggg equates to the Group Number and eeee equates to the Element Number within that Group.

如果想要快速查詢欄位標籤可以使用以下網站輔助:

如何知道DICOM檔是同個Study

使用程式讀取DICOM

此範例將示範如何取出DICOM檔案某個欄位標籤的數值。

npm init -y
npm i dicom-parser
const fs = require('fs');
const dicomParser = require('dicom-parser');

//讀取檔案
let fileBuffer = fs.readFileSync("./1.3.6.1.4.1.14519.5.2.1.5099.8010.199920086920823171706454903251/1.3.6.1.4.1.14519.5.2.1.5099.8010.260151978148957514594497217760/000001.dcm");
//將讀取後的Buffer轉成Uint8Array
let uint8FileBuffer = new Uint8Array(fileBuffer);
//使用DICOM Parser讀取DICOM檔
let dataSet = dicomParser.parseDicom(uint8FileBuffer);

//取出 Patient Name 0010,0010的數值
let patientName = dataSet.string("x00100010");
//印出取得的數值
console.log("Patient Name: " + patientName);

FHIR ImagingStudy

以上大致了解了如何讀取DICOM後,現在來了解FHIR ImagingStudy。

FHIR ImagingStudy官方文件以及下圖來看,ImagingStudy採用與DICOM一樣的架構來儲存資料(Study->Series->Instance)。

Mappings

官方文件也提供了DICOM轉換成FHIR ImagingStudy的Mappings,可以說是非常地友善。ImagingStudy Mappings使用此表格,我們就可以輕易地將DICOM轉成FHIR的格式。

DICOM轉成ImagingStudy

撰寫Data Types的Class

為方便使用及管理程式碼,首先要做的是幫 ImagingStudy 使用到的 Data Types 寫成 Class 以利組成 ImagingStudy。

⚠️

注意 Identifier 底下還包含了幾種需要建成 Class 的 Type: - CodeableConcept - Period - Reference

//Coding
class Coding {
    constructor() {
        this.system = undefined;
        this.version = undefined;
        this.code = undefined;
        this.display = undefined;
        this.userSelected = undefined;
    }
}
//CodeableConcept
class CodeableConcept {
    constructor() {
        this.Coding = undefined;
        this.text = undefined;
    }
}
//Period
class Period {
    constructor() {
        this.start = undefined;
        this.end = undefined;
    }
}
//Reference
class Reference {
    constructor() {
        this.reference = undefined; //(Literal reference, Relative, internal or absolute URL)(string)
        this.type = undefined; //string
        this.identifier = undefined;
        this.display = undefined;
    }
}
//Identifier
class Identifier {
    constructor() {
        this.use = undefined;
        this.type = new CodeableConcept();
        this.system = undefined;
        this.value = undefined;
        this.period = new Period();
    }
}

最後在一步一步把 ImagingStudy 的 Class 都寫完。

完整的FHIR Data Types Class:

Github 點我看程式碼

轉換主程式

上面已經把會用到的Data Types轉成 Class了,現在開始撰寫轉換的程式。思路如下

套件

npm install dicom-parser flat lodash moment

整體專案完整程式碼

到專案主頁面會有 C#Python 版本的範例,以下為 node.js 範例

Github 點我看程式碼

單檔案程式碼

👀

如果覺得上面的專案比較複雜,可以看看這支程式碼都寫在一個檔案的範例

Github 點我看程式碼

轉換結果

{
    "resourceType": "ImagingStudy",
    "id": "1.2.826.0.1.3680043.8.1055.1.20111102150758591.92402465.76095170",
    "identifier": [
        {
            "use": "official",
            "system": "urn:dicom:uid",
            "value": "urn:oid:1.2.826.0.1.3680043.8.1055.1.20111102150758591.92402465.76095170"
        }
    ],
    "status": "unknown",
    "subject": {
        "reference": "Patient/0",
        "type": "Patient",
        "identifier": {
            "use": "usual",
            "value": "0"
        }
    },
    "started": "2006-10-12T01:02:58.000Z",
    "description": "CT1 abdomen",
    "series": [
        {
            "uid": "1.2.826.0.1.3680043.8.1055.1.20111102150758591.96842950.07877442",
            "number": 6168,
            "modality": {
                "system": "http://dicom.nema.org/resources/ontology/DCM",
                "code": "CT"
            },
            "description": "ARTERIELLE",
            "instance": [
                {
                    "uid": "1.2.826.0.1.3680043.8.1055.1.20111102150758591.03296050.69180943",
                    "sopClass": {
                        "system": "urn:ietf:rfc:3986",
                        "code": "urn:oid:1.2.840.10008.5.1.4.1.1.2"
                    },
                    "number": 1,
                    "title": "ORIGINAL\\PRIMARY\\AXIAL\\HELIX"
                }
            ]
        }
    ]
}


Powered by Yiting & Majiang