#=============================================== # TkCRYSTAL06 #=============================================== package TkCRYSTAL06; use Crystal::CRYSTAL06; use TkPlotModule; @ISA = qw(CRYSTAL06 TkPlotModule); #公開したいサブルーチン #@EXPORT = qw(DelSpace Reduce01 MakePath RegExpQuote); use strict; use Utils; use MyTk::GraphFrameArray; use MyTk::BandGraphFrameArray; use MyTk::EnergyLevelGraphFrameArray; use GraphData; #============================================================ # 変数等取得、再定義関数 #============================================================ #============================================================ # コンストラクタ、デストラクタ #============================================================ sub new { my ($module, $app) = @_; # my ($module, $app, $canvas) = @_; my $this = {}; bless $this; $this->SetApplication($app); # $this->SetCanvas($canvas); return $this; } sub DESTROY { my $this = shift; $this->SUPER::DESTROY(@_); } #============================================================ # 継承クラスで定義しなおす関数 #============================================================ sub CheckFileType { my ($path) = @_; return CRYSTAL06::CheckFileType($path); } sub Read { my ($this, $filename, $TargetData) = @_; my $s = ''; if($TargetData) { $s = " for $TargetData"; # return $this->Draw(undef, $TargetData); } my $App = $this->App(); $this->mw()->WriteStatusBar("Reading $filename$s..."); my $ret = $this->ReadFiles($filename, $TargetData); $this->mw()->WriteStatusBar("Finish reading $filename$s..."); $App->print(" Finish reading $filename$s...\n"); } sub CreateGraphFrame { my ($this, $canvas, $TargetData) = @_; $canvas = $this->Canvas($canvas); # $this->SetCanvas($canvas) if($canvas); # $canvas = $this->Canvas() unless($canvas); my $App = $this->App(); my $pDataArray = $App->TkData(); my $font = $App->{'GraphFrameFont'}; my @font = split(/,/, $font) if($font); my $w = $canvas->width(); my $h = $canvas->height(); my $FileType = $this->FileType(); $TargetData = $pDataArray->{'TargetData'} unless(defined $TargetData); if($FileType eq "CRYSTAL06 DOS file") { my $GraphFrameArray = $this->{'GraphFrameArray'} = new GraphFrameArray($this->mw()); $GraphFrameArray->SetCanvasSize($w, $h); $GraphFrameArray->AddGraphFrame(); my $GraphFrame0 = $GraphFrameArray->GetGraphFrame(0); my $FramePosStr0 = $App->{"GraphFrameDOS0Position"}; my $XScale0 = $GraphFrame0->GetXScale(0); my $YScale0 = $GraphFrame0->GetYScale(0); $GraphFrame0->SetPositionByStr($FramePosStr0); $GraphFrame0->SetXCaption("Energy / eV"); $GraphFrame0->SetYCaption(""); $XScale0->SetScaleStringVisible(1); $XScale0->SetCaptionVisible(1); $GraphFrame0->SetViewRange(0, 0, 1, 1); my $nDOS = 1; if($nDOS > 1) { $GraphFrameArray->AddGraphFrame(); my $GraphFrame1 = $GraphFrameArray->GetGraphFrame(1); my $FramePosStr1 = $App->{"GraphFrameDOS1Position"}; my $XScale1 = $GraphFrame1->GetXScale(0); my $YScale1 = $GraphFrame1->GetYScale(0); $GraphFrame1->SetPositionByStr($FramePosStr1); $GraphFrame1->SetXCaption(""); $GraphFrame1->SetYCaption('DOS'); $XScale1->SetScaleStringVisible(0); $XScale1->SetCaptionVisible(0); $GraphFrame1->SetViewRange(0, 0, 1, 1); $GraphFrameArray->SetShowScaleDialogCallback( sub { $this->ShowScaleDialog(@_) } ); } } elsif($FileType eq "CRYSTAL06 BAND file") { my $GraphFrameArray = $this->{'GraphFrameArray'} = new BandGraphFrameArray($this->mw()); $GraphFrameArray->SetCanvasSize($w, $h); #print "GFA1:$GraphFrameArray\n"; $GraphFrameArray->AddGraphFrame(); my $GraphFrame0 = $GraphFrameArray->GetGraphFrame(0); my $FramePosStr0 = $App->{"GraphFrame0Position"}; my $XScale0 = $GraphFrame0->GetXScale(0); my $YScale0 = $GraphFrame0->GetYScale(0); $GraphFrame0->SetPositionByStr($FramePosStr0); $GraphFrame0->SetXCaption("k"); $GraphFrame0->SetYCaption("Energy / eV"); $XScale0->SetScaleStringVisible(1); $XScale0->SetCaptionVisible(1); $GraphFrame0->SetViewRange(0, 0, 1, 1); } elsif($FileType eq "CRYSTAL06 OUTPUT file") { my $GraphFrameArray; if(defined $TargetData and $TargetData eq 'EnergyLevels') { $GraphFrameArray = $this->{'GraphFrameArray'} = new EnergyLevelGraphFrameArray($this->mw()); $GraphFrameArray->SetCanvasSize($w, $h); } else { $GraphFrameArray = $this->{'GraphFrameArray'} = new GraphFrameArray($this->mw()); $GraphFrameArray->SetCanvasSize($w, $h); } $GraphFrameArray->AddGraphFrame(); my $GraphFrame0 = $GraphFrameArray->GetGraphFrame(0); my $FramePosStr0 = $App->{"GraphFrame0Position"}; #print "FramePosStr0 = $FramePosStr0\n"; $GraphFrame0->SetPositionByStr($FramePosStr0); my $XScale0 = $GraphFrame0->GetXScale(0); my $YScale0 = $GraphFrame0->GetYScale(0); if(!$TargetData or $TargetData eq 'EnergyConvergence') { $GraphFrame0->SetXCaption("Cycle"); $GraphFrame0->SetYCaption('Energy / eV'); $GraphFrame0->SetYScalePlotType('log(|x|)'); } elsif(defined $TargetData and $TargetData eq 'ForceConvergence') { $GraphFrame0->SetXCaption('Cycle'); $GraphFrame0->SetYCaption('RMS Force / eV/Angstrom'); } elsif(defined $TargetData and $TargetData eq 'EnergyLevels') { $GraphFrame0->SetXCaption("Cycle"); $GraphFrame0->SetYCaption('Energy / eV'); $XScale0->SetScaleStringVisible(0); $XScale0->SetCaptionVisible(0); } $GraphFrame0->SetViewRange(0, 0, 1, 1); } else { my $GraphFrameArray = $this->{'GraphFrameArray'} = new GraphFrameArray($this->mw()); $GraphFrameArray->SetCanvasSize($w, $h); } } sub ShowScaleDialog { my ($this, $GraphFrame, $command, $Title, @a) = @_; #$command: "XScale" "YScale" #最初の4つのundefはViewRangeに現在値を使う #次の2つのundefはPlotTypeに現在値を使う設定 #そのあとの1,0は、X,Y軸のPlotTypeの同期をおこなうかどうか #最後の1は、ScaleDialogでOKを押されたらグラフの再描画を行う #  Y軸のViewRangeは同期するが、PlotTypeの同期は無視する return $GraphFrame->ShowScaleDialog($Title, undef, undef, undef, undef, undef, undef, 1, 0, 1); } sub AssignGraphData { my ($this) = @_; my $GraphFrameArray = $this->GetGraphFrameArray(); my $GraphFrame0 = $GraphFrameArray->GetGraphFrame(0); my $pDataArray = $this->DataArray(); my $FileType = $this->FileType(); my $TargetData = $pDataArray->{'TargetData'}; return unless($pDataArray); if($FileType eq "CRYSTAL06 DOS file") { my $Data0 = $pDataArray->GetGraphData(0); my $nDOS = 1; my $GraphFrame1; my $Data1; if($nDOS > 1) { $GraphFrame1 = $GraphFrameArray->GetGraphFrame(1); $Data1 = $pDataArray->GetGraphData(1); return unless($Data1); } my $nData = $Data0->nData(); my $title = $Data0->Title(); for(my $i = 0 ; ; $i++) { my $pX0 = $Data0->GetDataArray("x$i"); last if(not defined $pX0); my $pY0 = $Data0->GetDataArray("y$i"); last if(not defined $pY0); my $nData0 = $GraphFrame0->AddGraphData($pX0, $pY0, 1, "auto", "", 6, "red", 0, "red", "XAutoSkip", $Data0->{"x${i}_Name"}, $Data0->{"y${i}_Name"}); if($nDOS > 1 and $i == 0) { my $pX1 = $Data1->GetDataArray("x$i"); my $pY1 = $Data1->GetDataArray("y$i"); my $nData1 = $GraphFrame1->AddGraphData($pX1, $pY1, 1, "auto", "", 6, "red", 0, "red", "XAutoSkip", $Data1->{"x0_Name"}, $Data1->{"y0_Name"}); } } $GraphFrame0->SetYScalePlotType('x'); $GraphFrame0->CalMinMax(); $GraphFrame0->AdjustViewRange(0.05, 0.05, 0.05, 0.05); if($nDOS == 1) { $GraphFrame0->SetXCaption("Energy / eV"); $GraphFrame0->SetYCaption('DOS'); } else { $GraphFrame1->SetYScalePlotType('x'); # $GraphFrame1->SetXCaption("Energy / eV"); # $GraphFrame1->SetYCaption('Ne'); $GraphFrame1->CalMinMax(); $GraphFrame1->AdjustViewRange(0.05, 0.05, 0.05, 0.05); $GraphFrame0->AddSynchronousFrame('x', $GraphFrame1); $GraphFrame1->AddSynchronousFrame('x', $GraphFrame0); # $GraphFrame0->AddSynchronousFrame('y', $GraphFrame1); # $GraphFrame1->AddSynchronousFrame('y', $GraphFrame0); # $GraphFrame0->SetYScalePlotType('x'); } } elsif($FileType eq "CRYSTAL06 BAND file") { my @GraphFrame; for(my $id = 0 ; ; $id++) { $GraphFrame[$id] = $GraphFrameArray->GetGraphFrame($id); last unless($GraphFrame[$id]); my $Data = $pDataArray->GetGraphData($id); my $pX0 = $Data->GetDataArray('x0'); my $linecolor; $linecolor = 'black' if($id == 0); $linecolor = 'red' if($id == 1); for(my $i = 0 ; ; $i++) { my $pY = $Data->GetDataArray("y$i"); last unless($pY); my $nData = $GraphFrame[$id]->AddGraphData($pX0, $pY, 1, $linecolor, "", 6, "red", 0, "red", "XAutoSkip", $Data->{"x0_Name"}, $Data->{"y${i}_Name"}); my $data = $GraphFrame[$id]->GetPlotData($nData-1); } $GraphFrame[$id]->CalMinMax(); $GraphFrame[$id]->AdjustViewRange(0.05, 0.05, 0.05, 0.05); $GraphFrame[$id]->{'pBandBoundaryDistances'} = $pDataArray->{'pBandBoundaryDistances'}; $GraphFrame[$id]->{'pBandBoundaryPositions'} = $pDataArray->{'pBandBoundaryPositions'}; $GraphFrame[$id]->{'pKPointName'} = $pDataArray->{'pKPointNameArray'}; } if($GraphFrame[1]) { $GraphFrame[0]->AddSynchronousFrame('x', $GraphFrame[1]); $GraphFrame[0]->AddSynchronousFrame('y', $GraphFrame[1]); $GraphFrame[1]->AddSynchronousFrame('x', $GraphFrame[0]); $GraphFrame[1]->AddSynchronousFrame('y', $GraphFrame[0]); } } elsif($FileType eq "CRYSTAL06 OUTPUT file") { return unless($pDataArray); my $Data = $pDataArray->GetGraphData(0); return unless($Data); my $nData = $Data->nData(); my $title = $Data->Title(); my $pX0 = $Data->GetDataArray('x0'); for(my $i = 0 ; ; $i++) { my $pY = $Data->GetDataArray("y$i"); last unless($pY); if($TargetData eq 'EnergyLevels') { } else { my $nData = $GraphFrame0->AddGraphData($pX0, $pY, 1, "auto", "", 6, "red", 0, "red", "XAutoSkip", $Data->{"x0_Name"}, $Data->{"y${i}_Name"}); } } if($TargetData =~ /EnergyConvergence/i) { $GraphFrame0->SetYScalePlotType('log(|x|)'); # $GraphFrame0->SetYScalePlotType('x'); $GraphFrame0->SetXCaption("Cycle"); $GraphFrame0->SetYCaption('Energy / eV'); } elsif($TargetData =~ /ForceConvergence/i) { $GraphFrame0->SetYScalePlotType('x'); $GraphFrame0->SetXCaption("Cycle"); $GraphFrame0->SetYCaption('Force / eV/Angstrom'); } else { $GraphFrame0->SetXCaption("Cycle"); $GraphFrame0->SetYCaption('Energy / eV'); } $GraphFrame0->CalMinMax(); $GraphFrame0->AdjustViewRange(0.05, 0.05, 0.05, 0.05); } $this->AdjustViewRange(); } sub AdjustViewRange { my ($this) = @_; my $GraphFrameArray = $this->GetGraphFrameArray(); my $pGraphFrame = $GraphFrameArray->GetpGraphFrameArray(); my $FileType = $this->FileType(); if($FileType eq "VASP DOSCAR file") { } elsif($FileType eq "VASP EIGENVAL file") { # my $GraphFrameArray = $this->GetGraphFrameArray(); # my $GraphFrame0 = $GraphFrameArray->GetGraphFrame(0); # my ($xmin, $xmax) = $GraphFrame0->GetViewXRange(); # my ($ymin, $ymax) = $GraphFrame0->GetViewYRange(); # for(my $id = 1 ; ; $id++) { # my $GraphFrame = $GraphFrameArray->GetGraphFrame($id); # last unless($GraphFrame); # $GraphFrame->SetViewRange($xmin, $ymin, $xmax, $ymax); # } } } sub Draw { my ($this, $canvas, $TargetData) = @_; my $mw; my $GraphFrameArray; my $App = $this->App(); my $font = $App->{'GraphFrameFont'}; my @font = split(/,/, $font) if($font); #TargetDataが指定されていたらOUTCARを読み込みなおす if($TargetData) { $this->DataArray()->{'TargetData'} = $TargetData; print "Read for $TargetData\n"; $canvas->ClearAll(); $this->mw()->RefleshCanvas(); #変数の再取得 $mw = $this->mw(); $canvas = $this->Canvas(); $this->ReadFiles($this->FileName(), $TargetData); $this->CreateGraphFrame($canvas, $TargetData); $this->AssignGraphData(); $this->SetFileInfo($this->{'SectionListbox'}, $this->{'FileContentText'}); } $canvas = $this->Canvas($canvas); $mw = $this->mw(); $GraphFrameArray = $this->GetGraphFrameArray(); if($font) { $canvas->SetFont(\@font); $GraphFrameArray->SetFont(\@font); } my $w = $canvas->width(); my $h = $canvas->height(); $GraphFrameArray->SetCanvasSize($w, $h); my $pGraphFrame = $GraphFrameArray->GetpGraphFrameArray(); my @GraphFrame = @$pGraphFrame; my $pDataArray = $this->DataArray(); my $pData = $pDataArray->GetGraphData(0); $TargetData = $pDataArray->{'TargetData'} unless($TargetData); my $FileType = $this->FileType(); #DOS if($FileType eq "CRYSTAL06 DOS file") { $mw->RefleshCanvas(); $mw->WriteStatusBar("Drawing DOS..."); $mw->Balloon()->detach($canvas); $GraphFrameArray->Draw($canvas); $this->mw()->WriteStatusBar("Finish Drawing DOS."); return; } #Band if($FileType eq "CRYSTAL06 BAND file") { $mw->RefleshCanvas(); $mw->WriteStatusBar("Drawing VASP Band..."); $mw->Balloon()->detach($canvas); $GraphFrameArray->Draw($canvas); $this->mw()->WriteStatusBar("Finish Drawing VASP Band."); return; } #OUTCAR $this->mw()->Balloon()->detach($canvas); #エネルギー準位をプロット if($TargetData =~ /EnergyLevels/i) { $this->mw()->WriteStatusBar("Drawing Energy Levels..."); return unless($TargetData eq 'EnergyLevels'); $GraphFrameArray->Draw($canvas); $this->mw()->WriteStatusBar("Finish Drawing Energy Levels..."); } else { print("Drawing $TargetData...\n"); $mw->WriteStatusBar("Drawing $TargetData..."); $GraphFrameArray->Draw($canvas); print("Finish Drawing $TargetData...\n"); $mw->WriteStatusBar("Finish Drawing $TargetData..."); } } sub DeleteWidget { my ($this, $Frame) = @_; return undef unless($Frame); return 1; } sub AddWidget { my ($this, $Frame) = @_; return undef unless($Frame); # 左枠3列目作成: ファイルの内容を表示するセクションリストボックス # $this->mw()->CreateSectionListBox(); # 左枠4列目作成: ファイルの内容を表示するテキストボックス # $this->mw()->CreateFileContentTextBox(); return 1; } 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); my $DataArray = $App->TkData(); return undef unless($DataArray); my $GraphFrameArray = $this->GetGraphFrameArray(); my $pGraphFrame = $GraphFrameArray->GetpGraphFrameArray(); my $GraphFrame0 = $pGraphFrame->[0]; my $pDataArray = $DataArray->DataArray(); return undef unless($pDataArray); my $Data = $pDataArray->GetGraphData(0); return undef unless($Data); if($this->FileType() eq "CRYSTAL06 OUTPUT file") { $ListBox->AddItem("EnergyConvergence"); # $ListBox->AddItem("ForceConvergence(RMS)"); # $ListBox->AddItem("ForceConvergence(AtomRange:1-3)"); # $ListBox->AddItem("ForceConvergence"); # $ListBox->AddItem("EnergyLevels"); } my $nData = $Data->nData(); my $title = $Data->Title(); $title = '' unless(defined $title); $TextBox->AddText("Title: $title\n"); $TextBox->AddText("$nData\n"); for(my $i = 0 ; $i < $nData ; $i++) { # my $x = $Data->x($i); my $str = ""; my $nX = $Data->nXColumn(); for(my $j = 0 ; $j < $nX ; $j++) { my $x = $Data->x($j, $i); next unless(defined $x); $x = sprintf("%7.3f", $x); $str = "$str\t$x"; } my $nY = $Data->nYColumn(); for(my $j = 0 ; $j < $nY ; $j++) { my $y = $Data->y($j, $i); next unless(defined $y); $y = sprintf("%9.3f", $y); my $convy = $GraphFrame0->YVal($y); $convy = sprintf("%9.3f", $convy); $str = "$str\t$y($convy)"; } $TextBox->AddText("$str\n"); } return 1; } #============================================================ # 一般関数 #============================================================ sub ConfigureIniFileVariables { my ($this) = @_; my $App = $this->App(); $App->ConfigureIniFileVariables(); my $Style = $App->Args()->GetGetArg("style"); $Style = "General" unless($Style); # $App->AddIniFileVariable("\\$Style\\GraphFrame_Position", "GraphFramePosition", "r0.20,0.80,0.80,0.10"); $App->AddIniFileVariable("\\$Style\\GraphFrameDOS0_Position", "GraphFrameDOS0Position", "r0.20,0.80,0.80,0.45"); $App->AddIniFileVariable("\\$Style\\GraphFrameDOS1_Position", "GraphFrameDOS1Position", "r0.20,0.45,0.80,0.10"); $App->ReadSetting(); } #============================================================ # bind応答関数 #============================================================ 1;