129#include "TRestAxionOpticsMirror.h"
162 RESTDebug <<
"Entering TRestAxionOpticsMirror constructor( cfgFileName, name )" <<
RESTendl;
227 if (mirrorFile !=
"" && windowFile !=
"") {
233 cout <<
"--------------------------------- INFO ------------------------------" << endl;
234 cout <<
"The optics material properties were not found in the database" << endl;
235 cout <<
"Downloading from Henke database. This process will take a long time." << endl;
236 cout <<
"After producing these files, please, contribute them to the " << endl;
237 cout <<
"rest-for-physics/axionlib-data inside the optics directory ..." << endl;
238 cout <<
"---------------------------------- INFO ------------------------------" << endl;
242 map<Int_t, std::vector<Float_t>> reflectivity;
243 map<Int_t, std::vector<Float_t>> transmission;
244 for (
double n = 0; n < 9; n = n + 4.5) {
249 vector<Float_t> reflect;
250 vector<Float_t> transm;
254 cout <<
"Scanning angles between " << n <<
" and " << n + 4.5 <<
".";
255 for (
int e = 30; e <= 15000; e += 30) {
261 std::vector<std::vector<Double_t>> data;
263 RESTError <<
"TRestAxionOpticsMirror. Error reading HenkeFile table" <<
RESTendl;
267 Int_t N = data.size() - 1;
268 if (n == 4.5) N = N + 1;
270 for (
int m = 0; m < N; m++) reflectivity[e].push_back((Float_t)data[m][1]);
271 for (
int m = 0; m < N; m++) transmission[e].push_back((Float_t)data[m][2]);
275 cout <<
"Number of angles stored : " << reflectivity[30].size() << endl;
277 for (
const auto& x : reflectivity) {
280 for (
const auto& x : transmission) {
321 RESTError <<
"Nothing to export!" <<
RESTendl;
325 string path = REST_USER_PATH +
"/export/";
328 std::cout <<
"Creating path: " << path << std::endl;
329 int z = system((
"mkdir -p " + path).c_str());
330 if (z != 0) RESTError <<
"Problem creating directory: " << path <<
RESTendl;
335 RESTInfo <<
"Reflectivity table generated at: " << path + fnameR <<
RESTendl;
339 RESTInfo <<
"Transmission table generated at: " << path + fnameT <<
RESTendl;
351 string perlName =
"laymir.pl";
352 if (
fMirrorType ==
"Bilayer") perlName =
"bimir.pl";
353 string url =
"https://henke.lbl.gov/cgi-bin/" + perlName;
356 size_t start = result.find(
"HREF=\"") + 6;
357 size_t length = result.find(
".dat\">") + 4 - start;
358 result = result.substr(start, length);
370 Double_t en = energy;
372 RESTWarning <<
"Energy is below 30eV! It should be between 30eV and 15keV" <<
RESTendl;
373 RESTWarning <<
"Setting energy to 30eV" <<
RESTendl;
378 RESTWarning <<
"Energy is above 15keV! It should be between 30eV and 15keV" <<
RESTendl;
379 RESTWarning <<
"Setting energy to 15keV" <<
RESTendl;
383 Int_t lowEnBin = (Int_t)((en - 0.03) / 0.03);
384 Double_t deltaE = (en - (Double_t)(lowEnBin + 1) * 0.03) / 0.03;
386 Double_t ang = angle;
388 RESTWarning <<
"Angle is below 0 degrees! It should be between 0 and 9 degrees" <<
RESTendl;
389 RESTWarning <<
"Setting angle to 0 degrees" <<
RESTendl;
394 RESTWarning <<
"Angle is above 9 degrees! It should be between 0 and 9 degrees" <<
RESTendl;
395 RESTWarning <<
"Setting angle to 9 degrees" <<
RESTendl;
399 Int_t lowAngBin = (Int_t)((ang) / 0.01);
400 Double_t deltaAng = (ang - (Double_t)(lowAngBin)*0.01) / 0.01;
411 return (1 - deltaE) * (1 - deltaAng) * REnLowAngLow + deltaE * (1 - deltaAng) * REnHiAngLow +
412 (1 - deltaE) * deltaAng * REnLowAngHi + deltaE * deltaAng * REnHiAngHi;
422 Double_t en = energy;
424 RESTWarning <<
"Energy is below 30eV! It should be between 30eV and 15keV" <<
RESTendl;
425 RESTWarning <<
"Setting energy to 30eV" <<
RESTendl;
430 RESTWarning <<
"Energy is above 15keV! It should be between 30eV and 15keV" <<
RESTendl;
431 RESTWarning <<
"Setting energy to 15keV" <<
RESTendl;
435 Int_t lowEnBin = (Int_t)((en - 0.03) / 0.03);
436 Double_t deltaE = (en - (Double_t)(lowEnBin + 1) * 0.03) / 0.03;
438 Double_t ang = angle;
440 RESTWarning <<
"Angle is below 0 degrees! It should be between 0 and 9 degrees" <<
RESTendl;
441 RESTWarning <<
"Setting angle to 0 degrees" <<
RESTendl;
446 RESTWarning <<
"Angle is above 9 degrees! It should be between 0 and 9 degrees" <<
RESTendl;
447 RESTWarning <<
"Setting angle to 9 degrees" <<
RESTendl;
451 Int_t lowAngBin = (Int_t)((ang) / 0.01);
452 Double_t deltaAng = (ang - (Double_t)(lowAngBin)*0.01) / 0.01;
464 return (1 - deltaE) * (1 - deltaAng) * REnLowAngLow + deltaE * (1 - deltaAng) * REnHiAngLow +
465 (1 - deltaE) * deltaAng * REnLowAngHi + deltaE * deltaAng * REnHiAngHi;
490 RESTMetadata <<
"+++++++++++++++++++++++++++++++++++++++++++++++++" <<
RESTendl;
527 Double_t lowRange2) {
532 if (optList.size() == 0)
534 "[1,4,7,10](0,9){0.6,0.68,0.9,0.88}:[0.25,0.5,0.75,1](0,10){0.2,0.2,0.45,0.45}");
536 if (optList.size() != 2) {
537 RESTError <<
"TRestAxionOpticsMirror::DrawOpticsProperties. Wrong arguments!" <<
RESTendl;
543 std::vector<double> eLegendCoords =
StringToElements(optList[0],
"{",
",",
"}");
547 std::vector<double> aLegendCoords =
StringToElements(optList[1],
"{",
",",
"}");
549 if (eRange[0] < 0.03) eRange[0] = 0.03;
550 if (eRange[1] > 15) eRange[1] = 15;
551 if (aRange[0] < 0.0) aRange[0] = 0.0;
552 if (aRange[1] > 9) aRange[1] = 9;
561 fCanvas =
new TCanvas(
"canv",
"This is the canvas title", 1400, 1200);
564 TPad* pad1 =
new TPad(
"pad1",
"This is pad1", 0.01, 0.02, 0.99, 0.97);
570 pad1->cd(1)->SetLogy();
571 pad1->cd(1)->SetRightMargin(0.09);
572 pad1->cd(1)->SetLeftMargin(0.15);
573 pad1->cd(1)->SetBottomMargin(0.15);
575 std::vector<TGraph*> ref_vs_ang_graph;
577 for (
unsigned int n = 0; n < energies.size(); n++) {
579 TGraph* gr =
new TGraph();
580 gr->SetName(grname.c_str());
581 for (
double a = aRange[0]; a <= aRange[1]; a += (aRange[1] - aRange[0]) / 10000.) {
584 gr->SetLineColor(49 - n * 3);
586 ref_vs_ang_graph.push_back(gr);
589 ref_vs_ang_graph[0]->GetXaxis()->SetLimits(aRange[0], aRange[1]);
590 ref_vs_ang_graph[0]->GetHistogram()->SetMaximum(1);
591 ref_vs_ang_graph[0]->GetHistogram()->SetMinimum(lowRange);
593 ref_vs_ang_graph[0]->GetXaxis()->SetTitle(
"Angle [degrees]");
594 ref_vs_ang_graph[0]->GetXaxis()->SetTitleSize(0.05);
595 ref_vs_ang_graph[0]->GetXaxis()->SetLabelSize(0.05);
596 ref_vs_ang_graph[0]->GetYaxis()->SetTitle(
"Reflectivity");
597 ref_vs_ang_graph[0]->GetYaxis()->SetTitleOffset(1.5);
598 ref_vs_ang_graph[0]->GetYaxis()->SetTitleSize(0.05);
599 ref_vs_ang_graph[0]->GetYaxis()->SetLabelSize(0.05);
600 pad1->cd(1)->SetLogy();
601 ref_vs_ang_graph[0]->Draw(
"AL");
602 for (
unsigned int n = 1; n < energies.size(); n++) ref_vs_ang_graph[n]->Draw(
"L");
604 Double_t lx1 = 0.6, ly1 = 0.75, lx2 = 0.9, ly2 = 0.95;
605 if (eLegendCoords.size() > 0) {
606 lx1 = eLegendCoords[0];
607 ly1 = eLegendCoords[1];
608 lx2 = eLegendCoords[2];
609 ly2 = eLegendCoords[3];
611 TLegend* legend =
new TLegend(lx1, ly1, lx2, ly2);
613 legend->SetTextSize(0.03);
614 legend->SetHeader(
"Energies",
"C");
615 for (
unsigned int n = 0; n < energies.size(); n++) {
619 legend->AddEntry(lname.c_str(), ltitle.c_str(),
"l");
625 pad1->cd(2)->SetLogy();
626 pad1->cd(2)->SetRightMargin(0.09);
627 pad1->cd(2)->SetLeftMargin(0.15);
628 pad1->cd(2)->SetBottomMargin(0.15);
630 std::vector<TGraph*> ref_vs_en_graph;
632 for (
unsigned int n = 0; n < angles.size(); n++) {
634 TGraph* gr =
new TGraph();
635 gr->SetName(grname.c_str());
636 for (
double e = eRange[0]; e <= eRange[1]; e += (eRange[1] - eRange[0]) / 10000.) {
639 gr->SetLineColor(49 - n * 3);
641 ref_vs_en_graph.push_back(gr);
644 ref_vs_en_graph[0]->GetXaxis()->SetLimits(eRange[0], eRange[1]);
645 ref_vs_en_graph[0]->GetHistogram()->SetMaximum(1);
646 ref_vs_en_graph[0]->GetHistogram()->SetMinimum(lowRange2);
648 ref_vs_en_graph[0]->GetXaxis()->SetTitle(
"Energy [keV]");
649 ref_vs_en_graph[0]->GetXaxis()->SetTitleSize(0.05);
650 ref_vs_en_graph[0]->GetXaxis()->SetLabelSize(0.05);
651 ref_vs_en_graph[0]->GetYaxis()->SetTitle(
"Reflectivity");
652 ref_vs_en_graph[0]->GetYaxis()->SetTitleOffset(1.5);
653 ref_vs_en_graph[0]->GetYaxis()->SetTitleSize(0.05);
654 ref_vs_en_graph[0]->GetYaxis()->SetLabelSize(0.05);
655 pad1->cd(2)->SetLogy();
656 ref_vs_en_graph[0]->Draw(
"AL");
657 for (
unsigned int n = 1; n < angles.size(); n++) ref_vs_en_graph[n]->Draw(
"L");
659 if (aLegendCoords.size() > 0) {
660 lx1 = aLegendCoords[0];
661 ly1 = aLegendCoords[1];
662 lx2 = aLegendCoords[2];
663 ly2 = aLegendCoords[3];
665 TLegend* legendA =
new TLegend(lx1, ly1, lx2, ly2);
666 legendA->SetTextSize(0.03);
667 legendA->SetHeader(
"Angles",
"C");
668 for (
unsigned int n = 0; n < angles.size(); n++) {
672 legendA->AddEntry(lname.c_str(), ltitle.c_str(),
"l");
680 pad1->cd(3)->SetRightMargin(0.09);
681 pad1->cd(3)->SetLeftMargin(0.15);
682 pad1->cd(3)->SetBottomMargin(0.15);
684 ref_vs_ang_graph[0]->Draw(
"AL");
685 for (
unsigned int n = 1; n < energies.size(); n++) ref_vs_ang_graph[n]->Draw(
"L");
689 pad1->cd(4)->SetRightMargin(0.09);
690 pad1->cd(4)->SetLeftMargin(0.15);
691 pad1->cd(4)->SetBottomMargin(0.15);
694 ref_vs_en_graph[0]->Draw(
"AL");
695 for (
unsigned int n = 1; n < angles.size(); n++) ref_vs_en_graph[n]->Draw(
"L");
699 TPad* pad5 =
new TPad(
"all",
"all", 0, 0, 1, 1);
700 pad5->SetFillStyle(4000);
703 TLatex* lat =
new TLatex();
709 lat->SetTextSize(0.02);
716 lat->SetTextSize(0.015);
718 lat->SetTextAlign(22);
719 lat->DrawLatexNDC(.5, .95, title.c_str());
A metadata class accessing the Henke database to load reflectivity data.
std::string fSigmaTop
Layer surface roughness in nm.
std::string fLayerThicknessBottom
The bottom layer thickness in nm. Only used for "Bilayer" mirror type.
std::string fSubstrate
The substrate material.
std::string GetTransmissionFilename()
It returns the corresponding transmission filename for the mirror properties defined in the data memb...
std::string fSigmaBottom
Bottom layer surface roughness in nm. Only used for "Bilayer" mirror type.
Double_t GetReflectivity(const Double_t angle, const Double_t energy)
It returns the interpolated reflectivity for a given angle (in degrees) and a given energy (in keV).
TCanvas * DrawOpticsProperties(std::string options="", Double_t lowRange=1.e-9, Double_t lowRange2=1.e-3)
A method that creates a canvas where the mirror optics properties are drawn. It generates two plots,...
std::string fLayerThicknessTop
The layer thickness in nm.
void LoadTables()
Loads the reflectivity table.
void PrintMetadata()
Prints on screen the information about the metadata members of TRestAxionOpticsMirror.
std::vector< std::vector< Float_t > > fReflectivityTable
The reflectivity loaded as a table with angle versus energy.
std::map< std::string, std::string > fHenkeKeys
A set of key-value pairs sent to the Henke website for data request.
Int_t ExportTables()
It is a private method to export the tables to a binary file once the tables have been downloaded fro...
TRestAxionOpticsMirror()
Default constructor.
void Initialize()
Initialization of TRestAxionOpticsMirror members.
std::string fLayerBottom
The mirror bottom layer material (chemical formula). Only used for "Bilayer" mirror type.
TCanvas * fCanvas
A canvas to insert the optic properties drawing.
~TRestAxionOpticsMirror()
Default destructor.
Double_t GetTransmission(const Double_t angle, const Double_t energy)
It returns the interpolated transmission for a given angle (in degrees) and a given energy (in keV).
std::string fLayerTop
The mirror layer material (chemical formula).
std::string GetReflectivityFilename()
It returns the corresponding reflectivity filename for the mirror properties defined in the data memb...
std::string fMirrorType
The mirror type (Thick, Single, Bilayer, Multilayer). Only Single/Bilayer is supported now.
std::string DownloadHenkeFile()
It downloads the reflectivity file for the present mirror properties defined at the metadata members.
std::vector< std::vector< Float_t > > fTransmissionTable
The transmission loaded as a table with angle versus energy.
@ REST_Info
+show most of the information for each steps
std::string IntegerToString(Int_t n, std::string format="%d")
Gets a string from an integer.
std::string DoubleToString(Double_t d, std::string format="%8.6e")
Gets a string from a double.
std::vector< double > StringToElements(std::string in, std::string separator)
Convert the input string into a vector of double elements.