994 lines
28 KiB
C
994 lines
28 KiB
C
/****************************************************************************
|
|
** ui.h extension file, included from the uic-generated form implementation.
|
|
**
|
|
** If you want to add, delete, or rename functions or slots, use
|
|
** Qt Designer to update this file, preserving your code.
|
|
**
|
|
** You should not define a constructor or destructor in this file.
|
|
** Instead, write your code in functions called init() and destroy().
|
|
** These will automatically be called by the form's constructor and
|
|
** destructor.
|
|
*****************************************************************************/
|
|
|
|
# This file is part of TrimSPGUI.
|
|
#
|
|
# TrimSPGUI is free software: you can redistribute it and/or modify
|
|
# it under the terms of the GNU General Public License as published by
|
|
# the Free Software Foundation, either version 3 of the License, or
|
|
# (at your option) any later version.
|
|
#
|
|
# TrimSPGUI is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with TrimSPGUI. If not, see <http://www.gnu.org/licenses/>.
|
|
#
|
|
# Copyright 2009 by Zaher Salman and the LEM Group.
|
|
# <zaher.salman@psi.ch>
|
|
|
|
void TrimSPGUI::ToggleScanSingle()
|
|
{
|
|
# Toggle between scan/single run mode
|
|
|
|
# First collect some information
|
|
my %All=();
|
|
$All{"ScanSeq"}=ScanSeq->isChecked();
|
|
$All{"ERadio"}=ERadio->isChecked();
|
|
$All{"SigERadio"}=SigERadio->isChecked();
|
|
$All{"AngleRadio"}=AngleRadio->isChecked();
|
|
$All{"SigAngleRadio"}=SigAngleRadio->isChecked();
|
|
$All{"NProjRadio"}=NProjRadio->isChecked();
|
|
$All{"dRadio"}=dRadio->isChecked();
|
|
$All{"ScandL"}=ScandL->text();
|
|
$All{"ListRadio"}=ListRadio->isChecked();
|
|
$All{"LoopRadio"}=LoopRadio->isChecked();
|
|
$All{"NL"}=NL->text();
|
|
|
|
# Enable everything
|
|
E->setDisabled(0);
|
|
# E->setText("2000");
|
|
SigE->setDisabled(0);
|
|
# SigE->setText("450");
|
|
Angle->setDisabled(0);
|
|
# Angle->setText("0");
|
|
SigAngle->setDisabled(0);
|
|
# SigAngle->setText("15");
|
|
NProj->setDisabled(0);
|
|
# NProj->setText("10000");
|
|
for (my $i=1;$i<=$All{"NL"};$i++) {
|
|
my $LayerAttrib = layerTable->item($i-1,2);
|
|
$LayerAttrib->setEnabled(1);
|
|
}
|
|
|
|
# Enable depth increment for Energy scan only
|
|
if ($All{"ERadio"} & $All{"ListRadio"}) {
|
|
dzListLabel->setHidden(0);
|
|
ScanListdz->setHidden(0);
|
|
dzListLabel->setDisabled(0);
|
|
ScanListdz->setDisabled(0);
|
|
dzListLabel->setText("Corresponding depth increment (optional)");
|
|
} elsif ($All{"SigAngleRadio"} & $All{"ListRadio"}) {
|
|
dzListLabel->setHidden(0);
|
|
ScanListdz->setHidden(0);
|
|
dzListLabel->setDisabled(0);
|
|
ScanListdz->setDisabled(0);
|
|
dzListLabel->setText("Corresponding energy");
|
|
} else {
|
|
dzListLabel->setHidden(1);
|
|
ScanListdz->setHidden(1);
|
|
dzListLabel->setDisabled(1);
|
|
ScanListdz->setDisabled(1);
|
|
}
|
|
|
|
if ($All{"ScanSeq"}==1) {
|
|
# But if we are in scan mode disable the appropriate box
|
|
# Start by enabling everything
|
|
E->setDisabled(0);
|
|
SigE->setDisabled(0);
|
|
Angle->setDisabled(0);
|
|
SigAngle->setDisabled(0);
|
|
NProj->setDisabled(0);
|
|
layerTable->setColumnReadOnly(2,0);
|
|
# then disable one
|
|
if ($All{"ERadio"}) {
|
|
E->setDisabled(1);
|
|
} elsif ($All{"SigERadio"}) {
|
|
SigE->setDisabled(1);
|
|
} elsif ($All{"AngleRadio"}) {
|
|
Angle->setDisabled(1);
|
|
} elsif ($All{"SigAngleRadio"}) {
|
|
SigAngle->setDisabled(1);
|
|
} elsif ($All{"NProjRadio"}) {
|
|
NProj->setDisabled(1);
|
|
} elsif($All{"dRadio"}) {
|
|
my $LayerAttrib = layerTable->item($All{"ScandL"}-1,2);
|
|
$LayerAttrib->setEnabled(0);
|
|
}
|
|
# and change title of tab to say enabled
|
|
tabs->changeTab( ScansTab, trUtf8("Scans (Enabled)") );
|
|
} else {
|
|
# Otherwise the title of the tab says disabled
|
|
tabs->changeTab( ScansTab, trUtf8("Scans (Disabled)") );
|
|
}
|
|
}
|
|
|
|
|
|
void TrimSPGUI::PrepLayers()
|
|
{
|
|
my %All=();
|
|
$All{"NL"}=NL->text();
|
|
|
|
# Prepare enough Rows in table for layers
|
|
my $OldNL=layerTable->numRows();
|
|
if ($OldNL<=$All{"NL"}) {
|
|
layerTable->setNumRows($All{"NL"});
|
|
} else {
|
|
for (my $i=$All{"NL"};$i<=$OldNL-1;$i++) {
|
|
removeRowFromTable($i);
|
|
}
|
|
}
|
|
}
|
|
# layerTable->horizontalHeader()->setResizeMode(Qt::HeaderView::Stretch);
|
|
# layerTable->adjustColumn(0);
|
|
# layerTable->adjustColumn(1);
|
|
# layerTable->adjustColumn(2);
|
|
}
|
|
|
|
void TrimSPGUI::removeRowFromTable()
|
|
{
|
|
# This function is to remove rows from table
|
|
# I cannot use the standard removeRow() due to a bug in perl-qt3
|
|
# This is a good and simple workaround.
|
|
|
|
# Takes as an input the row number to be removed
|
|
my ($deadRow) = @_;
|
|
|
|
# Loop over columns and take items of the row to remove
|
|
for my $col (0..layerTable->numCols()-1) {
|
|
my $dummy=layerTable->item($deadRow, $col);
|
|
# In the items is not defined the row can be removed by simply
|
|
# reducing the number of rows in table
|
|
if ($dummy ne "") {
|
|
layerTable->takeItem(layerTable->item($deadRow, $col));
|
|
for my $row ($deadRow..layerTable->numRows()-2) {
|
|
my $item = layerTable->item($row+1, $col);
|
|
layerTable->takeItem($item);
|
|
layerTable->setItem($row, $col, $item);
|
|
}
|
|
}
|
|
}
|
|
layerTable->setNumRows(layerTable->numRows()-1);
|
|
}
|
|
|
|
void TrimSPGUI::ProjSmartDefaults()
|
|
{
|
|
my %All=();
|
|
# Get typeof projectile
|
|
$All{"ProjType"}=ProjType->currentText();
|
|
|
|
if ($All{"ProjType"} eq "Muon") {
|
|
# For a muon set Sigma E=450 eV and Sigman angle=15 degrees by default
|
|
SigE->setText("450");
|
|
SigAngle->setText("15");
|
|
} elsif ( $All{"ProjType"} eq "Li8") {
|
|
# For Li8 set Sigma E=0 eV and Sigam angle=0 degrees by default
|
|
SigE->setText("0");
|
|
SigAngle->setText("0");
|
|
}
|
|
}
|
|
|
|
|
|
void TrimSPGUI::OpenHelpWindow()
|
|
{
|
|
my $HelpText="
|
|
This is a GUI that uses the Trim.SP simulation binary to calculate the
|
|
implantation profiles of implanted projectiles in a multilayer thin film
|
|
structure.
|
|
|
|
Usage:
|
|
|
|
Initially define your multilayer structure in the 'Layers' tab. This
|
|
can be formed of a maximum of 7 layers. Each layer is defined by giving
|
|
its chemical formula, its density in units of g/cm^3, and its thickness
|
|
in Ångström.
|
|
|
|
Next, choose the type of projectile to be implanted in the structure from
|
|
the drop-down menu. Set the 'Number of projectiles' to be implanted, were
|
|
a higher number will give better statistics. Finally define the rest of the pro-
|
|
jectile parameters such as implantation energy, energy spread, etc.
|
|
|
|
In the 'File names prefix' give a string which will be used to construct the
|
|
input/output file names of the simulation. These files will be collected and
|
|
saved in the subdirectory provided in 'Save in subdirectory' box.
|
|
|
|
The 'Additional Parameters' tab allows you to change additional parameters
|
|
in the simulation. Change these only if you know what you are doing, and have
|
|
read the original documentation of the Trim.SP simulation.
|
|
|
|
The 'Scans' tabs provides the ability to change the value of a certain
|
|
parameter in the simulation, such as implantation energy, spread in energy,
|
|
number of implanted projectiles, and the thickness of one layer. The values of
|
|
this parameter can be changed by a regualr step size ('Loop' checkbox and
|
|
parameters), or following a set of values ('List of values' checkbox and the
|
|
comma separated values). In the second case, in addition to the scanned
|
|
parameter, the user may be given an option to change another parameter. For
|
|
example, when scanning through a list of energies, the user may give a
|
|
corresponding depth increment for each energy value.
|
|
|
|
Copyright 2009-2011 (C) by Zaher Salman and the LEM Group
|
|
Last modified 23 Sep. 2011
|
|
";
|
|
my $HelpWindow = Qt::MessageBox::information( this, "TrimSP GUI Help Window",$HelpText);
|
|
}
|
|
|
|
void TrimSPGUI::CollectValues()
|
|
{
|
|
# This subroutine returns a hash with all the values collected from the GUI.
|
|
my %All=();
|
|
$All{"NL"}=NL->text();
|
|
# Collect layers parameters
|
|
for (my $i=1;$i<=$All{"NL"};$i++) {
|
|
my $LComp = "L".$i."Comp";
|
|
my $Lrho="L".$i."rho";
|
|
my $Ld="L".$i."d";
|
|
$All{"$LComp"}=layerTable->text($i-1,0);
|
|
$All{"$Lrho"}=layerTable->text($i-1,1);
|
|
$All{"$Ld"}=layerTable->text($i-1,2);
|
|
}
|
|
|
|
# Collect projectile parameters
|
|
$All{"ProjType"}=ProjType->currentText();
|
|
$All{"NProj"}=NProj->text();
|
|
if ($All{"NProj"}==0) {
|
|
$All{"NProj"}=10000;
|
|
NProj->setText("10000");
|
|
}
|
|
$All{"z0"}=z0->text();
|
|
$All{"dz"}=dz->text();
|
|
$All{"E"}=E->text();
|
|
$All{"SigE"}=SigE->text();
|
|
$All{"Angle"}=Angle->text();
|
|
$All{"SigAngle"}=SigAngle->text();
|
|
$All{"Seed"}=Seed->text();
|
|
# Format projectile parameters
|
|
$All{"NProj"}=sprintf("%8d",$All{"NProj"});
|
|
$All{"z0"}=sprintf("%6.2f",$All{"z0"});
|
|
$All{"dz"}=sprintf("%6.2f",$All{"dz"});
|
|
$All{"E"}=sprintf("%11.2f",$All{"E"});
|
|
$All{"SigE"}=sprintf("%8.2f",$All{"SigE"});
|
|
$All{"Angle"}=sprintf("%8.2f",$All{"Angle"});
|
|
$All{"SigAngle"}=sprintf("%8.2f",$All{"SigAngle"});
|
|
$All{"Seed"}=sprintf("%6.0f.",$All{"Seed"});
|
|
|
|
|
|
# Collect the additional parameters
|
|
$All{"EF"}=EF->text();
|
|
$All{"ESB"}=ESB->text();
|
|
$All{"SHEATH"}=SHEATH->text();
|
|
$All{"ERC"}=ERC->text();
|
|
$All{"RD"}=RD->text();
|
|
$All{"CA"}=CA->text();
|
|
$All{"KK0"}=KK0->text();
|
|
$All{"KK0R"}=KK0R->text();
|
|
$All{"KDEE1"}=KDEE1->text();
|
|
$All{"KDEE2"}=KDEE2->text();
|
|
$All{"IPOT"}=IPOT->text();
|
|
$All{"IPOTR"}=IPOTR->text();
|
|
$All{"IRL"}=IRL->text();
|
|
# format additional parameters
|
|
$All{"EF"}=sprintf("%8.2f",$All{"EF"});
|
|
$All{"ESB"}=sprintf("%8.2f",$All{"ESB"});
|
|
$All{"SHEATH"}=sprintf("%8.2f",$All{"SHEATH"});
|
|
$All{"ERC"}=sprintf("%8.2f",$All{"ERC"});
|
|
$All{"RD"}=sprintf("%5.0f.",$All{"RD"});
|
|
$All{"CA"}=sprintf("%6.2f",$All{"CA"});
|
|
$All{"KK0"}=sprintf("%3d",$All{"KK0"});
|
|
$All{"KK0R"}=sprintf("%3d",$All{"KK0R"});
|
|
$All{"KDEE1"}=sprintf("%3d",$All{"KDEE1"});
|
|
$All{"KDEE2"}=sprintf("%3d",$All{"KDEE2"});
|
|
$All{"IPOT"}=sprintf("%3d",$All{"IPOT"});
|
|
$All{"IPOTR"}=sprintf("%3d",$All{"IPOTR"});
|
|
$All{"IRL"}=sprintf("%2d",$All{"IRL"});
|
|
|
|
# Filenames etc. The filename should not have white spaces
|
|
$All{"FNPre"}=FNPre->text();
|
|
$All{"FNPre"}=~ s/\s+//g;
|
|
$All{"Path"}=Path->text();
|
|
|
|
# Scan parameters only if selected
|
|
$All{"ScanSeq"}=ScanSeq->isChecked();
|
|
# if ($All{"ScanSeq"}) {
|
|
$All{"ERadio"}=ERadio->isChecked();
|
|
$All{"SigERadio"}=SigERadio->isChecked();
|
|
$All{"AngleRadio"}=AngleRadio->isChecked();
|
|
$All{"SigAngleRadio"}=SigAngleRadio->isChecked();
|
|
$All{"NProjRadio"}=NProjRadio->isChecked();
|
|
$All{"dRadio"}=dRadio->isChecked();
|
|
$All{"ScandL"}=ScandL->text();
|
|
# Remove any white spaces
|
|
$All{"ScandL"} =~ s/\s+//g;
|
|
$All{"ListRadio"}=ListRadio->isChecked();
|
|
$All{"LoopRadio"}=LoopRadio->isChecked();
|
|
$All{"ScanList"}=ScanList->text();
|
|
# Remove any white spaces
|
|
$All{"ScanList"} =~ s/\s+//g;
|
|
$All{"ScanListdz"}=ScanListdz->text();
|
|
# Remove any white spaces
|
|
$All{"ScanListdz"} =~ s/\s+//g;
|
|
# These should be numeric
|
|
$All{"SFrom"}=1*SFrom->text();
|
|
$All{"STo"}=1*STo->text();
|
|
$All{"SStep"}=1*SStep->text();
|
|
# }
|
|
|
|
# Return values to caller
|
|
return %All;
|
|
}
|
|
|
|
void TrimSPGUI::CreateInpFile()
|
|
{
|
|
use Chem;
|
|
# The proper way I think is not to have scan sequences implimented here
|
|
# but rather call this multiple times to generate the scan
|
|
# To resolve this, the function CreateInpFile will expect a unique thickness for each layer,
|
|
# one energy value, one energy sigma and one projectile number.
|
|
# These will be stored in keys L1/2/3/4/5/6/7d, E, SigE and NProj, respectively.
|
|
|
|
# Chemical formulas will be parsed on the fly for each layer. However, we will check if
|
|
# all the layers have inputs for composition, thickness and density. If not fail and crash :)
|
|
|
|
# Values of Z,A as well as other needed parameters are obtained from Chem.pm.
|
|
|
|
# This is the form of the begining of the input file:
|
|
my $TemplateFile=
|
|
" ProjZ ProjAM E SigE Angle SigAngle EF ESB SHEATH ERC
|
|
NProj Seed Seed Seed z0 RD dz CA KK0 KK0R KDEE1 KDEE2 IPOT IPOTR IRL";
|
|
|
|
# Then comes the number of layers (new format) for example 4 layers:
|
|
# N_Layers=4
|
|
$TemplateFile=$TemplateFile."\n"."N_Layers=NL"."\n";
|
|
|
|
# Then loop over the layers and for each give the following structure
|
|
my $TemplateLayer=
|
|
"L1d L1rho L1CK
|
|
L1ELZ1 L1ELZ2 L1ELZ3 L1ELZ4 L1ELZ5
|
|
L1ELW1 L1ELW2 L1ELW3 L1ELW4 L1ELW5
|
|
L1ELC1 L1ELC2 L1ELC3 L1ELC4 L1ELC5
|
|
L1ELE1 L1ELE2 L1ELE3 L1ELE4 L1ELE5
|
|
L10301 L10302 L10303 L10304 L10305
|
|
0.0000 0.0000 0.0000 0.0000 0.0000
|
|
L1ELST11 L1ELST21 L1ELST31 L1ELST41 L1ELST51
|
|
L1ELST12 L1ELST22 L1ELST32 L1ELST42 L1ELST52
|
|
L1ELST13 L1ELST23 L1ELST33 L1ELST43 L1ELST53
|
|
L1ELST14 L1ELST24 L1ELST34 L1ELST44 L1ELST54
|
|
L1ELST15 L1ELST25 L1ELST35 L1ELST45 L1ELST55
|
|
";
|
|
|
|
# Get values from form
|
|
my %All = CollectValues();
|
|
my $ProjType=$All{"ProjType"};
|
|
$All{"ProjZ"}=sprintf("%6.2f",Chem::Zof($ProjType));
|
|
$All{"ProjAM"}=sprintf("%6.2f",Chem::Massof($ProjType));
|
|
|
|
my $Check=0;
|
|
my $Layer="";
|
|
my $Li="";
|
|
# Loop over layers an create appropriate values
|
|
for (my $i=1;$i<=$All{"NL"};$i++){
|
|
$Li = "L".$i;
|
|
$Layer = $TemplateLayer;
|
|
$Layer =~ s/L1/$Li/g;
|
|
$TemplateFile=$TemplateFile.$Layer;
|
|
$Check=0;
|
|
# Composition of layers
|
|
my $LComp="L".$i."Comp";
|
|
my $Comp = layerTable->text($i-1,0);
|
|
$All{$LComp} = $Comp;
|
|
my %LElComp=Chem::parse_formula($Comp);
|
|
if ($Comp eq "") {$Check++;}
|
|
|
|
# Densities of layers
|
|
my $Lrho="L".$i."rho";
|
|
my $rho = layerTable->text($i-1,1);
|
|
$All{$Lrho}=sprintf("%6.2f",$rho);
|
|
if ($rho eq "") {$Check++;}
|
|
|
|
# Thickness of layers
|
|
my $Ld ="L".$i."d";
|
|
my $d = layerTable->text($i-1,2);
|
|
$All{$Ld}=sprintf("%8.2f",$d);
|
|
if ($d eq "") {$Check++;}
|
|
|
|
# Sanity check, is the layer supposed to have value? are they all there?
|
|
if ($Check!=0) {
|
|
my $ErrMsg="Error: Layer $i is empty. Expecting it to be defined!\n";
|
|
print STDERR $ErrMsg;
|
|
my $HelpWindow = Qt::MessageBox::information( this, "Error!",$ErrMsg);
|
|
return "ERROR";
|
|
}
|
|
|
|
my $tmp = "L".$i."CK";
|
|
$All{$tmp}=sprintf("%6.2f",1.0);
|
|
|
|
my $Sum = 0;
|
|
foreach (keys %LElComp) {
|
|
$Sum=$Sum+$LElComp{$_};
|
|
}
|
|
if ($Sum==0) {$Sum=1;}
|
|
|
|
my @Els = keys %LElComp;
|
|
|
|
for (my $NEl=1;$NEl<=5;$NEl++) {
|
|
my $El = $Els[$NEl-1];
|
|
my $LEkey = "L".$i."EL";
|
|
my $ElZ = Chem::Zof($El);
|
|
my $ElW = Chem::Massof($El);
|
|
my $ElC = $LElComp{$El}/$Sum;
|
|
my $ElE = Chem::Elastof($El);
|
|
my $El030 = 30;
|
|
if ($El eq "") { $El030 = 0.0;}
|
|
|
|
$All{$LEkey."Z".$NEl}=sprintf("%8.4f",$ElZ);
|
|
$All{$LEkey."W".$NEl}=sprintf("%8.4f",$ElW);
|
|
$All{$LEkey."C".$NEl}=sprintf("%8.4f",$ElC);
|
|
$All{$LEkey."E".$NEl}=sprintf("%8.4f",$ElE);
|
|
$All{"L".$i."030".$NEl}=sprintf("%8.4f",$El030);
|
|
|
|
my $ElST = Chem::Stopicru($El);
|
|
my @ElSTs = split (/,/,$ElST);
|
|
my $j=1;
|
|
foreach (@ElSTs) {
|
|
$LEkey = "L".$i."ELST".$NEl.$j;
|
|
$j++;
|
|
$All{$LEkey}=sprintf("%11.6f",$_);
|
|
}
|
|
}
|
|
}
|
|
|
|
foreach my $key (keys %All) {
|
|
if ($All{$key} ne ""){
|
|
$TemplateFile =~ s/$key/$All{$key}/;
|
|
# Seed repeats three times
|
|
if ($key eq "Seed") { $TemplateFile =~ s/$key/$All{$key}/g;}
|
|
}
|
|
}
|
|
return $TemplateFile;
|
|
}
|
|
|
|
void TrimSPGUI::StartSequenceOne()
|
|
{
|
|
my %All = CollectValues();
|
|
my @SValues=();
|
|
my @SdzValues=();
|
|
my $cmd="";
|
|
|
|
if (!$ENV{'TRIMBIN'}) {
|
|
# If trim.sp binary is not defined give warning and return
|
|
my $Warning = Qt::MessageBox::information( this, "Warning",
|
|
"Warning:\n TrimSP binary is not found.\n Define using the Configuration tab.");
|
|
return(0);
|
|
|
|
}
|
|
|
|
# Cleanup from old files
|
|
if (-e "ausgabe1.inp") {
|
|
system("rm -f ausgabe*");
|
|
}
|
|
|
|
my $Progress=0;
|
|
if ($All{"ScanSeq"}) {
|
|
# For a scan
|
|
$All{"ERadio"}=ERadio->isChecked();
|
|
$All{"SigERadio"}=SigERadio->isChecked();
|
|
$All{"AngleRadio"}=AngleRadio->isChecked();
|
|
$All{"SigAngleRadio"}=SigAngleRadio->isChecked();
|
|
$All{"NProjRadio"}=NProjRadio->isChecked();
|
|
$All{"dRadio"}=dRadio->isChecked();
|
|
$All{"ScandL"}=ScandL->text();
|
|
# Remove any white spaces
|
|
$All{"ScandL"} =~ s/\s+//g;
|
|
$All{"ListRadio"}=ListRadio->isChecked();
|
|
$All{"LoopRadio"}=LoopRadio->isChecked();
|
|
$All{"ScanList"}=ScanList->text();
|
|
# Remove any white spaces
|
|
$All{"ScanList"} =~ s/\s+//g;
|
|
$All{"ScanListdz"}=ScanListdz->text();
|
|
# Remove any white spaces
|
|
$All{"ScanListdz"} =~ s/\s+//g;
|
|
# These should be numeric
|
|
$All{"SFrom"}=1*SFrom->text();
|
|
$All{"STo"}=1*STo->text();
|
|
$All{"SStep"}=1*SStep->text();
|
|
|
|
if ($All{"ListRadio"}) {
|
|
@SValues=split(/,/,$All{"ScanList"});
|
|
@SdzValues=split(/,/,$All{"ScanListdz"});
|
|
if ($#SValues == $#SdzValues) {$All{"SdzFlag"}=1;}
|
|
} elsif ($All{"LoopRadio"}) {
|
|
for (my $Val=$All{"SFrom"};$Val<=$All{"STo"};$Val=$Val+$All{"SStep"}) {
|
|
@SValues=(@SValues,$Val);
|
|
}
|
|
}
|
|
|
|
my $ScanName = "";
|
|
if ($All{"ERadio"}) {
|
|
$ScanName = "E";
|
|
} elsif ($All{"SigERadio"}) {
|
|
$ScanName = "SigE";
|
|
} elsif ($All{"AngleRadio"}) {
|
|
$ScanName = "Angle";
|
|
} elsif ($All{"SigAngleRadio"}) {
|
|
$ScanName = "SigAngle";
|
|
} elsif ($All{"NProjRadio"}) {
|
|
$ScanName = "NProj";
|
|
} elsif ($All{"dRadio"}) {
|
|
$ScanName = "Ld".$All{"ScandL"};
|
|
}
|
|
|
|
my $ScanAttrib = child($ScanName);
|
|
my $iScan=0;
|
|
foreach (@SValues) {
|
|
if ($All{"dRadio"}) {
|
|
$ScanAttrib->setText($All{"ScandL"},2,$_);
|
|
} else {
|
|
$ScanAttrib->setText($_);
|
|
}
|
|
if ( $All{"SdzFlag"} == 1) {
|
|
if ($All{"ERadio"}==1) {
|
|
dz->setText($SdzValues[$iScan]);
|
|
} elsif ($All{"SigAngleRadio"}==1) {
|
|
E->setText($SdzValues[$iScan]);
|
|
}
|
|
}
|
|
my $eingabe1=CreateInpFile();
|
|
if ($eingabe1 eq "ERROR") {return 0;}
|
|
my $FILENAME=$All{"FNPre"}."_".$ScanName.$_;
|
|
open (INPF,q{>}, "$FILENAME.inp" );
|
|
print INPF $eingabe1;
|
|
close(INPF);
|
|
# Use windoz version
|
|
# system("cp $FILENAME.inp eingabe1.inp; wine TrimSP7L.exe");
|
|
# Use Linux version
|
|
$Progress=$Progress+90/$#SValues;
|
|
Progress->setProgress($Progress);
|
|
Progress->update();
|
|
$cmd = "cp $FILENAME.inp eingabe1.inp; ".$ENV{'TRIMBIN'};
|
|
system($cmd);
|
|
|
|
foreach ("err","out","rge") {
|
|
system("mv -f ausgabe1.$_ $FILENAME.$_");
|
|
}
|
|
# Not needed if work path is changed
|
|
# $cmd="mv -f $FILENAME.* ".$All{"Path"};
|
|
# system($cmd);
|
|
$iScan++;
|
|
}
|
|
} else {
|
|
# For a single run
|
|
my $eingabe1=CreateInpFile();
|
|
if ($eingabe1 eq "ERROR") {return 0;}
|
|
my $FILENAME=$All{"FNPre"};
|
|
open (INPF,q{>}, "$FILENAME.inp" );
|
|
print INPF $eingabe1;
|
|
close(INPF);
|
|
$Progress=20;
|
|
Progress->setProgress($Progress);
|
|
|
|
# Use windoz version
|
|
# system("cp $FILENAME.inp eingabe1.inp; wine TrimSP7L.exe");
|
|
# Use Linux version
|
|
$cmd = "cp $FILENAME.inp eingabe1.inp; ".$ENV{'TRIMBIN'};
|
|
system($cmd);
|
|
foreach ("err","out","rge") {
|
|
system("mv -f ausgabe1.$_ $FILENAME.$_");
|
|
}
|
|
$Progress=90;
|
|
Progress->setProgress($Progress);
|
|
# If we change work directory this is not needed
|
|
# $cmd="mv -f $FILENAME.* ".$All{"Path"};
|
|
# system($cmd);
|
|
}
|
|
# Move the fort.33 file into the subdirectory and change its name
|
|
$cmd="rm -f eingabe1.inp; mv -f fort.33 ".$All{"Path"}."/".$All{"FNPre"}."_Seq_Results.dat";
|
|
system($cmd);
|
|
$Progress=100;
|
|
Progress->setProgress($Progress);
|
|
return 1;
|
|
}
|
|
|
|
|
|
void TrimSPGUI::DirectoryBrowse()
|
|
{
|
|
my $FileBrowser = Qt::FileDialog::getExistingDirectory("./",this,"get existing directory","Choose a directory",1);
|
|
if ($FileBrowser eq "") {$FileBrowser="./";}
|
|
Path->setText($FileBrowser);
|
|
|
|
# Create a subdirectory where all input/output files are saved
|
|
my $cmd="";
|
|
if (-d $FileBrowser) {
|
|
# Directory exists, do nothing
|
|
} else {
|
|
$cmd="mkdir $FileBrowser";
|
|
system($cmd);
|
|
}
|
|
# Change work directory accordingly
|
|
chdir ("$FileBrowser");
|
|
|
|
# Return a string with the directory name
|
|
return $FileBrowser ;
|
|
|
|
}
|
|
|
|
|
|
void TrimSPGUI::ConfirmQuit()
|
|
{
|
|
my $Ans = Qt::MessageBox::question( this, "Quit?","Are you sure you want to quit?","&Yes","&No","",0,1);
|
|
if ($Ans==0) {
|
|
# Then quit
|
|
Qt::Application::exit( 0 );
|
|
}
|
|
# Otherwize go back
|
|
# print STDOUT $ENV{'TRIMBIN'}."\n";
|
|
}
|
|
|
|
|
|
|
|
void TrimSPGUI::PlotProfiles()
|
|
{
|
|
my $files_ref=Qt::FileDialog::getOpenFileNames(
|
|
"RGE Files (*.rge)",
|
|
"./",
|
|
this,
|
|
"Select RGE files dialog",
|
|
"Choose RGE file to plot");
|
|
my @files_tmp = @$files_ref;
|
|
# Do "natural" sorting on the file name list
|
|
# This will produce (hopefully) a plot with largest needed depth scale
|
|
my @files = grep {s/(^|\D)0+(\d)/$1$2/g,1} sort grep {s/(\d+)/sprintf"%06.6d",$1/ge,1} @files_tmp;
|
|
|
|
my $filenames=join(",",@files);
|
|
|
|
if ($filenames ne "" ) {
|
|
# my $Warning = Qt::MessageBox::information( this, "Big Fat Warning",
|
|
# "Warning:\nClose the plot using the menu FILE -> Quit ROOT\nDO NOT CLOSE USING X.");
|
|
my $TrimPath = $ENV{'PERLLIB'};
|
|
# Now that we have the file list send it to root macro for plotting.
|
|
my $cmd='root -n -l "'.$TrimPath.'/plotRge.C(\"'.$filenames.'\")"&';
|
|
|
|
# my $pid = open(FTO,"$cmd");
|
|
# my $pid = open(FTO,"$cmd 2>&1 |");
|
|
# print "PID=$pid\n";
|
|
# while (<FTO>) {
|
|
# print "$_";
|
|
# }
|
|
# close(FTO);
|
|
my $pid=system($cmd);
|
|
}
|
|
}
|
|
|
|
|
|
void TrimSPGUI::PlotFraction()
|
|
{
|
|
my $file=Qt::FileDialog::getOpenFileName(
|
|
".",
|
|
"Implantation sequence file (*.dat)",
|
|
this,
|
|
"open sequence data file dialog",
|
|
"Choose a sequence data file");
|
|
|
|
if ($file ne "" ) {
|
|
my $TrimPath = $ENV{'PERLLIB'};
|
|
# Now that we have the file name send it to root macro for plotting.
|
|
my $cmd='root -n -l "'.$TrimPath.'/plotFrc.C(\"'.$file.'\")"&';
|
|
|
|
my $pid=system($cmd);
|
|
}
|
|
|
|
}
|
|
|
|
void TrimSPGUI::OpenAboutWindow()
|
|
{
|
|
my $HelpText="TrimSPGUI is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
TrimSPGUI is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with TrimSPGUI. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
Copyright 2009 by Zaher Salman and the LEM Group.
|
|
<zaher.salman\@psi.ch>
|
|
";
|
|
my $HelpWindow = Qt::MessageBox::about( this, "About TrimSP GUI",$HelpText);
|
|
}
|
|
|
|
|
|
void TrimSPGUI::OpenFile()
|
|
{
|
|
# Types of different input
|
|
my %Types = ();
|
|
# 0 - text (this is default), 1 - spin box, 2 - radio button, 3 - combo box
|
|
$Types{"NL"}=1 ;
|
|
$Types{"ProjType"}= 3;
|
|
$Types{"ScanSeq"}= 2;
|
|
$Types{"ERadio"}= 2;
|
|
$Types{"SigERadio"}= 2;
|
|
$Types{"AngleRadio"}= 2;
|
|
$Types{"SigAngleRadio"}= 2;
|
|
$Types{"NProjRadio"}= 2;
|
|
$Types{"dRadio"}= 2;
|
|
$Types{"ScandL"}= 1;
|
|
$Types{"ListRadio"}= 2;
|
|
$Types{"ScanListdz"}= 0;
|
|
$Types{"LoopRadio"}= 2;
|
|
|
|
|
|
my $file=Qt::FileDialog::getOpenFileName(
|
|
".",
|
|
"Initialization file (.* *.*)",
|
|
this,
|
|
"open file dialog",
|
|
"Choose an initialization file");
|
|
|
|
# If the user gave a valid filename try to read it
|
|
if ($file ne "") {
|
|
open (INF,q{<},"$file" );
|
|
my @lines = <INF>;
|
|
close(INF);
|
|
my $Attrib="";
|
|
foreach my $line (@lines) {
|
|
# Remove white spaces
|
|
$line =~ s/\s+//g;
|
|
my @InitPar = split (/=/,$line);
|
|
# Check it is not empty or title line
|
|
if ($InitPar[0] ne "" && $InitPar[1] ne "") {
|
|
# First take care of the layers, with patters L?Comp, L?rho, L?d
|
|
my $CRow=$InitPar[0];
|
|
if ($InitPar[0] =~ m/L.*Comp$/ ) {
|
|
$CRow =~ s/\D//g;
|
|
layerTable->setText($CRow-1,0,$InitPar[1]);
|
|
} elsif ($InitPar[0] =~ m/L.*rho$/ ) {
|
|
$CRow =~ s/\D//g;
|
|
layerTable->setText($CRow-1,1,$InitPar[1]);
|
|
} elsif ($InitPar[0] =~ m/L.*d$/ ) {
|
|
$CRow =~ s/\D//g;
|
|
layerTable->setText($CRow-1,2,$InitPar[1]);
|
|
} else {
|
|
$Attrib = child($InitPar[0]);
|
|
if ($Types{$InitPar[0]} == 1) {
|
|
$Attrib->setValue($InitPar[1]);
|
|
# Create enough rows in layerTable
|
|
if ($InitPar[0] eq "NL") {
|
|
layerTable->setNumRows($InitPar[1]);
|
|
}
|
|
} elsif ($Types{$InitPar[0]} == 2 ) {
|
|
if($InitPar[1] == 1) {
|
|
$Attrib->setChecked(1);
|
|
} else {
|
|
$Attrib->setChecked(0);
|
|
}
|
|
} elsif ($Types{$InitPar[0]} == 3) {
|
|
$Attrib-> setCurrentText($InitPar[1]);
|
|
} else {
|
|
$Attrib->setText($InitPar[1]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void TrimSPGUI::SaveFile()
|
|
{
|
|
my %All = CollectValues();
|
|
my $InitFile="
|
|
[Layers]
|
|
NL=$All{'NL'}";
|
|
|
|
for (my $i=1;$i<=$All{"NL"};$i++){
|
|
my $Li="L".$i;
|
|
my $LComp=$Li."Comp";
|
|
my $Lrho=$Li."rho";
|
|
my $Ld=$Li."d";
|
|
$InitFile=$InitFile."
|
|
$LComp=$All{$LComp}
|
|
$Lrho=$All{$Lrho}
|
|
$Ld=$All{$Ld}
|
|
";
|
|
}
|
|
|
|
$InitFile=$InitFile."
|
|
[ProjectileParameters]
|
|
ProjType=$All{'ProjType'}
|
|
NProj=$All{'NProj'}
|
|
z0=$All{'z0'}
|
|
dz=$All{'dz'}
|
|
E=$All{'E'}
|
|
SigE=$All{'SigE'}
|
|
Angle=$All{'Angle'}
|
|
SigAngle=$All{'SigAngle'}
|
|
Seed=$All{'Seed'}
|
|
|
|
[Files]
|
|
FNPre=$All{'FNPre'}
|
|
Path=$All{'Path'}
|
|
|
|
[ScanSequence]
|
|
ScanSeq=$All{'ScanSeq'}
|
|
ERadio=$All{'ERadio'}
|
|
SigERadio=$All{'SigERadio'}
|
|
AngleRadio=$All{'AngleRadio'}
|
|
SigAngleRadio=$All{'SigAngleRadio'}
|
|
NProjRadio=$All{'NProjRadio'}
|
|
dRadio=$All{'dRadio'}
|
|
ListRadio=$All{'ListRadio'}
|
|
ScanList=$All{'ScanList'}
|
|
ScanListdz=$All{'ScanListdz'}
|
|
LoopRadio=$All{'LoopRadio'}
|
|
SFrom=$All{'SFrom'}
|
|
STo=$All{'STo'}
|
|
SStep=$All{'SStep'}
|
|
";
|
|
|
|
# Save to default file name "TriumSP.cfg"
|
|
my $file = "TrimSP.cfg";
|
|
open (OUTF,q{>},"$file" );
|
|
print OUTF (" $InitFile");
|
|
close(OUTF);
|
|
}
|
|
|
|
|
|
void TrimSPGUI::SaveFileAs()
|
|
{
|
|
my %All = CollectValues();
|
|
my $InitFile="
|
|
[Layers]
|
|
NL=$All{'NL'}";
|
|
|
|
for (my $i=1;$i<=$All{"NL"};$i++){
|
|
my $Li="L".$i;
|
|
my $LComp=$Li."Comp";
|
|
my $Lrho=$Li."rho";
|
|
my $Ld=$Li."d";
|
|
$InitFile=$InitFile."
|
|
$LComp=$All{$LComp}
|
|
$Lrho=$All{$Lrho}
|
|
$Ld=$All{$Ld}
|
|
";
|
|
}
|
|
|
|
$InitFile=$InitFile."
|
|
[ProjectileParameters]
|
|
ProjType=$All{'ProjType'}
|
|
NProj=$All{'NProj'}
|
|
z0=$All{'z0'}
|
|
dz=$All{'dz'}
|
|
E=$All{'E'}
|
|
SigE=$All{'SigE'}
|
|
Angle=$All{'Angle'}
|
|
SigAngle=$All{'SigAngle'}
|
|
Seed=$All{'Seed'}
|
|
|
|
[Files]
|
|
FNPre=$All{'FNPre'}
|
|
Path=$All{'Path'}
|
|
|
|
[ScanSequence]
|
|
ScanSeq=$All{'ScanSeq'}
|
|
ERadio=$All{'ERadio'}
|
|
SigERadio=$All{'SigERadio'}
|
|
AngleRadio=$All{'AngleRadio'}
|
|
SigAngleRadio=$All{'SigAngleRadio'}
|
|
NProjRadio=$All{'NProjRadio'}
|
|
dRadio=$All{'dRadio'}
|
|
ListRadio=$All{'ListRadio'}
|
|
ScanList=$All{'ScanList'}
|
|
ScanListdz=$All{'ScanListdz'}
|
|
LoopRadio=$All{'LoopRadio'}
|
|
SFrom=$All{'SFrom'}
|
|
STo=$All{'STo'}
|
|
SStep=$All{'SStep'}
|
|
";
|
|
|
|
my $file=Qt::FileDialog::getSaveFileName(
|
|
"TrimSP.cfg",
|
|
"TrimSP GUI Initialization file (*.cfg)",
|
|
this,
|
|
"save file dialog",
|
|
"Choose a filename to save under");
|
|
|
|
# If the user gave a filename the copy to it
|
|
if ($file ne "") {
|
|
open (OUTF,q{>},"$file" );
|
|
print OUTF (" $InitFile");
|
|
close(OUTF);
|
|
}
|
|
}
|
|
|
|
|
|
void TrimSPGUI::GUIPath()
|
|
{
|
|
# This subroutine is used to define diffirent variables
|
|
my $FileBrowser = Qt::FileDialog::getExistingDirectory("./",this,"get existing directory","Choose the directory where the TrimSP GUI is.",1);
|
|
|
|
# If nothing is returned keep as is
|
|
if ($FileBrowser eq "") {
|
|
$FileBrowser=$ENV{'PERLLIB'};
|
|
} else {
|
|
$ENV{'PERLLIB'}=$FileBrowser;
|
|
}
|
|
TrimGUIPath->setText($FileBrowser);
|
|
# Return a string with the directory name
|
|
return $FileBrowser ;
|
|
|
|
|
|
}
|
|
|
|
sub TrimBin
|
|
{
|
|
|
|
my $file=Qt::FileDialog::getOpenFileName(
|
|
"$ENV{'TRIMBIN'}",
|
|
"Trim.SP binary (.* *.* *)",
|
|
this,
|
|
"open file dialog",
|
|
"Select the Trim.SP binary file");
|
|
|
|
# If the user gave a valid filename try to read it
|
|
if ($file eq "") {
|
|
$file=$ENV{'TRIMBIN'};
|
|
} else {
|
|
$ENV{'TRIMBIN'}=$file;
|
|
}
|
|
TRIMBIN->setText($file);
|
|
return $file;
|
|
}
|
|
|
|
|
|
void TrimSPGUI::TrimBin()
|
|
{
|
|
my $file=Qt::FileDialog::getOpenFileName(
|
|
"$ENV{'TRIMBIN'}",
|
|
"Trim.SP binary (.* *.* *)",
|
|
this,
|
|
"open file dialog",
|
|
"Select the Trim.SP binary file");
|
|
|
|
# If the user gave a valid filename try to read it
|
|
if ($file eq "") {
|
|
$file=$ENV{'TRIMBIN'};
|
|
} else {
|
|
$ENV{'TRIMBIN'}=$file;
|
|
}
|
|
TRIMBIN->setText($file);
|
|
return $file;
|
|
}
|
|
|
|
|
|
void TrimSPGUI::findDensity()
|
|
{
|
|
use Chem;
|
|
# Get sender name to know which layer
|
|
my $sender = sender()->name();
|
|
my $CCol=sender()->currentColumn();
|
|
if ($CCol==0) {
|
|
# The composition changed, find density
|
|
my $CRow=sender()->currentRow();
|
|
my $Compound=sender()->text($CRow,$CCol);
|
|
# See if you have the density
|
|
my $Density=Chem::Densities($Compound);
|
|
# If the density is in the database submit it
|
|
sender()->setText($CRow,1,$Density);
|
|
}
|
|
}
|
|
|
|
|