#=============================================== # TkWIEN2k #=============================================== package TkWIEN2k; use Crystal::WIEN2k; use TkPlotModule; @ISA = qw(WIEN2k TkPlotModule); #公開したいサブルーチン #@EXPORT = qw(DelSpace Reduce01 MakePath RegExpQuote); use strict; use Utils; use MyTk::GraphFrameArray; 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) = @_; my $FileType = WIEN2k::CheckFileType($path); #print "FileType: $FileType\n"; # return $this->SetFileType($FileType); return $FileType; } sub CreateGraphFrame { my ($this, $canvas) = @_; $canvas = $this->Canvas($canvas); # $this->SetCanvas($canvas) if($canvas); # $canvas = $this->Canvas() unless($canvas); my $mw = $this->mw(); 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(); return undef unless($FileType); my $pDataArray = $this->DataArray(); return unless($pDataArray); # Canvas, GraphFrameの初期化 my $GraphFrameArray = $this->SetGraphFrameArray(new GraphFrameArray($mw)); $GraphFrameArray->SetCanvasSize($w, $h); if($FileType eq "WIEN2k spaghetti Band file") { for(my $i = 0 ; ; $i++) { my $Data = $pDataArray->GetGraphData($i); last unless($Data); $GraphFrameArray->AddGraphFrame(); my $GraphFrame0 = $GraphFrameArray->GetGraphFrame($i); my $FramePosStr0 = $App->{"GraphFramePosition"}; my $XScale0 = $GraphFrame0->GetXScale(0); my $YScale0 = $GraphFrame0->GetYScale(0); $GraphFrame0->SetPositionByStr($FramePosStr0); $GraphFrame0->SetViewRange(0, 0, 1, 1); $GraphFrame0->SetSmoothLine(1); if($i > 0) { $XScale0->SetScaleStringVisible(0); $XScale0->SetScaleVisible(0); $XScale0->SetCaptionVisible(0); $YScale0->SetScaleStringVisible(0); $YScale0->SetScaleVisible(0); $YScale0->SetCaptionVisible(0); $GraphFrameArray->SetShowScaleDialogCallback(sub { $this->ShowScaleDialog(@_) } ); } } } elsif($FileType eq "WIEN2k PDOS files") { my $nGraph = 0; for(my $i = 0 ; ; $i++) { my $Data = $pDataArray->GetGraphData($i); last unless($Data); $GraphFrameArray->AddGraphFrame(); my $GraphFrame0 = $GraphFrameArray->GetGraphFrame($i); my $FramePosStr0 = $App->{"GraphFrame${i}Position"}; $GraphFrame0->SetPositionByStr($FramePosStr0); $GraphFrame0->SetViewRange(0, 0, 1, 1); $nGraph++; } if($nGraph > 1) { my $XScale0 = $GraphFrameArray->GetGraphFrame(0)->GetXScale(0); my $YScale0 = $GraphFrameArray->GetGraphFrame(0)->GetYScale(0); my $XScale1 = $GraphFrameArray->GetGraphFrame(1)->GetXScale(0); my $YScale1 = $GraphFrameArray->GetGraphFrame(1)->GetYScale(0); $XScale0->SetScaleVisible(1); $XScale0->SetScaleStringVisible(0); $XScale0->SetCaptionVisible(0); $YScale1->SetScaleVisible(1); $YScale1->ScaleStringVisible(1); $YScale1->SetCaptionVisible(0); $GraphFrameArray->SetShowScaleDialogCallback(sub { $this->ShowScaleDialog(@_) } ); } } else { $GraphFrameArray->AddGraphFrame(); my $GraphFrame0 = $GraphFrameArray->GetGraphFrame(0); my $FramePosStr0 = $App->{"GraphFramePosition"}; my $XScale0 = $GraphFrame0->GetXScale(0); my $YScale0 = $GraphFrame0->GetYScale(0); $GraphFrame0->SetPositionByStr($FramePosStr0); $GraphFrame0->SetXCaption("Energy"); $GraphFrame0->SetYCaption('PDOS'); $GraphFrame0->SetViewRange(0, 0, 1, 1); } unless($GraphFrameArray->GetGraphFrame(1)) { my $GraphFrame0 = $GraphFrameArray->GetGraphFrame(0); my $FramePosStr0 = $App->{"GraphFramePosition"}; $GraphFrame0->SetPositionByStr($FramePosStr0); } } sub ShowScaleDialog { my ($this, $GraphFrame, $command, $Title, @a) = @_; print "ShowScaleDialog\n"; #$command: "XScale" "YScale" #最初の4つのundefはViewRangeに現在値を使う #次の2つのundefはPlotTypeに現在値を使う設定 #そのあとの1,0は、X,Y軸のPlotTypeの同期をおこなうかどうか #最後の1は、ScaleDialogでOKを押されたらグラフの再描画を行う #  Y軸のViewRangeは同期するが、PlotTypeの同期は無視する $GraphFrame->ShowScaleDialog($Title, undef, undef, undef, undef, undef, undef, 1, 1, 1); $this->AdjustViewRange(); } sub AssignGraphData { my ($this) = @_; my $GraphFrameArray = $this->GetGraphFrameArray(); return undef unless($GraphFrameArray); my $GraphFrame0 = $GraphFrameArray->GetGraphFrame(0); return undef unless($GraphFrame0); my $FileType = $this->FileType(); my $pDataArray = $this->DataArray(); return unless($pDataArray); my $Data = $pDataArray->GetGraphData(0); return unless($Data); my $nData = $Data->nData(); my $title = $Data->Title(); my $pX0 = $Data->GetDataArray('x0'); my $linecolor = "auto"; if($FileType eq "WIEN2k spaghetti Band file") { my @GraphFrame; for(my $id = 0 ; ; $id++) { $GraphFrame[$id] = $GraphFrameArray->GetGraphFrame($id); last unless($GraphFrame[$id]); my $Data = $pDataArray->GetGraphData($id); $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); } 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 "WIEN2k PDOS files") { my @GraphFrame; for(my $id = 0 ; ; $id++) { $GraphFrame[$id] = $GraphFrameArray->GetGraphFrame($id); last unless($GraphFrame[$id]); my $Data = $pDataArray->GetGraphData($id); for(my $i = 0 ; ; $i++) { my $pY = $Data->GetDataArray("y$i"); last unless($pY); my $color = GraphFrame::GetColor($i); my $nData = $GraphFrame[$id]->AddGraphData($pX0, $pY, 1, $color, "", 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); } if($GraphFrame[1]) { $GraphFrame[0]->AddSynchronousFrame('x', $GraphFrame[1]); $GraphFrame[1]->AddSynchronousFrame('x', $GraphFrame[0]); $GraphFrame[0]->AddSynchronousFrame('y', $GraphFrame[1]); $GraphFrame[1]->AddSynchronousFrame('y', $GraphFrame[0]); $GraphFrame[1]->SetYScalePlotType('-x'); } } else { for(my $i = 0 ; ; $i++) { #print "Assign $i\n"; my $pY = $Data->GetDataArray("y$i"); last unless($pY); my $nData = $GraphFrame0->AddGraphData($pX0, $pY, 1, $linecolor, "", 6, "red", 0, "red", "XAutoSkip", $Data->{"x0_Name"}, $Data->{"y${i}_Name"}); my $data = $GraphFrame0->GetPlotData($nData-1); } $GraphFrame0->CalMinMax(); $GraphFrame0->AdjustViewRange(0.05, 0.05, 0.05, 0.05); } if($FileType eq "WIEN2k epsilon file") { $GraphFrame0->SetXCaption("Energy / eV"); $GraphFrame0->SetYCaption('eps'); } elsif($FileType eq "WIEN2k PDOS files") { $GraphFrame0->SetXCaption($Data->{"x0_Name"}); $GraphFrame0->SetYCaption('PDOS'); } elsif($FileType eq "WIEN2k spaghetti Band file") { $GraphFrame0->SetXCaption($Data->{"x0_Name"}); $GraphFrame0->SetYCaption('Energy'); } else { $GraphFrame0->SetXCaption($Data->{"x0_Name"}); $GraphFrame0->SetYCaption($Data->{"y0_Name"}); } $this->AdjustViewRange(); } sub AdjustViewRange { my ($this) = @_; my $GraphFrameArray = $this->GetGraphFrameArray(); my $pGraphFrame = $GraphFrameArray->GetpGraphFrameArray(); my $FileType = $this->FileType(); #print "FileType: $FileType\n"; if($FileType eq "WIEN2k spaghetti Band file") { my ($xmin, $xmax) = $pGraphFrame->[0]->GetViewXRange(); my ($ymin, $ymax) = $pGraphFrame->[0]->GetViewYRange(); print "x: $xmin - $xmax y: $ymin - $ymax\n"; for(my $id = 1 ; ; $id++) { my $GraphFrame = $GraphFrameArray->GetGraphFrame($id); #print "id=$id: p=$GraphFrame\n"; last unless($GraphFrame); $GraphFrame->SetViewRange($xmin, $ymin, $xmax, $ymax); } } elsif($FileType eq "WIEN2k PDOS files") { my ($xmin, $xmax) = $pGraphFrame->[0]->GetViewXRange(); my ($ymin, $ymax) = $pGraphFrame->[0]->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) = @_; $canvas = $this->Canvas($canvas); # $this->SetCanvas($canvas) if($canvas); my $mw = $this->mw(); $canvas->ClearAll(); $mw->RefleshCanvas(); my $FileType = $this->FileType(); 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 $SymbolFont = $App->{'GraphFrameSymbolFont'}; my @SymbolFont = split(/,/, $SymbolFont) if($SymbolFont); my $w = $canvas->width(); my $h = $canvas->height(); if($font) { $canvas->SetFont(\@font); $GraphFrameArray->SetFont(\@font); } $GraphFrameArray->SetCanvasSize($w, $h); $this->mw()->Balloon()->detach($canvas); my $pKPointName = $this->{'KPointNameArray'}; if($pKPointName) { $GraphFrameArray->SetScaleVisible('X', 0); $GraphFrameArray->SetScaleStringVisible('X', 0); $GraphFrame[0]->SetXCaption(''); } else { $GraphFrameArray->SetScaleVisible('X', 1); $GraphFrameArray->SetScaleStringVisible('X', 1); $GraphFrame[0]->SetXCaption('k'); } $this->mw()->WriteStatusBar("Drawing..."); $GraphFrameArray->SetX0LineVisible($GraphFrame[0]->X0LineVisible()); $GraphFrameArray->SetY0LineVisible($GraphFrame[0]->Y0LineVisible()); # if($GraphFrame[1]) { # $GraphFrame[1]->SetX0LineVisible($GraphFrame[0]->X0LineVisible()); # $GraphFrame[1]->SetY0LineVisible($GraphFrame[0]->Y0LineVisible()); # } $GraphFrameArray->Draw($canvas); #バンド構造図の縦線を描画 if($FileType eq "WIEN2k spaghetti Band file") { my $pDataArray = $this->DataArray(); my $pBandBoundaryDistances = $pDataArray->{'BandBoundaryDistances'}; my $pBoundaryPositions = $this->{'DataArray'}->{'BandBoundaryPositions'}; my $GraphFrame0 = $GraphFrameArray->GetGraphFrame(0); my ($x0, $y0, $x1, $y1) = $GraphFrame0->GetPosition(); my ($vx0, $vx1) = $GraphFrame0->GetViewXRange(); my %TagHash; for(my $i = 0 ; $i < @$pBandBoundaryDistances ; $i++) { my $b = $pBandBoundaryDistances->[$i]; next if($b < $vx0 or $vx1 < $b); my ($x, $y) = $GraphFrame0->ValueToPosition($b, 0); my $str = $pBoundaryPositions->[$i]; my $tag = "Boundary$i"; $b = Utils::Round($b, 4); $str = '' if(!defined $str); $TagHash{$tag} = "($str) x=$b"; $canvas->DrawLine($x, $y0, $x, $y1, 1, "black", $tag); if($pKPointName) { my $Name = $pKPointName->[$i]; #print "KPoint: $Name\n"; $this->DrawSymbolChar($canvas, $x, $y0+2, $Name); } } $this->mw()->Balloon()->attach($canvas, -balloonposition => 'mouse', -msg => \%TagHash); } $this->mw()->WriteStatusBar("Finish Drawing"); } sub DrawSymbolChar { my ($this, $canvas, $x, $y, $s) = @_; $canvas = $this->Canvas($canvas); my $App = $this->App(); my %CharTable; $CharTable{'ALPHA'} = 'A'; $CharTable{'alpha'} = 'a'; $CharTable{'BETA'} = 'B'; $CharTable{'beta'} = 'b'; $CharTable{'CHI'} = 'C'; $CharTable{'chi'} = 'c'; $CharTable{'DELTA'} = 'D'; $CharTable{'delta'} = 'd'; $CharTable{'EPSILON'} = 'E'; $CharTable{'epsilon'} = 'e'; $CharTable{'PHI'} = 'F'; $CharTable{'phi'} = 'f'; $CharTable{'GAMMA'} = 'G'; $CharTable{'gamma'} = 'g'; $CharTable{'LAMBDA'} = 'L'; $CharTable{'lambda'} = 'l'; if(length($s) > 1) { my $SymbolFont = $App->{'GraphFrameSymbolFont'}; # my $SymbolFont = $App->{'GraphFrameFont'}; my @SymbolFont = split(/,/, $SymbolFont) if($SymbolFont); print " KPoint: $s => "; $s = $CharTable{$s}; $s = '*' unless($s); print "$s ($SymbolFont)\n"; $canvas->DrawText($x, $y, $s, \@SymbolFont, 'n', '', 'XScale0'); } else { my $font = $App->{'GraphFrameFont'}; my @font = split(/,/, $font) if($font); $s = '*' unless($s); print " KPoint: $s ($font)\n"; $canvas->DrawText($x, $y, $s, \@font, 'n', '', 'XScale0'); } # $canvas->SetFont(\@font); } sub DeleteWidget { my ($this, $Frame) = @_; return undef unless($Frame); return 1; } sub AddWidget { my ($this, $Frame) = @_; return undef unless($Frame); # $this->mw()->packPropagate(0); # $this->mw()->packPropagate(1); 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 $pDataArray = $DataArray->DataArray(); return undef unless($pDataArray); 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"); for(my $i = 0 ; $i < $nData ; $i++) { my $str = ""; my $nY = $Data->nYColumn(); for(my $j = 0 ; $j < $nY ; $j++) { my $x = $Data->x($j, $i); $x = $Data->x(0, $i) unless(defined $x); next unless(defined $x); $x = sprintf("%7.3f", $x); $str = "$str\t$x"; my $y = $Data->y($j, $i); next unless(defined $y); $y = sprintf("%9.3f", $y); $str = "$str\t$y"; } $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(); } 1;