13 #include "TTreeReader.h"
14 #include "TTreeReaderValue.h"
15 #include "TTreeReaderArray.h"
19 #include <TSystemDirectory.h>
20 #include <TSystemFile.h>
35 return StatusCode::SUCCESS;
40 return StatusCode::SUCCESS;
44 TVectorD
tmp(vin.size());
57 for (
uint i = 0;
i <
v.size();
i++) {
59 if (
v[
i] - 0.00001 <
val &&
val <
v[
i] + 0.00001)
return i;
82 ATH_MSG_WARNING(
"ERROR: Initialize failed looking for file " << TCADfileListToLoad);
86 return StatusCode::FAILURE;
90 return StatusCode::SUCCESS;
101 std::ofstream efieldscalib;
102 efieldscalib.open(
"listOfEfields.txt");
103 TPRegexp rvo(
"\\b-[0-9](\\w+)V\\b");
104 TPRegexp rfl(
"\\bfl([\\w.]+)e[0-9]{1,2}");
105 TString
ext =
".dat";
107 TSystemDirectory
dir((TString)fpath, (TString)fpath);
108 TList*
files =
dir.GetListOfFiles();
113 while ((
file = (TSystemFile*)
next())) {
115 if (
fname.BeginsWith(
"fl") &&
file->IsDirectory()) {
116 TString deeppath = fpath;
118 deeppath +=
"/reference/";
119 TSystemDirectory deepdir(deeppath, deeppath);
120 TList* deepfiles = deepdir.GetListOfFiles();
122 TSystemFile* deepfile;
124 TIter deepnext(deepfiles);
125 while ((deepfile = (TSystemFile*) deepnext())) {
126 deepfname = deepfile->GetName();
127 if (!deepfile->IsDirectory() && deepfname.EndsWith(
ext)) {
128 svol = deepfname(rvo);
129 svol.ReplaceAll(
"-",
"");
130 svol.ReplaceAll(
"V",
"");
131 sflu = deeppath(rfl);
132 sflu.ReplaceAll(
"fl",
"");
135 if (!deepfname.Contains(
"pruned")) {
136 if (!sflu.IsFloat()) {
137 ATH_MSG_INFO(
"EfieldInterpolator load from directory - could not resolve fluence from " <<
fullpath);
140 if (!svol.IsFloat()) {
141 ATH_MSG_INFO(
"EfieldInterpolator load from directory - could not resolve voltage from " <<
fullpath);
148 efieldscalib <<
fullpath <<
" " << sflu <<
" " << svol << std::endl;
155 efieldscalib.close();
157 if (success)
ATH_MSG_INFO(
"Initialized from directory");
163 TString fpath = finpath;
167 if (fpath.EndsWith(
".txt")) {
170 ATH_MSG_INFO(
"Loaded file " << fpath <<
" - all maps accumulated in " << fTCAD);
176 if (fpath.EndsWith(
"toTTree.root")) {
181 if (fpath.EndsWith(
".root")) {
194 const std::vector<double>& voltages) {
195 bool tooLowVolt =
true;
196 bool tooHighVolt =
true;
198 for (
const auto iv : voltages) {
199 if (aimVoltage < iv) tooHighVolt =
false;
200 if (aimVoltage > iv) tooLowVolt =
false;
202 bool tooLowFlu =
true;
203 bool tooHighFlu =
true;
204 for (
double fluence : fluences) {
205 if (aimFluence < fluence) tooHighFlu =
false;
206 if (aimFluence > fluence) tooLowFlu =
false;
209 "WARNING: The fluence value you specified (" << aimFluence <<
") is too low to be reliably interpolated!");
211 "WARNING: The voltage value you specified (" << aimVoltage <<
") is too low to be reliably interpolated!");
213 "WARNING: The fluence value you specified (" << aimFluence <<
") is too high to be reliably interpolated!");
214 if (tooHighVolt)
ATH_MSG_WARNING(
"WARNING: The voltage value you specified (" << aimVoltage <<
") is too high to be reliably interpolated!");
218 if (12.2 < aimFluence || aimFluence < 1.)
ATH_MSG_WARNING(
" WARNING: The fluence value you specified (" << aimFluence <<
") is outside the range within it could be reliably interpolated!");
219 if (1010. < aimVoltage || aimVoltage < 79.)
ATH_MSG_WARNING(
" WARNING: The voltage value you specified (" << aimVoltage <<
") is outside the range within it could be reliably interpolated!"); }
222 hin->Scale(aimInt / (
float) hin->Integral(
first, last));
226 if (
x1 == 0.)
return 0.;
240 if (
delx == 0)
return 0.;
242 double dely =
y2 -
y1;
244 return(xaim * (dely /
delx) +
b);
259 if (!in.good())
break;
260 if (nlines < 3) printf(
"e=%s=%f, z=%s=%f \n",
e.Data(),
e.Atof(),
z.Data(),
z.Atof());
262 hefieldz->Fill(
z.Atof(),
e.Atof());
272 TString
tl = targetList;
273 TString
fName = targetList;
275 fName.ReplaceAll(
".txt",
"_toTTree.root");
277 TFile* bufferTCADtree =
new TFile(
fName.Data(),
"RECREATE");
279 if (
tl.Length() < 1) {
280 tl =
"list_TCAD_efield_maps.txt";
284 TTree* tcadtree =
new TTree(
"tcad",
"All TCAD E field simulations stored as individual events in tree");
285 double voltage = -1.;
286 double fluence = -1.;
287 std::vector<double> efield;
288 std::vector<Int_t> pixeldepth;
289 tcadtree->Branch(
"voltage", &voltage,
"voltage/D");
290 tcadtree->Branch(
"fluence", &fluence,
"fluence/D");
291 tcadtree->Branch(
"efield", &efield);
292 tcadtree->Branch(
"pixeldepth", &pixeldepth);
303 fluence = fluence * 1
e-14;
314 ATH_MSG_DEBUG(
"Reading input line: fluence=" << (
infile.at(
ifile).at(1)).Data() << fluence <<
" voltage=" << voltage <<
" e=" <<
e.Atof() <<
"=" <<
e.Data() <<
", z=" << (
int)
z.Atof() <<
"=" <<
z.Data() <<
" in file = " <<
ifile);
316 efield.push_back(
e.Atof());
317 pixeldepth.push_back((
int)
z.Atof());
318 if (
z.Atof() > 200)
isIBL =
false;
320 bufferTCADtree->cd();
325 ATH_MSG_INFO(
"Pixel depth read from file too big for IBL. Set to B layer, depth = 250um\n");
328 bufferTCADtree->cd();
330 bufferTCADtree->Close();
335 std::vector<std::vector<TString> >
filelist;
336 TString tmpname =
"";
337 TString tmpfluence =
"";
338 TString tmpvolt =
"";
339 std::vector<TString> vstr;
341 ATH_MSG_DEBUG(
"Try to open: " << fileList_TCADsamples.Data());
342 in.open(fileList_TCADsamples);
344 in >> tmpname >> tmpfluence >> tmpvolt;
345 if (!in.good())
break;
346 if (tmpname.BeginsWith(
'#'))
continue;
347 if (tmpname.EndsWith(
".dat")) {
348 vstr.push_back(tmpname);
349 vstr.push_back(tmpfluence);
350 vstr.push_back(tmpvolt);
352 ATH_MSG_DEBUG(
"Found and load:" << tmpfluence.Atof() <<
" neq/cm2 " << tmpvolt.Atof() <<
"V - " << tmpname.Data());
355 ATH_MSG_WARNING(
"Wrong extension: " << tmpname.Data() <<
" -- check input ");
365 TString tmpfinter = fTCAD;
367 tmpfinter.ReplaceAll(
"toTTree",
"toInterpolationTTree");
368 TFile* faim =
new TFile(tmpfinter,
"Recreate");
369 TFile* ftreeTCAD =
new TFile(fTCAD.c_str());
370 TTreeReader myReader(
"tcad", ftreeTCAD);
371 TTreeReaderValue<double> involtage(myReader,
"voltage");
372 TTreeReaderValue<double> influence(myReader,
"fluence");
373 TTreeReaderValue<std::vector<double> > inefield(myReader,
"efield");
374 TTreeReaderValue<std::vector<int> > inpixeldepth(myReader,
"pixeldepth");
379 std::vector<double> allFluences;
380 std::vector<double> allVoltages;
381 std::vector<double> allEfield;
383 double tmpflu, tmpvol;
384 while (myReader.Next()) {
388 if (std::find_if(allFluences.begin(), allFluences.end(), [&tmpflu](
const double&
b) {
389 return(std::abs(tmpflu - b) < 1E-6);
390 }) == allFluences.end()) allFluences.push_back(tmpflu);
391 if (std::find_if(allVoltages.begin(), allVoltages.end(), [&tmpvol](
const double&
b) {
392 return(std::abs(tmpvol - b) < 1E-6);
393 }) == allVoltages.end()) allVoltages.push_back(tmpvol);
397 std::sort(allFluences.begin(), allFluences.end());
398 std::sort(allVoltages.begin(), allVoltages.end());
399 for (
double & allFluence : allFluences)
ATH_MSG_DEBUG(
"fluences recorded: " << allFluence);
400 for (
double & allVoltage : allVoltages)
ATH_MSG_DEBUG(
"voltages recorded: " << allVoltage);
401 std::vector<double> tmpef;
407 std::vector<int> tmpz;
408 int nz = rightEdge - leftEdge;
411 std::vector<double> zpixeldepth(nz, -1);
412 std::vector<std::vector<double> > zfluence(nz, std::vector<double>(ne, -1));
413 std::vector<std::vector<double> > zvoltage(nz, std::vector<double>(ne, -1));
414 std::vector<std::vector<double> > zefield(nz, std::vector<double>(ne, -1));
415 std::vector<std::vector<std::vector<double> > > zefieldmap(nz, std::vector<std::vector<double> >(allFluences.size(), std::vector<double>(allVoltages.size(), -1)));
419 while (myReader.Next()) {
420 tmpz = *inpixeldepth;
421 ATH_MSG_DEBUG(
"Number of available z values = " << tmpz.size());
422 if (tmpz.at(0) > leftEdge)
ATH_MSG_WARNING(
"Map starting from high pixeldepth = " << tmpz.at(0) <<
". Might trouble readout.");
423 for (
int iz = leftEdge; iz < rightEdge; iz++) {
430 while ((tmpz.at(
index) != iz) && (
index < nz)) {
431 ATH_MSG_DEBUG(
"Adapt possible index shift for missing edge values: pixeldepth tree = " << nz <<
" current index = " <<
index);
434 if (iz % 2 == 0)
ATH_MSG_DEBUG(
"Index " <<
index <<
" - iev " << iev <<
" - iz " << iz);
438 zfluence.at(iz - leftEdge).at(iev) = tmpflu;
439 zvoltage.at(iz - leftEdge).at(iev) = tmpvol;
440 zefield.at(iz - leftEdge).at(iev) = tmpef.at(
index);
442 ATH_MSG_DEBUG(
"Event #" << iev <<
"-z=" << iz <<
": fluence =" << tmpflu <<
" voltage=" << tmpvol <<
", E=" << tmpef.at(
index));
449 TTree* tz_tmp =
new TTree(
"tz",
"All TCAD E field simulations stored splitted by pixel depth");
450 double pixeldepth = -1.;
451 std::vector<double> fluence;
452 std::vector<double> voltage;
453 std::vector<double> xfluence;
454 std::vector<double> yvoltage;
455 std::vector<double> efield;
456 std::vector<std::vector<double> > efieldfluvol;
458 tz_tmp->Branch(
"pixeldepth", &pixeldepth);
459 tz_tmp->Branch(
"voltage", &voltage);
460 tz_tmp->Branch(
"fluence", &fluence);
461 tz_tmp->Branch(
"yvoltage", &yvoltage);
462 tz_tmp->Branch(
"xfluence", &xfluence);
463 tz_tmp->Branch(
"efield", &efield);
464 tz_tmp->Branch(
"efieldfluvol", &efieldfluvol);
465 for (
int iz = leftEdge; iz < rightEdge; iz++) {
467 fluence = zfluence.at(iz - leftEdge);
468 voltage = zvoltage.at(iz - leftEdge);
469 efield = zefield.at(iz - leftEdge);
470 efieldfluvol = zefieldmap.at(iz - leftEdge);
471 xfluence = allFluences;
472 yvoltage = allVoltages;
473 ATH_MSG_DEBUG(
"Fill tree for z =" << iz <<
" pd=" << pixeldepth);
487 int EfieldInterpolator::fillXYvectors(
const std::vector<double> & vLoop,
int ifix,
const std::vector<std::vector<double> > & v2vsv1, std::vector<double>& xx, std::vector<double>&
yy,
bool regularOrder) {
493 double ef = v2vsv1.at(
ie).at(ifix);
496 xx.push_back(vLoop.at(
ie));
499 ATH_MSG_DEBUG(
"E field value not available for Phi=" << vLoop.at(
ie) <<
" index Vol= " << ifix);
505 double ef = v2vsv1.at(ifix).at(
ie);
508 xx.push_back(vLoop.at(
ie));
511 ATH_MSG_DEBUG(
"E field value not available for Phi=" << vLoop.at(ifix) <<
" U=" << vLoop.at(
ie));
527 ATH_MSG_WARNING(
"Use interpolation method _Inverse distance weighted_ - guarantees positive E field but no reliable interpolation");
533 for (
uint ivol = 0; ivol < vvol.size(); ivol++) {
534 for (
uint iflu = 0; iflu < vflu.size(); iflu++) {
535 efEntry = vfluvvol.at(iflu).at(ivol);
538 if (
distance < 0.00001)
return efEntry;
540 meanEf += efEntry * TMath::Power((1. /
distance), measure);
551 double EfieldInterpolator::estimateEfield(std::vector<double> vvol,
const std::vector<double>& vflu,
const std::vector<std::vector<double> >& vfluvvol,
double aimFlu,
double aimVol,
const std::string& prepend,
bool debug) {
553 std::vector<double> evol;
554 std::vector<double> vvolWoEp;
556 std::vector<double> evolWoEp;
558 for (
uint ifix = 0; ifix < vvol.size(); ifix++) {
559 std::vector<double> vx;
560 std::vector<double> vy;
562 int availableTCADpoints =
fillXYvectors(vflu, ifix, vfluvvol, vx, vy);
563 ATH_MSG_DEBUG(
"Number of available TCAD points for voltage " << vvol.at(ifix) <<
": " << availableTCADpoints);
564 TString
name =
"FluenceEfield_";
574 tmpgr->SetTitle(
name.Data());
581 efflu = tmpgr->Eval(aimFlu,
nullptr,
"S");
583 efflu = tmpgr->Eval(aimFlu);
587 aimFile.ReplaceAll(
".root",
"_debug.root");
588 aimFile.ReplaceAll(
".root", prepend);
591 tmpgr->SaveAs(aimFile);
595 vvolWoEp.push_back(vvol.at(ifix));
596 evolWoEp.push_back(efflu);
600 evol.push_back(efflu);
605 saveTGraph(vvol, vflu, vfluvvol, aimFlu, aimVol, prepend);
612 ATH_MSG_WARNING(
"E field created on extrapolation. Please check if reasonable!");
615 TString
name =
"VoltageEfield";
622 tmpgr->SetTitle(
name.Data());
629 aimEf = tmpgr->Eval(aimVol,
nullptr,
"S");
631 aimEf = tmpgr->Eval(aimVol);
635 aimFile.ReplaceAll(
".root",
"_debug.root");
636 aimFile.ReplaceAll(
".root", prepend);
639 tmpgr->SaveAs(aimFile);
646 void EfieldInterpolator::saveTGraph(std::vector<double> vvol, std::vector<double> vflu, std::vector<std::vector<double> > vfluvvol,
double aimFlu,
double aimVol,
const std::string& prepend,
bool skipNegative) {
647 TString
name =
"VoltageEfield";
653 TGraph2D* tmpgr =
new TGraph2D();
654 tmpgr->GetYaxis()->SetTitle(
"voltage");
655 tmpgr->GetXaxis()->SetTitle(
"fluence");
656 tmpgr->SetTitle(
name.Data());
657 ATH_MSG_DEBUG(
"E field values: " << vfluvvol.size() <<
" x " << vfluvvol.at(0).size() <<
", flu(x)" << vflu.size() <<
", vol(y)" << vvol.size());
659 for (
uint ix = 0; ix < vfluvvol.size(); ix++) {
660 for (
uint iy = 0; iy < vfluvvol.at(ix).
size(); iy++) {
661 printf(
"Set point %i, %f,%f,%f\n", npoint, vflu.at(ix), vvol.at(iy), vfluvvol.at(ix).at(iy));
662 if (vfluvvol.at(ix).at(iy) < 0) {
663 if (!skipNegative) tmpgr->SetPoint(npoint, vflu.at(ix), vvol.at(iy), -1);
665 tmpgr->SetPoint(npoint, vflu.at(ix), vvol.at(iy), vfluvvol.at(ix).at(iy));
671 aimFile.ReplaceAll(
".root",
"_debugAvailableEfieldVals.root");
672 aimFile.ReplaceAll(
".root", prepend);
675 tmpgr->SaveAs(aimFile);
683 if (aimFluence > 1e12) aimFluence = aimFluence / 1e14;
684 TString
title =
"hefieldz";
685 TString
info =
"#Phi=";
689 info +=
";Pixeldepth z [#mum]";
693 std::vector<double> xfluence;
694 std::vector<double> yvoltage;
695 std::vector<std::vector<double> > efieldfluvol;
696 TFile* ftreeInterpolation = TFile::Open(
m_fInter.c_str());
697 TTreeReader myReader(
"tz", ftreeInterpolation);
698 TTreeReaderValue<std::vector<double> > involtage(myReader,
"yvoltage");
699 TTreeReaderValue<std::vector<double> > influence(myReader,
"xfluence");
700 TTreeReaderValue<std::vector<std::vector<double> > > inefield(myReader,
"efieldfluvol");
701 TTreeReaderValue<double> inpixeldepth(myReader,
"pixeldepth");
703 while (myReader.Next()) {
705 pixeldepth = *inpixeldepth;
706 xfluence = *influence;
707 yvoltage = *involtage;
708 efieldfluvol = *inefield;
722 aimEf =
estimateEfield(yvoltage, xfluence, efieldfluvol, aimFluence, aimVoltage);
726 if (aimEf < 0.)
ATH_MSG_ERROR(
"TCAD E field negative at" << pixeldepth <<
" !");
732 TString debugName =
"negativeSplineZ";
734 aimEf =
estimateEfield(yvoltage, xfluence, efieldfluvol, aimFluence, aimVoltage, debugName.Data(),
true);
735 ATH_MSG_INFO(
"InterpolatorMessage: linearly interpolated e=" << aimEf <<
", z=" << pixeldepth <<
" Phi=," << aimFluence <<
" U=" << aimVoltage);
739 TString debugName =
"negativeLinearZ";
741 aimEf =
estimateEfield(yvoltage, xfluence, efieldfluvol, aimFluence, aimVoltage, debugName.Data(),
true);
742 ATH_MSG_ERROR(
"InterpolatorMessage: spline and linear interpolation failed => InvDistWeighhted e=" << aimEf <<
", z=" << pixeldepth <<
" Phi=," << aimFluence <<
" U=" << aimVoltage);
751 ftreeInterpolation->Close();
767 case TCAD: newtitle +=
" TCAD";
782 int nBins = hin->GetNbinsX();
787 for (
int i = 5;
i > 0;
i--) {
789 float curval = hin->GetBinContent(
i);
790 float binii = hin->GetBinContent(
i + 1);
791 float biniii = hin->GetBinContent(
i + 2);
792 float bini = hin->GetBinContent(
i);
793 if ((bini < 0.01 && binii > 0.01 && biniii > 0.01) || ((biniii - binii) / (
float) binii * (binii - bini) / (
float) binii < -0.2)) {
796 hin->SetBinContent(
i, bini);
799 if (curval <= 0.) hin->SetBinContent(
i, 1.);
805 curval = hin->GetBinContent(
nBins + 1 -
i);
806 binii = hin->GetBinContent(
nBins + 1 -
i - 1);
807 biniii = hin->GetBinContent(
nBins + 1 -
i - 2);
808 bini = hin->GetBinContent(
nBins + 1 -
i);
809 if ((bini < 0.01 && binii > 0.01 && biniii > 0.01) || ((biniii - binii) / (
float) binii * (binii - bini) / (
float) binii < -0.2)) {
812 hin->SetBinContent(
nBins + 1 -
i, bini);
815 if (curval <= 0.) hin->SetBinContent(
nBins + 1 -
i, 1.);
829 ATH_MSG_WARNING(
"EfieldInterpolator not initialized! Not able to produce E field.");