#=============================================== # TkCPM #=============================================== package TkCPM; use clib::TkFittingCommon; @ISA = qw(TkFittingCommon); #公開したいサブルーチン #@EXPORT = qw(DelSpace Reduce01 MakePath RegExpQuote); use strict; use Math::Spline; use Utils; use IniFile; use CSV; use MultiColumnData; use MyTk::GraphFrameArray; use Sci qw($e); use Sci::Algorism; use Sci::Optics; 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(); my $balloon = $this->mw()->Balloon(); my $ProgramName = $this->{ProgramName} = "CPM2007"; $this->{ini} = new IniFile; $this->{DataFile} = new MultiColumnData; $this->{pLSQData} = {}; $this->{Message} = ''; $this->{nConnection} = 10; $this->SUPER::CreateWidgets(); return if($DoSuperOnly); $this->mw()->SetTitle("$ProgramName / TkPlot"); $App->SetProgram("$ProgramName / TkPlot"); #=================================================== # Iniファイル読み込み #=================================================== my $Style = $App->Args()->GetGetArg("style"); $App->AddIniFileVariable("\\$Style\\SiSRFile", "SiSRFile", ""); $App->AddIniFileVariable("\\$Style\\InGaAsSRFile", "InGaAsSRFile", ""); $App->AddIniFileVariable("\\$Style\\AbsortpionFile", "AbsortpionFile", ""); $App->AddIniFileVariable("\\$Style\\DataDir", "DataDir", ""); $App->ReadSetting(); $this->{X} = ''; #=================================================== # ペインを作製 #=================================================== my $EntryWidth = 12; my $Frame = $mw->MyFrame()->pack(-anchor => 'nw', -fill => 'x'); $this->MakeChooseFileEntry($Frame, 'SiSR', 'SiSR:', \$App->{SiSRFile}, '&Choose', sub { $this->ChooseFile(@_); }, "ChooseSiSRFile"); $this->{EditSiSRButton} = $Frame->MyButton( -text => 'ed', -takefocus => 1, -command => sub { $this->ButtonPressed('RButtonDown', 'EditSiSRData'); }, )->pack(-side => 'left'); $Frame = $mw->MyFrame()->pack(-anchor => 'nw', -fill => 'x'); $this->MakeChooseFileEntry($Frame, 'InGaAsSR', 'InGaAsSR:', \$App->{InGaAsSRFile}, '&Choose', sub { $this->ChooseFile(@_); }, "ChooseSampleFile"); $this->{EditInGaAsSRButton} = $Frame->MyButton( -text => 'ed', -takefocus => 1, -command => sub { $this->ButtonPressed('RButtonDown', 'EditInGaAsSRData'); }, )->pack(-side => 'left'); $Frame = $mw->MyFrame()->pack(-anchor => 'nw', -fill => 'x'); $this->MakeChooseFileEntry($Frame, 'Absoprtion', 'Absorption:', \$App->{AbsortpionFile}, '&Choose', sub { $this->ChooseFile(@_); }, "ChooseAbsoprtionFile"); $this->{EditAbsoprtionButton} = $Frame->MyButton( -text => 'ed', -takefocus => 1, -command => sub { $this->ButtonPressed('RButtonDown', 'EditAbsoprtionData'); }, )->pack(-side => 'left'); $Frame = $mw->MyFrame()->pack(-anchor => 'nw', -fill => 'x'); $this->MakeChooseFileEntry($Frame, 'DataDir', 'DataDir:', \$App->{DataDir}, '&Choose', sub { $this->ChooseDataDir(@_); }, "ChooseDataDir"); $Frame = $mw->MyFrame()->pack(-anchor => 'nw', -fill => 'x'); $this->{FileListbox} = $Frame->Scrolled( 'MyListbox', -setgrid => 1, -height => 6, -scrollbars => 'e', # $this->{FileListbox} = $Frame->MyBrowseEntry( # -label => "Files:", # -state => "readonly", # -width => $App->{LeftFrameWidth}, -takefocus => 1, )->pack(-side => 'left', -expand => 'yes', -fill => 'x'); # $this->{FileListbox}->configure(-browsecmd => sub { $this->SelChangeListBox("FileList", $this->{FileListbox}); } ); $this->{FileListbox}->bind('' => sub { $this->SelChangeListBox("FileList", $this->{FileListbox}); } ); $this->{FileListbox}->bind('' => sub { $this->SelChangeListBox("FileList", $this->{FileListbox}); } ); $this->{FileListbox}->bind('' => sub { $this->ButtonPressed("Double-1", 'FileList'); } ); $this->{FileListbox}->SetCurSel(0); $balloon->attach($this->{FileListbox}, -msg => "Choose data to show", -balloonposition => 'mouse'); $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'); $lsb2->configure(-browsecmd => sub { $this->SelChangeListBox("Y1", $this->{ChooseY1ListBox}); } ); $Frame = $mw->MyFrame()->pack(-anchor => 'nw', -fill => 'x'); my $lsb4 = $this->{ChooseActionListBox} = $Frame->MyBrowseEntry( -label => "Action:", -state => "readonly", -takefocus => 1, -width => 10, -Selections => [ 'mlsq', ], -SelIndex => 0, )->pack(-side => 'left', -expand => 'yes', -fill => 'x'); $lsb4->configure(-browsecmd => sub { $this->SelChangeListBox("Direction", $this->{ChooseActionListBox}); } ); $this->{PlotTypeListbox} = $Frame->MyBrowseEntry( -label => "PlotType:", -state => "readonly", -width => 10, -takefocus => 1, )->pack(-side => 'left', -expand => 'yes', -fill => 'x'); $this->{PlotTypeListbox}->configure(-browsecmd => sub { $this->SelChangeListBox("PlotType", $this->{PlotTypeListbox}); } ); $Frame = $mw->MyLabFrame( -label => 'Output', -labelside => 'acrosstop', )->pack(-anchor => 'nw', -fill => 'x'); $this->MakeLabelEntry($Frame, "X0", "X:", $this->{ini}->pVariable('X0', 0.0), "%g", $EntryWidth, "", 0, 0); $this->MakeLabelEntry($Frame, "X1", "-", $this->{ini}->pVariable('X1', 0.0), "%g", $EntryWidth, "", 0, 1); $this->MakeLabelEntry($Frame, "XStep", ",", $this->{ini}->pVariable('XStep', 0.05), "%g", $EntryWidth, "", 0, 2); $Frame = $mw->MyLabFrame( -label => 'mlsq', -labelside => 'acrosstop', )->pack(-anchor => 'nw'); $this->MakeLabelEntry($Frame, "m", "m:", $this->{ini}->pVariable('m', 3), "%d", $EntryWidth, "", 0, 0); $Frame = $mw->MyLabFrame( -label => 'Find', -labelside => 'acrosstop', )->pack(-anchor => 'nw'); $this->MakeLabelEntry($Frame, "Y", "Y:", $this->{ini}->pVariable('Y', 1.0e-7), "%g", $EntryWidth, "", 0, 0); $this->MakeLabelEntry($Frame, "X", "X:", \$this->{X}, "%s", $EntryWidth, "", 0, 1); $this->{FindYButton} = $Frame->MyButton( -text => 'Find &X', -takefocus => 1, -command => sub { $this->ButtonPressed('RButtonDown', 'FindY'); }, )->grid(-row => 0, -column => 7, -columnspan => 1, -sticky => 'e'); $Frame = $mw->MyLabFrame( -label => 'CPM', -labelside => 'acrosstop', )->pack(-anchor => 'nw'); for(my $i = 0 ; $i < $this->{nConnection} ; $i++) { $this->MakeLabelEntry($Frame, "Ip$i", "Ip:", $this->{ini}->pVariable("Ip$i", 0.0), "%g", $EntryWidth, "A", $i, 0); $this->MakeLabelEntry($Frame, "E0$i", "E:", $this->{ini}->pVariable("E0$i", 0.0), "%6.3f", $EntryWidth-6, "-", $i, 1); $this->MakeLabelEntry($Frame, "E1$i", "", $this->{ini}->pVariable("E1$i", 0.0), "%6.3f", $EntryWidth-6, "eV", $i, 2); $this->MakeLabelEntry($Frame, "K$i", "K:", $this->{ini}->pVariable("K$i", 0.0), "%9.3g", $EntryWidth-3, "", $i, 3); $this->MakeLabelEntry($Frame, "n$i", "n:", $this->{ini}->pVariable("n$i", 0.0), "%d", 4, "", $i, 4); } $this->UpdateParameters(); $Frame = $mw->MyFrame()->pack(-anchor => 'nw', -fill => 'x'); $this->{LSQButton} = $Frame->MyButton( -text => '&LSQ', -takefocus => 1, -command => sub { $this->ButtonPressed('RButtonDown', 'LSQ'); }, )->pack(-side => 'left'); $this->{DeleteParameterFileButton} = $Frame->MyButton( -text => '&Delete Parameter File', -takefocus => 1, -command => sub { $this->ButtonPressed('RButtonDown', 'DeleteParameterFile'); }, )->pack(-side => 'left'); $this->{MeasuredRangeButton} = $Frame->MyButton( -text => 'Measured Range', -takefocus => 1, -command => sub { $this->ButtonPressed('RButtonDown', 'MeasuredRange'); }, )->pack(-side => 'left'); $this->{CPMButton} = $Frame->MyButton( -text => 'CPM', -takefocus => 1, -command => sub { $this->ButtonPressed('RButtonDown', 'CPM'); }, )->pack(-side => 'left'); $this->{SaveCPMButton} = $Frame->MyButton( -text => 'SaveCPM', -takefocus => 1, -command => sub { $this->ButtonPressed('RButtonDown', 'SaveCPM'); }, )->pack(-side => 'left'); $Frame = $mw->MyFrame()->pack(-anchor => 'nw', -fill => 'x'); $this->MakeLabelEntry($Frame, "Message", "Message:", \$this->{Message}, "%s", 40, "", 0, 0); #ツールバーのOpenボタンをファイル読み込みにバインドする $mw->{OpenButton}->configure( -command => sub { $this->ChooseFile($this->{SampleCSVEntry}); }, ) if($mw->{OpenButton}); $this->mw()->after(1, sub { $this->FirstShown(); }); } sub FirstShown { my ($this) = @_; $this->ReadDataDir($this->App()->{DataDir}) if($this->App()->{DataDir}); } sub Initialize { my ($this, $InitializeParameterFile, $InitializeData) = @_; $this->{DataFile} = new MultiColumnData; if($InitializeParameterFile) { $this->{ini}->{SampleCSVFile} = ''; $this->{PlotTypeListbox}->DeleteAllItem(); $this->{FileListbox}->DeleteAllItem(); for(my $i = 0 ; $i < $this->{nConnection} ; $i++) { $this->{ini}->{"Ip$i"} = 0.0; $this->{ini}->{"E0$i"} = 0.0; $this->{ini}->{"E1$i"} = 0.0; $this->{ini}->{"K$i"} = 0.0; $this->{ini}->{"n$i"} = 0; } } if($InitializeData) { $this->{pCalX} = undef; $this->{pCalY1} = undef; $this->{pCalY2} = undef; $this->{FindX} = undef; $this->{FindY} = undef; $this->{CPME} = undef; $this->{CPMIp} = undef; $this->{CPMIpd} = undef; $this->{CPMSR} = undef; $this->{CPMF} = undef; $this->{CPMAlpha} = undef; $this->{CPMK} = undef; $this->{Alpha} = undef; } } sub ChooseDataDir { my ($this, $type, $entry, $action) = @_; my $fmask = '*.*'; my $defstr = ''; my $message = 'Choose file'; my $dir = ''; my $filepath = Dialog::OpenFileDialog($this->mw(), 'open', $fmask, $defstr, $message, $dir); return if(!$filepath); my ($drive, $directory, $filename, $ext, $lastdir, $filebody) = Deps::SplitFilePath($filepath); my $dirpath = "$drive$directory"; if($entry) { $entry->SetText($dirpath); } $this->ReadDataDir($dirpath); } sub ReadDataDir { my ($this, $dirpath) = @_; $this->Initialize(1, 1); my $lb = $this->{FileListbox}; my $filemask = Deps::MakePath($dirpath, "*nm.csv", 0); my @files = glob($filemask); foreach my $f (sort { my ($a1) = ($a =~ /(\d+)\D+\.csv/i); my ($b1) = ($b =~ /(\d+)\D+\.csv/i); $a1+0.0 <=> $b1+0.0; } @files) { my ($drive, $directory, $filename, $ext, $lastdir, $filebody) = Deps::SplitFilePath($f); $lb->AddItem($filename); } return $dirpath; } sub SelChangeListBox { my ($this, $type, $lb) = @_; #print "this:$this type=$type lb=$lb\n"; my $s = $lb->GetText(); $this->{FileListPrevSel} = -1 if(!defined $this->{FileListPrevSel}); if($type eq 'FileList') { $this->{PlotTypeListbox}->AddItemIfNew('LSQ'); $this->{PlotTypeListbox}->SetText('LSQ'); my $sel = $lb->GetText(); return if(!defined $sel); return if($this->{FileListPrevSel} eq $sel); $this->{FileListPrevSel} = $sel; $this->{CalX} = undef; $this->{CalY1} = undef; $this->{FindX} = undef; $this->{FindY} = undef; $this->mw()->SetTitle("[$sel] - $this->{ProgramName} / TkPlot"); my $path = Utils::MakePath($this->App()->{DataDir}, $sel, '/', 0); print "path=$path\n"; $this->ReadSampleDataFile($path); } elsif($type eq 'PlotType') { } $this->AssignGraphData(1); $this->Draw(); } sub ButtonPressed { my ($this, $event, $type) = @_; my $App = $this->App(); #print "this=$this event=$event type=$type\n"; if($type eq 'LSQ') { my $sel = $this->{FileListbox}->GetText(); $this->LSQ($sel, 1, 1); } elsif($type eq 'MeasuredRange') { $this->MeasuredRange(); } elsif($type eq 'CPM') { $this->CPM(); } elsif($type eq 'FindY') { $this->FindY(); } elsif($type eq 'FileList' and $event eq 'Double-1') { my $sel = $this->{FileListbox}->GetText(); my $File = Utils::MakePath($this->App()->{DataDir}, $sel, '/', 0); my $Editor = $this->App()->{EditorPath}; my $command = "$Editor $File"; system($command); return; } elsif($type eq 'SaveCPM') { $this->SaveCPM(); return; } elsif($type eq 'SaveParam') { $this->SaveParameterFile($this->{ini}->{ParameterFile}); return; } elsif($type eq 'EditParam') { my $Editor = $this->App()->{EditorPath}; my $File = $this->{ini}->{ParameterFile}; my $command = "$Editor $File"; system($command); return; } elsif($type eq 'DeleteParameterFile') { my $sel = $this->{FileListbox}->GetText(); my $path = Utils::MakePath($this->App()->{DataDir}, $sel, '/', 0); $path = Deps::ReplaceExtension($path, ".prm"); if(unlink($path)) { $this->print("[$path] has been deleted.\n"); $this->{CalX} = undef; $this->{CalY1} = undef; $this->AssignGraphData(0); $this->Draw(); } } elsif($type eq 'EditInGaAsSRData') { my $Editor = $App->{EditorPath}; my $File = $App->{InGaAsSRFile}; my $command = "$Editor $File"; system($command); return; } elsif($type eq 'EditSiSRData') { my $Editor = $App->{EditorPath}; my $File = $App->{SiSRFile}; my $command = "$Editor $File"; system($command); return; } elsif($type eq 'EditAbsoprtionData') { my $Editor = $App->{EditorPath}; my $File = $App->{AbsortpionFile}; my $command = "$Editor $File"; system($command); return; } elsif($type eq 'EditSampleCSV') { my $Editor = $this->App()->{EditorPath}; my $File = $this->{ini}->{SampleCSVFile}; my $command = "$Editor $File"; system($command); return; } elsif($type eq 'EditSubstrateCSV') { my $Editor = $this->App()->{EditorPath}; my $File = $this->{ini}->{SubstrateCSVFile}; my $command = "$Editor $File"; system($command); return; } } #=================================================== # データ処理 #=================================================== sub FindY { my ($this) = @_; $this->{Message} = ''; $this->{FindX} = undef; $this->{FindY} = undef; my $sel = $this->{FileListbox}->GetText(); my $Data = $this->{pLSQData}->{$sel}; return if(!defined $Data); my ($xmin, $xmax) = $Data->GetXMinMax(); #print "xm=$xmin,$xmax\n"; my $absxmax = abs($xmax); $absxmax = abs($xmin) if($absxmax < abs($xmin)); my $y = $this->{ini}->{Y}; $this->App()->print("Find x for y=$y\n"); my $xf = $Data->XVal($y, $absxmax * 1.0e-8); my $yf; if(!defined $xf) { $xf = 'OutOfRange'; $yf = 'undefined'; $this->{X} = $xf; $this->{Message} = sprintf('The Y value [%12.6g] is out of range', $y); $this->App()->printf('The Y value [%12.6g] is out of range', $y); } else { $yf = $Data->YVal($xf); $this->{FindX} = [$xf]; $this->{FindY} = [$yf]; $this->{X} = Utils::DelSpace(sprintf("%12.6g", $xf)); } $this->App()->print("x=$xf, y=$yf\n"); $this->UpdateParameters(); $this->AssignGraphData(0); $this->Draw(); } sub LSQ { my ($this, $FileName, $ResetViewRange, $IsSaveParamterFile) = @_; $ResetViewRange = 1 if(!defined $ResetViewRange); $IsSaveParamterFile = 0 if(!defined $IsSaveParamterFile); $this->{Message} = ''; $this->{PlotTypeListbox}->AddItemIfNew('LSQ'); $this->{PlotTypeListbox}->SetText('LSQ'); my $pX = $this->{DataFile}->pX(); my $pY1 = $this->{DataFile}->pY(); my $nData = $this->{DataFile}->nData(); my $YLabel = ''; my $Action = $this->{ChooseActionListBox}->GetText(); my $x0 = $this->{ini}->{X0}; my $x1 = abs($this->{ini}->{X1}); my $xstep = abs($this->{ini}->{XStep}); #print "Action: $Action [x=$x0 - $x1, $xstep]\n"; $this->{iTargetGraphFrame} = 0; if($Action eq 'mlsq') { my $optimize = new Optimize(); my $X0 = $this->{ini}->{X0}; my $X1 = $this->{ini}->{X1}; my (@xa, @ya); my $c = 0; for(my $i = 0 ; $i < @$pX ; $i++) { my $x = $pX->[$i]; next if($x < $X0 or $X1 < $x); $xa[$c] = $x; $ya[$c] = $pY1->[$i]; $c++; } my @c = $optimize->mlsq2(\@xa, \@ya, [1..$this->{ini}->{m}]); $optimize->PrintParameters(); my (@x, @y); for(my $i = 0 ; ; $i++) { my $xx = $x0 + $xstep * $i; last if($xx > $x1); my $yy = $optimize->YCal($xx); $x[$i] = $xx; $y[$i] = $yy; } $this->{CalX} = \@x; $this->{CalY1} = \@y; if(Utils::IsIncreasingArray(\@y)) { my $sel = $this->{FileListbox}->GetText(); $sel = $FileName if(defined $FileName); my $Data = new MultiColumnData; $Data->SetXYData(\@x, \@y); $this->{pLSQData}->{$sel} = $Data;; #print "set to [$sel]: $this->{pLSQData}->{$sel}\n"; $this->SaveParameterFile($this->{Path}) if($IsSaveParamterFile); } else { # $this->{CalX} = undef; # $this->{CalY1} = undef; $this->{Message} = 'The fitted function is not monotonously increasing'; $this->App()->print('The fitted function is not monotonously increasing'); } } else { $this->App()->print("Error in Recalc:: Invalid Action [$Action] #3.\n"); return; } $this->AssignGraphData(0); if($this->{iTargetGraphFrame} >= 1) { my $GraphFrameArray = $this->GetGraphFrameArray(); my $GraphFrame1 = $GraphFrameArray->GetGraphFrame(1); $GraphFrame1->CalMinMax(); $GraphFrame1->AdjustViewRange(0.05, 0.05, 0.05, 0.05); } $this->Draw(); } sub MeasuredRange { my ($this) = @_; $this->print("\nMeasuredRange\n"); my (@x, @y); my $c = 0; for(my $i = 0 ; ; $i++) { my $sel = $this->{FileListbox}->GetItem($i); last if(!defined $sel); my $Data = $this->{pLSQData}->{$sel}; if($Data) { $this->print("Data for [$sel] is loaded.\n"); } else { my $path = Utils::MakePath($this->App()->{DataDir}, $sel, '/', 0); next if(!-e $path); if(!$this->ReadSampleDataFile($path)) { $this->print(" Can not read [$path]: Skip.\n"); next; } $path = Deps::ReplaceExtension($path, ".prm"); if(!-e $path) { $this->print(" [$path] does not exist: Skip.\n"); next; } #print "LSQ: $sel\n"; # $this->LSQ($sel, 1, 0); $this->mw()->update(); $Data = $this->{pLSQData}->{$sel}; if(!$Data) { $this->print(" Error: Data for [$sel] is not found.\n"); next; } } my ($xmin, $xmax, $ymin, $ymax) = $Data->GetMinMax(); my $ystep = ($ymax - $ymin) * 0.1; my ($wl) = ($sel =~ /^(\d+)/); my $E =Optics::nmToeV($wl); #print "wl: $sel: $wl\n"; for(my $i = 0 ; $i < 11 ; $i++) { $x[$c] = $E; $y[$c] = $ymin + $ystep * $i; #print "$c: $E: $x[$c],$y[$c]\n"; $c++; } } $this->{MeasuredRangeE} = \@x; $this->{MeasuredRangeIp} = \@y; $this->{PlotTypeListbox}->AddItemIfNew('MeasuredRange'); $this->{PlotTypeListbox}->SetText('MeasuredRange'); $this->CreateGraphFrame(); $this->AssignGraphData(1); $this->Draw(); } sub CPM { my ($this) = @_; my $kIp1 = 0.3; my $kIp2 = 0.7; my $App = $this->App(); $this->print("\nCPM\n"); my $SiSRData = new MultiColumnData; if(!$SiSRData->Read($App->{SiSRFile})) { $this->print("Error: Can not read [$App->{SiSRFile}].\n"); return; } my $InGaAsSRData = new MultiColumnData; if(!$InGaAsSRData->Read($App->{InGaAsSRFile})) { $this->print("Error: Can not read [$App->{InGaAsSRFile}].\n"); return; } my $AbsorptionData = new MultiColumnData; if(!$AbsorptionData->Read($App->{AbsortpionFile})) { $this->print("Error: Can not read [$App->{AbsortpionFile}].\n"); return; } my ($pE, $pa) = $AbsorptionData->SetXYDataByLabels('E.*', 'alpha.*'); my (@Ip, @Ipd, @SR, @F, @alpha, @K); my $c = 0; my $iConnection = 0; my $nConnection = 0; my $AlphaConnection = 0.0; my $PrevE = 0.0; my $K = 1.0; my $Ip; my @E = (); my @alphaCPM = (); # my @ECPM = (); # my @aCPM = (); # my $CPM = new MultiColumnData; # $CPM->SetXYDataByArrays(\@E, \@alphaCPM); # $CPM->SetXYDataByArrays(\@ECPM, \@aCPM); for(my $i = 0 ; ; $i++) { my $sel = $this->{FileListbox}->GetItem($i); last if(!defined $sel); my $Data = $this->{pLSQData}->{$sel}; next if(!$Data); my ($wl) = ($sel =~ /^(\d+)/); my $E =Optics::nmToeV($wl); my ($xmin, $xmax, $ymin, $ymax) = $Data->GetMinMax(); if(!defined $Ip) { #print "y=$ymin,$ymax\n"; $Ip = $ymin + ($ymax - $ymin) * $kIp1; $this->{ini}->{"Ip$iConnection"} = $Ip; $this->{ini}->{"E0$iConnection"} = $E; } my $Ipd = $Data->XVal($Ip, $xmax * 1.0e-8); if(!defined $Ipd) { $this->{ini}->{"E1$iConnection"} = $PrevE; $this->{ini}->{"n$iConnection"} = $nConnection; if($nConnection == 0) { } elsif($nConnection <= 2) { $c -= $nConnection; $nConnection = 0; } elsif($nConnection > 2) { $iConnection++; $nConnection = 0; } # $this->printf(" Ipd for Ip=%12.6g A is not found for E=%6.3f eV\n", $Ip, $E); my $Iph = $Ip * 0.7; my $Ip2 = $ymin + ($ymax - $ymin) * $kIp2; $Ip = ($Ip2 < $Iph)? $Iph : $Ip2; last if($Ip < 1.0e-17); # $this->printf(" Ip is changed to Ip=%12.6g A\n", $Ip); my $j; for($j = $i-1 ; $j >= 0 ; $j--) { my $selj = $this->{FileListbox}->GetItem($j); next if(!defined $selj); my $Dataj = $this->{pLSQData}->{$selj}; next if(!defined $Dataj); my ($xminj, $xmaxj, $yminj, $ymaxj) = $Dataj->GetMinMax(); #print "Ip=$Ip [$yminj, $ymaxj]\n"; last if($Ip < $yminj or $ymaxj < $Ip); } $i = $j+1 if($j > 0); my $seli = $this->{FileListbox}->GetItem($i); my ($wli) = ($seli =~ /^(\d+)/); my $Ei =Optics::nmToeV($wli); $AlphaConnection = 0.0; for(my $j = @E-1 ; $j >= 0 ; $j--) { #print "j=$j: $Ei / $E[$j]\n"; if(abs($E[$j] - $Ei) <= 1.0e-3) { $AlphaConnection = $alphaCPM[$j]; last; } } # $AlphaConnection = $CPM->YVal($Ei); $this->printf("Ei: %6.3feV a=%9.3g\n", $Ei, $AlphaConnection); $this->{ini}->{"Ip$iConnection"} = $Ip; $this->{ini}->{"E0$iConnection"} = $E; redo; } my $SiSR = $SiSRData->YVal($wl); my $InGaAsSR = $InGaAsSRData->YVal($wl); $alpha[$c] = $AbsorptionData->YVal($E); $E[$c] = $E; $Ip[$c] = $Ip; $Ipd[$c] = $Ipd; $SR[$c] = ($wl > 1100)? $InGaAsSR : $SiSR; $F[$c] = $Ipd / ($SR[$c]*0.001) / ($E * $e); my $aCPM = 1.0 / $F[$c] * $K; if($c == 0) { my $a = $AbsorptionData->YVal($E); $K = $a / $aCPM; $this->{ini}->{"K0"} = $K; printf "K0 set to %9.3g\n", $K; } if($nConnection == 0 and $aCPM > 0.0 and $AlphaConnection > 0.0) { $K *= $AlphaConnection / $aCPM; printf "K set to %9.3g\n", $K; } $K[$c] = $K; $alphaCPM[$c] = 1.0 / $F[$c] * $K; $this->{ini}->{"K$iConnection"} = $K; # push(@ECPM, $E); # push(@aCPM, $alphaCPM[$c]); $this->printf("%6.3feV a=%9.3g Ipd=%6.3fnA Ip=%4.0ffA SR=%4.0fmA/W F=%9.3g/s\n", $E, $alphaCPM[$c], $Ipd*1e9, $Ip*1e15, $SR[$c], $F[$c]); $c++; $nConnection++; $PrevE = $E; } $this->{ini}->{"E1$iConnection"} = $PrevE; $this->{ini}->{"n$iConnection"} = $nConnection; $this->{CPME} = \@E; $this->{CPMIp} = \@Ip; $this->{CPMIpd} = \@Ipd; $this->{CPMSR} = \@SR; $this->{CPMF} = \@F; $this->{CPMAlpha} = \@alphaCPM; $this->{CPMK} = \@K; $this->{Alpha} = \@alpha; $this->{PlotTypeListbox}->AddItemIfNew('CPMIp/Ipd'); $this->{PlotTypeListbox}->AddItemIfNew('CPMSR'); $this->{PlotTypeListbox}->AddItemIfNew('CPMF'); $this->{PlotTypeListbox}->AddItemIfNew('Alpha(CPM)'); $this->{PlotTypeListbox}->AddItemIfNew('Alpha(Optical)'); $this->{PlotTypeListbox}->SetText('Alpha(CPM)'); $this->UpdateParameters(); $this->CreateGraphFrame(); $this->AssignGraphData(1); $this->Draw(); } sub SaveCPM { my ($this) = @_; my $path = Utils::MakePath($this->App()->{DataDir}, 'CPM.csv', '/', 0); my $out = new JFile($path, "w"); if(!$out) { $this->print("\nError: Can not write to [$path].\n"); return 0; } $out->print("wl(nm),E(eV),Ip(A),Ipd(A),SR(mA/w),F(s-1),K,alpha(CPM cm-1),alpha(Optical cm-1)\n"); my $pE = $this->{CPME}; my $n = @$pE; for(my $i = 0 ; $i < $n ; $i++) { my $E = $pE->[$i]; my $wl = Optics::eVTonm($E); if($i > 0 and abs($this->{CPMIp}->[$i] - $this->{CPMIp}->[$i-1]) / $this->{CPMIp}->[$i] > 1.0e-3) { $out->print(",,,,,,,,\n"); } $out->print("$wl,$E,$this->{CPMIp}->[$i],$this->{CPMIpd}->[$i],$this->{CPMSR}->[$i]," ."$this->{CPMF}->[$i],$this->{CPMK}->[$i],$this->{CPMAlpha}->[$i],$this->{Alpha}->[$i]\n"); } $out->Close(); $this->print("\nCPM data has been saved to [$path].\n"); return 1; } sub ReadParameterFile { my ($this, $filepath) = @_; $filepath = Deps::ReplaceExtension($filepath, ".prm"); return 0 if(!-e $filepath); my $ini = new IniFile($filepath, 0, 0); return if(!$ini->ReadAll($filepath)); $this->{ini}->{m} = $ini->{m}; $this->{ini}->{X0} = $ini->{X0}; $this->{ini}->{X1} = $ini->{X1}; $this->{ini}->{XStep} = $ini->{XStep}; $this->{ChooseActionListBox}->SetText($ini->{Action}); $this->{ChooseXListBox}->SetText($ini->{X}); $this->{ChooseY1ListBox}->SetText($ini->{Y1}); $this->{ChooseActionListBox}->SetText($ini->{Action}); $this->print("Parameters have been red from [$filepath].\n"); $this->CreateGraphFrame() if(!defined $this->{GraphFrameArray}); my ($drive, $directory, $filename, $ext, $lastdir, $filebody) = Deps::SplitFilePath($filepath); #print "fb=$filebody\n"; $filename = Deps::ReplaceExtension($filename, ".csv"); $this->LSQ($filename, 1); return 1; } sub SaveParameterFile { my ($this, $filepath) = @_; $filepath = Deps::ReplaceExtension($filepath, ".prm"); my $ini = new IniFile($filepath, 0, 0); $ini->{m} = $this->{ini}->{m}; $ini->{X0} = $this->{ini}->{X0}; $ini->{X1} = $this->{ini}->{X1}; $ini->{XStep} = $this->{ini}->{XStep}; $ini->{Action} = $this->{ChooseActionListBox}->GetText(); $ini->{X} = $this->{ChooseXListBox}->GetText(); $ini->{Y1} = $this->{ChooseY1ListBox}->GetText(); $ini->{Action} = $this->{ChooseActionListBox}->GetText(); $ini->WriteAll($filepath); $this->print("Parameters have been saved to [$filepath].\n"); } sub ReadSampleDataFile { my ($this, $filepath, $IsPrint) = @_; 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; } 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); my $pX = $this->{DataFile}->GetXData(0); my $pY1 = $this->{DataFile}->GetYData(1); ($this->{ini}->{X0}, $this->{ini}->{X1}) = $this->{DataFile}->CalMinMax(); my ($minxstep, $maxstep) = $this->{DataFile}->CalMinMaxStep(); my $n = 0; if($minxstep > 0.0) { $n = int( abs($this->{ini}->{X1} - $this->{ini}->{X0}) / $minxstep + 1.0001); } if($n > 101 or $minxstep == 0.0) { $minxstep = abs($this->{ini}->{X1} - $this->{ini}->{X0}) / 101; } $this->{ini}->{XStep} = $minxstep; $this->ReadParameterFile($filepath); $this->UpdateParameters(); $this->CreateGraphFrame(); $this->AssignGraphData(1); return $filepath; } sub CreateGraphFrame { my ($this, $canvas, $TargetData) = @_; return if(defined $this->{GraphFrameArray}); $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 $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 @GraphFrame; $GraphFrame[0] = $GraphFrameArray->GetGraphFrame(0); $GraphFrame[0]->ClearAllData(); my $XLabel = $this->{"ChooseXListBox"}->GetText(); my $Y1Label = $this->{"ChooseY1ListBox"}->GetText(); $GraphFrame[0]->SetXCaption($XLabel); $GraphFrame[0]->SetYCaption("$Y1Label"); my $pX = $this->{DataFile}->GetData($XLabel) if($XLabel); my $pY1 = $this->{DataFile}->GetData($Y1Label) if($Y1Label); my $nData = $this->{DataFile}->nData(); my $PlotType = $this->{PlotTypeListbox}->GetText(); if($PlotType eq 'LSQ') { if($pX) { $GraphFrame[0]->AddGraphData($pX, $pY1, 2, "black", "", 6, "red", 0, "red", "XAutoSkip", "Energy", "${Y1Label}") if($pY1); } my $pCalX = $this->{CalX}; my $pCalY1 = $this->{CalY1}; if($pCalX) { $GraphFrame[0]->AddGraphData($pCalX, $pCalY1, 0, "black", "circle", 3, "", 1, "black", "XAutoSkip", "Energy", "${Y1Label}(cal)") if($pCalY1); } my $pFindX = $this->{FindX}; my $pFindY = $this->{FindY}; if($pFindX) { $GraphFrame[0]->AddGraphData($pFindX, $pFindY, 0, "red", "square", 8, "", 1, "red", "XAutoSkip", "Energy", "${Y1Label}(FindX)") if($pFindY); } $GraphFrame[0]->SetYScalePlotType('x'); if($ResetViewRange) { $GraphFrame[0]->CalMinMax(); $GraphFrame[0]->AdjustViewRange(0.20, 0.20, 0.05, 0.05); $GraphFrame[0]->SetViewXRange(0.0, $GraphFrame[0]->{ViewX1}, 0); $GraphFrame[0]->SetViewYRange(0.0, $GraphFrame[0]->{ViewY1}, 0); } } elsif($PlotType eq 'MeasuredRange') { my $pX = $this->{MeasuredRangeE}; my $pY = $this->{MeasuredRangeIp}; #print "MeasuredRange: $pX,$pY\n"; if($pY) { $GraphFrame[0]->AddGraphData($pX, $pY, 0, "", "circle", 3, "", 1, "black", "XAutoSkip", "Energy", "Ip"); $GraphFrame[0]->SetXCaption("Energy / eV"); $GraphFrame[0]->SetYCaption("Ip / A"); } $GraphFrame[0]->SetYScalePlotType('log(|x|)'); if($ResetViewRange) { $GraphFrame[0]->CalMinMax(); $GraphFrame[0]->AdjustViewRange(0.20, 0.20, 0.05, 0.05); $GraphFrame[0]->SetViewXRange($GraphFrame[0]->{ViewX0} - 0.2, $GraphFrame[0]->{ViewX1} + 0.2, 0); $GraphFrame[0]->SetViewYRange($GraphFrame[0]->{ViewY0} * 0.9, $GraphFrame[0]->{ViewY1} * 1.1, 0); } } elsif($PlotType =~ 'CPM') { my $pX = $this->{CPME}; my ($pY1, $pY2); if($PlotType eq 'CPMIp/Ipd') { $pY1 = $this->{CPMIpd}; $pY2 = $this->{CPMIp}; $GraphFrame[0]->SetYScalePlotType('log(|x|)'); $GraphFrame[0]->SetYCaption("Ip,Ipd / A"); } elsif($PlotType eq 'CPMSR') { $pY1 = $this->{CPMSR}; $GraphFrame[0]->SetYScalePlotType('x'); $GraphFrame[0]->SetYCaption("Spectral response / mA/W"); } elsif($PlotType eq 'CPMF') { $pY1 = $this->{CPMF}; $GraphFrame[0]->SetYScalePlotType('log(|x|)'); $GraphFrame[0]->SetYCaption("Photon flux / s-1"); } elsif($PlotType eq 'Alpha(CPM)') { $pY1 = $this->{CPMAlpha}; $GraphFrame[0]->SetYScalePlotType('x'); $GraphFrame[0]->SetYCaption("alpha (a.u.)"); } $GraphFrame[0]->SetXCaption("Energy / eV"); if($pY1) { $GraphFrame[0]->AddGraphData($pX, $pY1, 0, "", "circle", 3, "", 1, "black", "XAutoSkip", "Energy", "Ipd"); $GraphFrame[0]->AddGraphData($pX, $pY2, 0, "", "square", 3, "", 1, "red", "XAutoSkip", "Energy", "Ip"); } if($ResetViewRange) { $GraphFrame[0]->CalMinMax(); $GraphFrame[0]->AdjustViewRange(0.20, 0.20, 0.05, 0.05); $GraphFrame[0]->SetViewXRange($GraphFrame[0]->{ViewX0} - 0.2, $GraphFrame[0]->{ViewX1} + 0.2, 0); $GraphFrame[0]->SetViewYRange($GraphFrame[0]->{ViewY0} * 0.9, $GraphFrame[0]->{ViewY1} * 1.1, 0); } } elsif($PlotType eq 'Alpha(Optical)') { my $pX = $this->{CPME}; my $pY1 = $this->{Alpha}; $GraphFrame[0]->SetYScalePlotType('log(|x|)'); $GraphFrame[0]->SetYCaption("alpha (cm-1)"); $GraphFrame[0]->SetXCaption("Energy / eV"); if($pY1) { $GraphFrame[0]->AddGraphData($pX, $pY1, 0, "", "circle", 3, "", 1, "black", "XAutoSkip", "Energy", "Ipd"); } if($ResetViewRange) { $GraphFrame[0]->CalMinMax(); $GraphFrame[0]->AdjustViewRange(0.20, 0.20, 0.05, 0.05); $GraphFrame[0]->SetViewXRange($GraphFrame[0]->{ViewX0} - 0.2, $GraphFrame[0]->{ViewX1} + 0.2, 0); $GraphFrame[0]->SetViewYRange($GraphFrame[0]->{ViewY0} * 0.9, $GraphFrame[0]->{ViewY1} * 1.1, 0); } } } 1;