#=============================================== # TkPES #=============================================== package TkPES; use clib::TkFittingCommon2; @ISA = qw(TkFittingCommon2); #公開したいサブルーチン #@EXPORT = qw(DelSpace Reduce01 MakePath RegExpQuote); use strict; use Utils; use IniFile; use CSV; use MyTk::GraphFrameArray; use MyTk::MyDragDrop; 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 $mw = $this->mw(); my $ProgramName = "PES2008"; $this->{ini} = new IniFile(undef, 0, 0); $this->{dini} = new IniFile(undef, 0, 0); $this->{ini}->{nStepBG} = 2; $this->{ini}->{nGL} = 6; # $this->{DataFile} = new Ellipsometry; $this->InitializeParameters($this->{ini}, $this->{dini}); $this->SUPER::CreateWidgets(); return if($DoSuperOnly); $mw->SetTitle("$ProgramName / TkPlot"); $this->App()->SetProgram("$ProgramName / TkPlot"); #=================================================== # ペインを作製 #=================================================== my $EntryWidth = $this->{EntryWidth} = 12; $mw->{NoteBook} = $this->MakeNotebookPanes($mw, $EntryWidth, $this->{ini}->pVariable("nFilmLayers", 1), $this->{ini}->pVariable("nLorentz", 3), $this->{ini}->pVariable("nDrude", 0), $this->{ini}->pVariable("nStepBG", 2), $this->{ini}->pVariable("nGL", 6), [qw(Main ViewRange LSQ GaussLorentz Setup GraphFrame)], [qw(nPESStepBG nGaussLorentz)], ); $mw->{NoteBook}->pack(-fill => 'both', -expand => 'yes'); $this->UpdateParameters(); #ツールバーのOpenボタンをファイル読み込みにバインドする my $Samplefmask = '*.csv;*.spe;*.jel;*.asp;*.smo;*isa;*.ref;*.pal;*.bef;*.aft;*.txt'; $mw->{OpenButton}->configure( -command => sub { $this->{SampleCSV} = $this->ChooseFile("open", $Samplefmask, "ChooseSampleFile", "SampleCSV", $this->{SampleFileFrame}); }, ) if($mw->{OpenButton}); my $DragDrop = new MyDragDrop(); $DragDrop->ConfigureDrop( $this->mw(), [ "\\.prm\$", $this->{ParamFileEntry}, sub { $this->ReadParameterFile($_[0]); }, ], [ ".*", $this->{Sample1CSVFileEntry}, sub { $this->{Sample1CSVFileEntry}->SetText($_[0]); $this->ReadSampleDataFile($_[0], 1, 1); }, ], ); } sub BuildMainPane { my ($this, $MainPaneFrame, $EntryWidth) = @_; my $Frame = $MainPaneFrame->MyFrame()->pack(-anchor => 'nw', -fill => 'x'); my $savefmask = '*.prm'; $this->{ParameterFileFrame} = $this->MakeChooseFileEntry( $Frame, 'Param', 'Param:', $this->{ini}->pVariable("ParameterFile", ""), '&Choose', sub { $this->ChooseFile("save", $savefmask, "ChooseParameterFile", @_); }, 1, sub { $this->SaveParameterFile("SaveParam", '', @_); }, 1, sub { $this->EditFile('EditParam', @_); }, [] ); $this->{ParameterFileFrame}->pack(-anchor => 'nw', -fill => 'x'); $Frame = $MainPaneFrame->MyFrame()->pack(-anchor => 'nw', -fill => 'x'); my $Samplefmask = '*.csv;*.spe;*.jel;*.asp;*.smo;*isa;*.ref;*.pal;*.bef;*.aft;*.txt'; $this->{SampleFileFrame} = $this->MakeChooseFileEntry( $Frame, 'SampleCSV', 'Sample:', $this->{ini}->pVariable("SampleCSVFile", ""), '&Choose', sub { $this->{SampleCSV} = $this->ChooseFile("open", $Samplefmask, "ChooseSampleFile", @_); $this->AssignGraphData(); $this->Draw(); }, 0, sub {}, 1, sub { $this->EditFile('EditSampleCSV', @_); }, ['X1', 'Y1'] ); $this->{SampleFileFrame}->pack(-anchor => 'nw', -fill => 'x'); $this->{SampleFileFrame}->{pXDataLabel} = ['.*E.*', '.*eV.*']; $this->{SampleFileFrame}->{pYDataLabel} = ['.*signal.*', 'I.*', '.*']; $Frame = $MainPaneFrame->MyFrame()->pack(-anchor => 'nw', -fill => 'x'); $this->mw()->{LSQFrame2} = $this->MakeLSQPanes( $Frame, $EntryWidth, 'Fitting', [qw(FittingRange)], [], [], ['FitXMin', 'Emin:', 'FitXMax', 'Emax:', 'nSkipData', 'nSkip:'], ['EPS', 'EPS:', 'nMaxIter', 'MaxIter:', 'nSaveSpectraInterval', 'SaveIntvl:'], ); $this->mw()->{LSQFrame2}->pack(-anchor => 'nw', -expand => 'yes', -fill => 'x'); $Frame = $MainPaneFrame->MyLabFrame( -label => 'Model', -labelside => 'acrosstop', )->pack(-anchor => 'nw'); my $lsb5 = $this->{ChooseAppFunctionListBox} = $Frame->MyBrowseEntry( -variable => $this->{ini}->pVariable('AppFunction', 'Gauss'), -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}); }); my $lsb6 = $this->{ChooseConductionTypeListBox} = $Frame->MyBrowseEntry( -variable => $this->{ini}->pVariable('ConductionType', 'Metal'), -label => "Conduction Type:", -state => "readonly", -takefocus => 1, -width => 10, -Selections => ['Metal', 'Semiconductor'], -SelIndex => 0, )->pack(-side => 'left', -expand => 'yes', -fill => 'x'); $lsb6->configure(-browsecmd => sub { $this->SelChangeListBox("ConductionType", $this->{ChooseConductionTypeListBox}); }); $Frame = $MainPaneFrame->MyLabFrame( -label => 'Fermi-Dirac distribution', -labelside => 'acrosstop', )->pack(-anchor => 'nw'); $this->MakeCheckEntry($Frame, "EF", "EF:", $this->{dini}->pVariable('EFcheck', 0), $this->{ini}->pVariable('EF', 0.0), "%g", $EntryWidth, "eV", 0, 0); $this->MakeCheckEntry($Frame, "T", "T:", $this->{dini}->pVariable('Tcheck', 0), $this->{ini}->pVariable('T', 300.0), "%g", $EntryWidth, "K", 0, 1); $this->MakeCheckEntry($Frame, "Wa", "Wa:", $this->{dini}->pVariable('Wacheck', 1), $this->{ini}->pVariable('Wa', 0.1), "%g", $EntryWidth, "eV", 0, 2); $Frame = $MainPaneFrame->MyLabFrame( -label => 'Constant / Step BGs', -labelside => 'acrosstop', )->pack(-anchor => 'nw'); $this->MakeCheckEntry($Frame, "BG", "BG:", $this->{dini}->pVariable('BGcheck', 0), $this->{ini}->pVariable('BG', 0.0), "%g", $EntryWidth, "", 0, 0); for(my $i = 0 ; $i < $this->{ini}->{nStepBG} ; $i++) { $this->MakeCheckEntry($Frame, "EBG0$i", "E0:", $this->{dini}->pVariable("EBG0${i}check", 0), $this->{ini}->pVariable("EBG0$i", 0.0), "%g", $EntryWidth, "eV", $i+1, 0); $this->MakeCheckEntry($Frame, "BGLeft$i", "Left:", $this->{dini}->pVariable("BGLeft${i}check", 0), $this->{ini}->pVariable("BGLeft$i", 0.0), "%g", $EntryWidth, "", $i+1, 1); $this->MakeCheckEntry($Frame, "WBG$i", "W:", $this->{dini}->pVariable("WBG${i}check", 0), $this->{ini}->pVariable("WBG$i", 0.3), "%g", $EntryWidth, "eV", $i+1, 2); } $Frame = $MainPaneFrame->MyLabFrame( -label => 'Conduction / Valnce bands, Cut off, Secondary electron exponent', -labelside => 'acrosstop', )->pack(-anchor => 'nw'); $this->MakeCheckEntry($Frame, "ECBM", "ECBM:", $this->{dini}->pVariable('ECBMcheck', 0), $this->{ini}->pVariable('ECBM', 0.0), "%g", $EntryWidth, "eV", 0, 0); $this->MakeCheckEntry($Frame, "D0CB", "D0:", $this->{dini}->pVariable('D0CBcheck', 0), $this->{ini}->pVariable('D0CB', 0.0), "%g", $EntryWidth, "", 0, 1); $this->MakeCheckEntry($Frame, "EVBM", "EVBM:", $this->{dini}->pVariable('EVBMcheck', 0), $this->{ini}->pVariable('EVBM', 0.0), "%g", $EntryWidth, "eV", 1, 0); $this->MakeCheckEntry($Frame, "D0VB", "D0:", $this->{dini}->pVariable('D0VBcheck', 0), $this->{ini}->pVariable('D0VB', 0.0), "%g", $EntryWidth, "", 1, 1); $this->MakeCheckEntry($Frame, "Ecut", "Ecut:", $this->{dini}->pVariable('Ecutcheck', 0), $this->{ini}->pVariable('Ecut', 0.0), "%g", $EntryWidth, "eV", 2, 0); $this->MakeCheckEntry($Frame, "K0Ecut", "K0:", $this->{dini}->pVariable('K0Ecutcheck', 0), $this->{ini}->pVariable('K0Ecut', 0.0), "%g", $EntryWidth, "", 2, 1); $this->MakeCheckEntry($Frame, "BGcut", "BG:", $this->{dini}->pVariable('BGcutcheck', 0), $this->{ini}->pVariable('BGcut', 0.0), "%g", $EntryWidth, "", 2, 2); $this->MakeCheckEntry($Frame, "C0Exp", "C0:", $this->{dini}->pVariable('C0Expcheck', 0), $this->{ini}->pVariable('C0Exp', 0.0), "%g", $EntryWidth, "", 3, 0); $this->MakeCheckEntry($Frame, "WExp", "W:", $this->{dini}->pVariable('WExpcheck', 0), $this->{ini}->pVariable('WExp', 1.0), "%g", $EntryWidth, "eV", 3, 1); $this->MakeCheckEntry($Frame, "BetaExp", "beta:", $this->{dini}->pVariable('BetaExpcheck', 0), $this->{ini}->pVariable('BetaExp', 1.0), "%g", $EntryWidth, "", 3, 2); # $Frame = $MainPaneFrame->MyFrame()->pack(-anchor => 'nw', -fill => 'x'); $Frame = $MainPaneFrame->MyLabFrame( -label => 'Gauss-Lorentz functions', -labelside => 'acrosstop', )->pack(-side => 'top', -fill => 'x'); for(my $i = 0 ; $i < $this->{ini}->{nGL} ; $i++) { $this->MakeCheckEntry($Frame, "GLE0$i", "E0:", $this->{dini}->pVariable("GLE0${i}check", 0), $this->{ini}->pVariable("GLE0$i", 0.0), "%g", $EntryWidth, "eV", 2*$i, 0); $this->MakeCheckEntry($Frame, "GLC0$i", "C0:", $this->{dini}->pVariable("GLC0${i}check", 0), $this->{ini}->pVariable("GLC0$i", 0.0), "%g", $EntryWidth, "", 2*$i, 1); $this->MakeCheckEntry($Frame, "GLWL$i", "WL:", $this->{dini}->pVariable("GLWL${i}check", 0), $this->{ini}->pVariable("GLWL$i", 0.3), "%g", $EntryWidth, "", 2*$i, 2); $this->MakeCheckEntry($Frame, "GLGFraction$i", "GaussF:", $this->{dini}->pVariable("GLGFraction${i}check", 0), $this->{ini}->pVariable("GLGFraction$i", 1.0), "%g", $EntryWidth, "", 2*$i+1, 1); $this->MakeCheckEntry($Frame, "GLGWRatio$i", "WRatio:", $this->{dini}->pVariable("GLGWRatio${i}check", 0), $this->{ini}->pVariable("GLGWRatio$i", 1.0), "%g", $EntryWidth, "", 2*$i+1, 2); } $this->BuildFooter($MainPaneFrame, $EntryWidth); $this->UpdateParameters(); } sub BuildLSQPane { my ($this, $MainPaneFrame, $EntryWidth) = @_; my $Frame = $MainPaneFrame->MyFrame()->pack(-anchor => 'nw', -fill => 'x'); $this->mw()->{LSQFrame} = $this->MakeLSQPanes( $Frame, $EntryWidth, 'Fitting', [qw(LSQMethod FittingRange FittingConditions)], # [qw(LSQMethod FitTo FittingRange FittingConditions)], ['Amoeba::Simplex', 'PDL::Simplex', 'ModifiedNewton'], ['PES'], ['FitXMin', 'Emin:', 'FitXMax', 'Emax:', 'nSkipData', 'nSkip:'], ['EPS', 'EPS:', 'nMaxIter', 'MaxIter:', 'nSaveSpectraInterval', 'SaveIntvl:'], ); $this->mw()->{LSQFrame}->pack(-anchor => 'nw', -expand => 'yes', -fill => 'x'); # $this->mw()->{LSQFrame}->{FitToListBox}->SetText('alpha'); $this->BuildFooter($MainPaneFrame, $EntryWidth); } sub BuildViewRangePane { my ($this, $MainFrame, $EntryWidth) = @_; $this->SUPER::BuildViewRangePane($MainFrame, $EntryWidth, [ ['x'], ['x'] ], [ ['x'], ['x'] ] ); if($this->mw()->{NoteBook}->{ViewRangePaneFrame}->{GraphFrame1ViewY0Button}) { $this->mw()->{NoteBook}->{ViewRangePaneFrame}->{GraphFrame1ViewY0Button}->Select(); $this->mw()->{NoteBook}->{ViewRangePaneFrame}->{GraphFrame1ViewY0Entry}->SetText(0.0); } $this->BuildFooter($MainFrame, $EntryWidth); } sub BuildFooter { my ($this, $MainFrame, $EntryWidth) = @_; my $Frame1 = $MainFrame->MyFrame()->pack(-anchor => 'nw', -fill => 'x'); my $ButtonFrame = $this->MakeFittingButtons($Frame1, ("RePlot", "RestoreScale", "Re&calc", "&Fit", "Flip X", "&Save")); $ButtonFrame->pack(-anchor => 'nw', -expand => 'yes', -fill => 'x'); my $Frame = $MainFrame->MyFrame()->pack(-anchor => 'nw', -fill => 'x'); $this->{ChooseExcitatioListBox} = $ButtonFrame->MyBrowseEntry( -label => "Excitation:", -state => "readonly", -takefocus => 1, -width => 15, -Selections => ["He I(21.2eV)", "He IIalpha(40.80eV)", "He IIbeta(48.36eV)", "Ne I(16.7eV)", "Ne II(26.9eV)", "Al Ka(1486.6eV)", "Mg Ka(1253.6eV)", "HX-PES(BL47XU, 7935.2eV)", "HX-PES(BL15XU, 5950.2eV)"], -SelIndex => 0, )->pack(-side => 'left'); } #=================================================== # データ処理 #=================================================== sub FlipX { my ($this, $FlipRange) = @_; $FlipRange = 1 if(!defined $FlipRange); my $App = $this->App(); my $optics = new Optics; my $ini = $this->{ini}; return if(!defined $this->{DataFile}); #print "FlipX\n"; my $X1Label = $this->{SampleFileFrame}->{X1ListBox}->GetText(); my $Y1Label = $this->{SampleFileFrame}->{Y1ListBox}->GetText(); my $pX = $this->{DataFile}->GetData($X1Label) if($X1Label); # my $pY1 = $this->{DataFile}->GetData($Y1Label) if($Y1Label); my $nData = $this->{DataFile}->nData(); for(my $i = 0 ; $i < $nData ; $i++) { $pX->[$i] = -$pX->[$i]; } ($ini->{FitXMin}, $ini->{FitXMax}) = (-$ini->{FitXMax}, -$ini->{FitXMin}) if($FlipRange); if(!$this->{ini}->{FlipX}) { $this->{ini}->{FlipX} = 1; } else { $this->{ini}->{FlipX} = 0; } $this->RePlot(); } sub BuildOptimize { my ($this, $IsPrint) = @_; $IsPrint = 1 if(!defined $IsPrint); my $ini = $this->{ini}; my $dini = $this->{dini}; my $optimize = $this->{Optimize} = new Optimize;; $optimize->AddParameters( "EF", \$ini->{EF}, $dini->{EFcheck}, $dini->{EFscale}, $dini->{EFmin}, $dini->{EFmax}, sub { $ini->{EF} = $_[0]; }, "Wa", \$ini->{Wa}, $dini->{Wacheck}, $dini->{Wascale}, $dini->{Wamin}, $dini->{Wamax}, sub { $ini->{Wa} = $_[0]; }, "BG", \$ini->{BG}, $dini->{BGcheck}, $dini->{BGscale}, $dini->{BGmin}, $dini->{BGmax}, sub { $ini->{BG} = $_[0]; }, ); for(my $i = 0 ; $i < $this->{ini}->{nStepBG} ; $i++) { my $ii = $i; $optimize->AddParameters( "EBG0$ii", \$ini->{"EBG0$ii"}, $dini->{"EBG0${ii}check"}, $dini->{"EBG0${ii}scale"}, $dini->{"EBG0${ii}min"}, $dini->{"EBG0${ii}max"}, sub { $ini->{"EBG0$ii"} = $_[0]; }, "BGLeft$ii", \$ini->{"BGLeft$ii"}, $dini->{"BGLeft${ii}check"}, $dini->{"BGLeft${ii}scale"}, $dini->{"BGLeft${ii}min"}, $dini->{"BGLeft${ii}max"}, sub { $ini->{"BGLeft$ii"} = $_[0]; }, "WBG$ii", \$ini->{"WBG$ii"}, $dini->{"WBG${ii}check"}, $dini->{"WBG${ii}scale"}, $dini->{"WBG${ii}min"}, $dini->{"WBG${ii}max"}, sub { $ini->{"WBG$ii"} = $_[0]; }, ); } $optimize->AddParameters( "ECBM", \$ini->{ECBM}, $dini->{ECBMcheck}, $dini->{ECBMscale}, $dini->{ECBMmin}, $dini->{ECBMmax}, sub { $ini->{ECBM} = $_[0]; }, "D0CB", \$ini->{D0CB}, $dini->{D0CBcheck}, $dini->{D0CBscale}, $dini->{D0CBmin}, $dini->{D0CBmax}, sub { $ini->{D0CB} = $_[0]; }, "EVBM", \$ini->{EVBM}, $dini->{EVBMcheck}, $dini->{EVBMscale}, $dini->{EVBMmin}, $dini->{EVBMmax}, sub { $ini->{EVBM} = $_[0]; }, "D0VB", \$ini->{D0VB}, $dini->{D0VBcheck}, $dini->{D0VBscale}, $dini->{D0VBmin}, $dini->{D0VBmax}, sub { $ini->{D0VB} = $_[0]; }, "Ecut", \$ini->{Ecut}, $dini->{Ecutcheck}, $dini->{Ecutscale}, $dini->{Ecutmin}, $dini->{Ecutmax}, sub { $ini->{Ecut} = $_[0]; }, "K0Ecut", \$ini->{K0Ecut}, $dini->{K0Ecutcheck}, $dini->{K0Ecutscale}, $dini->{K0Ecutmin}, $dini->{K0Ecutmax}, sub { $ini->{K0Ecut} = $_[0]; }, "BGcut", \$ini->{BGcut}, $dini->{BGcutcheck}, $dini->{BGcutscale}, $dini->{BGcutmin}, $dini->{BGcutmax}, sub { $ini->{BGcut} = $_[0]; }, "C0Exp", \$ini->{C0Exp}, $dini->{C0Expcheck}, $dini->{C0Expscale}, $dini->{C0Expmin}, $dini->{C0Expmax}, sub { $ini->{C0Exp} = $_[0]; }, "WExp", \$ini->{WExp}, $dini->{WExpcheck}, $dini->{WExpscale}, $dini->{WExpmin}, $dini->{WExpmax}, sub { $ini->{WExp} = $_[0]; }, "BetaExp", \$ini->{BetaExp}, $dini->{BetaExpcheck}, $dini->{BetaExpscale}, $dini->{BetaExpmin}, $dini->{BetaExpmax}, sub { $ini->{BetaExp} = $_[0]; }, ); for(my $i = 0 ; $i < $this->{ini}->{nGL} ; $i++) { my $ii = $i; $optimize->AddParameters( "GLE0$ii", \$ini->{"GLE0$ii"}, $dini->{"GLE0${ii}check"}, $dini->{"GLE0${ii}scale"}, $dini->{"GLE0${ii}min"}, $dini->{"GLE0${ii}max"}, sub { $ini->{"GLE0$ii"} = $_[0]; }, "GLC0$ii", \$ini->{"GLC0$ii"}, $dini->{"GLC0${ii}check"}, $dini->{"GLC0${ii}scale"}, $dini->{"GLC0${ii}min"}, $dini->{"GLC0${ii}max"}, sub { $ini->{"GLC0$ii"} = $_[0]; }, "GLWL$ii", \$ini->{"GLWL$ii"}, $dini->{"GLWL${ii}check"}, $dini->{"GLWL${ii}scale"}, $dini->{"GLWL${ii}min"}, $dini->{"GLWL${ii}max"}, sub { $ini->{"GLWL$ii"} = $_[0]; }, "GLGFraction$ii", \$ini->{"GLGFraction$ii"}, $dini->{"GLGFraction${ii}check"}, $dini->{"GLGFraction${ii}scale"}, $dini->{"GLGFraction${ii}min"}, $dini->{"GLGFraction${ii}max"}, sub { $ini->{"GLGFraction$ii"} = $_[0]; }, "GLGWRatio$ii", \$ini->{"GLGWRatio$ii"}, $dini->{"GLGWRatio${ii}check"}, $dini->{"GLGWRatio${ii}scale"}, $dini->{"GLGWRatio${ii}min"}, $dini->{"GLGWRatio${ii}max"}, sub { $ini->{"GLGWRatio$ii"} = $_[0]; }, ); } } sub Recalc { my ($this) = @_; return if(!defined $this->{DataFile}); my $ini = $this->{ini}; # $ini->{AppFunction} = $this->{ChooseAppFunctionListBox}->GetText(); my $ConductionType = $this->{ini}->{ConductionType}; #$this->{ChooseConductionTypeListBox}->GetText(); my $IsMetal = 0; $IsMetal = 1 if($ConductionType eq 'Metal'); my $X1Label = $this->{SampleFileFrame}->{X1ListBox}->GetText(); my $Y1Label = $this->{SampleFileFrame}->{Y1ListBox}->GetText(); my $XMin = $ini->{FitXMin}; my $XMax = $ini->{FitXMax}; my $nSkipData = $ini->{nSkipData}; my $pX = $this->{DataFile}->GetData($X1Label) if($X1Label); my $pY1 = $this->{DataFile}->GetData($Y1Label) if($Y1Label); my (@X, @Y); my $c = 0; 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] = $x; $Y[$c] = $pY1->[$i]; $c++; } $this->{pCalX} = \@X; my ($pY, $pCB, $pVB, $pCBFD, $pVBFD, $pGLArray, $pFD, $pBG) = PES::CalTotalDOSSpectrum(\@X, $this->{ini}, $IsMetal); $this->{pObsY} = \@Y; $this->{pCalY} = $pY; $this->{pCalCB} = $pCB; $this->{pCalVB} = $pVB; $this->{pCalCBFD} = $pCBFD; $this->{pCalVBFD} = $pVBFD; $this->{pCalGLArray} = $pGLArray; $this->{pCalFD} = $pFD; $this->{pCalBG} = $pBG; $this->RePlot(); } sub Fit { my ($this) = @_; return if(!defined $this->{DataFile}); my $App = $this->App(); my $optics = new Optics; my $ini = $this->{ini}; $this->UpdateParameters(); $this->BuildOptimize(); my $Method = $this->mw()->{LSQFrame}->{LSQMethodListBox}->GetText(); #$this->{LSQMethodListBox}->GetText(); my $optimize = $this->{Optimize}; print "Method: $Method\n"; print "nMaxIter: $ini->{nMaxIter}\n"; # $this->{ini}->{AppFunction} = $this->{ChooseAppFunctionListBox}->GetText(); my $ConductionType = $this->{ini}->{ConductionType}; #$this->{ChooseConductionTypeListBox}->GetText(); my $IsMetal = 0; $IsMetal = 1 if($ConductionType eq 'Metal'); my $X1Label = $this->{SampleFileFrame}->{X1ListBox}->GetText(); my $Y1Label = $this->{SampleFileFrame}->{Y1ListBox}->GetText(); my $XMin = $ini->{FitXMin}; my $XMax = $ini->{FitXMax}; my $nSkipData = $ini->{nSkipData}; my $pX = $this->{DataFile}->GetData($X1Label) if($X1Label); my $pY1 = $this->{DataFile}->GetData($Y1Label) if($Y1Label); my (@X, @Y); my $c = 0; 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] = $x; $Y[$c] = $pY1->[$i]; $c++; } #========================================================= # 最適化の実行 #========================================================= $optimize->SetnS2Calculation(0); my ($OptVars, $MinVal) = $optimize->Optimize( $Method, undef, undef, undef, $ini->{EPS}, $ini->{nMaxIter}, $ini->{iPrintLevel}, sub { $this->CalS2(\@X, \@Y, $IsMetal, @_); }, undef, sub { Optimize::BuildDifferentialMatrixes(@_); }, ); print "\nOptimized at:\n"; $optimize->RecoverParameters($OptVars); $optimize->PrintParameters(1, $OptVars, $MinVal, 1); $this->SetS2($MinVal); $this->UpdateParameters(); $this->Recalc(); } sub CalS2 { my ($this, $pX, $pY, $IsMetal, $pVars, $iPrintLevel) = @_; #print "pVars=", join(',', @$pVars); my $optimize = $this->{Optimize}; my $ini = $this->{ini}; $optimize->RecoverParameters($pVars); my ($pCalY) = PES::CalTotalDOSSpectrum($pX, $ini, $IsMetal); my $S2 = 0.0; my $c = 0; for(my $i = 0 ; $i < @$pX ; $i++) { my $x = $pX->[$i]; my $d = $pCalY->[$i] - $pY->[$i]; $S2 += $d * $d; $c++; } $S2 = sqrt($S2 / $c) if($c > 0); $optimize->IncrementnS2(); my $nS2 = $optimize->nS2Calculation(); my $nS2Interval = $ini->{nSaveSpectraInterval}; print "S2[$nS2] = $S2 / "; $S2 += $optimize->CalPenalty(1.0e10, $pVars, 1); print "$S2\n"; $optimize->PrintParameters(1, $pVars, $S2, 0); if($nS2Interval > 0 and $nS2 % $nS2Interval == 0) { $this->SetS2($S2); $this->Recalc(); $this->RePlot(); } $this->UpdateParameters(); $this->mw()->update(); return $S2; } sub Save { my ($this) = @_; $this->Recalc() if(!defined $this->{pCalX}); my $path = $this->{ini}->{ParameterFile}; $path = $this->{ini}->{SampleCSVFile} if(!$path); my $dir = Deps::ExtractDirectory($path); $path = Deps::MakePath($dir, "PES.csv", 0); $this->print("\nSave decomposed spectra to [$path].\n"); my $out = new JFile($path, "w"); if(!$out) { $this->print("Error: Can not write to [$path].\n"); return; } $out->print("E,PES(obs),PES(cal),CB(cal),VB(cal),CB*FD(cal),VB*FD(cal)"); for(my $i = 0 ; $i < $this->{ini}->{nGL} ; $i++) { $out->print(",GL${i}(cal)"); } $out->print(",FD(cal),BG(cal)\n"); my $pE = $this->{pCalX}; my $pObs = $this->{pObsY}; my $pPES = $this->{pCalY}; my $pCB = $this->{pCalCB}; my $pVB = $this->{pCalVB}; my $pCBFD = $this->{pCalCBFD}; my $pVBFD = $this->{pCalVBFD}; my $pGLArray = $this->{pCalGLArray}; my $pFD = $this->{pCalFD}; my $pBG = $this->{pCalBG}; for(my $i = 0 ; $i < @$pE ; $i++) { $out->print("$pE->[$i],$pObs->[$i],$pPES->[$i],$pCB->[$i],$pVB->[$i],$pCBFD->[$i],$pVBFD->[$i]"); for(my $j = 0 ; $j < $this->{ini}->{nGL} ; $j++) { $out->print(",$pGLArray->[$j][$i]"); } $out->print(",$pFD->[$i],$pBG->[$i]\n"); } $out->Close(); } sub SaveParameterFile { my ($this, $Option, $filepath, $name, $Frame) = @_; $filepath = $Frame->{PathEntry}->GetText() if($filepath eq ''); $this->{ini}->{SampleX1} = $this->{SampleFileFrame}->{X1ListBox}->GetText(); $this->{ini}->{SampleY1} = $this->{SampleFileFrame}->{Y1ListBox}->GetText(); # $this->{ini}->{AppFunction} = $this->{ChooseAppFunctionListBox}->GetText(); # $this->{ini}->{ConductionType} = $this->{ChooseConductionTypeListBox}->GetText(); $this->{ini}->{YAxisPlotType} = $this->mw()->{NoteBook}->{ViewRangePaneFrame}->{GraphFrame1YAxisListBox}->GetText(); if(!defined $filepath or $filepath eq '') { $filepath = $this->{ini}->{Sample1CSVFile}; $filepath = $this->{ini}->{SampleCSVFile} if(!defined $filepath or $filepath eq ''); $filepath = $this->{ini}->{SubstrateCSVFile} if(!defined $filepath or $filepath eq ''); $filepath = 'save.prm' if(!defined $filepath or $filepath eq ''); $filepath =~ s/\.[^\.]+$/\.prm/i; # $filepath =~ s/\.csv$/\.prm/i; $filepath = Deps::ExtractFileName($filepath); $filepath = $this->ChooseSaveFile($filepath, '*.prm'); if($filepath) { my $ext = Deps::ExtractExtention($filepath); if(!defined $ext or $ext eq '') { $filepath = Deps::ReplaceExtension($filepath, ".prm"); } $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->DecomposeParameters($ini, $dini); $this->RefreshMainPane($this->{EntryWidth}); my $DataFrame = $this->{SampleFileFrame}; $this->{ini}->{SampleX1} = $this->{ini}->{X} if(!defined $this->{ini}->{SampleX1}); $this->{ini}->{SampleY1} = $this->{ini}->{Y1} if(!defined $this->{ini}->{SampleY1}); $DataFrame->{X1ListBox}->SetText($this->{ini}->{SampleX1}) if($this->{ini}->{SampleX1}); $DataFrame->{Y1ListBox}->SetText($this->{ini}->{SampleY1}) if($this->{ini}->{SampleY1}); # $this->{ChooseAppFunctionListBox}->SetText($this->{ini}->{AppFunction}); # $this->{ChooseConductionTypeListBox}->SetText($this->{ini}->{ConductionType}); if($this->{ini}->{SampleCSVFile}) { my $path = $this->{ini}->{SampleCSVFile}; $path = $this->GetValidDataPath($path, $filepath, $this->{ini}->{ParameterFile}); my $ret = $this->ReadSampleDataFile($path, 1, 0, 0); return undef unless($ret); $this->{ini}->{SampleCSVFile} = $path; $this->{ini}->{ParameterFile} = $filepath; if($this->{ini}->{FlipX}) { $this->FlipX(0); $this->{ini}->{FlipX} = 1; } } $this->RePlot(0, 1, 0, 0); $this->RefreshViewRangePane($this->{EntryWidth}); my $YAxisListBox = $this->{ini}->{YAxisPlotType}; #$this->mw()->{NoteBook}->{ViewRangePaneFrame}->{GraphFrame1YAxisListBox}; if($YAxisListBox) { $this->mw()->{NoteBook}->{ViewRangePaneFrame}->{GraphFrame1YAxisListBox}->SetText($this->{ini}->{YAxisPlotType}) if($this->{ini}->{YAxisPlotType}); } $this->RePlot(1, 0, 1, 1); return 1; } sub ReadSampleDataFile { my ($this, $filepath, $IsPrint, $UpdateRange, $IsPlot, $Frame) = @_; $UpdateRange = 1 if(!defined $UpdateRange); $IsPlot = 1 if(!defined $IsPlot); $Frame = $this->{SampleFileFrame} if(!defined $Frame); my $App = $this->App(); my $pXDataLabel = $Frame->{pXDataLabel}; my $pYDataLabel = $Frame->{pYDataLabel}; #print "type=$type\n"; $this->Initialize(0, 1); my $pData = $this->{DataFile} = new Ellipsometry; $this->{Path} = $filepath; my ($nData, $pLabelArray, @pDataArray) = $pData->Read($filepath); print "pDataArray[0],[1]=$pDataArray[0],$pDataArray[1]\n"; if($filepath =~ /\.txt$/i) { if($pDataArray[0] =~ /ARRAY/) { my $p = $pDataArray[0]; @pDataArray = @$p; } } # if($pDataArray[0] =~ /ARRAY/) { # my $p = $pDataArray[0]; # @pDataArray = @$p; # } #print "pL1=$pLabelArray->[0] / pL1=$pLabelArray->[1]\n"; #print "pD1=$pDataArray[0] / pD1=$pDataArray[1]\n"; #my $i =0; #while(1) { # my $x = $pDataArray[0][$i]; # last if(!defined $x); # my $y = $pDataArray[1][$i]; #print "$i: ($x, $y)\n"; # $i++; #} if(!defined $nData) { $App->print("Error: Can not read [$filepath].\n"); return $this->{Path} = undef; } if(!Utils::IsConstantStepArray($pDataArray[0], 0.01)) { $App->print("Error: The data step for X is not constant.\n"); return $this->{Path} = undef; } my $nDataArray = $this->{DataFile}->nDataArray(); $Frame->{X1ListBox}->DeleteAllItem() if(defined $Frame->{X1ListBox}); $Frame->{Y1ListBox}->DeleteAllItem() if(defined $Frame->{Y1ListBox}); for(my $i = 0 ; $i < $nDataArray ; $i++) { $Frame->{X1ListBox}->AddItem($pLabelArray->[$i]) if(defined $Frame->{X1ListBox}); $Frame->{Y1ListBox}->AddItem($pLabelArray->[$i]) if(defined $Frame->{Y1ListBox}); } $Frame->{X1ListBox}->SetCurSel(@$pXDataLabel) if(defined $Frame->{X1ListBox}); $Frame->{Y1ListBox}->SetCurSel(@$pYDataLabel) if(defined $Frame->{Y1ListBox}); $pData->GetXData(@$pXDataLabel); $pData->GetYData(@$pYDataLabel); $pData->CalMinMax(); ($this->{ini}->{FitEmin}, $this->{ini}->{FitEmax}) = $pData->GetXMinMax() if(!defined $this->{ini}->{FitEmin} or $this->{ini}->{FitEmin} eq ''); if($UpdateRange or !defined $this->{ini}->{FitXMin}) { ($this->{ini}->{FitXMin}, $this->{ini}->{FitXMax}) = Utils::CalMinMax($pDataArray[0]); } if($IsPlot) { $this->RePlot($UpdateRange); } else { $this->CreateGraphFrame() if(!$this->GetGraphFrameArray()); $this->AssignGraphData(); } return $filepath; } sub CreateGraphFrame { my ($this, $canvas, $TargetData, $DoUpdate) = @_; return if(!$DoUpdate and $this->GetGraphFrameArray()); $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 $RefreshGraphScaleFrame = (defined $this->{GraphFrameArray})? 0 : 1; 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); if($RefreshGraphScaleFrame) { my $EntryWidth = $this->{EntryWidth}; $this->RefreshViewRangePane($EntryWidth); } } sub AssignGraphData { my ($this, $ResetViewRange) = @_; $ResetViewRange = 1 if(!defined $ResetViewRange); return if(!defined $this->{ini}->{SampleCSVFile}); return if(!defined $this->mw()->{NoteBook}->{ViewRangePaneFrame}->{GraphFrame1YAxisListBox}); my $GraphFrameArray = $this->GetGraphFrameArray(); my $GraphFrame0 = $GraphFrameArray->GetGraphFrame(0); $GraphFrame0->ClearAllData(); my $X1Label = $this->{SampleFileFrame}->{X1ListBox}->GetText(); $X1Label = 'X' if(!$X1Label); my $Y1Label = $this->{SampleFileFrame}->{Y1ListBox}->GetText(); $Y1Label = 'Y1' if(!$Y1Label); $GraphFrame0->SetXCaption($X1Label); $GraphFrame0->SetYCaption($Y1Label); my $pX = $this->{DataFile}->GetData($X1Label) if($X1Label); 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}; my $pCB = $this->{pCalCB}; my $pVB = $this->{pCalVB}; my $pCBFD = $this->{pCalCBFD}; my $pVBFD = $this->{pCalVBFD}; my $pGLArray = $this->{pCalGLArray}; my $pFD = $this->{pCalFD}; my $pBG = $this->{pCalBG}; if($pCalX) { $GraphFrame0->AddGraphData($pCalX, $pCalY, 0, "", "circle", 3, "", 1, "red", "XAutoSkip", "Energy", "FT ${Y1Label}(real)") if($pCalY); $GraphFrame0->AddGraphData($pCalX, $pCB, 1, "blue", "", 3, "", 1, "red", "XAutoSkip", "Energy", "CB(cal)") if($pCB); $GraphFrame0->AddGraphData($pCalX, $pVB, 1, "blue", "", 3, "", 1, "red", "XAutoSkip", "Energy", "VB(cal)") if($pVB); $GraphFrame0->AddGraphData($pCalX, $pCBFD, 1, "green", "", 3, "", 1, "red", "XAutoSkip", "Energy", "CB*FD(cal)") if($pCBFD); $GraphFrame0->AddGraphData($pCalX, $pVBFD, 1, "green", "", 3, "", 1, "red", "XAutoSkip", "Energy", "VB*FD(cal)") if($pVBFD); for(my $i = 0 ; $i < $this->{ini}->{nGL} ; $i++) { $GraphFrame0->AddGraphData($pCalX, $pGLArray->[$i], 1, "blue", "", 3, "", 1, "red", "XAutoSkip", "Energy", "GL${i}(cal)") if($pGLArray->[$i]); } $GraphFrame0->AddGraphData($pCalX, $pBG, 1, "cyan", "", 3, "", 1, "red", "XAutoSkip", "Energy", "BG(cal)") if($pBG); } $GraphFrame0->SetXScalePlotType('x'); $GraphFrame0->SetYScalePlotType('x'); $this->SetViewRange($ResetViewRange); } sub Initialize { my ($this, $InitializeParameterFile, $InitializeData) = @_; $this->{DataFile} = new Ellipsometry; if($InitializeParameterFile) { $this->{ini}->{SampleCSVFile} = ''; $this->{ini}->{FlipX} = 0; $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, '', ''); $this->AddParameters($ini, $dini, "T", 300.0, 0, 10.0, 0.0, ''); $this->AddParameters($ini, $dini, "Wa", 0.1, 1, 0.2, 0.0, ''); $this->AddParameters($ini, $dini, "BG", 0.0, 1, 1000.0, 0.0, ''); for(my $i = 0 ; $i < $this->{ini}->{nStepBG} ; $i++) { $this->AddParameters($ini, $dini, "EBG0$i", 0.0, 0, 1.0, '', ''); $this->AddParameters($ini, $dini, "BGLeft$i", 0.0, 0, 1000.0, 0.0, ''); $this->AddParameters($ini, $dini, "WBG$i", 0.1, 0, 1.0, 0.0, ''); } $this->AddParameters($ini, $dini, "ECBM", 0.0, 0, 1.0, '', ''); $this->AddParameters($ini, $dini, "D0CB", 0.0, 0, 1000.0, 0.0, ''); $this->AddParameters($ini, $dini, "EVBM", -3.0, 0, 1.0, '', ''); $this->AddParameters($ini, $dini, "D0VB", 0.0, 0, 1000.0, 0.0, ''); $this->AddParameters($ini, $dini, "Ecut", 0.0, 0, 1.0, '', ''); $this->AddParameters($ini, $dini, "K0Ecut", 0.0, 0, 1000.0, 0.0, ''); $this->AddParameters($ini, $dini, "BGcut", 0.0, 0, 1000.0, 0.0, ''); $this->AddParameters($ini, $dini, "C0Exp", 0.0, 0, 1000.0, 0.0, ''); $this->AddParameters($ini, $dini, "WExp", 1.0, 0, 1.0, 0.0, ''); $this->AddParameters($ini, $dini, "BetaExp", 1.0, 0, 0.5, 0.0, ''); for(my $i = 0 ; $i < $this->{ini}->{nGL} ; $i++) { $this->AddParameters($ini, $dini, "GLE0$i", 0.0, 0, 1.0, '', ''); $this->AddParameters($ini, $dini, "GLC0$i", 0.0, 0, 1000.0, 0.0, ''); $this->AddParameters($ini, $dini, "GLWL$i", 0.3, 0, 0.1, 0.0, ''); $this->AddParameters($ini, $dini, "GLGFraction$i", 1.0, 0, 0.1, 0.0, 1.0); $this->AddParameters($ini, $dini, "GLGWRatio$i", 1.0, 0, 0.1, 0.0, ''); } } 1;