Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
9
Help us understand the problem. What is going on with this article?
@tchkwkzk

PythonでEDFファイルを読み込む方法

More than 3 years have passed since last update.

ほとんど需要がないと思いますが、pyedflibの使い方の説明です。
最新情報は公式や公式のgithubをご覧ください。
http://pyedflib.readthedocs.io/en/latest/
https://github.com/holgern/pyedflib

EDFファイルとは?

EDF(European Data Format)は,医療データ(脳波など)の保存に使われるデータの保存形式です。
サンプルファイルはpyedflib公式のgithubレポジトリにあります。
https://github.com/holgern/pyedflib/tree/master/pyedflib/tests/data
もう少し実用的なデータのサンプルは,睡眠時脳波(PSG)なら以下のアドレスで配布されています。
https://www.physionet.org/pn4/sleep-edfx/
ダウンロードは自己責任で。

インストール

pipからインストールできます。
pip install pyedflib

使い方

pyedflibはEdfReaderとEdfWriterの2つに分かれています。
ここではEdfReaderについて説明します。(Writerは気が向けば・・・)

まずはファイルの読み込み

EDFの読み込み
path = "path_to_your_edf_file"

edf = pyedflib.EdfReader(path)

EDFファイルは,生体信号・サンプリング周波数・被験者情報・センサ情報など,様々なデータを格納しているため,データを取得するメソッドもたくさんあります。

メソッド一覧
EdfReader
- getNSamples(self)
  - データ点数を返します。
   [100 200 100 100]のように各チャンネル毎の値が出力されます。
- readAnnotations(self)
- getHeader(self)
 - 被験者情報や機器情報を返します。多分あまり使いません。
- getSignalHeader(self, chn)
 - 引数で指定したチャンネルの情報(センサ名・サンプリング周波数など)を返します。
- getSignalHeaders(self)
 - 上の関数を全チャンネル同時に。
- getTechnician(self)
- getRecordingAdditional(self)
- getPatientName(self)
- getPatientCode(self)
- getPatientAdditional(self)
- getEquipment(self)
- getAdmincode(self)
- getGender(self)
- getFileDuration(self)
 - 計測時間を返します。単位は秒です。
- getStartdatetime(self)
- getBirthdate(self, string=True)
- getSampleFrequencies(self)
- getSampleFrequency(self,chn)
- getSignalLabels(self)
 - センサ名が全てのチャンネル分返ってきます。
- getLabel(self,chn)
 - 指定したチャンネルのセンサ名が返ってきます。
- getPrefilter(self,chn)
 - 指定したチャンネルの前処理に使用したフィルタ情報を返します。
- getPhysicalMaximum(self,chn=None)
- getPhysicalMinimum(self,chn=None)
- getDigitalMaximum(self, chn=None)
- getDigitalMinimum(self, chn=None)
- getTransducer(self, chn)
 - 指定したチャンネルの計測機器の種類を返します。
- getPhysicalDimension(self, chn)
 - 指定したチャンネルの計測データの単位を返します。uV, mAなど。
- readSignal(self, chn, start=0, n=None)
 - 指定したチャンネルの計測データを返します。一番使います。
- file_info(self)
- file_info_long(self)

実行例

ここでは,PhysioNetからダウンロードした睡眠時PSGで実行例を示します。

import numpy as np
import pyedflib
import matplotlib.pyplot as plt

ファイルを読み込みます

edf = pyedflib.EdfReader("SC/SC4001E0-PSG.edf")

ラベルを出力してみます。

labels = edf.getSignalLabels()
print(labels)

['EEG Fpz-Cz', 'EEG Pz-Oz', 'EOG horizontal', 'Resp oro-nasal', 'EMG submental', 'Temp rectal', 'Event marker']

「EEG Fpz-Cz」「EEG Pz-Oz」など,7個のデータが入っていることが分かります。
続いて,計測時間・計測のサンプリング周波数・データ点数・計測日を表示します。

print("Duaration:"+str(edf.getFileDuration()))
print("Freq.:"+str(edf.getSampleFrequencies()))
print("N-Sample(=Freq x Duaration):"+str(edf.getNSamples()))
print("Date:"+str(edf.getStartdatetime()))

Duaration:79500
Freq.:[100 100 100 1 1 1 1]
N-Sample(=Freq x Duaration):[7950000 7950000 7950000 79500 79500 79500 79500]
Date:1989-04-24 16:13:00

信号を描画します。
ラベルのEEG-Fpz-Czなどは脳波計のセンサの装着位置の名前です。

plt.plot(edf.readSignal(0)[0:1000],label=labels[0])
plt.plot(edf.readSignal(1)[0:1000],label=labels[1])
plt.plot(edf.readSignal(2)[0:1000],label=labels[2])
plt.legend()
plt.show()

output_4_0.png

きちんと信号が取れていますね。
続いて,信号以外の情報について表示します。

print("Anotation:"+str(edf.read_annotation()))
print("Technician:"+str(edf.getTechnician()))
print("Header:"+str(edf.getHeader()))

Anotation:[]
Technician:
Header:{'technician': '', 'recording_additional': '', 'patientname': '', 'patient_additional': '', 'patientcode': '', 'equipment': '', 'admincode': '', 'gender': '', 'startdate': datetime.datetime(1989, 4, 24, 16, 13), 'birthdate': ''}

フリーで公開しているデータなので,情報は入っていませんね。
計測機器の情報はどうでしょうか?CH0のセンサについて表示します。

print("SIgnal-Header(CH-0):"+str(edf.getSignalHeader(0))+"¥n")

SIgnal-Header(CH-0):{'label': 'EEG Fpz-Cz', 'dimension': 'uV', 'sample_rate': 100, 'physical_max': 192.0, 'physical_min': -192.0, 'digital_max': 2047, 'digital_min': -2048, 'prefilter': 'HP:0.5Hz LP:100Hz [enhanced cassette BW]', 'transducer': 'Ag-AgCl electrodes'}

センサ「EEG Fpz-Cz」は単位はuVでサンプリング周波数が100で・・・と様々な情報が表示されています。
最後にファイルについての情報を表示すると,

print(edf.file_info())

file name: SC/SC4001E0-PSG.edf
signals in file: 7

終わりに

ドキュメントがほとんどない状態でgithubなどを見ながら気合いで書いたので,不正確な情報が含まれているかもしれません。
その場合はご連絡ください。

9
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
tchkwkzk
修士の学生です。 専門はでぃーぷらーにんぐ。 Android関連の記事は計数技研様でのお仕事です。 記事に関してご意見などがあればqiitaのID+@gmail.comまで。

Comments

No comments
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account Login
9
Help us understand the problem. What is going on with this article?