class member function pointer

7월 14, 2016 C & C++ No comments

간혹 event 목적으로 function pointer를 사용하기도 합니다.

그런데 class member 를 function pointer로 사용하고 싶어도

static fuction 형태만 call이 가능하고 class member는 function pointer로 사용할 수 없죠.

찾다보니 c++ STL 에서 지원하네요.

1.STL 함수 포인터 선언

typedef std::function<void(int, int)> event_callback2;

2.class member function을 bind하여 전달

//placeholders는 parameter 수만큼 추가
event_callback2 eventCallback = std::bind(&MyClass::ReDraw, this, std::placeholders::_1, std::placeholders::_2);

//function pointer를 이용한 call 이 가능
eventCallback(1, 2);

numpy simple tip

7월 14, 2016 python No comments

hex 출력

import numpy as np
np.set_printoptions(formatter={'int':hex})
np.array([1,2,3,4,5])

import numpy as np
A = np.array([[1,2],[3,4]])

vhex = np.vectorize(hex)

vhex(A)
array([['0x1', '0x2'], ['0x3', '0x4']], dtype='<U8')

2차원 인경우 tuple로 전달(2차원 array삽입 및 ‘ ‘.join 출력)

data = np.ndarray((5,10), dtype=float) 
' '.join(['%f' % d for d in data[0]])

1로 채워진 ndarray 생성

v = np.ones(32,  dtype='uint32')

hjson module

7월 13, 2016 python No comments

hjson module ( https://hjson.org )

the Human JSON이라는 이름으로 json 파일을 setting 형태로 저장해서 사용 할 때

마지막 항목에 ,를 붙인다던가의 사소한 syntax error는 무시해 주는 확장형 json 입니다.

module간의 interface에서는 굳이 쓸 필요 없을 듯 하고,

주석도 지원해 주기는 하는데 추후 호환성을 위해서는 별로.. 안하는게 좋을듯 합니다.

1.pip로 hjson 설치

C:>pip instsall hjson

2.json과 동일하게 load

d = hjson.load(open('material.json', encoding='utf-8-sig'))

3.json 파일로 write

hson.dumpJSON(d, open('result,json', mode='x'), indent=2)

ipython plot test

7월 13, 2016 python No comments

1.ipython3를 –pylab parameter로 실행 c:>ipython3 –pylab

ipython_초기실행

2.numpy arange array 0~359 생성 d = np.arange(360)

3.sin 값으로 변환

d = np.sin(deg2rad(d))

4.matplotlib의 plot으로 sine graph출력 plot(d)

figure_1

ipython config

7월 13, 2016 python No comments

python config 파일 위치 확인

c:>ipython locate

python profile 생성 하기

c:/>ipython profile create  

ipython_config.py 파일에서 수정

c.TerminalInteractiveShell.editor = 'c:/program files/sublimetext3/sublimetext.exe'

ipython command에서 py파일 직접 수정 후 실행

IN]%edit test.py 

pandas excel file parsing

7월 13, 2016 python No comments

기존 time_zone data json형태로 변환

import json
records = [json.loads(line) for line in open('usagov.txt')]

records에서 timezone(‘tz’) 만 구하기

time_zones = [rec['tz'] for rec in records]

collections를 이용하여 각 timezone의 count 세기

from collections import defaultdict
def get_counts(sequence):
    counts = defaultdict(int)
    for x in sequence:
        counts[x] += 1
    return counts

Pandas로 DataFrame으로 Importing 하고 value_counts()를 통해 Series로 만든후 plot 출력

from pandas import DataFrame, Series
import numpy as npimport pandas as pd

frame = DataFrame(records)
tz_counts = frame['tz'].value_counts()
tz_counts.plot(kind='barh')

Load Excel File

  • excel 파일 load후 parse를 통해 해당 sheet DataFrame으로 변환
xls_file = pd.ExcelFile(exlFName)
xl = xls_file.parse(xls_file.sheet_names[sheetIdx])

loc를 이용하여 query 수행 및 특정 Series에 삽입

for i in range(len(xl)):    
    mt.loc[mt.id == xl.icol(idx)[i], ['price']] = xl.icol(amountIdx)[i]

원하는 colume순으로 재정렬

  • DataFrame 새로 생성시 columns에 원하는 array전달
cols = ['id', 'name', 'spec', 'remark', 'info'] 
mt = pd.DataFrame(mt, columns=cols)

records형태의 json으로 출력 후 json으로 parsing

j = json.loads(mt.to_json(orient='records'))

json load & save

7월 13, 2016 python No comments

import json

1.우선 json 파일 read

fs = open('L3-12.json')
data = fs.read()

2.read한 str을 json.loads() 수행

json.loads(data)

file pointer를 이용한 직접 전달은

json.load(fs)

또는

[json.loads(line) for line in open('L3-12.json')]

그런데 encoding 문제로 utf-8-sig로 변경

fs = open('L3-12.json', encoding='utf-8-sig')

하지만 이역시도 간혹 json 문법에 맞지 않으면 error발생됨

ex)

{
    "test" : 1,
}

마지막 element인데도 불구하고 , 가 있기에 error발생

  1. json file로 write하기

– mode=’x’ : create file의 file handle전달
– indent=2 : indent된 json output출력
– sort_keys=True : key 값으로 sort 후 출력

json.dump(j, open('result.json', mode='x'), indent=2, sort_keys=True)

10. US DICOM Image

7월 13, 2016 DICOM No comments

이번에 설명드릴 DICOM은 US 영상 즉 Ultrasound인 초음파 영상 입니다.

나름 초음파장비는 의료 영상 장비내에서 DICOM으로 File을 저장 해주며 PACS로 전송도 해줍니다.

즉 DICOM이 지원되는 장비죠. 하지만 모든 초음파 장비가 지원되는것은 아니지만 최근에는 기본적으로 포함됩니다.

간혹 영업에 의해서 DICOM Module이라는 이름으로 Lock을 걸고 비용을 지불해야 이 Lock을 풀어줌으로써 사용할 수 있는경우도

있습니다. 그래서 DICOM Module 비용이 고가 인경우에는 내시경영상에서 설명드렸던 Gateway를 초음파에서도 사용하곤 합니다.

US DICOM은 ES보다는 조금 복잡합니다. 특히 아래 이미지에서 보이듯이 Doppler Mode니 M mode와 같이 각 Mode별로 이미지의

영역이 구분되어 지기에 추가적인 정보를 포함하고 있습니다.

us

이렇게 영역 정보를 가지는 이유는 Measurement 때문 입니다. 즉 정확한 데이터 측정을 위해서 필요한거죠. 예를 들어 상단이미지에서

B Mode영상에 혈류의 흐름을 보여주고 있습니다. 이때 하단에 있는 그래프에서 속도의 차이를 계산하고 싶다고 하면 아래 그래프가

분리된 영역으로 존재해야 정확한 측정이 가능하게 됩니다.

관련 내용이 DICOM Standard Part3. C.8.5.5.1.3 Region Flags Intersecting Spatial Format Regions and Overlapping Measurement

에 자세히 설명되어 있습니다.

dicom_us

각 Region A, B, C와 같이 각 Region을 구분해 주며 해당 Region의 Pixel의 단위가 mm인지 degree 인지 와관련된 Unit정보가 포함되며

각 영역이 B, C, M Mode인지 ECG인지 같이 종류도 명시합니다.

us_dicom_doppler

위 영상은 이러한 정보를 이용하여 분석할 수 있는 예제를 DICOM Standard에서 발췌하였습니다.

DICOM Standard Part3. C.8.5 Ultrasound Modules에서 부터 US Region이라는 항목으로 워낙 자세히 나와있으니 Standard를 참고

하시는 쪽이 더 좋을듯 하네요.

초음파 영상도 Multiframe DICOM을 지원합니다. 즉 여러 영상이 하나의 DICOM파일에 저장된다는 얘기지요.

하지만 US Multiframe DICOM은 각 Region정보가 포함되어 있기에 전체 영상을 다 가지고 있을 필요가 없게 됩니다.

그리하여 첫번째 영상은 Base가 되는 B Mode 전체 영상을 나머지 나오는 영상은 변하는 부분의 Region영상만을 가지고 있는 경우도

있습니다.

그럼 Display하는 입장에서는 해당 첫번째 영상에 해당 Region만을 Overwrite하여 반복적으로 Display하면 Cine Play를 할 수

있는겁니다.

이렇게 하는 이유는 단지 용량을 줄여보고자 한것 같습니다. 이런식으로 유사하게 한게 DICOM Overlay입니다.

기회가 되면 추후에 자세히 설명하겠지만 CT나 MR에 12bit영상인경우 실제 저장은 어쩔수 없이 16bit 2byte를 저장하게됩니다.

이때 4bit는 남게 되죠. 여기에 overlay라는 data를 4bit에 저장하여 추후 활용 할 수 있게 됩니다.

Bit로 풀어써보면 아래와 같은 형식으로 저장됩니다.

bit 15..12 :Overlay Data
bit 11..0 : Pixel Data

ex) 아래와 같이 특정위치에 Pixel Data 2byte 값이 하단과 같다면
bit16..0 1111 1111 1111 1000  ( 보기 편하게 bit순서를 반대로 적었습니다.)    
이는 12bit 모두 1이기에 4095는 Pixel Data값을 의미하고
마지막 4bit는 1이기에 overlay Data는 1이라는 값을 가집니다.

개념적으로 아래와 같은 그림으로 이해하시면 됩니다.

dicom_overlay

원래 MR이미지에 선이 표시된 Overlay 이미지가 있고 이것을 화면에 Display할때는 결과 화면과 같이 표시하게 됩니다.

그럼 뭐하러 굳이 이렇게 Overlay를 구분할까요? 다양한 장점이 있습니다. 우선 Overlay는 판독에 불필요 할 수도 있기에

Show & Hide가 가능하겠네요. 그리고 별도의 이미지다 보니, WWL(Window Width Level)과 같이 설정 변경시 실제 MR이미지는

WWL에 맞추어 변경이 되지만 Overlay는 변경되어서는 안되겠지요.

09. ES DICOM Image

7월 13, 2016 DICOM No comments

ES는 Endoscopy 즉 내시경을 의미합니다.

즉 내시경영상을 저장하는 DICOM에 대해서 설명하려고 합니다.

우선 내시경장비는 현재 까지 DICOM이 지원되는 장비가 없습니다.

DICOM이 지원된다는 의미는 초음파, CT, MR장비와 같이 의료기기에서 DICOM 형식으로 File을 저장하며 전송 할 수 있는

장비를 의미합니다.

하지만 내시경 장비는 꽤 오래전부터 광학장비로 사용되어 왔지만 이런 의료IT와 관련하여서는 받아들이는 속도가 느린듯 합니다.

그래서 일반적으로 전용 칼라프린터를 연결하여 프린트 출력하여 차트에 붙이곤 하죠. 하지만 아시다시피 내시경 칼라 프린터 전용

용지는 꽤 비싸기에 사용에 부담이 되곤 합니다. 그래서 초기에 는 내시경장비에서 나오는 신호 보통 일반 장비에서는 NTSC

신호가 나오죠. 이 NTSC신호라는것은 예전 칼라TV신호라고 생각하시면 됩니다. 예전 VTR과 칼라 TV를 연결할 때 흰색 빨간색

composite을 통해 연결하 게 되는데 이때 신호가 NTSC신호가 TV로 입력되어 비디오를 볼 수 있는거죠.

그래서 초기에는 간혹 NTSC신호를 TV캡쳐카드를 이용하여 이미지 파일로 저장하고 관리하는 프로그램도 있었습니다.

하지만 요즘은 PACS와의 연동이 중요시 되기에 Gateway를 사용하여 내시경영상을 DICOM으로 저장하고 PACS로 전송 합니다.

Gateway라는 것은 이처럼 의료기기와 PACS 중간에서 의료기기에서 나오는 영상을 DICOM으로 변환하고

PACS로 전송까지 하는 역할을 담당하게 됩니다.

보통 이때 추후에 자세히 설명하겠지만 DICOM 통신 관련하여 PACS로 DICOM 파일을 전송하는 DICOM Send기능을 수행하고,

그 이전에 환자 및 검사관련 정보를 받아볼 수 있는 DICOM Q/R을 지원하게 됩니다.

DICOM Q/R이란 DICOM Query & Retrieve로 DICOM통신 표준중에 “오늘 내과 내시경 검사실의 2번 내시경장비에서 검사할 환자정보를

알려줘~!” 라고 요청(Query)하면 그에대한 대답으로 PACS측에서 “오늘 10시 30분 위내시경검사 환자 홍길동, 11시 00부 대장내시경

검사 환자 김철수가 있다~!”라는 응답(Retrieve)을 받게 됩니다.

그럼 사용자 입장에서는 검사전 DICOM QR을 통해 검사할 환자 목록을 확인후 선택만 하면 환자 및 검사와 관련된 정보가 사용자의

수작업 없이 바로 입력되게 됩니다.

이는 환자정보를 수작업으로 입력하는데 발생되는 오류, 환자ID를 잘못입력하여 엉뚱한 환자에 잘못된 영상이 저장되는 오류를 방지하는

효과가 있습니다.

그럼 ES영상의 DICOM 구조를 살펴보죠. 아주 단순합니다.

es

우선 SOP Class UID는 Secondary Capture Image Storage를 1.2.840.10008.5.1.4.1.1.7를 많이 사용합니다.

uid

DICOM Standard 6. Annex A Registry of DICOM unique identifiers (UID)

다음은 환자 정보가 있겠죠. Patient ID, Name, Sex, Birth-Date…

그리고 Study 정보가 오겠네요. Study Date, Modality…

다음으로 Pixel Data를 해석하는데 필요한 Rows, Columns, Bit관련 Tag들이 오겠네요.

일반적으로 내시경영상은 24bit BITMAP형식으로 저장하여 Pixel Data에 넣게 됩니다.

그렇기에 Photometric Interpretation(0028,0004)는 RGB가 오고, Bit Stored(0028,0101)는 R,G,B가 8bit씩 저장되기에

8을 High Bit(0028,0102)는 7을 가지게 됩니다.

참고로 위의 내시경영상에서 보이듯 실제 의미 있는 영상은 전체 영상에서 약 60%만 의미 있으며 나머지 검은색 부분은

실질적으로 불필요한 부분입니다. 그래서 Gateway에서 영상 획득시 원하는 부분만 Crop하여 저장하기도 합니다.

워낙 기존에 설명드렸던 DICOM과 별반 다른 것이 없기에 설명이 너무 짧긴 한데요.

정말 별다른게 없기에 마땅히 더 설명드릴게 없네요;;

굳이 기존 설명중에 말씀안드리것중에 Manufacture(0008,0070)에 Gateway를 제작한 회사이름이 보통 들어가게 되고,

Institution Name(0008,0080)에는 병원이름이 들어값니다.

Operator Name(0008,1070)에 처방내린의사분들이 실제 검사도 같이 진행 하기에 보통 담당 의사명을 집어넣게 되죠.

08. Multiframe DICOM

7월 13, 2016 DICOM No comments

DICOM파일에는 일반적으로 한장의 Image가 포함되지만 2장이상의 이미지도 포함 할 수 있습니다.

하나의 DICOM파일에 여러장의 이미지가 저장되게 되며 보통 이런 영상을 한장씩 한장씩 보여주면서

마치 동영상과 같은 역활을 하기도 합니다.

이때 하나의 영상을 Frame이라고 부르며, 이런 Frame들이 모여 Multiframe DICOM영상을 구성합니다.

아래 그림과 같이 기존 DICOM하고 크게 다른것이 없으며 단지 Pixel Format(7FE0,0010) Tag에 여러장의 Frame이 순서대로

저장되어 있는 구조 입니다.

multiframeDICOM

Multiframe DICOM영상은 특히 US에서 Doppler영상이나, 뇌혈관 조영술에서 Xray영상, 기타 CT,MR영상등 요즘 들어 활용빈도가

높아지고 있습니다. 그런데 Multiframe DICOM영상이라는게 결국 각각의 영상 한장, 한장을 따로 저장하고 있기에 동영상과 비교해

보면 용량의 크기가 너무 커지는 단점이 있습니다. 그래서 기존 Pixel Format(7FE0,0010) Tag에 Image대신 MPEG2 와 같은 동영상

데이터를 저장하기도 합니다.

DICOM Standard Part.6 Data Dictionary에서 Transfer Syntax에 MPEG2 압축 관련이 존재하는것을 확인 할 수 있습니다.

(또한, DICOM Standard Part.5 Data Structures and Encoding에 각 MPEG 압축관련 자세한 설명이 나와 있습니다.)

transfer_syntax_mpeg

Multiframe DICOM영상은 마치 동영상 처럼 Play하면서 보기 때문에 cine영상이라고 부르기도 합니다.

Multiframe관련 Tag로는 주로 아래 Tag가 필요합니다.

multiframe_module

나머지 Tag는 그닥 중요한게 없으며 기존 1장으로 구성된 DICOM 영상을 읽는 방식과 동일하게 Pixel Format에 저장된 데이터를

읽어 들이면 되고, 단지 Number of Frames(0028,0008) 만큼 영상을 불러오기만 하면 됩니다.

Frame Increment Pointer(0028,0009)에 명시적으로 각 Frame의 Offset위치를 저장하기도 하지만 거의 저장되어 있지 않기에

그냥 1장의 영상을 계산후 그 크기만큼 이동후 다음영상을 읽는 방식을 취하는게 가장 안전성이 좋습니다.