【Python】DICOMヘッダーをCSVに保存

1. 目的

PythonのPydicomライブラリを用いて、DICOMヘッダーをCSVにまとめて保存

2. 準備

2.1. ライブラリの準備

Pydicomは、DICOMのヘッダーや画像を操作するのに用いるライブラリである。

Pydicomのインストールは、以下のコマンドを実行。

pip3 install pydicom

CSV形式の表データを扱うには、Pandasライブラリを用いる。

Pandasライブラリのインストールは、以下のコマンドを実行。

pip3 install pandas

2.2. データの準備

次のような、フォルダ構造でデータを準備する。この場合では、各被験者フォルダの中にDICOMが保存されている。

DICOM_folder
├── Subject001
│   ├── XXX.dcm
│   ├── ...
│   └── XXX.dcm
├── Subject002
│   ├── XXX.dcm
│   ├── ...
│   └── XXX.dcm
├── ...
└── SubjectXXX

2.3. スクリプトの準備

次のコードを、extract_dcm_header.pyとして保存する。このとき、スクリプトはDICOM_folderフォルダと同じ階層に保存する。

import os
import pydicom
import pandas as pd

input='DICOM_folder'  # Input folder
output='dicom_headers.csv'  # Output CSV

dcm_dfs = []
failed_files = []
processed_files = []
for root, _, files in os.walk(input):  # Find DICOM file for each subject
    if len(files) != 0:  # If DICOM files exist
        try:
            f = os.path.join(root, files[0])
            dcm = pydicom.dcmread(f)  # Read DICOM
            _df = pd.DataFrame({dcm[k].keyword: [dcm[k].value] for k in dcm.keys() if dcm[k].keyword != "PixelData"})  # Read Headers
            dcm_dfs.append(_df)  # Gather headers of all subjects in a list
            processed_files.append(f)
        except:
            failed_files.append(f)

dcm_dfs = pd.concat(dcm_dfs, ignore_index=True)  # Concat headers of all subjects in a table
dcm_dfs.to_csv(output, index=False)  # Save as CSV

3. プログラムの実行

2.3. スクリプトの準備で用意した、extract_dcm_header.pyを実行するには、次のコマンドを実行する。

python3 ./extract_dcm_header.py

4. 結果の確認

収集したDICOMヘッダーは、dicom_headers.csvとして保存される。

5. コードの解説

まず、必要なライブラリを読み込む。

import os
import pydicom
import pandas as pd

ここでは、入力となるDICOMフォルダーと出力となるDICOMヘッダーのまとまったCSVの名前を定義している。

今回の場合だとinput='DICOM_folder'output='dicom_headers.csv'

input='DICOM_folder'  # Input folder
output='dicom_headers.csv'  # Output CSV

データを格納するための、箱(リスト)を定義。

dcm_dfs = []
failed_files = []
processed_files = []

被験者ごとのDICOMファイルを検索。

for root, _, files in os.walk(input):  # Find DICOM file for each subject

DICOMファイルがある場合のみ、処理を実行。

    if len(files) != 0:  # If DICOM files exist

Pydicomを用いて、DICOMデータを読み込む。

        try:
            f = os.path.join(root, files[0])
            dcm = pydicom.dcmread(f)  # Read DICOM

DICOMからヘッダー(Header)情報を、Pandasで読み込む。

PixelDataタグを含めると、出力(CSV)が崩れておかしくなるので、収集に含めないようにしている。

            _df = pd.DataFrame({dcm[k].keyword: [dcm[k].value] for k in dcm.keys() if dcm[k].keyword != "PixelData"})  # Read Headers

収集した結果を、被験者ごとに処理をして、一つの箱(リスト)にまとめる。

            dcm_dfs.append(_df)  # Gather headers of all subjects in a list
            processed_files.append(f)
        except:
            failed_files.append(f)

すべての被験者のヘッダー情報を、一つの表形式のデータ(DataFrame型)に変換する。


dcm_dfs = pd.concat(dcm_dfs, ignore_index=True)  # Concat headers of all subjects in a table

結果を、CSVとして保存する。

dcm_dfs.to_csv(output, index=False)  # Save as CSV

2024年10月現在、FreeSurferはUbuntu 24.04 では動作しません

ときどきこの質問を受けるので言及しておきます。

2024年4月にUbuntu 24.04が公開されました。
しかし、Ubuntu 24.04上では現行のFreeSurfer 7.4.1は動きません。
このため、FreeSurferを実行したい場合は、しばらくUbuntu 22.04からアップグレードしないようにしましょう。

過去のPhilipsのfMRIデータをdcm2niixで変換しようとした時に4次元データにならない問題の解決法

ある施設のrs-fMRIのDICOMデータをNiftiに変換しようとした時に、以下のようになってしまい、4次元データができませんでした。

sub1_+rsfMRI_201.nii
sub1_+rsfMRI_201_t10000.nii
sub1_+rsfMRI_201_t100000.nii
sub1_+rsfMRI_201_t102500.nii
sub1_+rsfMRI_201_t105000.nii
sub1_+rsfMRI_201_t107500.nii
sub1_+rsfMRI_201_t110000.nii
sub1_+rsfMRI_201_t112500.nii
sub1_+rsfMRI_201_t115000.nii
sub1_+rsfMRI_201_t117500.nii
sub1_+rsfMRI_201_t120000.nii
sub1_+rsfMRI_201_t122500.nii
sub1_+rsfMRI_201_t12500.nii
...

ポイントは、ファイル名の後ろに tの後に数字がつくことです。

この原因を探っていたところ、dcm2niixのGitHubページを見つけました。
https://github.com/rordenlab/dcm2niix/issues/428

ここで開発者のChris Rorden教授が以下のように述べています。

your files have a bogus value for cardiac trigger time (0018,1060). This is a limitation of your images, not dcm2niix. You should work with your Philips Research Collaboration manager to fix your scanner. For archival-quality data you could purge the invalid tags from your images, e.g. gdcmanon –dumb –remove 0018,1060 -i … -o …

Cardiac Trigger Timeというタグに値が入ってしまっていることで、dcm2niixはこれを別々のものと認識してひとつにしないようです。過去に撮像したデータの場合、0018,1060を削除するのは一手ではないかとおっしゃっています。実際に確認したところ、そのタグが入っていました。

そこで、このタグを削除する以下のようなPythonスクリプトを書いてみました。pydicomが入っていれば動くはずです。
こちらから手に入れられます。

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

# Script to remove trigger time from Philips fMRI
# source: https://github.com/rordenlab/dcm2niix/issues/428
# 14 Oct 2023 K. Nemoto

import sys, os, time, argparse
import pydicom

__version__ = '20231004'

__desc__ = '''
Remove Trigger Time (0018,1060) from Philips rsfMRI
'''
__epilog__ = '''
examples:
  dcm_rm_trigger_time.py DICOM_DIR1 DICOM_DIR2 ...
'''

def remove_triggertime(src_dir):
    # modify files
    for root, dirs, files in os.walk(src_dir):
        for file in files:
            try:
                src_file = os.path.join(root, file)
                ds = pydicom.dcmread(src_file)
                pid = src_dir.replace('/','')
                del ds[0x0018, 0x1060]
                ds.save_as(src_file)
            except:
                pass

if __name__ == '__main__':
    start_time = time.time()
    parser = argparse.ArgumentParser(description=__desc__, epilog=__epilog__,
        formatter_class=argparse.RawDescriptionHelpFormatter)
    parser.add_argument('dirs', metavar='DICOM_DIR', help='DICOM directories.', nargs='+')

    err = 0
    try:
        args = parser.parse_args()
        for dicom_dir in args.dirs:  # Loop through all the provided directories
            print(f'remove dicom tag (0018,1060) from {dicom_dir}')
            remove_triggertime(dicom_dir)
        print("execution time: %.2f second." % (time.time() - start_time))
    except Exception as e:
        print("%s: error: %s" % (__file__, str(e)))
        err = 1

    sys.exit(err)

これは、

dcm_rm_triggertime.py DICOMフォルダ

とすることで、そのフォルダ内のtrigger timeタグを削除します。

この処理をした後のDICOMを使って dcm2niix を行ったところ、問題なく変換されました。

困っている人がいると思うので共有しておきます。

Windows 10/11 で、WSL2 を使って FSL をインストールする方法

Windows 10/11 では、Windows Subsystem for Linux (WSL) を使ってUbuntuなどのLinuxをインストールできます。WSL2 を使うと、GPUも使えるとのことです。

しかし、WSL2は基本、コマンドラインです。LinuxのGUIを起動するためには、工夫が必要です。現在、いくつかのアプリが公開されていますが、FSLの公式ページでは、VcXsrv を勧めていますのでそれを使うのが無難でしょう。

Ubuntu 22.04 も発表されて1年が過ぎて安定してきましたので、ここでは、

  • WSL2
  • Ubuntu 22.04
  • VcXsrv

をいれたうえで、FSL をインストールしてみます。

なお、このページは、FSLの公式サイトを参考に作成しました。

続きを読む

FreeSurferとFSL 6.0.6以降を同時にインストールしている時に起きる事象への対処法

FreeSurfer と FSL 6.0.6以降を使っていると、ある事象が起きます。

  • Python3がFSLが提供するPython3になります。
  • dcm2niixがFSLが提供するdcm2niixになります。

これの影響を受けているかの確認法および対処法を最初に解説した後、その理由を述べます。

続きを読む

CONNで前処理したfMRI画像の時系列データを取り出す方法

ある方から、「CONNで前処理したfMRI画像から、デフォルト・モード・ネットワーク(DMN)の時系列データを取り出すにはどうしたらよいですか?」というご質問をいただきました。

鍵となるプログラムは以下の2つです。

  • conn_matc2nii
  • spm_summarise

以下に、方法を記載します。

続きを読む

Ubuntu 20.04/22.04 上の FSL6.0.6 以降で CUDA 11以降のGPUを使う方法

FSL 6.0.6 以降で、CUDA 11以降も対応するようになりました。

いろいろ試行錯誤した結果、以下のようなシンプルな方法でFSLでCUDAを上手に使うことができるようになったので紹介します。

なお、Amulet社から販売している Powerstep Tower for Lin4Neuro は、既にこれらの設定が済んでいますので、電源入れたらすぐにEDDY, BEDPOSTX, XTRACTなどがGPUを使って解析できます。
なお、FSL 6.0.6 以降は既にインストールされているとします。

続きを読む

FSLの設定ファイルを読み解く

FSLはデフォルトでは、Linuxの場合は、.profile の下、macOS の場合はお使いのシェルに応じて、.bash_profile もしくは .zprofile の下に 以下のような設定が書き込まれます。(6.0.6以降の設定です)

# FSL Setup
FSLDIR=/usr/local/fsl
PATH=${FSLDIR}/share/fsl/bin:${PATH}
export FSLDIR PATH
. ${FSLDIR}/etc/fslconf/fsl.sh

この内容を理解できると、ソフトの設定がわかるようになるので、1行ずつ解説してみます。

続きを読む

FreeSurfer で Local Gyrification Index を求めるための準備

FreeSurfer では Local Gyrification Index (LGI) を求めることができます。LGIを一言で言えば、脳の皮質の折りたたみの状態を指標化とでも言えるでしょうか。
詳細は、本家のウェブサイトにありますが、ポイントを示します。

  • 必要なソフトウェアとしては、Matlab と Matlab Imaging Toolbox が必要となります。
  • Matlab のパスに $FREESURFER_HOME/matlab を追加しておくことが必要です。
  • 画像の準備としては、recon-all が終わっていることが必要です。

この3つを準備しておけば、あとは、以下のコマンドをタイプするだけです。

recon-all -s <fsid> -localGI

Ubuntu 20.04, 22.04 に HCP Pipeline の環境を設定する方法

しばらく前に、Ubuntu 18.04用にHCP Pipelineの環境を設定する方法を記載しましたが、いくつかアップデートもあるので、Ubuntu 20.04用以降でも設定できるようにします。

*2023/10/08追記: Neurodebianの設定についてうまく動かないミスがありましたので修正しました。神谷先生、ご指摘ありがとうございました。

*2024/03/29追記: Ubuntu 22.04でFreeSurferのスクリプトがダウンロードできない不具合を解消しました。金子先生、ご指摘ありがとうございました。

続きを読む

macOSへのFreeSurfer7.3.2のインストールスクリプト

FreeSurfer 7.3.2が公開されました。色々新しい機能が実装されています。

macOSへのインストールはデモ動画が示されていますが、コマンドラインで一気にインストールしたいと思いました。

インストールスクリプトを作成しましたので、公開します。

スクリプトの内容はこちらから確認できます。実際の方法は下に記載してありますので、そちらに従ってください。

続きを読む

dcm2niix -r y でDICOMソートができる!

DICOMファイルがひとつのディレクトリに入っていて、パルスシーケンスごとにわけたくなることがありませんか?
これまで、私はpydicomを使ったり、DCMTKのツールを使ったスクリプトを使用していました。
しかし、先日、dcm2niixにDICOMソート機能があることを知りました。

ヘルプには

-r : rename instead of convert DICOMs (y/n, default n)

としか書いていないのですが、dcm2niix のGitHubのissue 604に以下の記載がありました。
https://github.com/rordenlab/dcm2niix/issues/604#issuecomment-1120269405

dcm2niix -r y /path/to/DICOMS – this will simply rename rather than convert the data. It sorts each session into a separate folder, which makes subsequent conversion much easier.

実際試してみます。DICOM というディレクトリにDICOM画像が入っていて、sorted というディレクトリに保存したいとします。

mkdir sorted
dcm2niix -r y -o sorted DICOM

これで見事、sortedディレクトリの下に撮像年月日のディレクトリが作成され、その下にシーケンスごとにサブディレクトリにソートされたDICOM画像ができていました!

既に匿名化されているDICOMなどは、これを使うだけでソートが問題なくできますね。

知られていない裏技だと思うので紹介しておきます。

bedpostx_gpu のエラー: –cnonlinear/bin/merge_parts_gpu: そのようなファイルやディレクトリはありません の対処法

bedpostx_gpu を走らせると、以下のエラーがでます。

/usr/local/fsl/bin/bedpostx_postproc_gpu.sh: 行 20: --cnonlinear/bin/merge_parts_gpu: そのようなファイルやディレクトリはありません

この解決法がFSLのMLで紹介されています。

https://www.jiscmail.ac.uk/cgi-bin/wa-jisc.exe?A2=FSL;ee0b1626.2112

具体的には、

${FSLDIR}/bin の中にある bedpostx_postproc_gpu.sh の

# last 2 parameters are subjdir and bindir
parameters=""
while [ ! -z "$2" ]
do

# last 2 parameters are subjdir and bindir
parameters=""
while [ ! -z "${2+x}" ]
do

に変更します。

while の後の test文 の中が、 $2 が ${2+x} になっています。

これで無事に動きます。

ご紹介まで。(金子貴久子先生、情報提供ありがとうございました)

How to setup CUDA 10.2, 11.0, and 11.5 in order to use eddy_cuda10.2 (in FSL 6.0.5.x), PyTorch, and Tensorflow 2

ATTENTION (16 Apr 2023): From 6.0.6, you can use the latest CUDA to run eddy_cuda10.2. So this post is obsolete. I wrote a new post, so please check it out.

FSL 6.0.5 ships eddy_cuda10.2 which literally uses CUDA 10.2.
I explored a way to use eddy_cuda10.2, PyTorch and Tensorflow concurrently. Below is How-To for Ubuntu 18.04/20.04.

続きを読む