科学計算のためのObject Perlライブラリィ


設計方針


神谷ライブラリィファイル

d:\Programs\Perl\lib

│ Deps.pm                OS/PC依存ルーチン (MS-Win32, Linuxに対応)
│ Utils.pm                汎用ルーチン
│ JFile.pm                汎用ファイルクラス
│    IniFile.pm            初期設定ファイルクラス(MS-Windows Iniファイル形式)
│ MyApplication.pm    アプリケーション基本クラス
│ MyDocument.pm    ドキュメント基礎クラス
│ GetArg.pm            コマンドラインオプション処理クラス
│ MyCGI.pm             CGI汎用ルーチン
│ MyScript.pm         一行スクリプトクラス
│ GraphData.pm        科学データクラス
│ Rect.pm                四角形範囲処理クラス
│ Favorites.pm         (Internet ExplorerのFavoriteクラス)

Crystal::
│ CrystalObject.pm           結晶構造基本クラス
│    Crystal.pm                  結晶構造クラス
│ AtomTypeObject.pm       原子種類基本クラス
│    AtomType.pm              原子種類クラス
│ AtomSiteObject.pm        結晶内原子基本クラス 
│    AtomSite.pm                結晶内原子クラス
│ SpaceGroupObject.pm    空間群基本クラス
│    SpaceGroup.pm            空間群クラス
│ CIFObject.pm                CIFファイル処理基本クラス
│    CIF.pm                         CIFファイルクラス
│ CASTEP.pm                  CASTEPクラス
│ GULP.pm                      GULPクラス
│ LD.pm                          LDクラス
│ MXD.pm                       MXDOrto/MXDTriclクラス
│ PWSCF.pm                   PWScfクラス
│ Rietan.pm                     Rietanクラス
│ TranSIESTA.pm             Virtual Nanolabクラス
│ VASP.pm                      VASPクラス
│ WIEN2k.pm                    WIEN2kクラス
│ XCrySDen.pm                XCrySDenクラス
│ VRML.pm                      VRML 2.0クラス
│ VRML1.pm                     VRML 1.0クラス
│ POVRay.pm                   POV-Rayクラス
│ DiffractionPeak.pm          回折クラス
│ GeneralFile.pm                (ファイル処理汎用クラス)
│ GeneralFileFormat.pm      (ファイルフォーマットクラス)
│ MyUtility.pm                   (汎用ルーチン)
│ Science.pm                    (科学計算クラス)

MyTk::
│ MyTkApplication.pm         Perl/Tkアプリケーションクラス
│    <= MyApplication.pm
│ MyMainWindow.pm           MainWindow widgetラッパークラス
│ MyToplevel.pm                Toplevel widgetラッパークラス
│ MyFrame.pm                   Frame widgetラッパークラス
│ MyAdjuster.pm                Adjuster widgetラッパークラス
│ MyButton.pm                  Button widgetラッパークラス
│ MyLabel.pm                     Label widgetラッパークラス
│ MyEntry.pm                    Entry widgetラッパークラス
│ MyText.pm                     Text widgetラッパークラス
│ MyListbox.pm                  Listbox widgetラッパークラス
│ MyBrowseEntry.pm          BrowseEntry widgetラッパークラス
│ MyCanvas.pm                 Canvas widgetラッパークラス
│ Dialog.pm                        Dialogクラス
│ GraphFrame.pm              グラフ表示枠クラス
│ GraphScale.pm               グラフ目盛クラス
│ TkRietan.pm                   Perl/Tk Rietanクラス
│    <= Crystal::Rietan.pm

Sci::
│ Science.pm                    科学計算クラス


Crystal::ライブラリィサンプルプログラム

Crystal::CIF.pl

内容: CIFファイルを読み込み、結晶情報を表示する
文法: コマンドライン引数にCIFファイル名を与える
  例:  perl CIF.pl BaTiO3.cif
注: Crystalクラスは使っているが、Applicationクラスなどは使っていない。
   標準的なPerlスクリプト形式

=== CIF.pl start =======================================================================
#!/usr/bin/perl

use lib 'd:/Programs/Perl/lib';

use strict;

use Crystal::CIF;
use Crystal::Crystal;

my $LF = "\n";

#CIFクラスを作成
my $cif = new CIF($ARGV[0]);
print "CIF: ", $cif->FileName(), "$LF";
#CIFファイル名を引数に与えて読み込む
$cif->Read($ARGV[0]);

#CIFクラスの内容から、Crystalクラスを作成
#  作成した時点で、Metricsの計算、イオン情報(原子量など)の読み込み、
#  格子体積の計算は終わっている
my $Crystal = $cif->GetCCrystal();

print "$LF";
my $CrystalName = $Crystal->CrystalName();
print "CrystalName: $CrystalName\n";
#格子定数
my ($a,$b,$c,$alpha,$beta,$gamma) = $Crystal->LatticeParameters();
print "cell: $a $b $c $alpha $beta $gamma$LF";
#単位格子の計量成分
my ($g11,$g12,$g13,$g21,$g22,$g23,$g31,$g32,$g33) = $Crystal->Metrics();
print "Metrics: $g11 $g22 $g33 $g12 $g23 $g31$LF";
#単位格子体積
my $vol = $Crystal->Volume();
print "Volume: $vol$LF";

print "$LF";
#Crystalクラスから、SpaceGroupクラスを取り出す
#  この時点で、並進対称要素の抽出、LatticeSystemの抽出は完了している
my $SPG = $Crystal->GetCSpaceGroup();
#空間群の名前
my $SPGName = $SPG->SPGName();
#空間群の設定番号
my $iSPG = $SPG->iSPG();
#格子系の名前
my $LatticeSystem = $SPG->LatticeSystem();
print "Space Group: $SPGName ($iSPG)$LF";
print "Lattice System: $LatticeSystem$LF";

print "$LF";
#並進対称操作の数
my $nTranslation = $SPG->nTranslation();
print "nTranslation: $nTranslation$LF";
#並進対称操作のベクトル
for(my $i = 0 ; $i < $nTranslation ; $i++) {
    my ($x,$y,$z) = $SPG->TranslationVector($i+1);
    print " ($x, $y, $z)$LF";
}

print "$LF";
#並進対称を除いた対称操作の数
my $nSymmetryOperation = $SPG->nSymmetryOperation();
print "nSymmetryOperation: $nSymmetryOperation$LF";
#対称操作の行列表示
for(my $i = 0 ; $i < $nSymmetryOperation ; $i++) {
    my $symop = $SPG->SymmetryOperation($i+1);
    print " $symop$LF";

    my ($x1,$y1,$z1,$t1,
        $x2,$y2,$z2,$t2,
        $x3,$y3,$z3,$t3)
            = $SPG->SymmetryOperationByMatrix($i+1);
    print " $x1 $y1 $z1 $t1$LF";
    print " $x2 $y2 $z2 $t2$LF";
    print " $x3 $y3 $z3 $t3$LF";
}

print "$LF";
#Crystalクラス中の、原子の種類 AtomTypeクラスのリストをとる
my @AtomTypeList = $Crystal->GetCAtomTypeList();
my $nAtomType = @AtomTypeList;
print "nAtomType: $nAtomType$LF";
for(my $i = 0 ; $i < $nAtomType ; $i++) {
#原子種のラベル、名前、原子番号、イオン価数、原子量
    my $label = $AtomTypeList[$i]->Label();
    my $atomname = $AtomTypeList[$i]->AtomName();
    my $charge = $AtomTypeList[$i]->Charge();
    my $AtomicNumber = $AtomTypeList[$i]->AtomicNumber();
    my $AtomicMass = $AtomTypeList[$i]->AtomicMass();
    my $i1 = $i+1;
    print " #$i1: $label : $atomname [$AtomicNumber] ($charge) "
            ."($AtomicMass)$LF";
}

print "$LF";
#Crystalクラス中の、非対称単位中の原子 AsymmetricAtomSiteクラスのリストをとる
my @AtomSiteList = $Crystal->GetCAsymmetricAtomSiteList();
my $nAsymmetricAtomSite = @AtomSiteList;
print "nAsymmetricAtomSite: $nAsymmetricAtomSite$LF";
for(my $i = 0 ; $i < $nAsymmetricAtomSite ; $i++) {
#結晶中の非対称単位中の原子のラベル、原子種名、部分座標、占有率、原子種の番号
    my $label = $AtomSiteList[$i]->Label();
    my $type = $AtomSiteList[$i]->AtomName();
    my ($x,$y,$z) = $AtomSiteList[$i]->Position(1);
    my $occupancy = $AtomSiteList[$i]->Occupancy();
    my $iAtomType = $Crystal->FindiAtomType($type);

    print " $label ($type)[#$iAtomType]: ($x, $y, $z) [$occupancy]$LF";
}

#対称要素を使い、非対称単位中の原子を展開する
#この際、Densityも計算される
$Crystal->ExpandCoordinates();

print "$LF";
#対称操作で展開した全ての原子の情報を配列に格納する
my @ExpandedAtomSiteList = $Crystal->GetCExpandedAtomSiteList();
my $nTotalExpandedAtomSite = $Crystal->nTotalExpandedAtomSite();
#対称操作で展開した全ての原子の多重度を配列に格納する
my @nMultiplicityExpandedAtomSiteList 
        = $Crystal->GetCnMultiplicityExpandedAtomSiteList();
print "nTotalExpandedAtomSite: $nTotalExpandedAtomSite$LF";
for(my $i = 0 ; $i < $nTotalExpandedAtomSite ; $i++) {
#対称操作で展開した原子のラベル、原子種名、部分座標、占有率、
#非対称単位原子の番号($id)、多重度
    my $label = $ExpandedAtomSiteList[$i]->Label();
    my $type = $ExpandedAtomSiteList[$i]->AtomName();
    my ($x,$y,$z) = $ExpandedAtomSiteList[$i]->Position(1);
    my $occupancy = $ExpandedAtomSiteList[$i]->Occupancy();
    my $id = $ExpandedAtomSiteList[$i]->IdAsymmetricAtomSite();
    my $mult = $nMultiplicityExpandedAtomSiteList[$id-1];
    my $i1 = $i+1;
    print " $i1: [$id]$label ($type): ($x, $y, $z) [$occupancy][$mult]$LF";
}

print "$LF";
#X線密度
my $Density = $Crystal->Density();
print "Density: $Density g/cm^3$LF";

#$Crystalをもとに、($nx,$ny,$nz)に展開した超格子の結晶格子$SuperLatticeを作る
#  同時に、格子定数と、全ての原子座標も超格子に展開される
my ($nx,$ny,$nz) = (2,2,2);
$Crystal->CreateSuperLattice($nx,$ny,$nz);
#展開したSuperlatticeのクラスを、$SuperLattice変数に代入する
my $SuperLattice = $Crystal->GetCSuperLattice();

print "$LF";
print "SuplaerLattice $nx x $ny x $nz$LF";
#超格子の格子定数
my ($a,$b,$c,$alpha,$beta,$gamma) = $SuperLattice->LatticeParameters();
print "Cell: $a $b $c $alpha $beta $gamma$LF";

#超格子単位格子内の原子座標を配列に取得する
my @ExpandedAtomSiteList = $SuperLattice->GetCExpandedAtomSiteList();
my $nTotalExpandedAtomSite = $SuperLattice->nTotalExpandedAtomSite();
#超格子単位格子内の原子の多重度を配列に取得する
my @nMultiplicityExpandedAtomSiteList 
            = $SuperLattice->GetCnMultiplicityExpandedAtomSiteList();
print "nTotalExpandedAtomSite: $nTotalExpandedAtomSite$LF";
for(my $i = 0 ; $i < $nTotalExpandedAtomSite ; $i++) {
#超格子内の全ての原子のラベル、原子種名、部分座標、占有率、
#元の単位格子内の原子の番号($id)、多重度
    my $label = $ExpandedAtomSiteList[$i]->Label();
    my $type = $ExpandedAtomSiteList[$i]->AtomName();
    my ($x,$y,$z) = $ExpandedAtomSiteList[$i]->Position(1);
    my $occupancy = $ExpandedAtomSiteList[$i]->Occupancy();
    my $id = $ExpandedAtomSiteList[$i]->IdAsymmetricAtomSite();
    my $mult = $nMultiplicityExpandedAtomSiteList[$id-1];
    my $i1 = $i+1;
    print " $i1: [$id]$label ($type): ($x, $y, $z) [$occupancy][$mult]$LF";
}

exit;

=== CIF.pl end =======================================================================


Crystal::ライブラリィサンプルプログラム2

Crystal::CIF-Object.pl

内容: CIFファイルを読み込み、結晶情報を表示する
文法: コマンドライン引数にCIFファイル名を与える
  例:  perl CIF.pl BaTiO3.cif
注: CIF.plのApplicationクラス試用版
   この場合は返ってプログラムが長くなる
   コマンドライン引数と初期設定ファイルの処理が簡単になっている

=== CIF-Object.pl start ================================================================
#!/usr/bin/perl

#ライブラリィファイルのディレクトリィを指定
use lib 'd:/Programs/Perl/lib';

#必要なパッケージを指定
use MyApplication;
use Crystal::CIF;
use Crystal::Crystal;

use strict;

#===============================================
# Applicationクラス作製
#===============================================
#簡単なプログラムの場合、直接MyApplicationクラスを使ってもいい
my $App = new MyApplication;
#アプリケーション変数の初期化。失敗したら強制終了
exit 1 if($App->Initialize() < 0);

#後でよく使う変数を設定しておく
my $LF = $App->LF();

# 実行プログラム名(デフォルトでは$0から取得)
my $Program = $App->Program();
# アプリケーション名
$App->SetAppName($Program);
# バージョン
my $Version = $App->SetVersion("Ver 0.1");

#===============================================
# 環境設定
#===============================================
my $ProgramPath = $App->SpeculateProgramPath($0);
print "Program Path: $ProgramPath\n";

#Iniファイルの読み込み
#最後の引数を0にすると、IniFileが存在しなくてもエラーがでない
my $IniFile = $App->OpenIniFile($ProgramPath, 0);

#===============================================
# コマンドラインオプションの設定
#===============================================
$App->AddArgument("--help", "--help : Show this help");
# コマンドラインオプション読み込み
exit 1 if($App->ReadArgs() != 1);

# Iniファイル読み込み
&ConfigureIniFileVariables();

#CIFクラスを作成
#CIFファイル名は、$App->GetArg(ファイル番号)で取得できる
my $CIFFile = $App->GetArg(0);
#引数にCIFファイル名が与えられていない場合、Usageを表示して終了
unless($CIFFile) {
    $App->Usage();
    exit 1;
}
#CIFクラスを作成
my $cif = new CIF;
#CIFファイル名を引数に与えて読み込む
unless($cif->Read($CIFFile)) {
#CIFファイルの読み込みに失敗したら終了
    print "Error: Can not read [$CIFFile]\n\n";
    exit 2;
}
print "CIF: ", $cif->FileName(), "$LF";

#メインサブルーチンの実行
&Execute();

exit 0;

#===============================================
# スクリプト終了
#===============================================

#==========================================
# サブルーチン
#==========================================

# IniFileの設定と読み込み
sub ConfigureIniFileVariables
{
#Iniファイル内の記述とアプリケーション変数の関連付け
#  Iniファイルの "\\Section名\\キー名"、$Appクラスのキー変数名($key)、初期値を指定する
#  ここで設定した変数は、ReadSetting()で読み込まれ、SaveSetting()で書き込まれる
#  ReadSetting()で読み込まれた内容は、$App->{$key}に代入される。
#  SaveSetting()では、全ての$keyに対して、$App->{$key}が "\\Section名\\キー名"に保存される
    $App->AddIniFileVariable("\\Preferences\\WorkDir", "WorkDir");
#Iniファイルから、上で設定したセクション/キーの内容を$App変数に読み込む
    $App->ReadSetting();
}

#メインサブルーチンの実行
sub Execute
{
#次の行からサブルーチンの終了までは、CIF.plとまったく同じ

#作成した時点で、Metricsの計算、イオン情報(原子量など)の読み込み、
#格子体積の計算は終わっている
    my $Crystal = $cif->GetCCrystal();

.....(途中略)

    my @ExpandedAtomSiteList = $SuperLattice->GetCExpandedAtomSiteList();
    my $nTotalExpandedAtomSite = $SuperLattice->nTotalExpandedAtomSite();
    my @nMultiplicityExpandedAtomSiteList 
                = $SuperLattice->GetCnMultiplicityExpandedAtomSiteList();
    print "nTotalExpandedAtomSite: $nTotalExpandedAtomSite$LF";
    for(my $i = 0 ; $i < $nTotalExpandedAtomSite ; $i++) {
        my $label = $ExpandedAtomSiteList[$i]->Label();
        my $type = $ExpandedAtomSiteList[$i]->AtomName();
        my ($x,$y,$z) = $ExpandedAtomSiteList[$i]->Position(1);
        my $occupancy = $ExpandedAtomSiteList[$i]->Occupancy();
        my $id = $ExpandedAtomSiteList[$i]->IdAsymmetricAtomSite();
        my $mult = $nMultiplicityExpandedAtomSiteList[$id-1];
        my $i1 = $i+1;
        print " $i1: [$id]$label ($type): ($x, $y, $z) [$occupancy][$mult]$LF";
    }
}
#メインサブルーチンの終了

=== CIF-Object.pl end ================================================================


MyTk::ライブラリィサンプルプログラム

VASPPlot.pl

構成:
  VASPPlot.pl              実行スクリプト
  VASPPlotApp.pm       アプリケーションクラス (MyTkApplicationを継承)
  VASPPlotDoc.pm       ドキュメントクラス (MyDocumentを継承)
  VASPPlotWindow.pm  MainWindowクラス (MyMainWindowを継承)  

実行の仕方: perl VASPPlot.pl

注: Application, Document, MainWindowクラスを使ったGUIアプリケーションの例

=== VASPPlot.pl start ================================================================

#!/usr/bin/perl -w

#神谷ライブラリィのディレクトリィ
use lib 'd:/Programs/Perl/lib';
#VASPPlotApp.pm, VASPPlotDoc.pm, VASPPlotWindow.pmのあるディレクトリィ
use lib 'd:/Programs/Perl/VASPPlot';

use strict;

#VASPPlotApp.pm, VASPPlotDoc.pm, VASPPlotWindow.pmを読み込む
use VASPPlotApp;
use VASPPlotDoc;
use VASPPlotWindow;

#===============================================
# アプリケーションクラスの設定
#===============================================
# アプリケーションクラスの作製
my $App = new VASPPlotApp;
# アプリケーションクラスの初期化。失敗したら終了
exit if($App->Initialize() < 0);

# ルートディレクトリィ
my $BaseDir = "D:\\Programs\\Perl\\VASPPlot";

# 実行プログラムのファイル名を$0から取得する
my $Program = $App->Program();
# アプリケーション名の設定
$App->SetAppName($Program);
# バージョン番号の設定
my $Version = $App->SetVersion("Ver 0.1");
# ウィンドウに表示するタイトルの設定
my $Title = $App->SetTitle("VASPPlot 2005/pl");

#===============================================
# 環境設定
#===============================================
# スクリプトのフルパス名を推定する ($BaseDirは指定しなくてもいい)
my $ProgramPath = $App->SpeculateProgramPath($0, $BaseDir);
print "Program Path: $ProgramPath\n";

# 初期化ファイル(Iniファイル)を設定
my $IniFile = $App->OpenIniFile($ProgramPath, 1);
my $IniFilePath = $App->IniFile()->IniFile();
print "IniFile Path: $IniFilePath\n";

#==========================================
# メインダイアログ作成
#==========================================

# コマンドラインオプションの設定。
#  このプログラムで受け入れるオプション、説明、初期値を設定
    $App->AddArgument("--ReadPrev", "--ReadPrev: Read previous Working Direcotry", 1);
    $App->AddArgument("--vertical", "--vertial : Align panes vertically", 0);
    $App->AddArgument("--help", "--help : Show this help");
# コマンドラインオプションの読み込み。上で設定されていないオプションが与えられたら、終了。
    exit 1 if($App->ReadArgs() != 1);
# Iniファイルから読み書きする変数の設定と実際の読み込み(後ろでサブルーチンを宣言している)
   
&ConfigureIniFileVariables();
# Document, Windowの設定
$App->ConnectDocument(VASPPlotDoc->new());
$App->CreateWindow(VASPPlotWindow->new());

#==========================================
# メインループ
#==========================================
$App->MainLoop();

exit;

#==========================================
# サブルーチン
#==========================================
sub ConfigureIniFileVariables
{
#Iniファイル内の記述とアプリケーション変数の関連付け
#  Iniファイルの "\\Section名\\キー名"、$Appクラスのキー変数名($key)、初期値を指定する
#  ここで設定した変数は、ReadSetting()で読み込まれ、SaveSetting()で書き込まれる
#  ReadSetting()で読み込まれた内容は、$App->{$key}に代入される。
#  SaveSetting()では、全ての$keyに対して、$App->{$key}が "\\Section名\\キー名"に保存される
    $App->AddIniFileVariable("\\Preferences\\WorkDir", "WorkDir");
    $App->AddIniFileVariable("\\Preferences\\EditorPath", "EditorPath", "notepad.exe");
    $App->AddIniFileVariable("\\Window\\geometry", "geometry");
    $App->AddIniFileVariable("\\Window\\vgeometry", "vgeometry");
    $App->AddIniFileVariable("\\Preference\\Debug", "Debug");
    $App->AddIniFileVariable("\\FileContentText\\Font", "FileContentFont", "times,10.5,normal"); 
#Iniファイルから、上で設定したセクション/キーの内容を$App変数に読み込む
    $App->ReadSetting();
}

=== VASPPlot.pl end ================================================================

=== VASPPlotApp.pm start ================================================================

#VASPPlotAppクラスの宣言
package VASPPlotApp;
#MyTk::MyTkApplicationクラスを読み込む
use MyTk::MyTkApplication;
#MyTk::MyTkApplicationクラスを継承することを指定
@ISA = qw(:MyTkApplication);

#お約束
use strict;

BEGIN {
}

#VASPPlotAppクラスの生成メソッド
sub new
{
    my $class = shift;
#上位クラスのnewを呼び出し、クラスを生成する。$selfに自分自身のリファレンスが返る
    my $self = MyTkApplication->new(@_);
#上位クラス($class)の継承を指定して、$selfをVASPPlotAppクラスに結びつける
#  blessからは自分自身のリファレンスが返るので、それをnewメソッドの返り値にする
    return bless $self, $class;
}

#VASPPlotAppクラスの削除メソッド
sub DESTROY
{
    my $this = shift;
#上位クラスの削除メソッドを呼び出す
#終了時に処理をしたい場合、この前に処理を終える
    $this->SUPER::DESTROY(@_);
}

#必ず、パッケージの最後は1を返す (return 1; と同じ)
1;

=== VASPPlotApp.pm end ================================================================

=== VASPPlotDoc.pm start ================================================================

#VASPPlotDocクラスの宣言
package VASPPlotDoc;
#MyTk::MyDocumentクラスを読み込む
use MyDocument;
#MyTk::MyDocumentクラスを継承することを指定
@ISA = qw(MyDocument);

#お約束
use strict;

BEGIN {
}

#VASPPlotAppクラスの生成メソッド、削除メソッドの説明はVASPPlotAppクラスを参照
sub new
{
    my $class = shift;
    my $self = MyDocument->new(@_);
    my $ret = bless $self, $class;
#クラス変数の初期化
    $self->{'GraphFrame.x0'} = 0.0;
    $self->{'GraphFrame.y0'} = 0.0;
    $self->{'GraphFrame.x1'} = 1.0;
    $self->{'GraphFrame.y1'} = 1.0;
    return $ret;
}

sub DESTROY
{
    my $this = shift;
    $this->SUPER::DESTROY(@_);
}

1;

=== VASPPlotDoc.pm end ================================================================

MainWindowクラスは長いので、要約のみ
=== VASPPlotWindow.pm start ============================================================

#VASPPlotWindowクラスの宣言
package VASPPlotWindow;
#MyTk::MyMainWindowクラスを読み込む
use MyTk::MyMainWindow;
#MyTk::MyMainWindowクラスを継承することを指定
@ISA = qw(MyMainWindow);

use strict;
#必要なパッケージを読み込む
use Jcode;
use Tk;
use MyTk::Dialog;
use MyTk::MyFrame;
use MyTk::MyLabel;
use MyTk::MyEntry;
use MyTk::MyListbox;
use MyTk::MyBrowseEntry;
use MyTk::MyText;
use MyTk::MyButton;
use MyTk::MyCanvas;
use MyTk::MyAdjuster;
use OptionDialog;
use MyTk::GraphFrame;

use MyTk::TkRietan;

BEGIN {
}

#VASPPlotAppクラスの生成メソッド、削除メソッドの説明はVASPPlotAppクラスを参照
sub new
{
    my $class = shift;
    my $self = MyMainWindow->new(@_);
    my $this = bless $self, $class;
    $this->protocol('WM_DELETE_WINDOW' => sub { $this->Close(); });
    return $this;
}

sub DESTROY
{
    my $this = shift;
    $this->SUPER::DESTROY(@_);
}

#メニューの作成(MyTkApplication::CreateWindowから呼び出される)
sub CreateMenu
{
    my ($this) = @_;
    $this->{'MenuBar'} = $this->Menu;
    $this->configure(-menu => $this->{'MenuBar'});

    my $FileInfoMenu = [
        [command => '~Environment Vars', 
            -command => sub { Dialog::ShowEnvDialog($this); } ],
        [command => '~Information', 
            -command => sub { $this->App()->ShowInfoDialog($this); } ],
        ];
    my $FileMenu = $this->{'MenuBar'}->cascade(
            -label => 'File',
            -underline => 0,
            -menuitems =>
        [
            [command => '~Option', -command => [\&SetupOption, $this] ],
            [cascade => '~Info', -menuitems => $FileInfoMenu],
            [command => '~Quit', -command => [\&Close, $this] ],
        ]);

    return $this->{'MenuBar'};
}

#メインウィンドウの作成(MyTkApplication::CreateWindowから呼び出される)
sub CreateWidgets
{
    my ($this) = @_;

#アプリケーションクラス、コマンドライン引数クラスを取得。後で利用する
    my $App = $this->App();
    my $args = $App->Args();

# ここから、必要なwidgetを追加する(詳細略)
......

# Iniファイルの内容で、ウィンドウ位置を設定
# VASPPlot.plのConfigureIniFileVariablesにより、$App->{$key}に読み込まれていることに注意
    my $geo = $App->{'geometry'};
# MainWindowの位置、サイズを設定
    $this->SetGeometry($geo);

# ウィンドウサイズが変更されたときに、$this->Drawを実行する
# $this->bind( "<Configure>", [ \&Draw, $this ]);

# グラフ枠などを初期化する(省略)
......

# コマンドラインオプションの処理
#  VASPPlot.plの$App->ReadArgs()ですでに読み込まれていることに注意。
#  引数の値は、$this->GetArg($key)で取得できる。
#  引数がない場合、undefが返ることに注意
    if(defined $this->GetArg("ReadPrev")) {
        my $WorkDir = $App->{'WorkDir'};
#   --ReadPrevオプションが指定された場合、起動時に前回のディレクトリィを読み込む
        $this->ReadDirectory($WorkDir);
    }
#  ファイル名は、$this->GetArg(番号)で取得できる。
    my $filepath = $this->GetArg(0);
    if($filepath) {
        unless(-f $filepath ) {
            print "\nError: $filepath does not exist.\n";
            exit 1;
        }
# ファイル名からフルパス名を推定し、ディレクトリィの設定とファイルの読み込みを行う
        my ($drive, $dir, $filename, $ext, $lastdir, $filebody)
                = Deps::SplitFilePath($filepath );
        $dir = Deps::MakePath($drive, $dir);
        $this->ReadDirectory($dir);
        $this->{'FileListbox'}->SetText($filename);
        $this->ReadFile($filepath );
    }

    return $this;
}

# サブルーチン(省略)
.....

1;

=== VASPPlotWindow.pm end============================================================