#=============================================== # TkSchottkyJunction #=============================================== package TkSchottkyJunction; use clib::TkFittingCommon; @ISA = qw(TkFittingCommon); #公開したいサブルーチン #@EXPORT = qw(DelSpace Reduce01 MakePath RegExpQuote); use strict; use Tk::JPEG; use Utils; use CSV; use MyTk::GraphFrameArray; use GraphData; use Sci qw($pi $kB $c $e $e0 $me $mp $mn $h $hbar); use Sci::Material; use Sci::TFT; my $material = new Material; #============================================================ # 変数等取得関数 #============================================================ #============================================================ # コンストラクタ、デストラクタ #============================================================ #呼び出されることはない 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 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 $Program = "SchottkyJunction2007"; $this->{ini} = new TFT(); $this->{dini} = new TFT(); $this->InitializeParameters($this->{ini}, $this->{dini}); $this->SUPER::CreateWidgets(); return if($DoSuperOnly); $mw->SetTitle("$Program / TkPlot"); $this->App()->SetProgram("$Program / TkPlot"); #=================================================== # TFTペインを作製 #=================================================== my $EntryWidth = 12; 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'); $this->{ChooseXListBox} = $Frame->MyBrowseEntry( -label => "X:", -state => "readonly", -takefocus => 1, -width => 5, -Selections => [], -SelIndex => 0, )->pack(-side => 'left', -expand => 'yes', -fill => 'x'); $this->{ChooseXListBox}->configure(-browsecmd => sub { $this->SelChangeListBox("X", $this->{ChooseXListBox}); } ); $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'); $this->MakeLabelEntry($Frame, "V0", "V:", $this->{ini}->pVariable('V0', -1.0), "%g", $EntryWidth, "", 0, 0); $this->MakeLabelEntry($Frame, "V1", "-", $this->{ini}->pVariable('V1', 1.0), "%g", $EntryWidth, "", 0, 1); $this->MakeLabelEntry($Frame, "VStep", ",", $this->{ini}->pVariable('VStep', 0.02), "%g", $EntryWidth, "V", 0, 2); $Frame = $mw->MyFrame()->pack(-anchor => 'nw'); $this->{ChoosePlotTypeListBox} = $Frame->MyBrowseEntry( -label => "Plot:", -state => "readonly", -takefocus => 1, -Selections => ["I-V", "x-E"], -SelIndex => 0, )->pack(-side => 'left', -expand => 'yes', -fill => 'x'); $this->{ChooseModelListBox} = $Frame->MyBrowseEntry( -label => "Model:", -state => "readonly", -takefocus => 1, -width => 20, -Selections => ["Simple", "Diffusion", "Schottky"], -SelIndex => 0, )->pack(-side => 'left', -expand => 'yes', -fill => 'x'); $this->{ChooseModelListBox}->configure( -browsecmd => sub { $this->SelChangeListBox("Model", $this->{ChooseModelListBox}); } ); $Frame = $mw->MyLabFrame( -label => 'Common', -labelside => 'acrosstop', )->pack(-anchor => 'nw'); $this->MakeLabelEntry($Frame, "T", "T:", $this->{ini}->pVariable('T', 300.0), "%g", $EntryWidth, "", 0, 0); $this->MakeLabelEntry($Frame, "Area", "Area:", $this->{ini}->pVariable('Area', 1.0e-2), "%g", $EntryWidth, "cm2", 0, 1); $this->MakeLabelEntry($Frame, "ndiode", "n:", $this->{ini}->pVariable('ndiode', 1.0), "%g", $EntryWidth, "", 1, 0); $this->MakeLabelEntry($Frame, "W", "W:", $this->{ini}->pVariable('W', 0.0), "%g", $EntryWidth, "nm", 1, 1, "disabled"); $this->MakeLabelEntry($Frame, "phiB", "phiB:", $this->{ini}->pVariable('phiB', 0.0), "%g", $EntryWidth, "eV", 2, 0, 'disabled'); $this->MakeLabelEntry($Frame, "Vbi", "Vbi:", $this->{ini}->pVariable('Vbi', 0.0), "%g", $EntryWidth, "eV", 2, 1, 'disabled'); $this->MakeLabelEntry($Frame, "Js", "Js:", $this->{ini}->pVariable('Js', 0.0), "%g", $EntryWidth, "A/cm2", 3, 0, "disabled"); $this->MakeLabelEntry($Frame, "Rs", "Rs:", $this->{ini}->pVariable('Rs', 0.0), "%g", $EntryWidth, "A/cm2", 3, 1, "disabled"); $this->MakeLabelEntry($Frame, "nx", "nx:", $this->{ini}->pVariable('nx', 301), "%g", $EntryWidth, "", 4, 0); $Frame = $mw->MyLabFrame( -label => 'metal', -labelside => 'acrosstop', )->pack(-anchor => 'nw'); $this->MakeLabelEntry($Frame, "EFm", "EF:", $this->{ini}->pVariable('EFm', 4.0), "%8.6g", $EntryWidth, "eV", 0, 0); $this->MakeLabelEntry($Frame, "Nem", "Ne:", $this->{ini}->pVariable('Nem', 5.0e22), "%12.6g", $EntryWidth, "cm-3", 0, 1); $this->MakeLabelEntry($Frame, "mem", "me:", $this->{ini}->pVariable('mem', 1.0), "%8.6g", $EntryWidth, "me", 2, 0); $this->MakeLabelEntry($Frame, "Am", "A*:", $this->{ini}->pVariable('Am', 1.0), "%12.6g", $EntryWidth, "A/m2/K2", 2, 1, "disabled"); $this->MakeLabelEntry($Frame, "dm", "d:", $this->{ini}->pVariable('dm', 50.0), "%g", $EntryWidth, "nm", 3, 0); $Frame = $mw->MyLabFrame( -label => 'semiconductor', -labelside => 'acrosstop', )->pack(-anchor => 'nw'); $this->MakeLabelEntry($Frame, "ECn", "EC:", $this->{ini}->pVariable('ECn', 4.05), "%g", $EntryWidth, "eV", 0, 0); $this->MakeLabelEntry($Frame, "EFn", "EF:", $this->{ini}->pVariable('EFn', 3.3), "%g", $EntryWidth, "eV", 0, 1); $this->MakeCheckEntry($Frame, "NDn", "ND:", $this->{ini}->pVariable('NDncheck', 0), $this->{ini}->pVariable('NDn', 1.0e16), "%g", $EntryWidth, "cm-3", 1, 0); $this->MakeLabelEntry($Frame, "Epsn", "er:", $this->{ini}->pVariable('Epsn', 11.9), "%g", $EntryWidth, "e0", 1, 1); $this->MakeCheckEntry($Frame, "dn", "d:", $this->{ini}->pVariable('dncheck', 0), $this->{ini}->pVariable('dn', 1000), "%g", $EntryWidth, "nm", 2, 0); $this->MakeLabelEntry($Frame, "Cn", "Cn:", $this->{ini}->pVariable('Cn', 0.0), "%g", $EntryWidth, "F", 2, 1, "disabled"); $this->MakeLabelEntry($Frame, "men", "me:", $this->{ini}->pVariable('men', 0.19), "%g", $EntryWidth, "me", 3, 0); $this->MakeLabelEntry($Frame, "NCn", "NC:", $this->{ini}->pVariable('NCn', 8.5e18), "%g", $EntryWidth, "cm-3", 3, 1, "disabled"); $this->MakeLabelEntry($Frame, "mun", "mu:", $this->{ini}->pVariable('mun', 1500.0), "%g", $EntryWidth, "cm2/Vs", 5, 0); $this->MakeLabelEntry($Frame, "Dn", "De:", $this->{ini}->pVariable('Dn', 0.0), "%g", $EntryWidth, "cm2/s", 5, 1, "disabled"); $this->MakeLabelEntry($Frame, "sigman", "s:", $this->{ini}->pVariable('sigman', 0.0), "%g", $EntryWidth, "S/cm", 6, 0, "disabled"); $this->MakeLabelEntry($Frame, "Rn", "R:", $this->{ini}->pVariable('Rn', 0.0), "%g", $EntryWidth, "ohm cm2", 6, 1, "disabled"); $this->MakeLabelEntry($Frame, "taun", "taun:", $this->{ini}->pVariable('taun', 10.0e-6), "%g", $EntryWidth, "s", 7, 0); $this->MakeLabelEntry($Frame, "Ln", "Ln:", $this->{ini}->pVariable('Ln', 0.0), "%g", $EntryWidth, "m", 7, 1); $this->MakeLabelEntry($Frame, "Wn", "W:", $this->{ini}->pVariable('Wn', 0.0), "%g", $EntryWidth, "nm", 8, 0, "disabled"); $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->ChooseVdsIdsFile($this->{VdsIdsFileEntry}); }, ) if($mw->{OpenButton}); $this->UpdateParameters(); } sub ChooseFile { my ($this, $type, $widget, $Option) = @_; my $App = $this->App(); my $canvas = $this->Canvas(); my $mw = $this->mw(); #print "ChooseFile: type=$type Option=$Option\n"; my $mode = 'open'; my $fmask = '*.csv;*.spe;*.jel;*.asp;*.smo;*isa;*.ref;*.pal;*.bef;*.aft'; if($Option eq 'ChooseParameterFile') { $fmask = '*.prm'; } my $dir = ''; unless($widget) { $dir = $this->App()->{WorkDir}; chdir($dir); } my $defstr = ''; my $message = 'Choose file'; my $filepath = Dialog::OpenFileDialog($mw, 'open', $fmask, $defstr, $message, $dir); if($filepath) { my $DirPath = $this->SetWorkDir($filepath); if($widget) { $widget->SetText($filepath); } } else { return undef; } my $ret; if($type eq 'Param') { $ret = $this->ReadParameterFile($filepath); return undef unless($ret); $this->Draw(); } elsif($type eq 'SampleCSV') { $ret = $this->ReadSampleDataFile($filepath); return undef unless($ret); $this->Draw(); } return $ret; } sub ButtonPressed { my ($this, $event, $type) = @_; if($type eq 'Recalc') { $this->Recalc(); $this->CreateGraphFrame() if(!defined $this->{GraphFrameArray}); $this->AssignGraphData(1); $this->Draw(); } else { $this->SUPER::ButtonPressed($event, $type); } } sub UpdateParameters { my ($this) = @_; my $ini = $this->{ini}; my $T = $ini->{T}; my $S = $ini->{Area} * 1.0e-4; my $Epsn = $ini->{Epsn}; my $ECn = $ini->{ECn}; my $NDn = $ini->{NDn}; my $men = $ini->{men}; my $dn = $ini->{dn}*1.0e-9; my ($R, $Reff) = $material->RichardsonDushman($this->{ini}->{mem}*$me); my $Am = $ini->{Am} = $Reff; my $EFm = $ini->{EFm}; my $NCn = $ini->{NCn} = $material->Nc($men*$me, 1.0, $T) * 1.0e-6; # cm-3 my $EFn = $ini->{EFn} = $ECn - $kB * $T / $e * log($NDn / $NCn) if($ini->{NDn} > 0 and $NCn > 0); my $phiB = $ini->{phiB} = -($ECn - $EFm); my $Vbi = $ini->{Vbi} = -($EFn - $EFm); $ini->{sigman} = $e * $NDn * $ini->{mun}; $ini->{Rn} = 1.0 / $ini->{sigman} * $ini->{dn} * 1.0e-7; $ini->{Rs} = $ini->{Rn}; $ini->{Cn} = $material->CalCapacitance($Epsn, $S, $dn); # F my $Dn = $ini->{Dn} = $ini->{mun} * $kB * $T / $e; my $Ln = $ini->{Ln} = sqrt($Dn * $ini->{taun}); # m $ini->{Js} = ($Am*1.0e-4) * $T * $T * exp(-$e * $phiB / $kB / $T); $ini->{Wn} = sqrt(2.0 * $Epsn*$e0 * $Vbi / $e / ($NDn*1.0e6)) * 1.0e9 if($Vbi >= 0.0); # nm $this->SUPER::UpdateParameters(); } sub EntryFocusedIn { my ($this, $obj, $event, $type) = @_; # $this->{PrevValue} = $obj->GetText(); $this->SUPER::EntryFocusedIn($obj, $event, $type); } sub EntryFocusedOut { my ($this, $obj, $event, $type) = @_; return if($obj->{PrevValue} eq $obj->GetText()); if($event eq 'FocusOut') { if($type eq 'T') { } $this->UpdateParameters(); return $this->SUPER::EntryFocusedOut($obj, $event, $type); } else { return $this->SUPER::EntryFocusedOut($obj, $event, $type); } } #=================================================== # データ処理 #=================================================== sub Initialize { my ($this, $InitializeParameterFile, $InitializeData) = @_; $this->{Optimize} = undef; if($InitializeParameterFile) { $this->{ini}->{SampleCSVFile} = ''; } if($InitializeData) { $this->{pEArray} = undef; } } sub InitializeParameters { my ($this, $ini, $dini) = @_; $this->AddParameters($ini, $dini, "EFm", 5.0, 0, 1.0, '', ''); $this->AddParameters($ini, $dini, "mem", 1.0, 0, 1.0, 0.0, ''); $this->AddParameters($ini, $dini, "Epsn", 11.9, 0, 1.0, 0.0, ''); $this->AddParameters($ini, $dini, "dn", 1000.0, 0, 10.0, 0.0, ''); $this->AddParameters($ini, $dini, "NDn", 1.0e16, 0, 0.5, 0.0, ''); } sub Recalc { my ($this) = @_; my $ini = $this->{ini}; $this->UpdateParameters(); my $Model = $this->{ChooseModelListBox}->GetText(); my $iModel = 0; if($Model eq 'Diffusion') { $iModel = 1; } elsif($Model eq 'Schottky') { $iModel = 2; } my $Plot = $this->{ChoosePlotTypeListBox}->GetText(); $this->print("\nRecalc for $Plot / $Model\n"); my $T = $ini->{T}; my $V0 = $ini->{V0}; my $V1 = $ini->{V1}; my $VStep = $ini->{VStep}; my $nV = int( ($V1-$V0) / $VStep + 1.0001); if($Plot eq 'x-E') { my $Wn = $ini->{Wn}; my $dn = $ini->{dn} * 1.0e-9; my $x0 = -$ini->{dn}; my $x1 = $ini->{dm}; my $nx = $ini->{nx}; my $xStep = ($x1 - $x0) / ($nx - 1); my $Vbi = $ini->{Vbi}; my $phiB = $ini->{phiB}; my $sn = $ini->{sigman}; my $NDn = $ini->{NDn}; my $Epsn = $ini->{Epsn} * $e0; my $Ke = $e / 4.0 / $pi / $Epsn; my (@CalV, @Calx, @CalEArray); for(my $iv = 0 ; $iv < $nV ; $iv++) { my $V = $V0 + $iv * $VStep; $CalV[$iv] = $V; my $Vnet = -$V + $Vbi; my $WnV = ($Vnet >= 0)? $Wn * sqrt($Vnet / $Vbi) : 0; #print "V=$V Vn=$Vn Vp=$Vp\n"; $CalEArray[$iv] = []; for(my $ix = 0 ; $ix < $nx ; $ix++) { my $x = $x0 + $ix * $xStep; my $E; if($V <= $Vbi) { if($x < -$WnV) { $E = $V; } elsif($x < 0) { if($WnV < -$x0) { my $dx = ($x + $WnV) * 1.0e-9; $E = $e * ($NDn*1.0e6) / $Epsn / 2.0 * $dx * $dx + $V; } else { my $dx = ($x - $x0) * 1.0e-9; my $K1 = -($V-$Vbi) / $dn - $e * ($NDn*1.0e6) / $Epsn / 2.0 * $dn; $E = $e * ($NDn*1.0e6) / $Epsn / 2.0 * $dx * $dx + $K1 * $dx + $V; } if($iModel == 2) { # if($V < 0 and $iModel == 2) { $E -= $Ke / (abs($x)*1.0e-9); } } else { $E = $Vbi - $phiB; } } else { if($x <= 0.0) { $E = ($V-$Vbi) * $x / $x0 + $Vbi; } else { $E = $Vbi - $phiB; } } $Calx[$ix] = $x; $CalEArray[$iv][$ix] = $E; } } $this->{pCalV} = \@CalV; $this->{pCalx} = \@Calx; $this->{pCalEArray} = \@CalEArray; } elsif($Plot eq 'I-V') { my $NCn = $ini->{NCn}; my $NDn = $ini->{NDn}; my $mun = $ini->{mun}; my $Epsn = $ini->{Epsn} * $e0; my $Am = $ini->{Am}; my $Js = $ini->{Js}; my $Rs = $ini->{Rs}; my $ndiode = $ini->{ndiode}; my $Vbi = $ini->{Vbi}; my $phiB = $ini->{phiB}; my $S = $ini->{Area}; my (@CalV, @CalVdiode, @CalI); my $Vinitial = $V0 * 0.2; for(my $i = 0 ; $i < $nV ; $i++) { my $V = $V0 + $i * $VStep; my ($Vdiode, $I) = &CalDiodeI($iModel, $V, $T, $mun, $NCn, $NDn, $Epsn, $Am, $Vbi, $phiB, $Js, $ndiode, $Rs, $S, $Vinitial); print "V=$V: I=$i Vdiode=$Vdiode\n"; $CalV[$i] = $V; $CalVdiode[$i] = $Vdiode; $CalI[$i] = $I; $Vinitial = $Vdiode; #last; } $this->{pCalV} = \@CalV; $this->{pCalVdiode} = \@CalVdiode; $this->{pCalI} = \@CalI; } } sub CalDiodeI { my ($iModel, $Vtarget, $T, $mus, $NCs, $NDs, $Epss, $Am, $Vbi, $phiB, $Js, $ndiode, $Rs, $S, $Vinitial, $dV, $EPS, $nMaxIter) = @_; $Vinitial = $Vtarget if(!defined $Vinitial); $dV = 1.0e-4 if(!defined $dV); $EPS = 1.0e-6 if(!defined $EPS); $nMaxIter = 100 if(!defined $nMaxIter); return (0.0, 0.0) if($Vtarget == 0.0); #print "e=$e phiB=$phiB Rs=$Rs\n"; my $Vdiode = $Vinitial; my $I = 0.0; for(my $i = 0 ; $i < $nMaxIter ; $i++) { my ($Im, $Ip); if($Vtarget >= 0.0 or $iModel == 0 or $Vbi-$Vdiode-$dV < 0) { $Im = $Js * (exp($e * ($Vdiode-$dV) / $ndiode / $kB / $T) - 1.0) * $S; } elsif($iModel == 1) { #printf "A=$Vbi-$Vdiode+$dV = %g Eps=$Epss\n", $Vbi-$Vdiode+$dV; my $sqr = sqrt(2.0*$e * ($NDs*1.0e6) * ($Vbi - $Vdiode+$dV) / $Epss); #printf "exp=%g\n", exp(-$e * $phiB); my $kexp = $e * ($mus*1.0e-4) * ($NCs*1.0e6) * $sqr * exp(-$e * $phiB / $kB / $T); $Im = $kexp * (exp($e * ($Vdiode - $dV) / $ndiode / $kB / $T) - 1.0) * 1.0e-4 * $S; } else { my $K1 = ($e/$Epss)**1.5 * sqrt(2)/4.0/$pi * sqrt($NDs*1.0e6) * sqrt($Vbi - $Vdiode+$dV); my $kexp = exp($e/$kB/$T * sqrt($K1)); $Im = $Js * $kexp * (exp($e * ($Vdiode-$dV) / $ndiode / $kB / $T) - 1.0) * $S; } my $Vtotalm = $Vdiode-$dV + $Im * $Rs; if($Vtarget >= 0.0 or $iModel == 0 or $Vbi-$Vdiode-$dV < 0) { $Ip = $Js * (exp($e * ($Vdiode+$dV) / $ndiode / $kB / $T) - 1.0) * $S; } elsif($iModel == 1) { #printf "A=$Vbi-$Vdiode-$dV = %g Eps=$Epss\n", $Vbi-$Vdiode-$dV; my $sqr = sqrt(2.0*$e * ($NDs*1.0e6) * ($Vbi - $Vdiode-$dV) / $Epss); my $kexp = $e * ($mus*1.0e-4) * ($NCs*1.0e6) * $sqr * exp(-$e * $phiB / $kB / $T); $Ip = $kexp * (exp($e * ($Vdiode + $dV) / $ndiode / $kB / $T) - 1.0) * 1.0e-4 * $S; } else { my $K1 = ($e/$Epss)**1.5 * sqrt(2)/4.0/$pi * sqrt($NDs*1.0e6) * sqrt($Vbi - $Vdiode-$dV); my $kexp = exp($e/$kB/$T * sqrt($K1)); $Ip = $Js * $kexp * (exp($e * ($Vdiode+$dV) / $ndiode / $kB / $T) - 1.0) * $S; } my $Vtotalp = $Vdiode+$dV + $Ip * $Rs; my $Vtotal = 0.5 * ($Vtotalm + $Vtotalp); $I = 0.5 * ($Im + $Ip); last if(abs($Vtotal - $Vtarget) < $EPS); #printf " V=%6.3g / %6.3g", $Vdiode, $Vtotal; # $Vdiode += ($Vtarget - $Vtotal) * 0.1; my $dVdV = ($Vtotalp - $Vtotalm) / $dV / 2.0; $Vdiode += -($Vtotal - $Vtarget) / $dVdV; #printf "=> %6.3g\n", $Vdiode; } #print "V=$Vtarget: Vd=$Vdiode I=$I\n"; return ($Vdiode, $I); } sub SaveParameterFile { my ($this, $filepath) = @_; $this->{ini}->{X} = $this->{ChooseXListBox}->GetText(); $this->{ini}->{Y1} = $this->{ChooseY1ListBox}->GetText(); $this->{ini}->{Model} = $this->{ChooseModelListBox}->GetText() if($this->{ChooseModelListBox}); 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: [$filepath]\n"); $this->ComposeParameters($this->{dini}, $this->{ini}); $this->{ini}->WriteAll(); $this->DecomposeParameters($this->{ini}, $this->{dini}); } sub ReadParameterFile { my ($this, $filepath) = @_; my $DirectorySeparator = Deps::DirectorySeparator(); my $RegSeparator = Utils::RegExpQuote($DirectorySeparator); 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); if($this->{ini}->{SampleCSVFile}) { my $ret; if(-e $this->{ini}->{SampleCSVFile}) { $ret = $this->ReadSampleDataFile($this->{ini}->{SampleCSVFile}, 1, 0, 0); } unless($ret) { my ($drive0, $directory0, $filename0, $ext0, $lastdir0, $filebody0) = Deps::SplitFilePath($this->{ini}->{ParameterFile}); my ($drive1, $directory1, $filename1, $ext1, $lastdir1, $filebody1) = Deps::SplitFilePath($filepath); $this->{ini}->{SampleCSVFile} =~ s/\//$DirectorySeparator/g; #print "RelPath = Utils::MakeRelativePath($this->{ini}->{SampleCSVFile}, $drive0$directory0, 0)\n"; my $RelPath = Utils::MakeRelativePath($this->{ini}->{SampleCSVFile}, "$drive0$directory0"); #print "R: $RelPath\n"; $RelPath =~ s/^\.$RegSeparator/$drive1$directory1/; #print "R: $RelPath\n"; if(-e $RelPath) { $ret = $this->ReadSampleDataFile($RelPath, 1, 0, 0); } unless($ret) { ($drive0, $directory0, $filename0, $ext0, $lastdir0, $filebody0) = Deps::SplitFilePath($filepath); ($drive1, $directory1, $filename1, $ext1, $lastdir1, $filebody1) = Deps::SplitFilePath($this->{ini}->{SampleCSVFile}); my $f = Deps::MakePath("$drive0$directory0", $filename1, 0); $ret = $this->ReadSampleDataFile($f, 1, 0, 0); return undef unless($ret); $this->{ini}->{SampleCSVFile} = $f; } else { $this->{ini}->{SampleCSVFile} = $RelPath; } } } $this->{ini}->{ParameterFile} = $filepath; $this->{ChooseXListBox}->SetText($this->{ini}->{X}); $this->{ChooseY1ListBox}->SetText($this->{ini}->{Y1}); return 1; } sub ReadSampleDataFile { my ($this, $filepath, $IsPrint, $UpdateRange) = @_; $UpdateRange = 1 if(!defined $UpdateRange); my $App = $this->App(); #print "filepath=$filepath\n"; $this->Initialize(0, 1); $this->{Path} = $filepath; $this->{DataFile} = new MultiColumnData; 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('V.*'); $this->{"ChooseY1ListBox"}->SetCurSel('I.*'); if($UpdateRange or !defined $this->{ini}->{FitXMin}) { ($this->{ini}->{FitXMin}, $this->{ini}->{FitXMax}) = Utils::CalMinMax($pDataArray[0]); ($this->{ini}->{V0}, $this->{ini}->{V1}) = 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 $GraphFrameArray = $this->{'GraphFrameArray'} = new GraphFrameArray($this->mw()); $GraphFrameArray->SetCanvasSize($w, $h); $GraphFrameArray->AddGraphFrame(); my $GraphFrame0 = $GraphFrameArray->GetGraphFrame(0); my $FramePosStr0 = $App->{"GraphFrame0Position"}; my $XScale0 = $GraphFrame0->GetXScale(0); my $YScale0 = $GraphFrame0->GetYScale(0); $GraphFrame0->SetPositionByStr($FramePosStr0); $GraphFrameArray->AddGraphFrame(); my $GraphFrame1 = $GraphFrameArray->GetGraphFrame(1); my $FramePosStr1 = $App->{"GraphFrame1Position"}; my $XScale1 = $GraphFrame1->GetXScale(0); my $YScale1 = $GraphFrame1->GetYScale(0); $GraphFrame1->SetPositionByStr($FramePosStr1); $GraphFrame0->SetXCaption(""); $GraphFrame0->SetYCaption("I / F"); $GraphFrame1->SetXCaption("V / V"); $GraphFrame1->SetYCaption(""); $XScale0->SetScaleStringVisible(0); $XScale0->SetCaptionVisible(0); $XScale1->SetScaleStringVisible(1); $XScale1->SetCaptionVisible(1); $GraphFrame0->SetViewRange(0, 0, 1, 1); } sub ShowScaleDialog { my ($this, $GraphFrame, $command, $Title, @a) = @_; #$command: "XScale" "YScale" #最初の4つのundefはViewRangeに現在値を使う #次の2つのundefはPlotTypeに現在値を使う設定 #そのあとの1,0は、X,Y軸のPlotTypeの同期をおこなうかどうか #最後の1は、ScaleDialogでOKを押されたらグラフの再描画を行う #  Y軸のViewRangeは同期するが、PlotTypeの同期は無視する return $GraphFrame->ShowScaleDialog($Title, undef, undef, undef, undef, undef, undef, 1, 0, 1); } sub AdjustViewRange { my ($this) = @_; my $GraphFrameArray = $this->GetGraphFrameArray(); my $pGraphFrame = $GraphFrameArray->GetpGraphFrameArray(); my $FileType = $this->FileType(); if($FileType =~ /(Ids)/i) { } } sub AssignGraphData { my ($this, $ResetViewRange) = @_; $ResetViewRange = 1 if(!defined $ResetViewRange); my $ini = $this->{ini}; my $GraphFrameArray = $this->GetGraphFrameArray(); my $GraphFrame0 = $GraphFrameArray->GetGraphFrame(0); my $GraphFrame1 = $GraphFrameArray->GetGraphFrame(1); $GraphFrame0->ClearAllData() if($GraphFrame0); $GraphFrame1->ClearAllData() if($GraphFrame1); my $Model = $this->{"ChooseModelListBox"}->GetText(); my $Plot = $this->{ChoosePlotTypeListBox}->GetText(); my $XLabel = $this->{"ChooseXListBox"}->GetText(); my $Y1Label = $this->{"ChooseY1ListBox"}->GetText(); $GraphFrame1->SetXCaption($XLabel); $GraphFrame0->SetYCaption($Y1Label); if($this->{DataFile}) { 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, 0, "black", "circle", 3, "black", 0, "black", "XAutoSkip", "$XLabel", "$Y1Label") if($pY1); } } if($Plot eq 'x-E') { my $pCalV = $this->{pCalV}; my $pCalx = $this->{pCalx}; my $pCalEArray = $this->{pCalEArray}; my $n = @$pCalEArray; for(my $i = 0 ; $i < $n ; $i++) { my $V = $pCalV->[$i]; $GraphFrame0->AddGraphData($pCalx, $pCalEArray->[$i], 1, "blue", "", 6, "black", 0, "black", "XAutoSkip", "x(nm)", "E($V eV)") if($pCalEArray->[$i]); } $GraphFrame0->SetYCaption("E / eV"); $GraphFrame1->SetXCaption("x / nm"); } elsif($Plot eq 'I-V') { my $pCalV = $this->{pCalV}; my $pCalVdiode = $this->{pCalVdiode}; my $pCalI = $this->{pCalI}; if($pCalV) { $GraphFrame0->AddGraphData($pCalV, $pCalI, 1, "blue", "", 6, "black", 0, "black", "XAutoSkip", "V", "I") if($pCalI); $GraphFrame1->AddGraphData($pCalV, $pCalV, 1, "black", "", 6, "black", 0, "black", "XAutoSkip", "V", "Vtotal") if($pCalV); $GraphFrame1->AddGraphData($pCalV, $pCalVdiode, 1, "blue", "", 6, "black", 0, "black", "XAutoSkip", "V", "Vdiode") if($pCalVdiode); $GraphFrame0->SetYCaption("I / A"); $GraphFrame1->SetXCaption("V / V"); } } if($GraphFrame1) { $GraphFrame0->AddSynchronousFrame('x', $GraphFrame1); $GraphFrame1->AddSynchronousFrame('x', $GraphFrame0); } if($ResetViewRange) { $GraphFrame0->CalMinMax(); $GraphFrame1->CalMinMax(); $GraphFrame1->AdjustViewRange(0.05, 0.05, 0.05, 0.05, 0, 0); $GraphFrame0->AdjustViewRange(0.05, 0.05, 0.05, 0.05, 1, 0); # $GraphFrame0->SetViewYRange(0); } } 1;