#=============================================== # TkConvolution #=============================================== package TkConvolution; use clib::TkFittingCommon; @ISA = qw(TkFittingCommon); #公開したいサブルーチン #@EXPORT = qw(DelSpace Reduce01 MakePath RegExpQuote); use strict; use Utils; use IniFile; use CSV; use MyTk::GraphFrameArray; use GraphData; use Sci::Science; use Sci::PES; use Sci::Ellipsometry; use Sci::Optimize; #============================================================ # 変数等取得関数 #============================================================ #============================================================ # コンストラクタ、デストラクタ #============================================================ #呼び出されることはない sub new { my ($module, $app) = @_; my $this = {}; bless $this; return $this; } sub DESTROY { my $this = shift; $this->SUPER::DESTROY(@_); } #============================================================ # 継承クラスで定義しなおす関数 #============================================================ sub CreateLeftFrame { my ($this, $ConfigSide, @args) = @_; # return $this->SUPER::CreateLeftFrame(); return undef; } sub CreateSelectFilePane { my ($this) = @_; # return $this->SUPER::CreateSelectFilePane(); return undef; } sub CreateFileContentPane { return undef; } sub CreateWidgets { my ($this, $DoSuperOnly) = @_; $DoSuperOnly = 0 if(!defined $DoSuperOnly); my $App = $this->App(); my $args = $App->Args(); my $mw = $this->mw(); $this->{nStepBG} = 3; $this->{nGL} = 5; $this->{ini} = new IniFile(undef, 0, 0); $this->{dini} = new IniFile(undef, 0, 0); $this->InitializeParameters($this->{ini}, $this->{dini}); $this->{DataFile} = new Ellipsometry; $this->SUPER::CreateWidgets(); return if($DoSuperOnly); $mw->SetTitle("Convolution2007 / TkPlot"); $this->App()->SetProgram("Convolution2007 / TkPlot"); #=================================================== # ペインを作製 #=================================================== my $EntryWidth = 8; my $Frame = $mw->MyFrame()->pack(-anchor => 'nw', -fill => 'x'); $this->MakeChooseFileEntry($Frame, 'Param', 'Param:', $this->{ini}->pVariable("ParameterFile", ""), '&Choose', sub { $this->ChooseFile(@_); }, "ChooseParameterFile"); $this->{SaveParamButton} = $Frame->MyButton( -text => '&Save', -takefocus => 1, -command => sub { $this->ButtonPressed('RButtonDown', 'SaveParam'); }, )->pack(-side => 'left'); $this->{EditParamButton} = $Frame->MyButton( -text => 'ed', -takefocus => 1, -command => sub { $this->ButtonPressed('RButtonDown', 'EditParam'); }, )->pack(-side => 'left'); $Frame = $mw->MyFrame()->pack(-anchor => 'nw', -fill => 'x'); $this->MakeChooseFileEntry($Frame, 'SampleCSV', 'Sample:', $this->{ini}->pVariable("SampleCSVFile", ""), '&Choose', sub { $this->ChooseFile(@_); }, "ChooseSampleFile"); $this->{EditDataButton} = $Frame->MyButton( -text => 'ed', -takefocus => 1, -command => sub { $this->ButtonPressed('RButtonDown', 'EditSampleCSV'); }, )->pack(-side => 'left'); $Frame = $mw->MyFrame()->pack(-anchor => 'nw', -fill => 'x'); my $lsb1 = $this->{ChooseXListBox} = $Frame->MyBrowseEntry( -label => "X:", -state => "readonly", -takefocus => 1, -width => 5, -Selections => [], -SelIndex => 0, )->pack(-side => 'left', -expand => 'yes', -fill => 'x'); $lsb1->configure(-browsecmd => sub { $this->SelChangeListBox("X", $this->{ChooseXListBox}); } ); my $lsb2 = $this->{ChooseY1ListBox} = $Frame->MyBrowseEntry( -label => "Y1:", -state => "readonly", -takefocus => 1, -width => 5, -Selections => [], -SelIndex => 1, )->pack(-side => 'left', -expand => 'yes', -fill => 'x'); $Frame = $mw->MyFrame()->pack(-anchor => 'nw', -fill => 'x'); $this->MakeLabelEntry($Frame, "FitXMin", "XMin:", $this->{ini}->pVariable('FitXMin', ''), "%s", $EntryWidth, "", 0, 0); $this->MakeLabelEntry($Frame, "FitXMin", "XMax:", $this->{ini}->pVariable('FitXMax', ''), "%s", $EntryWidth, "", 0, 1); $this->MakeLabelEntry($Frame, "nSkipData", "nSkip:", $this->{ini}->pVariable('nSkipData', 2), "%d", $EntryWidth, "", 0, 2); $this->MakeLabelEntry($Frame, "EPS", "EPS:", $this->{ini}->pVariable('EPS', 1.0e-3), "%g", $EntryWidth, "", 1, 0); $this->MakeLabelEntry($Frame, "nMaxIter", "MaxIter:", $this->{ini}->pVariable('nMaxIter', 30), "%d", $EntryWidth, "", 1, 1); $this->MakeLabelEntry($Frame, "Dumping", "Dumping:", $this->{ini}->pVariable('Dumping', 0.3), "%g", $EntryWidth, "", 1, 2); $Frame = $mw->MyFrame()->pack(-anchor => 'nw', -fill => 'x'); my $lsb4 = $this->{ChooseActionListBox} = $Frame->MyBrowseEntry( -label => "Action:", -state => "readonly", -takefocus => 1, -width => 8, -Selections => ['Convolution', 'Deconvolution'], -SelIndex => 0, )->pack(-side => 'left', -expand => 'yes', -fill => 'x'); $lsb4->configure(-browsecmd => sub { $this->SelChangeListBox("Action", $this->{ChooseActionListBox}); }); my $lsb5 = $this->{ChooseAppFunctionListBox} = $Frame->MyBrowseEntry( -label => "App Function:", -state => "readonly", -takefocus => 1, -width => 8, -Selections => ['Gauss', 'Lorentz'], -SelIndex => 0, )->pack(-side => 'left', -expand => 'yes', -fill => 'x'); $lsb5->configure(-browsecmd => sub { $this->SelChangeListBox("AppFunction", $this->{ChooseAppFunctionListBox}); }); $Frame = $mw->MyFrame()->pack(-anchor => 'nw'); $this->MakeCheckEntry($Frame, "Wa", "Wa:", $this->{dini}->pVariable('Wacheck', 1), $this->{ini}->pVariable('Wa', 0.1), "%g", $EntryWidth, "eV", 0, 0); $this->UpdateParameters(); $Frame = $mw->MyFrame()->pack(-anchor => 'nw', -fill => 'x'); $this->{RecalcButton} = $Frame->MyButton( -text => 'Re&calc', -takefocus => 1, -command => sub { $this->ButtonPressed('RButtonDown', 'Recalc'); }, )->pack(-side => 'left'); #ツールバーのOpenボタンをファイル読み込みにバインドする $mw->{OpenButton}->configure( -command => sub { $this->ChooseFile('SampleCSV', $this->{SPEFileFileEntry}); }, ) if($mw->{OpenButton}); } sub Initialize { my ($this, $InitializeParameterFile, $InitializeData) = @_; $this->{DataFile} = new Ellipsometry; if($InitializeParameterFile) { $this->{ini}->{SampleCSVFile} = ''; $this->{ini}->{FitXMin} = ''; $this->{ini}->{FitXMax} = ''; } if($InitializeData) { $this->{pCalX} = undef; $this->{pCalY} = undef; } } sub InitializeParameters { my ($this, $ini, $dini) = @_; # $this->AddParameters($ini, $dini, "EF", 0.0, 1, 1.0, '', ''); } #=================================================== # データ処理 #=================================================== sub Recalc { my ($this) = @_; return if(!defined $this->{DataFile}); my $ini = $this->{ini}; $ini->{Action} = $this->{ChooseActionListBox}->GetText(); $ini->{AppFunction} = $this->{ChooseAppFunctionListBox}->GetText(); print "Action: $ini->{Action}\n"; print "Action: $ini->{AppFunction}\n"; my $XLabel = $this->{"ChooseXListBox"}->GetText(); my $Y1Label = $this->{"ChooseY1ListBox"}->GetText(); my $pX = $this->{DataFile}->GetData($XLabel) if($XLabel); my $pY1 = $this->{DataFile}->GetData($Y1Label) if($Y1Label); my $XMin = $ini->{FitXMin}; my $XMax = $ini->{FitXMax}; my $nSkipData = $ini->{nSkipData}; my $EPS = $ini->{EPS}; my $nMaxIter = $ini->{nMaxIter}; my $Dumping = $ini->{Dumping}; my $CorrectZero = 0; my $c = 0; my (@X, @Y); for(my $i = 0 ; $i < @$pX ; $i++) { my $x = $pX->[$i]; next if($x < $XMin or $XMax < $x); next if($nSkipData > 0 and $i % $nSkipData != 0); $X[$c] = $pX->[$i]; $Y[$c] = $pY1->[$i]; $c++; } my $n = @X; print "n=$n\n"; $this->{pCalX} = \@X; if($this->{ini}->{Action} eq 'Convolution') { $this->{pCalY} = PES::Convolution(\@X, \@Y, $ini->{AppFunction}, $ini->{Wa}); } else { ($this->{pCalY}) = PES::Deconvolution(\@X, \@Y, $ini->{AppFunction}, $ini->{Wa}, $CorrectZero, $Dumping, $nMaxIter, $EPS); } #for(my $i = 0 ; $i < @$pX ; $i++) { # print "$i: $pX->[$i], $this->{pCalY}->[$i]\n"; #} # $this->CreateGraphFrame(); $this->AssignGraphData(0); $this->Draw(); } sub SaveParameterFile { my ($this, $filepath) = @_; $this->{ini}->{X} = $this->{ChooseXListBox}->GetText(); $this->{ini}->{Y1} = $this->{ChooseY1ListBox}->GetText(); if(!defined $filepath or $filepath eq '') { $filepath = $this->ChooseSaveFile('save.prm', '*.prm'); if($filepath) { $this->{ini}->{ParameterFile} = $filepath; } else { return; } } $this->{ini}->SetIniFile($filepath, undef, 1); $this->App()->print("\nSaveParameterFile:\n"); $this->ComposeParameters($this->{dini}, $this->{ini}); $this->{ini}->WriteAll(); $this->DecomposeParameters($this->{ini}, $this->{dini}); } sub ReadParameterFile { my ($this, $filepath) = @_; my $ini = $this->{ini}; my $dini = $this->{dini}; $this->Initialize(1, 1); $this->App()->print("\nRead paramter from [$filepath].\n"); $this->{ini}->ReadAll($filepath); $this->{ini}->{ParameterFile} = $filepath; $this->DecomposeParameters($ini, $dini); $this->{ChooseXListBox}->SetText($this->{ini}->{X}); $this->{ChooseY1ListBox}->SetText($this->{ini}->{Y1}); if($this->{ini}->{SampleCSVFile}) { my $ret = $this->ReadSampleDataFile($this->{ini}->{SampleCSVFile}, 1, 0, 0); return undef unless($ret); } return 1; } sub ReadSampleDataFile { my ($this, $filepath, $IsPrint, $UpdateRange) = @_; $UpdateRange = 1 if(!defined $UpdateRange); my $App = $this->App(); #print "type=$type\n"; $this->Initialize(0, 1); $this->{Path} = $filepath; my ($nData, $pLabelArray, @pDataArray) = $this->{DataFile}->Read($filepath); if(!defined $nData) { $App->print("Error: Can not read [$filepath].\n"); return $this->{Path} = undef; } if(!Utils::IsConstantStepArray($pDataArray[0])) { $App->print("Error: The data step for X is not constant.\n"); return $this->{Path} = undef; } my $nDataArray = $this->{DataFile}->nDataArray(); #print "nDataArray: $nDataArray\n"; $this->{"ChooseXListBox"}->DeleteAllItem(); $this->{"ChooseY1ListBox"}->DeleteAllItem(); for(my $i = 0 ; $i < $nDataArray ; $i++) { #print "$i: $pLabelArray->[$i]\n"; $this->{"ChooseXListBox"}->AddItem($pLabelArray->[$i]); $this->{"ChooseY1ListBox"}->AddItem($pLabelArray->[$i]); } $this->{"ChooseXListBox"}->SetCurSel(0); $this->{"ChooseY1ListBox"}->SetCurSel(1); if($UpdateRange or !defined $this->{ini}->{FitXMin}) { ($this->{ini}->{FitXMin}, $this->{ini}->{FitXMax}) = Utils::CalMinMax($pDataArray[0]); } $this->CreateGraphFrame(); $this->AssignGraphData(); return $filepath; } sub CreateGraphFrame { my ($this, $canvas, $TargetData) = @_; $canvas = $this->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(); # return undef unless($FileType); # my $pDataArray = $this->DataArray(); # return unless($pDataArray); my $GraphFrameArray = $this->{'GraphFrameArray'} = new GraphFrameArray($this->mw()); $GraphFrameArray->SetCanvasSize($w, $h); $GraphFrameArray->AddGraphFrame(); my $GraphFrame0 = $GraphFrameArray->GetGraphFrame(0); my $FramePosStr0 = $App->{"GraphFrame0Position"}; $GraphFrame0->SetPositionByStr($FramePosStr0); my $XScale0 = $GraphFrame0->GetXScale(0); my $YScale0 = $GraphFrame0->GetYScale(0); $XScale0->SetScaleStringVisible(1); $XScale0->SetCaptionVisible(1); $GraphFrame0->SetViewRange(0, 0, 1, 1); } sub AssignGraphData { my ($this, $ResetViewRange) = @_; $ResetViewRange = 1 if(!defined $ResetViewRange); my $GraphFrameArray = $this->GetGraphFrameArray(); my $GraphFrame0 = $GraphFrameArray->GetGraphFrame(0); $GraphFrame0->ClearAllData(); my $XLabel = $this->{"ChooseXListBox"}->GetText(); $XLabel = 'X' if(!$XLabel); my $Y1Label = $this->{"ChooseY1ListBox"}->GetText(); $Y1Label = 'Y1' if(!$Y1Label); $GraphFrame0->SetXCaption($XLabel); $GraphFrame0->SetYCaption("$Y1Label"); my $pX = $this->{DataFile}->GetData($XLabel) if($XLabel); my $pY1 = $this->{DataFile}->GetData($Y1Label) if($Y1Label); my $nData = $this->{DataFile}->nData(); if($pX) { $GraphFrame0->AddGraphData($pX, $pY1, 2, "black", "", 6, "red", 0, "red", "XAutoSkip", "Energy", "${Y1Label}") if($pY1); } my $pCalX = $this->{pCalX}; my $pCalY = $this->{pCalY}; if($pCalX) { $GraphFrame0->AddGraphData($pCalX, $pCalY, 0, "", "circle", 3, "", 1, "red", "XAutoSkip", "Energy", "FT ${Y1Label}(real)") if($pCalY); } $GraphFrame0->SetYScalePlotType('x'); if($ResetViewRange) { $GraphFrame0->CalMinMax(); $GraphFrame0->AdjustViewRange(0.05, 0.05, 0.05, 0.05); } } 1;