IRAF/IMFORTによるソフト開発 (第2.1版)

東京大学理学部天文学教育研究センター 浜部 勝
1997年3月1日


本稿ははじめ1年余り前に書いたものであったが、出版までに時間が 経ちすぎ若干内容が古くなってしまった。とりあえずは最小限の書き 直しにとどめておくが、本来は本書の別記事「FITSIO入門」もこの中に 組み入れられて然るべきものである。


ワークステーションの環境をフルに生かした画像処理プロプログラムを 作ることは本来あまり易しくはない。また特に、それをFortranで行うのは さらに容易ではない。しかし、IRAFの一部であるIMFORT、さらにPGPLOT(あるいは MONGO)やSPIRAL Library を用いればかなり簡単に画像処理プログラムを書くこと ができる。 本稿では、Sun版SPIRALの移植・開発を通して蓄積されたそのノウハウを 簡単に紹介する。ただし、SPIRAL Libraryはまだ開発途中のものであり、完璧では ないことをあらかじめ断っておきたい。この事を念頭に、本稿をプログラム開発の 一助としていただければ幸いである。

なお、ここでは計算機としては主にSunのSPARCstationを考えているが、一部の SunFortranに特有な機能を除けば、他のプラットホームにも適用できる。 筆者は、Sun(Solaris1.1.2およびSolaris2.5)およびLinuxを使用している。

また、本稿の旧版ではグラフィックルーチンとしてMONGOを取り上げたが この版からはPGPLOTを使うものとした。MONGOについては旧版「IRAF/IMFORT、MONGO およびKISOlibによるソフト開発」を参照していただきたい。

IMFORTを用いたプログラムの作成

IRAFとファイルを共用する、あるいはIRFA環境で使用するためのプログラムを 書くにあったっては、IRAFシステムの一部として提供されているIMFORTライブ ラリが使える。

IMFORTを使うと、(1) バイナリファイルの読み書き、(2) IRAF形式 の画像の読み書き、(3) コマンドラインの引数の使用、 (4) 画像ファイルのヘッダの読み書きなどが容易にできる。

(注) 現在のSPIRALはIMFORTの他にFITSIOも用いて、IRAF形式の画像だけではなく FITS形式の画像も扱えるようにしている

(1)、(2)、(4)については説明を要さないだろうが、(3)については簡単な説明を要 するかもしれない。ここでいうコマンドライン引数を使用できるということは、プ ログラムの実行時に、
	program  argument1 argument2 ...
というようにプログラムのパラメータをコマンドラインに指定できるということであ る。また、引数を省略した場合には、その引数がそのプログラムにとって必須 のものであれば、プログラムの中からこれを要求してやるというようなことも 可能である。

IMFORTルーチン

IMFORTルーチンの一覧を以下に示す(一部筆者が使用した経験がなく 用途の良くわかっていないものもある)が、これを頼りにマニュアルページを読め ば簡単に使用できると思う。(マニュアルページ読むためには、IRAFを起動してから help imopenなどとすれば良い)

IMFORTルーチン一覧

バイナリファイル用ルーチン

UNIXではファイルの終端記号として16進数の 0Aを用いている。このため、 たとえばFortranではその中に 0Aを含むような画像ファイルをうまく読み 込めない。このような場合に有用なのが、IMFORTの BFルーチンである。

以下にあげる例は、IRAF形式で書かれた符号無しの2バイト整数型(unsigned short integer)の画像ファイルを読み、実数型の配列を得るための サブルーチンの例である。

入力画像は既にIMOPENルーチンでオープンされ、画像識別番号(image descriptor) im が得られているものとし、画像の大きさ iext, jextも既知とする。 このサブルーチンによって実数型の配列 gに画像が読み込まれる。 ierはリターンコード(正常終了なら0)である。

BFルーチンによるプログラム例

コマンドライン、キーワード、画像のアクセス

ここでは、もっと一般的にIRAF形式の画像にアクセスする例を挙げよう。

はじめの例は、コマンドラインの iarg番目の引数として画像のファイル名 imageを与えた時に、オープンモード modeでファイルをオープンし、 その画像識別番号 im、画像のタイトル title、データ型(変数の型) dtype、画像の大きさ iext, jextを得るためのサブルーチンである (ここで mode = 1 なら Read only、mode = 3 なら Read/write モードになる)。 さらに、リターンコードが0以外なら、呼び出しプログラムの任意の行へ戻れるよう になっている。(このサブルーチンの最後の引数はその行番号となる)

画像ファイルへのアクセス例

次の例は、画像識別番号 im としてオープンされたファイルから、 変数型が dtype で、大きさが iext, jext の画像を、実数型の配列 g に 読み込むためのサブルーチンである。 dtype としては 単精度実数型あるいは2バイト符号付整数のみを扱えるようにしてある。

画像入力の例

PGPLOTによるグラフィック・プログラム

PGPLOTをライブラリとして用いると、グラフィックを使用するプログラムが簡 単に作成できる。また、同じプログラムを用いて、画面に表示したりレーザー ライタに出力したりということも可能である。

プログラムの構成

PGPLOTサブルーチンの詳しい使用法はPGPLOTのマニュアルに譲り、ここでは全 体の流れとしてどのようにプログラムを書けばよいかを示す。 PGPLOTを使ってプログラムを作るときは、次のような構成で書くとよい (#以下はコメント)。ここでは、まずは画面に描画し、次いでその図を PostScript形式のファイルとして出力するものとする。このような流れになるのは、 PGPLOTのサブルーチンが一度一つの出力デバイスしか開けないためである。

      Interger hard
      hard=0                    	# ハードコピーのflag

      call PGBEG(0,'/xserve',1,1)  	# 画面表示用デバイスの設定
 1000 continue
 
      # ここに描画コマンドを使う
      
      if ( hard.eq.0 ) then
         call PGEND				# 以下はハードコピーの取り方
         write(*,'(a,$)') 'Hardcopy 1:yes, 0:no'
         read(*,'(i)') hard
         if ( hard.eq.1 ) then 
            call PGBEG(0,'output.ps/ps',1,1)	# LANDSCAPEモードの時
            call PGSCF(2)
            go to 1000
         end if
      end if
      if ( hard.eq.1 ) then
         call PGEND
      end if
      
      stop
      end

マウス・カーソルの利用

またPGPLOTの PGCURS関数を使うとマウス・カーソルの位置を読み取る ことができ、対話的に処理を進めるプログラムを書くのに利用できる。 具体的な使用法については、以下のプログラムをコンパイルして試してみるのが よいだろう。 (コンパイルは
f77 -o crstest crstest.f -lpgplot -lX11
等とする)

PGCURSの使用例

このプログラムは文字「q」を入力する(単にqを押す)ことで終了する。 マウスのボタンも文字に対応しているが、一応念のため上記のテストプログラムで ボタンと文字コードの対応を調べておいたほうがよいだろう。

なお、上記の PGCURSは本来は整数型の関数であり idum = PGCURS(x, y, ch) と いった呼ばれ方をすべきであるが、何故か Linux の場合はエラーとなってしまう。 上記の記述に従えば、SunでもLinuxでもうまく働く。

SPIRAL Libraryの利用

上記に紹介したIMFORT, PGPLOT(およびFITSIO)を用いれば、画像表示、グラフィックを 駆使した画像処理プログラムをFortranベースで作成することができる。しかし、 上記の3つのサブルーチンパッケージは単体の機能の集合であり、そのままでは、 まだ使いにくい部分もある。

一方、SPIRALは上記を駆使したプログラムパッケージであり、そのノウハウの一部が サブルーチンパッケージとして蓄えられている。これが、SPIRAL Libraryである。 SPIRAL Libraryは、SPIRALの中の、source/libディレクトリにあるサブルーチン群 の総称である(あるいはlibspiral.aがそのオブジェクトをライブラリ化したもの である)。

SPIRAL libraryには画像処理プログラム(とりわけSPIRAL)で良く使われるサブルーチンの 他 PGPLOTやIMFORTあるいはFITSIOを使い易くするための、一種のマクロ的なサブルーチン が含まれている。したがって、SPIRAL LibraryによってIMFORT, FITSIO, PGPLOTも より容易に使えるようになっている。

ただし、SPIRAL libraryのうちかなりの部分は、Facom S-3500版の開発時に 作成されたKISOlibをSun用に書き換えたものであり、中にはチェックの充分でないもの 等もあり、使用に際しては注意が必要である(特に下記の表に無いものは使用しないほうが 無難)。

使用法については、各サブルーチンのソースの始めの部分にあるコメントが 使用法、引数の意味等について解説しているのでそれを参照されたい。 また、SPIRALの中の、source/libにあるlibspiral.docがそれらをまとめた 簡易マニュアルとなっている。

下記は、SPIRAL Libraryの主なルーチンと、その機能を簡単に記したものである。 たとえば、SUBGUTYのサブルーチンのソースは subguty.fにある。

具体的なサブルーチンの呼び方については後述の Makefileを参照されたい。

SPIRAL Library一覧

コンパイル、リンクの方法

IMFORT, FITSIO, PGPLOT, SPIRAL Libraryを用いたプログラムをコンパイルする場合に、 他のプログラムと異なるのはライブラリだけである。
 IMFORTを使用するプログラムの場合は、libimfort.a, libsys.a, libvops.a, libos.a
 FITSIOを使用する場合は、libfitsio.a
 PGPLOTを使用する場合は、libpgplot.a, libX11.a
 SPIRAL Libraryを使用する場合は、libspiral.a
といったライブラリをリンクしなくてはならない。

ライブラリの格納場所はサイトによって異なるはずである。 後述のSPIRALの Makefileの実例を参考にしていただきたい。

簡単な例: PGPLOTのみを使うとき src.f をコンパイルして object を作るなら

     f77 -o object src.f -lpgplot -lX11
もしもPGPLOTのライブラリが /usr/lib 以外にあるならば、-lpgplot の 代りに /usr/local/pgplot/libpgplot.a などとする。

makeの活用

多くのソフトウエアを同時に開発しているような場合、また得にそれらのプログラム が幾つかの共通のファイルからなっているような場合には、常に全てのファイルの 依存関係を把握しておき、一部分の変化が確実に全体に反映し、矛盾の無いように する必要がある。また一方で、不必要な再コンパイルも避けたいものである。

このような目的のために、UNIXにはプログラム開発用のツールmakeが用意されている。 これはMakefikeというファイルに、ファイルの依存関係や作成法(コンパイル法)を 記述しておき、必要なものだけを必要なときにだけ実行するものである。

やや詳しくかつわかりやすい参考書としては、「unixツールガイドブック」(坂本文著; 共立出版)があるので、それを勉強していただきたいが、ここではSPIRALの開発時に 使用しているMakefileの例を紹介しよう。

Makefileの書き方

具体例では、冒頭の部分で共通の変数などを定義し、以下の部分ではプログラムの コンパイルを指示している。プログラムのコンパイルを指示している部分は、次の ような形式になっている。
	ターゲット: 依存するファイル
	<TAB> コマンド  (ターゲットの作成法)
makeはターゲットとその依存するファイルの更新日付を比較し、依存するファイルの方が新しい日付を持っていればコマンドを起動してターゲットを作成し直す。
例)     program: source1.o source2.o
                 f77 -o program source1.o sourece2.o
                 
        source1.o:
                 f77 -c source1.f

        source2.o:
                 f77 -c source2.f
        (f77の前には空白ではなくタブが入る)
この場合は、たとえば souce1.fだけが変更されると source1.fのみが コンパイルされ、次いで、 programが作り直される。source2.fは 再コンパイルされない。

多くのプログラムから成るシステムを作るときは、Makefileの中に依存関係と コンパイル法などを記述しておくと、再コンパイルが楽なだけでなく、多くの部分に影響する変更を行ったときも、全体を完全に変更することが出来間違いを防ぐことができる。

Makefileの具体例

ここでは具体的な例の一つとしてSPIRALのMakefileをあげる。 最初に断っておくが、これは作者が見よう見まねで作成したものであり、 必ずしも良い例となってはいない。

以下で # はコメント行、\ は継続行の印である。 <TAB>は表示されていない。

Makefileの例

この例では、プログラムのコンパイルのほか、ライブラリの作成、圧縮ファイルの 作成などもできるようになっている。 Makefileのもっと良い例としては、X-Window System, PGPLOT その他のPDS、 フリーソフトのものが挙げられる。もしも、手元にあればぜひ眺めていただきたい。

具体的なプログラムの実例

以下に具体的なプログラム例 としてあげるものは、IRAFフォーマットの画像を読み、 その等輝度線図を描くためのプログラムである。SPIRALのisophotesプログラムを 簡略化して、そのエッセンスのみを残してある。

このプログラムをコンパイルしたものが isocontourであるとすると、

	% isocontour   image       
とすれば画面にコントアを描き、
	% isocontour   image   m51.ps 
とすれば、画面にコントアを描いた後 PostScript 形式のファイルを m51.ps という名前でハードコピーを出力する。

この例では、IMFORT, PGPLOTのサブルーチンの他に、上で例に挙げたSPIRAL Libraryの サブルーチン opninp, matrd も使ってある。また、pointerと mallocによって、画像のためのメモリを動的に割り当てている事にも 注目して欲しい。

プログラム例