昨日のPCI

何時間もかかってペルーのリマに入ったのは一昨日真夜中でした これで中南米の諸国でその国の首都に入ったのは、1999年に初めて訪れてからの順番で サンパウロ、サンチャゴ、ブエノスアイレス、メキシコシティー、ハバナ、ボゴタそして今回のリマと7番目です。ハバナ以外の都市は全て激しい渋滞であり、かつてのバンコクのようです。
リマに行く前は、何となく小さな街だろうと思っていたのですが、来てみると大都会です。しかし、極端な高層ビルはそれほど無く、低層の建物が多く、何となく落ち着いた街並みでした。ペルーにはブラジルよりも数年早く日本人が移住したということですので、日系人も多い、ということですが、サンパウロと異なり街中では日系人らしい方々にはお会いできませんでした。リマには有名な日本食レストランが三軒あります。「TOSHIRO」「FUJI」そして「ICHIBAN」です。TOSHIROというのが一番人気でリマ最古の日本食レストラン、ということですが、僕からすると今一つ、という感じでした。FUJIは格式高いような印象です。一番良かったのはICHIBANです。メニューにはもちろん日本語がありますし、全て写真付きというのも嬉しいものです。そして、メニュー内容には日本の「メシ屋」で食べるようなものもあり、親しみが湧きます。また、その中の三点に関しては、キャッチフレーズが付いていて思わず注文したくなるのです。味噌ラーメンには「店を支えたラーメン」、「歴代総理が認めた逸品」というのが、一番風カルパッチョに、そして宮様弁当には、「宮様ご接待記念弁当」という説明文がついているのです。


昨日は早朝にINCORに行きました。INCORというのはスペイン語で国立心臓センターという意味です。病院は2年前に新築されたそうで、とても綺麗な病院でした。入り口の警備は非常に厳しく、パソコンやカメラなど全て登録させられたのです。入り口のみならず、各階にはたくさんの警備の人が立っています。やはり20年前にペルーを覆っていた反政府軍によるテロの嵐、その記憶が残っているということです。もっとも、私達からすれば、街は安全で静かな感じで、こんな街にテロが吹き荒れていたなんて信じられません。そのような印象は、ボゴタに行った時にも感じました。でも実際にはその歴史は事実であり、現実世界の厳しさ、というものを思い知ります。日本人駐在員に対する自動車の防弾車普及率は70%ということです。食事を一緒にさせて頂いたブリジストンの中南米唯一の駐在員の方とお話していたらば、何とその前日夜も、ペルー人社員3名がレストランで食事をして、自家用車に三名で乗り込もうとしたところを三名の男に銃をつきつけられ、顔を殴られ、お金でなく、パソコンと書類を強奪されたそうです。こんなんではいくら防弾車があっても役に立ちませんね。ブリジストンは直径4Mにも達する鉱山用トラックのタイヤをたくさん販売しているそうです。日本人一人で何とこの地域で年間100億円の売り上げがあるらしいのです。ものすごく頑張っている日本人っておられるのですね・・
さてさてINCORでは1時間にわたって講堂で講義を行い、それからすぐに Hospital Edgardo Rebagiati Martins というペルー最大の病院に移動しました。この病院もペルー保健省が運営している国立病院であり、大学病院です。建物は巨大でしかも14階建です。その11階が循環器病棟であり、カテ室も一つあり、東芝のマシンが入っていました。
一例目は診断カテから開始しました。右橈骨動脈アプローチで開始しました。患者さんはインディオ系の方でしたが、右腕頭動脈が蛇行し、しかも上行大動脈が短くて、とても難儀しました。何とか造影すると右冠動脈#3の慢性完全閉塞でした。カテの種類も少なく、大変でしたが、そのままPCIに移行したのです。病変をワイヤーでクロスするのは難しくなかったのですが、その後が大変でした。ガイドカテのバック・アップも無く、空中戦のようでした。バルーンが通過せず、幸い持ち合わせていた5Frガイドカテを用いて、5 in 6を行い何とか拡張し、結局 TAXUS Express薬剤溶出性ステントを3本植え込みました。結果は良く、見学に来られていた近隣の先生方もお喜びでした。
ステントの選択も限られ、基本的に薬剤溶出性ステントはTAXUS Expressのみであり、しかも本数も種類も限られていました。
それから1.5時間ぐらいの患者さん入れ替え時間の次に用意されていたのは、右冠動脈近位部の慢性完全閉塞です。一回トライされ不成功だった方で女性の方でした。右冠動脈は入口部からすぐに直角に曲がり頭の方に向かい、そこでまた直角に曲がりすぐに下行する、といういわゆるShephard Crook typeのものであり、しかもその頂上部分で1CMぐらいの慢性完全閉塞なのです。こんなの順行性では絶対に不可能です。最初から逆行性アプローチで入りました。中隔枝通過は非常に難しく、うーん なかなか理解してくれる人は少ないと思いますが、繊細なワイヤーコントロールを行い、またSion BlueとFielder-FCを適宜入れ替えながらやっと通過させました。本当にものすごく難しいテクニックを使ったのです。もちろん右冠動脈の屈曲は逆行性でも同じなので、そう簡単には慢性完全閉塞を通過できません。右冠動脈に順行性ガイドカテを挿入しましたが、御理解頂ける方はなかなかPCIが上手な人だと思いますが、このようなケースではALでバック・アップをとるのが困難です。何故かと言えばあまりバック・アップを強くしようとすれば、容易に右冠動脈入口部から解離を起こしてしまいます。ぎりぎりで右冠動脈に挿入すれば簡単に落ちてしまいます。そんな中でまずは逆行性にワイヤー通過を試みたのですが、案の定柔いワイヤーではまったく通過できません。そこでConquest-Proを90度ぐらいdouble bendingとして、穿通を試みました。何とか穿通され右冠動脈近位部にこの屈曲を越えて通過したので、少しは右冠動脈が伸びた、考えられ、順行性を開始し、何とか通過できました。しかし、バック・アップがとれませんので、なかなか通過できません。何とか1.25mm balloonが通過し、最終的にはこれも3本の薬剤溶出性ステントを植え込み綺麗に仕上がりました。いやあ 正直 最高難度に属する慢性完全閉塞でしたがうまくいって良かったです。
この後また長い入れ替え時間の後、まあその頃にはオネムとなっていましたが、左橈骨動脈アプローチ、これほど僕の不得手はないのですが、その穿刺からやらされました。辛かったなあ、でもうまく行って良かった。その患者さんはLIMA graftしかない患者さんなのですが、そのLIMA graftを造影し、それだけで終了したのです。そしてホテルに戻ったのでした。
本日は昨日行った INCORでPCIをします。最善を尽くします。

心臓病学会座長終了

無事 座長の仕事も終え、今サンダーバードで富山に向かっています。小牧からの便は満席だったので、富山から羽田に戻ります。
電車の中で大きな過ちに気付きました

typedef struct JPEGTAGTBL {
  BYTE *DHT;
  BYTE *SOI;
};

としていたのですが、以下のように変数を宣言すると訳の分からないエラーが出るのです

typedef struct JPEGTAGTBL {
  BYTE *DHT;
  BYTE *SOI;
} *jpegTagTbl;

どういうこと? と考えあぐね、やっとtypedefがいらないことに気付きました バカみたい

昨日のライブ

昨日のカナダへの中継は成功裡に終了しました。僕は松陰先生とコンビを組み、舛谷先生は吉町先生とコンビを組み、無事二例のslender TRIを終えました。
その後、甲子園界隈で真夜中まで歓談したので今朝は眠い 眠い
朝一番のサンダーバードに乗って、今福井駅です。これから金沢に入り、心臓病学会シンポで座長し、それからすぐに鎌倉に戻ります。忙しいですね。

今新幹線で大垣あたり移動中 – C++で二進出力を可能とするクラス

本日はこれから兵庫医科大学病院に行き、AIM-TRIというカナダのケベックで開催されている学会に、同院よりライブを飛ばします。舛谷先生、松陰先生、そして吉町先生と一緒なので気が楽です。新幹線の中では相変わらず C++を用いて DICOM XA関係のプログラムを書いて、そしてコンパイルして、そしてrunして試しています。

その過程でかつて書いた部品プログラムを幾つか改良しつつあります。デバッグ用に重宝しているのが、二進出力用のクラスなのです。以前も紹介しましたが、それを書いた時には、何と愚かにも整数型int というのは16 bitsと思い込んでいたのです。ですから、int型の値を二進出力しても16桁しか出力しませんでした。何でこんな思い込みをしていたのか? と言いますと、僕がプログラミングの世界に入ったのは、何と1978年頃なのです。当時  Intel 8080/8085とか、Zilog Z-80といった 8-bits CPUの世界であり、そのCPUをボードに2KBぐらいの少ないメモリー、クロック回路、それに4桁のLCDそして簡単なインターフェースを一つの配線ボードに載せた「ワンボード・コンピューター」というのがそうですね、当時の価格で15万円ぐらいで売り出され、メカの好きな人たちには絶大な人気だったのです。「トレーニング・キット」とも言いました。

最もポピュラーだったのは、NECが発売していてIntel 8085を載せていた TK-80というトレーニング・キットでしたが、僕が購入したのは、Sharpが発売していたMBS80Kとかいうトレーニング・キットで、Z-80が載っていました。何しろ僕のプログラミングはそこに始まりました。ですから、当然キーボードなど無く、16 Keyのパッドのみですから、プログラムの入力は、全て機械語で16進入力するのです。それから暫くすると、世の中に「マイコン」つまりMy Computerを短くしたものですが、それが出てきて、僕はすぐに Sharpの MZ80というベストセラーのマイコンに移行しました。

これは、ディスプレー(といっても、たかだか80 x 40文字しか出ない)と、フル・キーボード、そして外部記憶としてカセット・テープがついていたのです。その上では、BASIC言語、Assembler言語、Pascalなどが走り、そのような「高級言語」でプログラムを書いて楽しむことができました。ものすごい進歩!!!

当時は CPUが 8bitsでしたし、次に出てきた8086といった世間を席巻したCPUは 16 bitsでしたので、整数型 intというのは2 bytes用いた 16 bitsというのが世間の常識でした。その頃の記憶が体に染みついているのですね。

何はともあれ、現在は 32 bits or 64 bits CPUが主流ですので、何時の頃からか世間の常識は 整数型 intは 32 bitsというのが当たり前となっているのです。何しろ16 bitsでは 0から 65535までの数しか表せませんが、32 bitsでは 0から何と 4294967295という巨大な数まで表すことができます。すっ、すっ、すっごーーーいっ!!

ということで、これまで16 bitsで書いていた二進出力を修正したのです。まずは ヘッダ部分です:

#ifndef __OSTREAM_H_
#define __OSTREAM_H_
// 二進出力を可能とした ostream (Programmedd by Shigeru SAITO, MD on June 5th, 2009)
// modified by S. SAITO, MD on December 14th, 2010
// 使い方: このheader fileをインクルードし、名前空間ostを用いてcoutに出力する
// ost::ostream cout; とcoutを生成し、
// cout << value;
// のように使う、そして標準出力については std::cout << std::endl; のようにする
// 入力の型(BYTE, WORD, int)に応じて自動的に8桁、16桁で出力するがsetw()で出力桁数を変更できる
// modified on Sepptember 14th, 2012 (hex出力の大文字化および32 bits, 16 bitsのint型に対応)
//
#include <iostream>
#include <iomanip>
#include <string>
typedef unsigned char BYTE;
typedef unsigned short WORD;

namespace ost {
	enum e_manip {bin, hex, dec, endl};
	class setw {
		int width_;
		setw() {}	// 引数無しコンストラクタ禁止
	public:
		setw(int n);
		int get_width(void) const;
	};

	class ostream {
	private:
		int width, bitWidth;
		e_manip mManip;
		bool mIsSetW;
		void setWidth(int w);
		void out(int n);
	public:
		ostream();
		ostream & operator << (const setw & sw);
		ostream & operator << (const e_manip em);
		ostream & operator << (const BYTE n);
		ostream & operator << (const WORD n);
		ostream & operator << (const int n);
		ostream & operator << (const char* s);
		ostream & operator << (const std::string str);
	};

};	// namespace ost

#endif __OSTREAM_H_

そして次はコードです:

#include "ostream.h"
#include "stdafx.h"

namespace ost {
	setw::setw(int n): width_(n) {
			if (width_ < 1) width_ = 1;
			if ((sizeof n == 4)&&(width_ > 32)) width_ = 32;
			if ((sizeof n == 2)&&(width_ > 16)) width_ = 16;
		}
	int setw::get_width(void) const { return width_; }

	void ostream::out(int n) {
			int printWidth = 0;
			mIsSetW ? (printWidth = width): (printWidth = bitWidth);
			switch (mManip) {
				case bin:
					for (int i = printWidth; i > 0; --i) {
						std::cout << (((n >> (i - 1)) & 0x00000001) ? '1': '0');
						if ((i != 8) && ((i - 1)%4 == 0)) std::cout << " ";
					}
					break;
				case hex:
					std::cout << "0x" << std::hex << std::uppercase << std::setw(printWidth);
					std::cout << std::setfill('0') << n;
					std::cout << " ";
					break;
				case dec:
					std::cout << std::dec << std::setw(printWidth) << std::setfill('0') << n;
					break;
				default:
					break;
			}
		}

	ostream::ostream(): width(1), bitWidth(8), mManip(bin), mIsSetW(false) {}
	ostream& ostream::operator << (const setw & sw) {
			width = sw.get_width();
			mIsSetW = true;
			return *this;
	}
	ostream& ostream::operator << (const e_manip em) {
			if (em == endl) { std::cout << std::endl; } else { mManip = em; }
			mIsSetW = false;
			return *this;
	}
	ostream & ostream::operator << (const BYTE n) {
			switch (mManip) {
				case bin:
					bitWidth = 8;
					break;
				case hex:
					bitWidth = 2;
					break;
				case dec:
					bitWidth = 3;
					break;
			}
			out(static_cast<int>(n));
			mIsSetW = false;
			return *this;
	}
	ostream & ostream::operator << (const WORD n) {
			switch (mManip) {
				case bin:
					bitWidth = 16;
					break;
				case hex:
					bitWidth = 4;
					break;
				case dec:
					bitWidth = 5;
					break;
			}
			out(static_cast<int>(n));
			mIsSetW = false;
			return *this;
	}
	ostream & ostream::operator << (const int n) {
			switch (mManip) {
				case bin:
					if (sizeof n == 4) {
						bitWidth = 32;
					}
					if (sizeof n == 2) {
						bitWidth = 16;
					}
					break;
				case hex:
					bitWidth = 4;
					break;
				case dec:
					bitWidth = 5;
					break;
			}			
			out(n);
			mIsSetW = false;
			return *this;
	}
	ostream & ostream::operator << (const char* s) {
			std::cout << s;
			mIsSetW = false;
			return *this;
	}
	ostream & ostream::operator << (const std::string str) {
			std::cout << str;
			mIsSetW = false;
			return *this;
	}

} // namespace ost

使い方はどうするか?と言いますと 実際のコード例を示します:

#include "ostream.h"

int main() {
  ost::ostream cout;  // 二進出力クラスの実体化
  int i = 1; -1という整数はどのように出力されるか?

 cout << "16進出力: " << ost::hex << i << ost::endl;
  cout << "2進出力: " << ost::bin << i << ost::endl;

  return 0;
}

DICOM XA解析

さてさて疑問は尽きぬものの、ゆっくりとDICOM Viewerに向けて進んでいます。その過程で改めてC++について学びながらやっていますので、本当にゆっくりしか進みません。

今迄したことは

  1. ファイルをメモリーに読み込む
  2. ファイル内容をメモリー・バッファに展開する
  3. これらの過程で例外が発生すれば例外クラスを用いてキャッチする
  4. メモリー・バッファをスキャンして、何コマ(何フレーム)かを見出し、その過程でJPEG Tagを検出する

というものです この後の予定としては

  1. メモリー・バッファからDHTを読み、ハフマン表を作成する
  2. フレームを指定してビット出力をメモリー・バッファに命じ、ハフマン表から解読する
  3. 解読結果をビットマップに転送する

というものです。そこで問題がありました。現実のDICOM XAではファイルの中のフレーム毎にDHTが変わるのか否か そして、実際のイメージ・データの両端マーカーは何か? というものでした

実際のファィルを調べるとどうやらDHTはファイル毎に同一であり、両端マーカーはこのようになっていました


SOF3については、位置が一定ではないようです。そして、それぞれのタグの間には何か分からない意味の無いデータが何バイトか挟まっています。何れにしてもイメージ・データの両端はSOS (Start of Scan)とEOI (End of Image)のようです。

日中友好TRIセミナー

本日は朝から沖縄南部徳洲会病院で日中友好TRIセミナーを開催しました。沖縄と中国と言えば、今年は尖閣問題で対立しています。開催が危ぶまれたのですが、僕と中国とのかかわりはもっと深いため、開催することを決定しました。

沖縄南部徳洲会病院の方々には大変お世話になりましたが、お蔭様で大変良いセミナーが開催できました。医学的・科学的な交流のみならず、日中間の友好にも寄与できたと思いますし、実際に沖縄経済にも少なからず貢献できたと思います。

症例は最少から制約しましたが、そこはライブデモンストレーションです。最終症例はなかなか見ごたえがあるものだったと思います。このような困難な症例も成功裡に終えることができて嬉しく思いますし、自分自身「結構すごい」、「またまだやれる」と思いました。

今 那覇空港ラウンジです。これから羽田に戻ります。

ハフマン符号表は完成したものの

一昨日ハフマン符号表解読プログラムが完成したものの、いくつかのDICOM XA fileを解読していたらこんな符号表に出くわしました

実際の DICOM XAより抽出したハフマン符号表

あれあれ?という感じです 何故ってビット長が何と値 16まであるのです。だって、DICOM XAの1 pixelは 8bitsの深度の筈です。実際のこのファイルのBits Allocatedなどを調べても8 bitsとしてしか記載は無いのです。だとすると、その値の差分も8 bits以内に収まらねばなりません。これってどういうこと? 何で 16 bitsあるの?

誰か御存知の方 ご指導頂けませんでしょうか? 大混乱しています。