TkPlot.pl


用語


入手方法

    \\lucid.msl.titech.ac.jp\pool\CalculationServer\Windows\D\Programs\Perl

の内容を、適当なディレクトリィにコピーします(ここにObject PerlライブラリィTkPlotが含まれています)。

 他にあった方が良いプログラム(エディターやPostScript Viewerなど)も含まれているので、

    \\lucid.msl.titech.ac.jp\pool\CalculationServer\Windows\D\Programs

をすべて

    d:\Programs

にコピーすることを薦めます。この場合には、それぞれのディレクトリィは、

    Object Perlライブラリィ d:\Programs\lib
TkPlot d:\Programs\TkPlot

になります。


TkPlot.plとは

 Perl/Tk と神谷が作ったObject Perlライブラリィを使って作った、汎用グラフ表示プログラムです。
現在のところ、次のデータに対応しています。
対応ファイルは、kPlotのインストールディレクトリィ下のdlib下記の仕様のモジュールを追加することによって拡張できます。
モジュールの例は、TkPlotディレクトリィのdlibディレクトリィ内にあります。
プログラム データタイプ ファイル名
(ワイルドカード的表示)
備考 識別子
($FileType, $TargetData)
モジュール
Rietan2000

 

 
測定XRD図形 *.int   Rietan Intensity File Crystal::Rietan, dlib::TkRietan

 

シミュレーションパターン *.pat   Rietan Pattern File (IGOR)
Rietan Pattern File (RietPlot)
Rietan Pattern File (gnuplot)
フィッティングパターン *.pat Rietan Fitting Pattern File
WIEN2k

 

 
PDOSファイル *.dos(1|2|3)?(ev)?(up|dn)?
& *.int
WIEN2k PDOS files Crystal::WIEN2k, dlib::TkWIEN2k
誘電関数ファイル *.epsilon(up|dn)?   WIEN2k epsilon file
バンド構造ファイル *.spaghetti(up|dn)?_ene WIEN2k spaghetti Band file
VASP OUTCAR出力の
エネルギー収束過程
 OUTCAR   VASP Output file,
EnergyConvergence
Crystal::VASP, dlib::TkVASP
OUTCAR出力の
エネルギー準位収束過程
 OUTCAR   VASP Output file,
EnergyLevels
Virtual NanoLabo 出力ファイル  *   ATK 2.0 Output Crystal::TranSIESTA, 
dlib::TkVNL
DVXa GPGL出力  ?07   DVXa GPGL File Crystal::DVXa, dlib::TkDVXa
その他 CSVファイル
X,Yデータファイル
 *   Sci::GeneralDataFile, CSV,
dlib::TkGeneralDataFile

また、同様のモジュールを作ることにより、TkPlot.plの機能をベースに、別のアプリケーションを作ることもできます。ためしに、TkPlotディレクトリィDraw.batを実行してみてください。このモジュールはclib\TkDraw.pmです。

プログラム 説明 備考 モジュール
Drawアプリケーション マウスで線画を描き、PostScriptファイルに保存する   clib::TkDraw
リアルタイム測定アプリケーション Startボタンを押すと、リアルタイムでデータを追加し、
グラフを再描画し、同時にデータファイルに保存する
  clib::TkGPIBTest

TkPlot.plを使うメリット

  1. PerlとPerl/Tkが動く環境であれば、コンピュータ、OS、コンパイラに依存せずに使える。
    (PerlはVer5.8で、Windows, Fedora Core4、Redhat Linux7で動作を確認。) 
      Microsoft Visual C++は、Windowsでしか使えない。
        将来バージョンとの互換性も不安(もっとも、Perlでも将来の互換性は保証できない)。
     
  2. エディターのみでプログラムを書き、拡張できる。
      速くなったとはいえ、やっぱりコンパイルするのは面倒くさい。
     
  3. 開発環境にお金がかからない。
      Microsoft Visual C++は高い。
     
  4. Graphics User Interface (GUI)を作るのが簡単
        Perl/Tkが使える。コード(モジュール)の再利用性も高い。
        Visual C++のコードの再利用は面倒くさい。
        JavaのGUIはどれを使ったらいいかわからない(3Dなど、高度な処理はJavaの方が良いか?)。  
      
  5. Perlの強力な文字列処理機能(正規表現など)を使えるので、データファイル処理が楽。
        C++などだと、専用の処理関数をたくさん作らないと対応しきれない
  6. Perlの強力なハッシュ変数(連想配列)を使えるので、データ処理が楽。
        C++などでも、自分でクラスを作れば対応できる。
     
  7. Perlの膨大なモジュールを使える。
        特にシステム管理、ネットワーク処理、データベース処理など
     
  8. 必ずコンソールから起動するため、デバッグにprintなどを使えるので、デバッグがしやすい面がある。
        Visual C++でもコンソールを使えないことはないが、手続きが面倒。

TkPlot.plを使うデメリット

  1. 基本的にPerlはインタープリターなので、動作が遅い。
    (正確には、起動時にコンパイルしますが、それでも純粋なコンパイラ型言語に比べると圧倒的に遅い)
     
  2. 科学計算用のライブラリィが少ない。 
        Fortranにはlapackなど、多くのライブラリィがある。C++にもlapackなどは移植されているが、充分ではない。
        Perlについては不明だが、あてにはできない (もっとも、C => Perlの移植は楽そう)。
     
  3. プログラムの文法チェックが甘いことと、コーディングが柔軟すぎて、デバッグがしにくい面がある。
        C++では文法チェックが割りとしっかりとしているので、バグを見つけやすいことがある。
        ただし、反面、柔軟なコーディングはできない(それぞれはトレードオフの関係)。 
     
  4. 日本語を使いにくい。
  5. 特殊なパス名(日本語を含む、途中に空白文字があるなど)を扱いにくい(あるいは、扱えない)。
  6. Perl/Tkが提供していない機能の実装は面倒くさい。
     例: 縦書きの文字列を書く、点線などを描く、他のアプリケーションからのドラッグ&ドロップを実装する

わかっている問題点

対応する予定がない(できない)
  1. 縦書きの文字がかけない。Perl/Tkの仕様か?
  2. 点線などが描けない。Perl/Tkの仕様か?
  3. 動作が遅い。Perl/Tkなので仕方がないので、PCを速くして対応する。 

対応予定

  1. Log, 1/xなどのスケール表示が変。近いうちに対応予定。
  2. Rietan フィッティング .pat ファイルが2相以上を含む場合に未対応。近いうちに対応予定。
  3. 軸の数値が逆転したグラフがかけない。たとえば、X軸の左端を1.0、右端を-1.0にするなど。

対応予定

  1. Log, 1/xなどのスケール表示が変なのを直す。
  2. Rietan フィッティング .pat ファイルが2相以上を含む場合に対応させる。
  3. 軸の数値が逆転したグラフを描けるようにする。
  4. 複数の目盛りを相関させる機構を作る(例: 1000/TとTをそれぞれの目盛りに表示させる)。
  5. 試みにフィッティングプログラムモジュールを作ってみる。

TkPlot.plで使うファイル

Perl関係

  1. perl.exe (ActivePerlで動作確認)
     perl.exeのあるディレクトリィはPATH変数で指定されている必要があります。
     コマンドコンソール (Windowsでは cmd.exe、Linuxではktermなど)で、
      $ perl --version
    と入力し、PATHが通っているかどうか確認できます。
  2. Perl/Tk (ActivePerl 5.8以降では標準装備。Linuxでは、自分でインストールする必要がある。)
      $ perl -e "use Tk"
    と入力し、エラーメッセージが出なければ、インストールされています
  3. Math::Matrixモジュール (とりあえず、なくても動きます。自分でインストールする必要がある)
      $ perl -e "use Math::Matrix"
    と入力し、エラーメッセージが出なければ、インストールされています
  4. Math::MatrixRealモジュール (自分でインストールする必要がある)
      $ perl -e "use Math::MatrixReal"
    と入力し、エラーメッセージが出なければ、インストールされています
  5. Jcodeモジュール (自分でインストールする必要がある?)
     $ perl -e "use Jcode"
    と入力し、エラーメッセージが出なければ、インストールされています

ライブラリィおよびTkPlot

以下のファイルは、\\lucid.msl.titech.ac.jp\pool\CalculationServer\Windows\D\Programs\Perlにあります。

  1. Object Perlライブラリィ
  2. TkPlotファイル
        TkPlot.pl: TkPlotスクリプト本体
        TkPlotApp.pm: TkPlotアプリケーションクラス
        TkPlotDoc.pm: TkPlotドキュメントクラス
        TkPlotWindow.pm: TkPlotメインウィンドウクラス
        RietPlot.bat (Unixでは RietPlot)など: TkPlot.plを Rietan2000用に起動するスクリプト
        TkPlot/dlib下のファイル: データ処理モジュール
        TkPlot/clib下のファイル: その他のアプリケーション処理モジュール

あった方が良いプログラム

  1. エディター
     初期化ファイル(TkPlot.ini)の編集やモジュールの作成に必要です。
  2. PostScript Viewer
     TkPlotでは、直接プリンターに印刷できません。
    グラフなどを印刷するには、GhostScript, Adobe Illustratorなど、PostScriptを表示・印刷できるソフトウェアが必要です。

Windows上でのTkPlot.plのクイックインストール

この説明でわからない場合、下のTkPlot.plのインストールを読んでください。

  1. Perl/TkPlotとPerl/libを適当なディレクトリィにコピーする。 
     
  2. perlをインストールする。
    Windows用のActivePerlは、 http://www.activestate.com/Perl.plex?hdr=1 からダウンロードできます。
     
  3. Perl/TkPlotディレクトリィに移り、setup.batを実行します。この際、インターネットにつながっている必要があります。
     
  4. RietPlot.bat, VAPPlot.bat, WIENPlot.batなどから起動します。 

Unix上でのTkPlot.plのクイックインストール

この説明でわからない場合、下のTkPlot.plのインストールを読んでください。

  1. Perl/TkPlotとPerl/libを適当なディレクトリィにコピーする。 
     
  2. perlをインストールする(通常はすでにインストールされているはず)。
     
  3. JcodeMath::Matrix、Math::MatrixRealから、
      Jcode-2.03.tar.gz
      Math-Matrix-0.4.tar.gz
      Math-MatrixReal-2.01.tar.gz
    をダウンロードし、Perl/TkPlotディレクトリィにコピーします。
     
  4. Perl/TkPlotディレクトリィに移り、./installを実行します。
      % sh ./install
     
  5. シェルスクリプト RietPlot, VAPPlot, WIENPlot などから起動します。

簡単な動作チェック

Draw.batで実行チェック

  1. Perl/TkPlotディレクトリィに移り、Draw.batを実行してみてください。
    これが動かないときは、エラーメッセージを教えてください。
    #エラーメッセージは、コマンドラインからDraw.batを実行しないとわかりません
  2. Draw.batが起動したら、マウスの左ボタンを押したまま動かします。   線が書けるはず。それだけです。

RietPlot.batで実行チェック

  1. Rietan2000のファイルを表示するには、RietPlot.batを実行してみてください。
  2. Perl/TkPlot/SampleData/Rietan2000 にサンプルファイルがあるので、
    「PATH」ボタンを使って、このディレクトリィ内のファイルを選択します。
  3. その後、その下のリストボックスから、EuCUSeF.pat を選びます。
    データ量が多いので、Pentium4 3GHzでも、グラフの表示に数秒かかります。
  4. 表示されたら、グラフ上の線の上にマウスカーソルをおいたり、  グラフ枠内でドラッグしたりしてみてください。

その他:


TkPlot.plのインストール

TkPlotのインストール:Windows, Unixの場合

 \\lucid.msl.titech.ac.jp\pool\CalculationServer\Windows\D\Programs\Perlを適当なディレクトリィ $TKPERLDIR にコピーします。
以後、

    Object Perlライブラリィのディレクトリィは $TKLIBDIR (= $TKPERLDIR/lib)、
    TkPlotのディレクトリィは $TKPLOTDIR (= $TKPERLDIR/TkPlot)

と表します。

PerlとPerlモジュールのインストール:Windowsの場合

  1. ActiveState.comPerlサイトから ActivePerlのStandard Distributionをダウンロードし、インストールします (Ver5.8以降を推奨)。
  2. PATHにperl.exeのあるディレクトリィを追加します。
  3. Math::Matrixモジュールをインストールします。cmd.exeを起動し、
      c:> ppm install Math-Matrix
    と入力します。
  4. Math::MatrixRealモジュールをインストールします。cmd.exeを起動し、
      c:> ppm install Math-MatrixReal
    と入力します。
  5. Jcodeモジュール をインストールします。cmd.exeを起動し、
      c:> ppm install Jcode
    と入力します。

PerlとPerlモジュールのインストール:Unixの場合

  1. ほとんどの場合、perlは標準でインストールされています。
    そうでない場合はインストールし、PATHにperl.exeのあるディレクトリィを追加します。
     
  2. Perl/Tk をダウンロードし、インストールします。rootユーザーになり、
      # perl Makefile.PL; make; make install
    を実行します。
     
  3. Jcode、Math::Matrixと、Math::MatrixRealモジュールをCPANからダウンロードします。
    それぞのページは
        Jcode
        Math::Matrix
        Math::MatrixReal
    です。
     
     インストールは、それぞれのアーカイブを展開して、展開ディレクトリィに移り、
      # perl Makefile.PL; make; make install
    を実行します。
     
  4. 環境変数TkPerlDirに、上記の$TKPERLDIR (Object PerlライブラリィおよびTkPlotの入っているディレクトリィ)を指定します。
     
    例 (bashの場合):
      ライブラリィ: $TkPerlDir/lib (以下、$TKLIBDIR)
      TkPlot: $TkPerlDir/TkPlot  (以下、$TKPLOTDIR)
    にそれぞれのファイルがある場合は、
        export TkPerlDir=$HOME/bin
    を実行します。

ファイルの変更:Windows, Unixの場合

  1. $TKPLOTDIR/TkPlot.plの
     use lib 'd:/Programs/Perl/lib';
     use lib 'd:/Programs/Perl/TkPlot';
     use lib "/home/tkamiya/bin/lib";
     use lib "/home/tkamiya/bin/TkPlot";
    の行を、
     use lib '$TKLIBDIR';
     use lib '$TKPLOTDIR';
    に変更します($TKLIBDIR、$TKPLOTDIRは実際のディレクトリィパスに置き換えます)。

TkPlot.plの起動時引数

引数

  1. --style=$STYLE
     現在、$STYLEとしては、Rietan、GPGL、VASP、WIEN、Testが使えます。
     TkPlot.plを$STYLE用の設定で起動します。
     この場合、TkPlot.iniの[$STYLE]セクションから初期化情報を得、ウィンドウタイトルも "$STYLE Plot"になります。
     また、$TKPLOTDIR/dlibディレクトリィ下に Tk$STYLE.pmがあれば、一番最初にロードします。
  2. --LoadModule=$ModulePath
     起動時に読み込むアプリケーション処理モジュールを、$TKPLOTDIRからの相対パスで指定します(拡張子の.pmはつけません)。
     例: --LoadModule=clib/TkDraw
  3. --vertical
     ファイルペインとグラフ表示ペインを縦置きに配置します。この場合、ファイル内容を示すテキストボックスなどは省略されます。
     このオプションが指定されていない場合、各ペインを横置きに配置し、ファイル内容テキストボックスなどを表示します。
  4. --ReadPrev
     前回のWorking Directoryを読み込んで起動します。
  5. ファイル名
     指定されたファイルを読み込んで起動します。

以上の引数を使うことにより、アプリケーションに特化したウィンドウ構成でTkPlot.plを起動できます。

例: Rietan2000
    Unix:   perl -w -x -S $TKPLOTDIR/TkPlot.pl --style=Rietan --vertical --ReadPrev $@
    Windows: perl -w -x -S $TKPLOTDIR\TkPlot.pl --style=Rietan --vertical --ReadPrev %*

例: VASP
    Unix:   perl -w -x -S $TKPLOTDIR/TkPlot.pl --style=VASP --ReadPrev $@
    Windows: perl -w -x -S $TKPLOTDIR\TkPlot.pl --style=VASP --ReadPrev %*

例: Draw
    Unix:   perl -w -x -S $TKPLOTDIR/TkPlot.pl --style=Draw --LoadModule=clib/TkDraw --vertical --ReadPrev %*
    Windows: perl -w -x -S TkPlot.pl --style=Draw --LoadModule=clib\TkDraw --vertical --ReadPrev %*

注: Perlのオプションは次のとおり
     -w 詳細なエラー、警告メッセージを表示する
     -x 
     -S スクリプトの先頭行を、#! までスキップする


基本的な使い方

  1. なるべく、上記のアプリケーション用に用意されたスクリプトから起動しましょう。
  2. 起動したら、「Path」ボタンを押し、データファイルのあるディレクトリィを選択します。
    起動時オプションに--ReadPrevが指定されている場合、前回使ったディレクトリィがすでに選択されています。
  3. ディレクトリィ内にあるファイルのリストが、Files: ドロップダウンリストボックスに表示されます。
  4. Files: ドロップダウンリストボックスでファイルを選択すると、データを読み込んで表示します。
     
  5. 表示されたグラフのデータ上にマウスを移動させると、データの説明がバルーンヘルプで表示されます。
    Rietan2000のフィッティングデータを表示させると、一番下のグラフ枠にピーク位置がでますが、このピーク位置上にマウスを移動させると、回折指数、Kα1、Kα2の区別、回折角が表示され、XRDプロファイル上にピーク位置を示すグレーラインが表示されます。
  6. スケール上でダブルクリックすると、表示範囲を変更するダイアログが出ます。
  7. グラフ枠内を始点にしてマウスをドラッグすると、その範囲を拡大するかどうかのポップアップメニューが出ます。ポップアップメニューからは、表示範囲変更ダイアログを表示させることができます。
  8. 表示範囲を元に戻すには、メニューの"View"=>"Restore scale"を選びます。
  9. 印刷はできませんが、グラフは、"Save as PostScript"で、PostScript形式で保存できます。
    表示にはGhostViewやAdobe Illustratorが使えます。Adobe Acrobatを使うと、PDFファイルにも変換できます。

注:読み込むファイルの種類は、TkPlot.iniの
            FileMask=(.*\.int$|.*\.pat$)
   で指定できます。FileMaskの指定は正規表現であることに注意してください。
   Windowsでファイルを指定する際のワイルドカードは、
            * (あらゆる文字列) は .*
            ? (あらゆる一文字)は .
            .  (ピリオド)は \.
  で指定します。
    また、^はファイル名の先頭、$は最後を意味します。
    全体を()で囲って、|で分離すると、複数のファイルマスクを指定できます。
    上の例( FileMask=(.*\.int$|.*\.pat$) )では、ワイルドカードで、*.int と *.pat を指定していることになります。


TkPlot.plへの対応ファイルの追加

下記の仕様のデータ処理用Perlモジュールを、$TKPLOTDIR/dlibに保存することで、TkPlot.plが扱えるデータを拡張することができます。
($TKPLOTDIR/dlib/TkTest.pmを参考のこと)
 

  1. データ処理モジュールを$TKPLOTDIR/dlibに作ります。モジュールファイル名は必ず "Tk" から始まり、モジュール名 + ".pm" とします。
    たとえば、XXDataのデータを処理する場合、モジュール名は"TkXXData"、モジュールファイル名は "TkXXData.pm"です。
     
  2. 下記のうち、【必須ではない】と書かれているものは、基本的な動作をする関数がMyTk::TkDataに定義されているので、特別な処理をする場合以外は必須ではありません。
     
  3. 【必須】TkXXData.pmは、MyTk::TkDataの継承クラスとします。
    use以下は、必要なモジュールをロードしています(use stict以外は、$TKLIBDIR以下にあります)。
     
        package TkXXData
        use MyTk::TkData;
        @ISA = qw(TkData);

        use strict;
        use Utils;
        use MyTk::GraphFrameArray;
        use GraphData;

     
  4. 【必須】ファイルタイプをチェックするサブルーチン CheckFileType を追加します。
      (CheckFileTypeは静的メンバー関数なので、TkXXData::CheckFileType($filename) として呼び出す必要があります)
    CheckFileType では、ファイル名$filenameを受け取り、そのファイルがXXData.pmで処理するファイルであれば、そのタイプを文字列で返します。
    対応しない場合、undefを返します。
     
    sub CheckFileType
    {
        my ($path) = @_;
    # パス名をドライブ、ディレクトリィ、拡張子つきファイル名、拡張子、最後のディレクトリィ名、
    # 拡張子なしのファイル名に分解する
        my ($drive, $dir, $filename, $ext, $lastdir, $filebody)
                = Deps::SplitFilePath($path);

    # ファイル名、拡張子名、ファイルの内容などからファイルタイプを判断し、
    # 対応するファイルタイプであれば、ファイルタイプを文字列で返す
        if($ext =~ /^\.test$/i) {
            return "Test data file";
        }
        # 対応しないファイルタイプであれば、undefを返す
        return undef;

    }
     
  5. 【必須】次のメンバー関数を定義します。
     
    #コンストラクタ(new)は、アプリケーションオブジェクトとCanvasウィジェットオブジェクトを受け取り、保存します。
        sub new
        {
            my ($module, $app, $canvas) = @_;
            my $this = {};
            bless $this;
            $this->SetApplication($app);
            $this->SetCanvas($canvas);
            return $this;
        }
    #デストラクタ
        sub DESTROY
        {
            my $this = shift;
            $this->SUPER::DESTROY(@_);
        }
  6. 【必須】データを読み込むサブルーチンReadを追加します。ファイル名$filenameを受け取り、
      ファイルタイプを $this->{'FileType'} に保存
      ファイル名をSetFileNameで保存
    し、データを読み込みます。
     対応していないファイルタイプの場合、undefを返します。
      
        sub Read
        {
    # Readはファイル名$filenameのみを引数として受け取る($thisは自分自身のオブジェクトへのリファレンス)
            my ($this, $filename) = @_;
    # 初期化(お約束)
            $this->ClearAll();

    # CheckFileTypeを呼び出し、ファイルタイプをチェックし、$this->{'FileType'}に格納する
            my $FileType = $this->SetFileType(CheckFileType($filename));
    # 対応するファイルタイプでなければ、undefを返す
            return undef unless($FileType eq "Test data file");

    #ファイルを読み込み用にオープンする
            my $infile = new JFile($filename, "r");
    #オープンに失敗したらundefを返す
            return undef unless($infile);

    #ファイル名を格納
            $this->SetFileName($filename);
    #1行スキップ
            my $line = $infile->ReadLine();

    #X,Yデータ用の配列
            my (@X, @Y);
            for(my $i = 0 ; ; $i++) {
                my $line = $infile->ReadLine();
                last unless(defined $line);
    #print "line: $line\n";
    #X,Yデータを読み込み、配列に格納する
                my ($x, $y) = ($line =~ /(\S+)\s+(\S+)/);
    #print  "i=$i x,y=$x, $y\n";
                $X[$i] = $x;
                $Y[$i] = $y;
        }
        $infile->Close();

    #データはGraphDataArrayオブジェクトのGraphDataオブジェクトとして格納する(お約束)
        $this->SetDataArray(new GraphDataArray);
    #GraphDataオブジェクトを作る(お約束)
        my $Data = new GraphData;
    #GraphDataオブジェクトをGraphDataArrayオブジェクトに追加する(お約束)
        $this->DataArray()->AddGraphData($Data);

    #GraphDataオブジェクトにデータを設定(これらはAssignDataメンバー関数で、グラフ枠のキャプションや
    #データ上のバルーンヘルプの表示利用される
        $Data->SetTitle("Test Data");
        $Data->SetXCaption("X Axis");
        $Data->SetYCaption("Y Axis");
        $Data->{"x0_Name"} = "X0 Data";
        $Data->{"y0_Name"} = "Y0 Data";

    #GraphDataオブジェクトにX,Yデータの配列を設定する。
    #要素名を"x0"、"y?" (?は0からの連番)にすると、AssignDataメンバー関数で自動的にグラフ表示用の
    #X,YデータにAssignされる。
    #AssignData関数を自分で作る場合、要素名は自由に決めて構わない
        $Data->{"x0"} = \@X;
        $Data->{"y0"} = \@Y;

    #GraphDataのデータ("x?","y?")の最大値、最小値を計算する
        $Data->CalMinMax();

        return 1;
    }
      
  7. 最低限、以上の関数を作るだけで動作します。
     
  8. 複雑なデータを読み込む場合、複雑なグラフを作る場合は、次のメンバー関数を作ります。
     
  9. 【単純なグラフの場合、必須ではない】 グラフ枠を作るメンバー関数
     
        sub CreateGraphFrame
        {
            my ($this, $canvas) = @_;
    #各パラメータの設定
            $this->SetCanvas($canvas) if($canvas);
            $canvas = $this->Canvas() unless($canvas);
            my $App = $this->App();
            my $font = $App->{'GraphFrameFont'};
            my @font = split(/,/, $font) if($font);
            my $w = $canvas->width();
            my $h = $canvas->height();
            my $FileType = $this->FileType();
     
    # GraphFrameArrayを作り、$this->{'GraphFrameArray'}に格納する
            my $GraphFrameArray = $this->{'GraphFrameArray'}
                    = new GraphFrameArray($this->mw(), $canvas);
    # GraphFrameArrayにCanvasの大きさを設定する
            $GraphFrameArray->SetCanvasSize($w, $h);
     
    #グラフ枠を一つ作り、$GraphFrame0に受け取る
            $GraphFrameArray->AddGraphFrame();
            my $GraphFrame0 = $GraphFrameArray->GetGraphFrame(0);
    #TkPlot.iniから、0番のグラフ枠のサイズを受け取り、設定する
            my $FramePosStr0 = $App->{"GraphFrame0Position"};
            $GraphFrame0->SetPositionByStr($FramePosStr0);
    # $GraphFrame0のX軸、Y軸目盛りオブジェクトを取得する
            my $XScale0 = $GraphFrame0->GetXScale(0);
            my $YScale0 = $GraphFrame0->GetYScale(0);
    #X,Y軸のキャプションを設定する。
            $GraphFrame0->SetXCaption("Energy");
            $GraphFrame0->SetYCaption('PDOS');
    #$GraphFrame0の表示値範囲を初期化する
            $GraphFrame0->SetViewRange(0, 0, 1, 1);
        }
     
  10. 【単純なグラフの場合、必須ではない】 XXData->Read()で読み込んだデータ配列を、グラフ表示するデータに関連付けます
     
        sub AssignGraphData
        {
            my ($this) = @_;
    #グラフ枠配列を$GraphFrameArrayに取得します。
            my $GraphFrameArray = $this->GetGraphFrameArray();
    #最初のグラフ枠を$GraphFrame0に取得します。
            my $GraphFrame0 = $GraphFrameArray->GetGraphFrame(0);

    #XXData->Read()で読み込んだデータを、DataArray()から受け取ります
        my $pDataArray = $this->DataArray();
    #DataArrayから、最初のデータを取得します。
        my $Data = $pDataArray->GetGraphData(0);
    #$Dataにあるデータ数を取得します
        my $nData = $Data->nData();
    #$Dataの名前を取得します
        my $title = $Data->Title();

    #$Dataから、'x0'の要素のデータ配列のリファレンスを取得します
        my $pX0 = $Data->GetDataArray('x0');
     
    #$Dataから、'y?'の要素のデータ配列のリファレンスを取得し、X,Y軸データの組として
    #$GraphFrame0に追加します
        for(my $i = 0 ; $i<$nData ; $i++) {
            my $pY = $Data->GetDataArray("y$i");
            last unless($pY);
    #X,Y軸データの組として$GraphFrame0に追加します
    #引数は順番に、
    #  Xデータ配列のリファレンス、Yデータ配列のリファレンス、
    #    データ線幅、データ線色、
    #    シンボル型、シンボルサイズ、シンボル色、シンボル線幅、シンボル線色、
    #    オプション("XAutoSkip"で、画面の解像度に合わせてXデータを間引きする)、
    #    X軸の名前、Y軸の名前
            my $nData = $GraphFrame0->AddGraphData($pX0, $pY, 
                        1, "auto", 
                        "", 6, "red", 0, "red", 
                        "XAutoSkip",
                        "Energy", $Data->{"y${i}_Name"});
        }
     
    # 必要であれば、$GraphFrame0のX,Yキャプションを再設定する
    #  (CreateGraphFrameでも設定しているので、やらなくてもいい)
        $GraphFrame0->SetXCaption($Data->{"x0_Name"});
        $GraphFrame0->SetYCaption('PDOS');
     
    # $GraphFrame0内にあるデータの最大・最小値を計算
        $GraphFrame0->CalMinMax();
    # $GraphFrame0の表示範囲を設定する
        $GraphFrame0->AdjustViewRange(0.05, 0.05, 0.05, 0.05);

    # 必要があれば、データ種独自の表示範囲設定サブルーチンを呼び出す
        $this->AdjustViewRange();
    }
     
  11. 【必須ではない】データ種独自の表示範囲を設定するメンバー関数AdjustViewRange を作成する
    以下のサブルーチンでは、何もしません。
    たとえば、2つのグラフ枠がある場合に、X軸を同期させたいときなどに使います。
    TkPlot.pl内で表示範囲がリセットされたときに呼び出されます。
    以下の例では、何もしていません。例としては$TKPLOTDIR/dlib/TkRietan.pmを参考のこと。
     
        sub AdjustViewRange
        {
            my ($this) = @_;
            my $GraphFrameArray = $this->GetGraphFrameArray();
            my $pGraphFrame = $GraphFrameArray->GetpGraphFrameArray();
            my ($xmin, $xmax) = $pGraphFrame->[0]->GetViewXRange();
        }
     
  12. 【必須ではない】グラフ描画サブルーチンDrawを作成します。
    通常のグラフを表示するのであれば、初期化作業をした後$GraphFrameArray->Draw()を呼び出すだけですが、
    複雑なグラフを書く場合、ここに描画ルーチンを追加します。例としては$TKPLOTDIR/dlib/TkDVXa.pmを参考のこと。
     
        sub Draw
        {
            my ($this, $canvas) = @_;
    #各変数の設定
            $this->SetCanvas($canvas) if($canvas);
            $canvas = $this->Canvas() unless($canvas);
            my $mw = $this->mw();
            my $GraphFrameArray = $this->GetGraphFrameArray();
            my $pGraphFrame = $GraphFrameArray->GetpGraphFrameArray();

            my @GraphFrame = @$pGraphFrame;
            my $App = $this->App();
            my $font = $App->{'GraphFrameFont'};
            my @font = split(/,/, $font) if($font);
            my $w = $canvas->width();
            my $h = $canvas->height();

    #フォントの設定
            if($font) {
                $canvas->SetFont(\@font);
                $GraphFrameArray->SetFont(\@font);
            }
     
    #現在のCanvasサイズを設定します。
            $GraphFrameArray->SetCanvasSize($w, $h);
     
    #Balloonをリセットします(機能していないみたい??)
            $this->mw()->Balloon()->detach($canvas);
    #$GraphFrameArrayを描画します。
            $GraphFrameArray->Draw($canvas);
     
    #必要であれば、$GraphFrameArrayで描画できない描画ルーチンを書きます
     
        }
     
  13. 【必須ではない】 メインウィンドウの左(--verticalオプションを指定した場合は上)ペインに、ウィジェットを追加できます。
     ウジェットは引数で渡されたフレームウィジェット$Frameの下に作ります。
     まず、ウジェットを追加するサブルーチンを追加します。
     この例では、Textウィジェットを追加することを考えています。
     
        sub AddWidget
        {
            my ($this, $Frame) = @_;
            return undef unless($Frame);

    #メインウィンドウの更新を抑止する
            $this->mw()->packPropagate(0);

            $this->{'FileContentText'} = $Frame->Scrolled(
                    'MyText', -height => 3, -scrollbars => 'e',
                )->pack(-side => 'top', -expand => 'yes', -fill => 'both');

    #メインウィンドウの更新を再開する
            $this->mw()->packPropagate(1);
            return 1;
        }
     
  14. 【必須ではない】 次に、別のデータを読み込んだときの初期化のために、作成したウィジェットを削除する関数を追加します。
     
        sub DeleteWidget
        {
            my ($this, $Frame) = @_;
            return undef unless($Frame);

    #すでにTextウィジェットを作っていたら、削除する
            if($this->{'FileContentText'}) {
                $this->{'FileContentText'}->packForget();
                $this->{'FileContentText'}->destroy();
            undef $this->{'FileContentText'};
            }
            return 1;
        }
     
  15. 【必須ではない】 データを読み込んだときに、左ペインのファイル内容セクションリストボックス、テキストボックスへの追加ができます。
    セクションリストボックスを使う例としては、$TKPLOTDIR/dlib/VASP.pmを参考のこと。
     OUTCARを読み込んだとき、セクションリストボックスに選択肢を追加しています。
     セクションリストボックスの選択肢が変更されると、ファイル名と選択された文字列を引数としてRead関数が呼び出されます。
    ファイル内容テキストボックスを使う例としても、$TKPLOTDIR/dlib/VASP.pmを参考のこと。
     ファイルを読み込んだ後、テキストボックスにデータの数値を表示しています。
     
        sub SetFileInfo
        {
            my ($this, $ListBox, $TextBox) = @_;
            return undef unless($ListBox);
            return undef unless($TextBox);
    #リストボックス、テキストボックスをクリアー
            $ListBox->ClearAll();
            $TextBox->ClearText();

        my $App = $this->App();
    #フォント設定
        my @Font = split(/,/, $App->{"FileContentFont"});
        $TextBox->configure(-font => \@Font) if(@Font > 0);
    #Tk用モジュールオブジェクトを取得
        my $DataArray = $App->{'DataArray'};
        return undef unless($DataArray);

    #TkモジュールオブジェクトからPlotDataオブジェクトを取得
        my $pDataArray = $DataArray->DataArray();
        return undef unless($pDataArray);

    #最初のデータはPlotData->GetGraphData(0)で取得できる
        my $Data = $pDataArray->GetGraphData(0);
        return undef unless($Data);

        my $nData = $Data->nData();
        my $title = $Data->Title();

        $TextBox->AddText("Title: $title\n");
        $TextBox->AddText("$nData\n");
    #Xデータ配列の数を取得
        my $nX = $Data->nXColumn();
    #Yデータ配列の数を取得
        my $nY = $Data->nYColumn();
        for(my $i = 0 ; $i < $nData ; $i++) {
            my $str = "";
            for(my $j = 0 ; $j < $nX ; $j++) {
    #$j番目のXデータ配列の$i番目のデータを取得
            my $nY = $Data->nYColumn();
                my $x = $Data->x($j, $i);
                next unless(defined $x);
                $str = "$str\t$x";
            }
            for(my $j = 0 ; $j < $nY ; $j++) {
    #$j番目のYデータ配列の$i番目のデータを取得
                my $y = $Data->y($j, $i);
                next unless(defined $y);
                $str = "$str\t$y";
            }
            $TextBox->AddText("$str\n");
        }
        return 1;
    }

 データ処理モジュールのメンバー関数からは、たとえば
                $this->App()
でアプリケーションオブジェクト、
                $this->mw()
でメインウィンドウオブジェクトが取得できるので、Perl/Tkの機能を使えば、あらゆる操作が可能なはずです。


その他

GPIBシミュレートデモ

 TkPlotディレクトリィのGPIBTest.batを実行。
「Choose」ボタンで保存するデータファイル名を選び、「Start」ボタンを押すだけ。

 ただ、問題があり、Perl/TkのCanvasの内部構造では、作ったウィジェットやアイテム(線や円などの図形)をsigned integerの連番で管理しているようで、不要なアイテムを削除しても、作ったアイテムが累積3万2千個ていどになると強制終了してしまいます。今のプログラムでは、1点測定するごとにアイテムを全部削除して作り直しているので、800点程度測ってグラフを書き直すと(1/2*n*(n+1)~3万2千で勘定が合う)、強制終了します。

 これを直すのは結構大変なので、測定点が多い場合は、10点ごとに書き直すとかの工夫が必要そうです。

 GPIBTestのモジュールは、TkPlot/clib/TkGPIBTest.pmです。

必要なことは、

だけです。ただ、StartButton()内でループをまわすと、ウィンドウがすべて応答しなくなるので、実際にはafter($itime)を使って、$itimeごとに測定・再描画ルーチンMeasure()を呼び出しています。

 

インストールスクリプトについて

を適当なディレクトリィの下にコピーしてください。

 インストールについては、上記のPerlディレクトリィにある

を参考にしてください。

 すでにPerlがインストールされている場合でも、最低、Jcodeモジュールをインストールする必要があります。Windowsの場合、TkPlot/setup.batを起動すると、ppmを使ってJcode, Math::Matrix, Math::MatrixRealを自動的にインストールし、上記のlib,TkPlotディレクトリィをモジュール検索パスに追加します。ですから、基本的に、setup.batを実行するだけで使えるはずです。その後は、RietPlot.batなどから起動する際に毎回、モジュール検索パスをupdateします。 

 そのため、次回からは、TkPlotをupdateしたり、ディレクトリィを変えても、setup.batを実行する必要はありません。

 linuxの場合は、モジュールを手動でインストールしてください。上記の3つはCPANにあります。その後は、sh setup をするようになっていますが、実際に行っているのは、*Plot,*Viewのスクリプトにchmod +xをしているだけです。RietPlotなどのスクリプトは、TkPlot.plのモジュール検索パスをupdateしたのち、TkPlot.plを実行しています。