#=============================================== # TkFFT #=============================================== package TkFFT; use TkPlotModule; @ISA = qw(TkPlotModule); #公開したいサブルーチン #@EXPORT = qw(DelSpace Reduce01 MakePath RegExpQuote); use strict; #use Tk::JPEG; use Utils; use IniFile; use CSV; use Tk; use Tk::Balloon; use MyTk::Dialog; use MyTk::MyFrame; use MyTk::MyLabFrame; use MyTk::MyLabel; use MyTk::MyEntry; use MyTk::MyListbox; use MyTk::MyBrowseEntry; use MyTk::MyText; use MyTk::MyButton; use MyTk::MyCheckbutton; use MyTk::MyMenubutton; use MyTk::MyCanvas; use MyTk::MyAdjuster; use MyTk::MyScale; use MyTk::GraphFrameArray; use GraphData; use Sci::Science; use Sci::Material; use Sci::Ellipsometry; use Sci::MyFFT; #============================================================ # 変数等取得関数 #============================================================ sub FileType { return shift->{FileType}; } sub SetFileType { my ($this,$t)=@_; return $this->{FileType} = $t; } sub FileName { my ($this)=@_; $this->{FileName} = '' if(!defined $this->{FileName}); return shift->{FileName}; } sub SetFileName { my ($this,$f)=@_; return $this->{FileName} = $f; } sub SetDataArray { my ($this, $da)=@_; return $this->{DataArray} = $da; } sub DataArray { return shift->{DataArray}; } sub GetColor { return shift->{Color}; } sub ColorMapImage { return shift->{ColorMapImage}; } sub SetColorMapImage { my ($this,$m)=@_; return shift->{ColorMapImage} = $m; } #============================================================ # コンストラクタ、デストラクタ #============================================================ #呼び出されることはない 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->{ini} = new IniFile; $this->{DataFile} = new Ellipsometry; $this->SUPER::CreateWidgets(); return if($DoSuperOnly); $mw->SetTitle("FFT2007 / TkPlot"); $this->App()->SetProgram("FFT2007 / TkPlot"); #=================================================== # ペインを作製 #=================================================== my $EntryWidth = 12; my $Frame = $mw->MyFrame()->pack(-anchor => 'nw', -fill => 'x'); $this->MakeChooseFileEntry($Frame, 'SampleCSV', 'Sample:', $this->{ini}->pVariable("SampleCSVFile", ""), '&Choose', \&ChooseFile, "ChooseSampleFile"); $this->{EditDataButton} = $Frame->MyButton( -text => 'ed', -takefocus => 1, -command => [ \&ButtonPressed, $this, '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 => [\&SelChangeListBox, $this, "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 => [\&SelChangeListBox, $this, "Y1", $this->{ChooseY1ListBox}]); my $lsb3 = $this->{ChooseY2ListBox} = $Frame->MyBrowseEntry( -label => "Y2:", -state => "readonly", -takefocus => 1, -width => 5, -Selections => [], -SelIndex => 2, )->pack(-side => 'left', -expand => 'yes', -fill => 'x'); $lsb3->configure(-browsecmd => [\&SelChangeListBox, $this, "Y2", $this->{ChooseY2ListBox}]); $Frame = $mw->MyLabFrame( -label => 'FFT', -labelside => 'acrosstop', )->pack(-anchor => 'nw', -fill => 'x'); my $lsb4 = $this->{ChooseDirectionListBox} = $Frame->MyBrowseEntry( -label => "Direction:", -state => "readonly", -takefocus => 1, -width => 5, -Selections => ['forward:complex', 'inverse:complex', 'forward:real', 'inverse:real', 'forward:sine', 'inverse:sine', 'forward:cosine', 'inverse:cosine', ], -SelIndex => 0, )->pack(-side => 'left', -expand => 'yes', -fill => 'x'); $lsb4->configure(-browsecmd => [\&SelChangeListBox, $this, "Direction", $this->{ChooseDirectionListBox}]); my $lsb5 = $this->{ChooseDataAdjustListBox} = $Frame->MyBrowseEntry( -label => "Adjust:", -state => "readonly", -takefocus => 1, -width => 5, -Selections => ['truncate', 'fillzero'], -SelIndex => 0, )->pack(-side => 'left', -expand => 'yes', -fill => 'x'); $lsb5->configure(-browsecmd => [\&SelChangeListBox, $this, "DataAdjust", $this->{ChooseDataAdjustListBox}]); $this->UpdateParameters(); $Frame = $mw->MyFrame()->pack(-anchor => 'nw', -fill => 'x'); $this->{FFTButton} = $Frame->MyButton( -text => '&FFT', -takefocus => 1, -command => [\&ButtonPressed, $this, 'RButtonDown', 'FFT'], )->pack(-side => 'left'); #ツールバーのOpenボタンをファイル読み込みにバインドする $mw->{OpenButton}->configure( -command => [ \&ChooseFile, $this, $this->{SPEFileFileEntry} ], ) if($mw->{OpenButton}); } sub InsertToolBar { my ($this, $frame) = @_; #print "this=$this\n"; #ツールバーに追加 my $spb1 = $this->mw()->{ShowRecalcDataButton} = $frame->MyCheckbutton( -text => 'Show Recalc data', -takefocus => 1, -variable => $this->{ini}->pVariable('ShowRecalcData', 1), -indicatoron => 0, )->pack(-side => 'left', -fill => 'x'); my $spb2 = $this->mw()->{ShowCalcPlotButton} = $frame->MyCheckbutton( -text => 'Show CalcPlot', -takefocus => 1, -variable => $this->{ini}->pVariable('ShowCalcPlot', 1), -indicatoron => 0, )->pack(-side => 'left', -fill => 'x'); my $spb3 = $this->mw()->{AutoUpdateButton} = $frame->MyCheckbutton( -text => 'Auto Update', -takefocus => 1, -variable => $this->{ini}->pVariable('AutoUpdate', 0), -indicatoron => 0, )->pack(-side => 'left', -fill => 'x'); } sub Initialize { my ($this, $InitializeParameterFile, $InitializeData) = @_; $this->{DataFile} = new Ellipsometry; if($InitializeParameterFile) { $this->{ini}->{SampleCSVFile} = ''; } if($InitializeData) { $this->{pFreq} = undef; $this->{pReal} = undef; $this->{pImag} = undef; } } sub MakeChooseFileEntry { my ($this, $Frame, $name, $Label, $pVariable, $ButtonLabel, $pFunction, $Option) = @_; $Frame->MyLabel(-text => $Label)->pack(-side => 'left'); $this->{"${name}FileEntry"} = $Frame->MyEntry(-takefocus => 1, -textvariable => $pVariable)->pack(-side => 'left', -expand => 'yes', -fill => 'x'); $this->{"${name}FileEntry"}->focus(); $this->{"${name}FilePathButton"} = $Frame->MyButton( -text => $ButtonLabel, -takefocus => 1, -command => [$pFunction, $this, $name, $this->{"${name}FileEntry"}, $Option], )->pack(-side => 'left'); return $this->{"${name}FileEntry"}; } sub MakeLabelEntry { my ($this, $Frame, $name, $label1, $pVariable, $format, $EntryWidth, $label2, $row, $column, $state) = @_; #print "name=$name, pVariable=$pVariable, v=$$pVariable, format=$format\n"; $state = 'normal' if(!defined $state); if(!$pVariable) { $this->{$name} = ''; $pVariable = \{$this->{$name}}; } #print "p=$pVariable,$$pVariable f=$format\n"; #print "Frame=$Frame name=$name,$label1,$format,$label2\n"; $$pVariable = Utils::DelSpace(sprintf($format, $$pVariable)) if($pVariable); $Frame->MyLabel(-text => $label1)->grid(-row => $row, -column => 3*$column+0, -columnspan => 1, -sticky => 'e' ); my $ent = $Frame->MyEntry( -name => $name, -width => $EntryWidth, # -text => $val, -textvariable => $pVariable, -state => $state, -format => $format, )->grid(-row => $row, -column => 3*$column+1, -columnspan => 1, -sticky => 'e' ); $Frame->MyLabel(-text => $label2)->grid(-row => $row, -column => 3*$column+2, -columnspan => 1, -sticky => 'w' ); $ent->bind('', [\&EntryFocusedIn, $this, 'FocusIn', $name]); $ent->bind('', [\&EntryFocusedOut, $this, 'FocusOut', $name]); $this->{pEntryArray} = [] if(!$this->{pEntryArray}); push(@{$this->{pEntryArray}}, $ent); return $this->{"${name}Entry"} = $ent; } sub MakeCheckEntry { my ($this, $Frame, $name, $label1, $pCheckVariable, $pVariable, $format, $EntryWidth, $label2, $row, $column, $state) = @_; $state = 'normal' if(!defined $state); #print "name=$name p=$pVariable,$$pVariable check: $pCheckVariable, $$pCheckVariable f=$format\n"; $$pVariable = Utils::DelSpace(sprintf($format, $$pVariable)); my $button = $Frame->MyCheckbutton( -text => $label1, -variable => $pCheckVariable, -onvalue => 1, -offvalue => 0, -indicatoron => 'no', )->grid(-row => $row, -column => 3*$column+0, -columnspan => 1, -sticky => 'e' ); # $button->configure(-command => sub { print "$label1 is pressed [", $button->GetText(), "]\n"; }); my $ent = $Frame->MyEntry( -name => $name, -width => $EntryWidth, # -text => $val, -textvariable => $pVariable, -state => $state, -format => $format, )->grid(-row => $row, -column => 3*$column+1, -columnspan => 1, -sticky => 'e' ); $Frame->MyLabel(-text => $label2)->grid(-row => $row, -column => 3*$column+2, -columnspan => 1, -sticky => 'w' ); $ent->bind('', [\&EntryFocusedIn, $this, 'FocusIn', $name]); $ent->bind('', [\&EntryFocusedOut, $this, 'FocusOut', $name]); $this->{pEntryArray} = [] if(!$this->{pEntryArray}); push(@{$this->{pEntryArray}}, $ent); return $this->{"${name}Button"} = $button; return $this->{"${name}Entry"} = $ent; } sub ButtonPressed { my ($this, $event, $type) = @_; my $App = $this->App(); #print "this=$this\n"; if($type eq 'FFT') { $this->FFT(); } 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 '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 EntryFocusedIn { my ($obj, $this, $event, $type) = @_; #print "In: obj=$obj, this=$this, event=$event, type=$type\n"; if($event eq 'FocusIn') { $obj->{PrevValue} = $obj->GetText(); } } sub EntryFocusedOut { my ($obj, $this, $event, $type) = @_; #print "Out: obj=$obj, this=$this, event=$event, type=$type\n"; my $ini = $this->{ini}; my $dini = $this->{dini}; if($event eq 'FocusOut') { } if($ini->{AutoUpdate} and defined $dini->{"${type}check"} and $obj->{PrevValue} != $obj->GetText()) { $this->Recalc(); # $this->CreateGraphFrame(); $this->AssignGraphData(0); $this->Draw(); } else { $this->UpdateParameters(); } } sub SelChangeListBox { my ($this, $type, $lb) = @_; #print "this:$this lb=$lb\n"; my $s = $lb->GetText(); if($type eq 'LayerModel') { if($s eq "C12A7:e-(sub)") { # $this->{SurfaceThicknessButton}->SetText("Surface thickness:"); } elsif($s eq "C12A7/C12A7:e-(sub)") { # $this->{SurfaceThicknessButton}->SetText("Interface thickness:"); } else { } } $this->CreateGraphFrame(); $this->AssignGraphData(); $this->Draw(); } sub ChooseFile { my ($this, $type, $widget, $Option) = @_; my $App = $this->App(); my $canvas = $this->Canvas(); my $mw = $this->mw(); #print "Opt=$Option\n"; my $mode = 'open'; my $fmask = '*.csv;*.spe;*.jel;*.asp;*.smo;*isa;*.ref;*.pal;*.bef;*.aft'; if($Option eq 'ChooseParameterFile') { # $mode = 'save'; $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($Option eq 'ChooseParameterFile') { $ret = $this->ReadParameterFile($filepath); return undef unless($ret); $this->Draw(); } elsif($Option eq 'ChooseSampleFile') { $ret = $this->ReadSampleDataFile($filepath); return undef unless($ret); $this->Draw(); } return $ret; } sub ChooseSaveFile { my ($this, $path, $fmask, $widget) = @_; $path = 'save.csv' if(!defined $path); $fmask = '*.csv' if(!defined $fmask); $path = $widget->GetText() if($widget); $path = 'out.csv' if(!$path); my $App = $this->App(); my $mw = $this->mw(); my $dir = $this->App()->{WorkDir}; chdir($dir) if($dir); my $defstr = $path; my $message = 'Choose file'; my $filepath = Dialog::OpenFileDialog($mw, 'save', $fmask, $defstr, $message, $dir); if($filepath) { my $DirPath = $this->SetWorkDir($filepath); if($widget) { $widget->SetText($filepath); } } return $filepath; } sub UpdateParameters { my ($this) = @_; return if(!defined $this->{pEntryArray}); my $pEA = $this->{pEntryArray}; for(my $i = 0 ; $i < @$pEA ; $i++) { $pEA->[$i]->Update(); } } #=================================================== # データ処理 #=================================================== sub FFT { my ($this) = @_; my $App = $this->App(); my $optics = new Optics; my $ini = $this->{ini}; return if(!defined $this->{DataFile}); my $Direction = $this->{ChooseDirectionListBox}->GetText(); my $DataAdjust = $this->{ChooseDataAdjustListBox}->GetText(); my $XLabel = $this->{"ChooseXListBox"}->GetText(); my $Y1Label = $this->{"ChooseY1ListBox"}->GetText(); my $Y2Label = $this->{"ChooseY2ListBox"}->GetText(); my $pX = $this->{DataFile}->GetData($XLabel) if($XLabel); my $pY1 = $this->{DataFile}->GetData($Y1Label) if($Y1Label); my $pY2 = $this->{DataFile}->GetData($Y2Label) if($Y2Label); my $nData = $this->{DataFile}->nData(); my $fft = new MyFFT; my ($n, $pX2, $pData) = $fft->SetData($pX, $pY1, $pY2, $Direction, $DataAdjust); my ($pFreq, $pReal, $pImag) = $fft->FFT(); $this->{pFreq} = $pFreq; $this->{pReal} = $pReal; $this->{pImag} = $pImag; # $this->CreateGraphFrame(); $this->AssignGraphData(); $this->Draw(); } 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(); $this->{"ChooseY2ListBox"}->DeleteAllItem(); for(my $i = 0 ; $i < $nDataArray ; $i++) { #print "$i: $pLabelArray->[$i]\n"; $this->{"ChooseXListBox"}->AddItem($pLabelArray->[$i]); $this->{"ChooseY1ListBox"}->AddItem($pLabelArray->[$i]); $this->{"ChooseY2ListBox"}->AddItem($pLabelArray->[$i]); } $this->{"ChooseXListBox"}->SetCurSel(0); $this->{"ChooseY1ListBox"}->SetCurSel(1); $this->{"ChooseY2ListBox"}->SetCurSel(2); $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); $GraphFrameArray->AddGraphFrame(); my $GraphFrame1 = $GraphFrameArray->GetGraphFrame(1); my $FramePosStr1 = $App->{"GraphFrame1Position"}; $GraphFrame1->SetPositionByStr($FramePosStr1); my $XScale0 = $GraphFrame0->GetXScale(0); my $YScale0 = $GraphFrame0->GetYScale(0); $XScale0->SetScaleStringVisible(1); $XScale0->SetCaptionVisible(1); $GraphFrame0->SetViewRange(0, 0, 1, 1); $GraphFrame1->SetViewRange(0, 0, 1, 1); } sub AssignGraphData { my ($this, $ResetViewRange) = @_; $ResetViewRange = 1 if(!defined $ResetViewRange); my $GraphFrameArray = $this->GetGraphFrameArray(); my $GraphFrame0 = $GraphFrameArray->GetGraphFrame(0); my $GraphFrame1 = $GraphFrameArray->GetGraphFrame(1); $GraphFrame0->ClearAllData(); $GraphFrame1->ClearAllData(); my $XLabel = $this->{"ChooseXListBox"}->GetText(); $XLabel = 'X' if(!$XLabel); my $Y1Label = $this->{"ChooseY1ListBox"}->GetText(); $Y1Label = 'Y1' if(!$Y1Label); my $Y2Label = $this->{"ChooseY2ListBox"}->GetText(); $Y2Label = 'Y2' if(!$Y2Label); $GraphFrame0->SetXCaption($XLabel); $GraphFrame0->SetYCaption("$Y1Label,$Y2Label"); my $pX = $this->{DataFile}->GetData($XLabel) if($XLabel); my $pY1 = $this->{DataFile}->GetData($Y1Label) if($Y1Label); my $pY2 = $this->{DataFile}->GetData($Y2Label) if($Y2Label); my $nData = $this->{DataFile}->nData(); if($pX) { $GraphFrame0->AddGraphData($pX, $pY1, 2, "black", "", 6, "red", 0, "red", "XAutoSkip", "Energy", "${Y1Label}") if($pY1); $GraphFrame0->AddGraphData($pX, $pY2, 2, "red", "", 6, "red", 0, "red", "XAutoSkip", "Energy", "${Y2Label}") if($pY2); } my $pFreq = $this->{pFreq}; my $pReal = $this->{pReal}; my $pImag = $this->{pImag}; #print "f: $pFreq,$pReal\n"; if($pFreq) { $GraphFrame1->AddGraphData($pFreq, $pReal, 1, "black", "", 3, "", 1, "black", "XAutoSkip", "Energy", "FT ${Y1Label}(real)") if($pReal); $GraphFrame1->AddGraphData($pFreq, $pImag, 1, "red", "", 3, "", 1, "red", "XAutoSkip", "Energy", "FT ${Y2Label}(imag)") if($pImag); $GraphFrame1->SetXCaption("Frequency"); $GraphFrame1->SetYCaption("FT"); } $GraphFrame0->SetYScalePlotType('x'); $GraphFrame1->SetYScalePlotType('x'); if($ResetViewRange) { $GraphFrame0->CalMinMax(); $GraphFrame0->AdjustViewRange(0.05, 0.05, 0.05, 0.05); $GraphFrame1->CalMinMax(); $GraphFrame1->AdjustViewRange(0.05, 0.05, 0.05, 0.05); } } sub AdjustViewRange { my ($this) = @_; my $GraphFrameArray = $this->GetGraphFrameArray(); my $pGraphFrame = $GraphFrameArray->GetpGraphFrameArray(); my $FileType = $this->FileType(); if($FileType =~ /(Ids)/i) { } } sub Draw { my ($this, $canvas, $TargetData) = @_; my $mw = $this->mw(); $canvas = $this->Canvas() if(!$canvas); # my $FileType = $this->FileType(); my $App = $this->App(); my $font = $App->{'GraphFrameFont'}; my @font = split(/,/, $font) if($font); my $GraphFrameArray = $this->GetGraphFrameArray(); return unless($GraphFrameArray); $canvas->ClearAll(); $mw->RefleshCanvas(); if($font) { $canvas->SetFont(\@font); $GraphFrameArray->SetFont(\@font); } my $w = $canvas->width(); my $h = $canvas->height(); $GraphFrameArray->SetCanvasSize($w, $h); $this->mw()->WriteStatusBar("Drawing Ellipsometry..."); # $this->ReadFiles($this->FileName(), $TargetData); # $this->CreateGraphFrame($canvas, $TargetData); # $this->AssignGraphData(); $mw->Balloon()->detach($canvas); $GraphFrameArray->Draw($canvas); $this->mw()->WriteStatusBar("Finish Ellipsometry."); } 1;