#=============================================== # RietPlot #=============================================== package RietPlot; use Crystal::Rietan; use TkFittingCommon; @ISA = qw(Rietan TkFittingCommon); #use TkPlotModule; #@ISA = qw(Rietan TkPlotModule); #公開したいサブルーチン #@EXPORT = qw(DelSpace Reduce01 MakePath RegExpQuote); use strict; use Utils; use MyTk::GraphFrameArray; use GraphData; #============================================================ # Global変数 #============================================================ #my $material = new Material; my $Program = "RietPlot2010"; my $EntryWidth = 12; my $TextBoxWidth = 30; my $TextBoxHeight = 20; #============================================================ # コンストラクタ、デストラクタ #============================================================ sub new { my ($class, $app, @a) = @_; # my ($module, $app, $canvas) = @_; my $self = TkFittingCommon->new($app, @a); my $this = bless $self, $class; # my $this = {}; # bless $this; $this->SetApplication($app) if($app); # $this->SetCanvas($canvas) if($canvas); return $this; } sub DESTROY { my $this = shift; $this->SUPER::DESTROY(@_); } #============================================================ # 継承クラスで定義しなおす関数 #============================================================ sub CheckFileType { my ($path) = @_; my $ret = Rietan::CheckFileType($path); return $ret; } sub Read { my ($this, $filename) = @_; return Rietan::Read($this, $filename); } sub CreateGraphFrame { my ($this, $canvas) = @_; $canvas = $this->Canvas($canvas); my $FileType = $this->FileType(); my $App = $this->App(); my $font = $App->{'GraphFrameFont'}; my @font = split(/,/, $font) if($font); my $w = $canvas->width(); my $h = $canvas->height(); my $GraphFrameArray = $this->{'GraphFrameArray'} = new GraphFrameArray($this->mw()); $GraphFrameArray->AddGraphFrame(); my $GraphFrame0 = $GraphFrameArray->GetGraphFrame(0); my $GraphFrame1 = ''; my $GraphFrame2 = ''; #print "FileType:$FileType\n"; if($FileType =~ /Fitting/i) { $GraphFrameArray->AddGraphFrame(); $GraphFrame1 = $GraphFrameArray->GetGraphFrame(1); $GraphFrameArray->AddGraphFrame(); $GraphFrame2 = $GraphFrameArray->GetGraphFrame(2); } elsif($FileType =~ /(Igor|RietPlot|gnuplot)/i) { $GraphFrameArray->AddGraphFrame(); $GraphFrame1 = $GraphFrameArray->GetGraphFrame(1); } $GraphFrameArray->SetCanvasSize($w, $h); my $FramePosStr0 = $App->{"GraphFrame0Position"}; $GraphFrame0->SetPositionByStr($FramePosStr0); $GraphFrame0->SetYCaption('Intensity / cps'); $GraphFrame0->SetViewRange(0, 0, 1, 1); my $XScale0 = $GraphFrame0->GetXScale(0); my $YScale0 = $GraphFrame0->GetYScale(0); if($FileType =~ /Fitting/i) { $XScale0->SetScaleStringVisible(0); $XScale0->SetCaptionVisible(0); my $FramePosStr1 = $App->{"GraphFrame1Position"}; $GraphFrame1->SetPositionByStr($FramePosStr1); my $XScale1 = $GraphFrame1->GetXScale(0); my $YScale1 = $GraphFrame1->GetYScale(0); $XScale1->SetScaleStringVisible(0); $XScale1->SetCaptionVisible(0); $YScale1->SetCaptionVisible(0); $YScale1->SetnMaxScale(5); $GraphFrame1->SetViewRange(0, 0, 1, 1); $YScale1->CalScale(); my $FramePosStr2 = $App->{"GraphFrame2Position"}; $GraphFrame2->SetPositionByStr($FramePosStr2); $GraphFrame2->SetXCaption('2Theta'); my $XScale2 = $GraphFrame2->GetXScale(0); my $YScale2 = $GraphFrame2->GetYScale(0); $YScale2->SetScaleVisible(0); $YScale2->SetScaleStringVisible(0); $YScale2->SetCaptionVisible(0); $YScale2->SetnMaxScale(5); $GraphFrame2->SetViewRange(0, 0, 1, 1); $YScale2->CalScale(); $GraphFrame0->AddSynchronousFrame('x', $GraphFrame1); $GraphFrame0->AddSynchronousFrame('x', $GraphFrame2); $GraphFrame1->AddSynchronousFrame('x', $GraphFrame0); $GraphFrame1->AddSynchronousFrame('x', $GraphFrame2); $GraphFrame2->AddSynchronousFrame('x', $GraphFrame0); $GraphFrame2->AddSynchronousFrame('x', $GraphFrame1); } elsif($FileType =~ /(Igor|RietPlot|gnuplot)/i) { $XScale0->SetScaleStringVisible(0); $XScale0->SetCaptionVisible(0); my $FramePosStr1 = $App->{"GraphFrame1Position"}; $GraphFrame1->SetPositionByStr($FramePosStr1); $GraphFrame1->SetXCaption('2Theta'); my $XScale1 = $GraphFrame1->GetXScale(0); my $YScale1 = $GraphFrame1->GetYScale(0); $GraphFrame1->SetViewRange(0, 0, 1, 1); $YScale1->SetScaleVisible(0); $YScale1->SetScaleStringVisible(0); $YScale1->SetCaptionVisible(0); $YScale1->SetnMaxScale(5); $YScale1->CalScale(); $GraphFrame0->AddSynchronousFrame('x', $GraphFrame1); $GraphFrame1->AddSynchronousFrame('x', $GraphFrame0); } else { $GraphFrame0->SetXCaption('2Theta'); } $GraphFrameArray->SetFont(\@font) if($font); $GraphFrameArray->SetCanvasSize($w, $h); } sub AssignGraphData { my ($this) = @_; my $GraphFrameArray = $this->GetGraphFrameArray(); my $GraphFrame0 = $GraphFrameArray->GetGraphFrame(0); my $GraphFrame1 = $GraphFrameArray->GetGraphFrame(1); my $GraphFrame2 = $GraphFrameArray->GetGraphFrame(2); my $pDataArray = $this->DataArray(); return unless($pDataArray); my $IntData = $pDataArray->GetGraphData(0); return unless($IntData); my $nData = $IntData->nData(); my $title = $IntData->Title(); my $p2QData = $IntData->GetDataArray('x0'); my $pObsIntensityData = $IntData->GetDataArray('y0'); my $pCalIntensityData = $IntData->GetDataArray('y1'); my $pBGIntensityData = $IntData->GetDataArray('y2'); my $pDiffIntensityData = $IntData->GetDataArray('y3'); if($pCalIntensityData) { $GraphFrame0->AddGraphData($p2QData, $pCalIntensityData, 1, "black", "", 6, "red", 0, "red", "XAutoSkip", "2Theta", "Calc. Intensity"); } if($pObsIntensityData and $pCalIntensityData) { $GraphFrame0->AddGraphData($p2QData, $pObsIntensityData, 0, "black", "cross", 6, "white", 0, "red", "XAutoSkip", "2Theta", "Obs. Intensity"); } elsif($pObsIntensityData and !$pCalIntensityData) { my $XName = "2Theta"; my $YName = "Obs. Intensity"; $XName = $IntData->{'x0_Name'} if($IntData->{'x0_Name'}); $YName = $IntData->{'y0_Name'} if($IntData->{'y0_Name'}); $GraphFrame0->SetXCaption($IntData->XCaption()) if($IntData->XCaption()); $GraphFrame0->SetYCaption($IntData->YCaption()) if($IntData->YCaption()); $GraphFrame0->AddGraphData($p2QData, $pObsIntensityData, 1, "black", "", 4, "", 0, "black", "XAutoSkip", "2Theta", $YName); } if($pBGIntensityData) { $GraphFrame0->AddGraphData($p2QData, $pBGIntensityData, 1, "blue", "", 6, "blue", 0, "blue", "XAutoSkip", "2Theta", "Background"); } $GraphFrame0->CalMinMax(); $GraphFrame0->AdjustViewRange(0.05, 0.05, 0.05, 0.05); if($GraphFrame1) { if($pDiffIntensityData) { $GraphFrame1->AddGraphData($p2QData, $pDiffIntensityData, 1, "black", "", 6, "black", 0, "black", "XAutoSkip", "2Theta", "Difference Intensity"); $GraphFrame1->CalMinMax(); $GraphFrame1->AdjustViewRange(0.05, 0.05, 0.05, 0.05); my ($vy00, $vy01) = $GraphFrame0->GetViewYRange(); my ($x00, $y00, $x01, $y01) = $GraphFrame0->GetPosition(); my ($vy10, $vy11) = $GraphFrame1->GetViewYRange(); my ($x10, $y10, $x11, $y11) = $GraphFrame1->GetPosition(); $y01 = $y00 + 1.0 if($y00 == $y01); $y11 = $y10 + 1.0 if($y10 == $y11); my $r1 = ($vy01 - $vy00) / ($y01 - $y00); my $r2 = ($vy11 - $vy10) / ($y11 - $y10); my $k; if($r2 == 0.0) { $GraphFrame1->SetViewYRange($vy00, $vy10); } else { $k = $r1 / $r2; $GraphFrame1->SetViewYRange($vy10*$k, $vy11*$k); } } else { my ($vx10, $vx11) = $GraphFrame1->GetViewXRange(); $GraphFrame1->SetViewRange($vx10, 0, $vx11, 1); } } $this->AdjustViewRange(); } sub AdjustViewRange { my ($this) = @_; my $GraphFrameArray = $this->GetGraphFrameArray(); my $pGraphFrame = $GraphFrameArray->GetpGraphFrameArray(); my ($xmin, $xmax) = $pGraphFrame->[0]->GetViewXRange(); my $nGraphFrame = 2; for(my $i = 1 ; $i < $nGraphFrame ; $i++) { next unless($pGraphFrame->[$i]); my ($xmin0, $xmax0) = $pGraphFrame->[$i]->GetViewXRange(); $xmin = $xmin0 if($xmin0 < $xmin); $xmax = $xmax0 if($xmax < $xmax0); } for(my $i = 0 ; $i < @$pGraphFrame ; $i++) { next unless($pGraphFrame->[$i]); $pGraphFrame->[$i]->SetViewXRange($xmin, $xmax); # $pGraphFrame->[$i]->RecalcScale(); } } sub Draw { my ($this, $canvas) = @_; $canvas = $this->Canvas(); my $FileType = $this->FileType(); my $mw = $this->mw(); my $App = $this->App(); my $GraphFrameArray = $this->GetGraphFrameArray(); my $pGraphFrame = $GraphFrameArray->GetpGraphFrameArray(); my @GraphFrame = @$pGraphFrame; my $font = $App->{'GraphFrameFont'}; my @font = split(/,/, $font) if($font); my $w = $canvas->width(); my $h = $canvas->height(); $this->mw()->WriteStatusBar("Drawing..."); $canvas->ClearAll(); $mw->RefleshCanvas(); if($font) { $canvas->SetFont(\@font); $GraphFrameArray->SetFont(\@font); } $GraphFrameArray->SetCanvasSize($w, $h); $GraphFrameArray->Draw($canvas); #print "End: Draw\n"; #ピーク位置をプロット my $TkData = $App->TkData(); my $pPeakArray = $TkData->GetpDiffractionPeakArray(); $pPeakArray = $this->GetpDiffractionPeakArray() if(!defined $pPeakArray); print "pPeakArray=$FileType: $this, $pPeakArray, $this->{DiffractionPeakArray}\n"; return unless($pPeakArray); my $PeakFrame = $pGraphFrame->[2]; if($FileType =~ /Fitting/i) { $PeakFrame = $pGraphFrame->[2]; # $PeakFrame = $pGraphFrame->[1]; } elsif($FileType =~ /(Igor|RietPlot|gnuplot)/i) { $PeakFrame = $pGraphFrame->[1]; } return unless($PeakFrame); my $nDiffractionType = 2; if($pPeakArray->[0]->Q2Cal(0) eq '') { $nDiffractionType = 1; } my ($x0, $y0, $x1, $y1) = $PeakFrame->GetPosition(); #print "Frame2: ($x0, $y0, $x1, $y1)\n"; # my ($vx0, $vx1) = $PeakFrame->GetViewXRange(); my $nPeakArray = $TkData->GetnDiffractionPeakArray(); # my $nPeakArray = $this->GetnDiffractionPeakArray(); my $BarBoxHeight = int(abs($y1 - $y0) / $nPeakArray); my $BarLength = int($BarBoxHeight / 2.0 * 0.7); #$BarLength = 5 if($BarLength < 5); my %TagHash; #print "nPeak: $nPeakArray\n"; for(my $id = 0 ; $id < $nPeakArray ; $id++) { #print "id=$id\n"; my $iPhase = $id+1; my $peak = $pPeakArray->[$id]; next unless($peak); my $nPeak = $peak->nPeaks(); my $ybase = $y1 + $id*$BarBoxHeight; for(my $i = 0 ; $i < $nPeak ; $i++) { my $hkl = $peak->hkl($i); my $Q2Obs = $peak->Q2Obs($i); #print "Q=$Q2Obs\n"; my $Q2Cal = $peak->Q2Cal($i); #print "id=$id i=$i hkl=$hkl at $Q2Obs / $Q2Cal\n"; my ($xa, $ya) = $PeakFrame->ValueToPosition($Q2Obs, 0); my $ybasea = $ybase + $BarBoxHeight / $nDiffractionType * 0.8; my ($xb, $yb, $ybaseb); if($Q2Cal ne '') { ($xb, $yb) = $PeakFrame->ValueToPosition($Q2Cal, 0); $ybaseb = $ybasea + $BarBoxHeight / $nDiffractionType; } #print "x: $xa, $ybasea / $xb, $ybaseb ($BarBoxHeight/$BarLength)\n"; if($x0 < $xa and $xa < $x1) { $Q2Obs = $Q2Cal if(!defined $Q2Obs); my $stra = "Phase$iPhase Ka1(Obs): ${hkl} 2Q=$Q2Obs"; my $taga = "${iPhase}_${hkl}_1(Obs)"; $taga =~ s/\s/-/g; if($TagHash{$taga}) { $stra = "Phase$iPhase Ka2(Obs): ${hkl} 2Q=$Q2Obs"; $taga = "${iPhase}_${hkl}_2(Obs)"; $taga =~ s/\s/-/g; } #rint "Q=$Q2Obs x=$xa y=$ybasea tag=$taga\n"; #print "DrawLine($xa, $ybasea, $xa, $ybasea-$BarLength\n"; $TagHash{$taga} = $stra; my $a = $canvas->DrawLine($xa, $ybasea, $xa, $ybasea-$BarLength, 1, "red", $taga); $canvas->bind($taga, "", [\&HoverItem, $this, "Enter", $stra, $xa]); $canvas->bind($taga, "", [\&HoverItem, $this, "Leave", $stra, $xa]); } if($Q2Cal ne '' and $x0 < $xb and $xb < $x1) { my $strb = "Phase$iPhase Ka1(Cal): ${hkl} 2Q=$Q2Cal"; my $tagb = "${iPhase}_${hkl}_1(Cal)"; $tagb =~ s/\s/-/g; if($TagHash{$tagb}) { $strb = "Phase$iPhase Ka2(Cal): ${hkl} 2Q=$Q2Cal"; $tagb = "${iPhase}_${hkl}_2(Cal)"; $tagb =~ s/\s/-/g; } $TagHash{$tagb} = $strb; $canvas->DrawLine($xb, $ybaseb, $xb, $ybaseb-$BarLength, 1, "blue", $tagb); $canvas->bind($tagb, "", [\&HoverItem, $this, "Enter", $strb, $xb]); $canvas->bind($tagb, "", [\&HoverItem, $this, "Leave", $strb, $xb]); } } } $this->mw()->WriteStatusBar("Finish Drawing"); $this->mw()->Balloon()->attach($canvas, -balloonposition => 'mouse', -msg => \%TagHash); } 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応答関数 #============================================================ sub HoverItem { my ($canvas, $this, $event, $str, $x) = @_; return; if($event eq 'Enter') { my $GraphFrameArray = $this->GetGraphFrameArray(); my $pGraphFrame = $GraphFrameArray->GetpGraphFrameArray(); my ($x00, $y00, $x01, $y01) = $pGraphFrame->[0]->GetPosition(); my ($x10, $y10, $x11, $y11) = $pGraphFrame->[1]->GetPosition(); # my ($x20, $y20, $x21, $y21) = $pGraphFrame->[2]->GetPosition(); #print "Y: $y20 - $y01\n"; if($pGraphFrame->[2]) { $canvas->DrawLine($x, $y01, $x, $y10, 1, "grey", "SelPeakPosition"); } else { $canvas->DrawLine($x, $y01, $x, $y00, 1, "grey", "SelPeakPosition"); } $this->mw()->WriteStatusBar($str); } elsif($event eq 'Leave') { $canvas->delete("SelPeakPosition"); $this->mw()->WriteStatusBar(''); } } 1;