diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 53dd9fbc..f9bc2a43 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -91,12 +91,12 @@ optics: script: - . ${CI_PROJECT_DIR}/install/thisREST.sh - cd ${CI_PROJECT_DIR}/pipeline/metadata/optics/ - - wget https://sultan.unizar.es/axionlib-data/optics/mirrors.rml - wget https://sultan.unizar.es/axionlib-data/optics/optics.rml - - wget https://sultan.unizar.es/axionlib-data/optics/Reflectivity_Single_C_30_SiO2_0.N901f - - wget https://sultan.unizar.es/axionlib-data/optics/Transmission_Single_C_30_SiO2_0.N901f - - wget https://sultan.unizar.es/axionlib-data/optics/Reflectivity_Single_Au_250_Ni_0.4.N901f - - wget https://sultan.unizar.es/axionlib-data/optics/Transmission_Single_Au_250_Ni_0.4.N901f + - wget https://sultan.unizar.es/axionlib-data/opticsMirror/mirrors.rml + - wget https://sultan.unizar.es/axionlib-data/opticsMirror/Reflectivity_Single_C_30_SiO2_0.N901f + - wget https://sultan.unizar.es/axionlib-data/opticsMirror/Transmission_Single_C_30_SiO2_0.N901f + - wget https://sultan.unizar.es/axionlib-data/opticsMirror/Reflectivity_Single_Au_250_Ni_0.4.N901f + - wget https://sultan.unizar.es/axionlib-data/opticsMirror/Transmission_Single_Au_250_Ni_0.4.N901f - python mirrors.py - python optics.py - python basic.py diff --git a/data b/data index 22cf5a4d..36629372 160000 --- a/data +++ b/data @@ -1 +1 @@ -Subproject commit 22cf5a4dd9f3b07e0d0017c767c62839988c99c7 +Subproject commit 36629372bcffddd6f95eb12a565c1b15475a64be diff --git a/images/windowsTransmission.png b/images/windowsTransmission.png index f642ad8f..3eabc04e 100644 Binary files a/images/windowsTransmission.png and b/images/windowsTransmission.png differ diff --git a/inc/TRestAxionXrayWindow.h b/inc/TRestAxionXrayWindow.h index fe8a671f..9e4fc1c7 100644 --- a/inc/TRestAxionXrayWindow.h +++ b/inc/TRestAxionXrayWindow.h @@ -24,6 +24,7 @@ #define _TRestAxionXrayWindow #include +#include //! A metadata class to create x-ray transmission window definitions class TRestAxionXrayWindow : public TRestMetadata { @@ -31,26 +32,14 @@ class TRestAxionXrayWindow : public TRestMetadata { /// Position of the center of the window in mm TVector3 fCenter = TVector3(0, 0, 0); //< - /// Type of window (foil, stripped, grid) - std::string fWindowType = "foil"; //< - /// Thicknesss of window material in mm Double_t fThickness = 0.0; //< /// Window material name std::string fMaterial = "Si"; //< - /// Window radius in mm. For the moment the window is always a circle - Double_t fRadius = 8; //< - - /// The periodity of the pattern structure in mm - Double_t fPatternGap = 1; //< - - /// The width of the pattern structure mm - Double_t fPatternWidth = 0.5; //< - - /// The offset in mm for the first pattern structure. If 0, the first masking structure will be at origin. - Double_t fPatternOffset = 2; //< + /// A mask defining a pattern where the transmission will be effective + TRestPatternMask* fMask = nullptr; //< /// A vector with the energies loaded from the material file. Not stored in disk. std::vector fEnergy; //! @@ -67,12 +56,18 @@ class TRestAxionXrayWindow : public TRestMetadata { Int_t GetEnergyIndex(Double_t energy); public: - Double_t GetWindowRadius() { return fRadius; } + Double_t GetWindowRadius() { + if (!fMask) return 0; + return fMask->GetMaskRadius(); + } + + TRestPatternMask* GetMask() const { return fMask; } Double_t GetTransmission(Double_t energy, Double_t x, Double_t y); void PrintTransmissionData(); + void InitFromConfigFile(); void PrintMetadata(); TRestAxionXrayWindow(); diff --git a/pipeline/metadata/transmission/windowPlot.py b/pipeline/metadata/transmission/windowPlot.py index e75f731d..f6c60f29 100644 --- a/pipeline/metadata/transmission/windowPlot.py +++ b/pipeline/metadata/transmission/windowPlot.py @@ -3,6 +3,7 @@ import ROOT, math outfname = "windowsTransmission.png" +patternType = "strongBack" from ROOT import ( TChain, TFile, TTree, TCanvas, TPad, TRandom3, @@ -27,10 +28,10 @@ totalSamples = 100000 cathode = ROOT.TRestAxionXrayWindow("windows.rml", "cathode") -strongBack = ROOT.TRestAxionXrayWindow("windows.rml", "strongBack") +strongBack = ROOT.TRestAxionXrayWindow("windows.rml", patternType) siFoil = ROOT.TRestAxionXrayWindow("windows.rml", "siliconFoil") -radius = cathode.GetWindowRadius() +radius = strongBack.GetWindowRadius() print ( "\nGetting window radius" ) if radius != 8: print ("\nThe window radius is not as expected! Exit code : 102") @@ -62,13 +63,13 @@ for n in range(totalSamples): x = (radius+2) * (rnd.Rndm() - 0.5) * 2 y = (radius+2) * (rnd.Rndm() - 0.5) * 2 - en = 15. * rnd.Rndm() + en = 0.01 + 14.9 * rnd.Rndm() cth = cathode.GetTransmission( en, x, y) stb = strongBack.GetTransmission( en, x, y) sil = siFoil.GetTransmission( en, x, y) - if( cth == 0 ): + if( stb == 0 ): continue #print ("x: " + str(x) + " y: " + str(y) + " en: " + str(en) ) #print ("cathode: " + str(cth) + " sBack: " + str(stb) + " siFoil: " + str(sil) ) @@ -132,15 +133,25 @@ pad1.cd(3) histH.SetStats(0) histH.Draw("colz") -#graphsOP[0].GetXaxis().SetLimits(-maxRingRadius-20,maxRingRadius+20); -#graphsOP[0].GetHistogram().SetMaximum(maxRingRadius+20); -#graphsOP[0].GetHistogram().SetMinimum(-maxRingRadius-20); -#graphsOP[0].Draw("AP") -#for n in range(1,rings): -# graphsOP[n].Draw("P") c1.Print(outfname) +if( histL.Integral() < 10000 ): + print( "Effective counts at low energy below 10000!!") + print ( "Low: " + str( histL.Integral() ) ) + exit(103) + +if( histM.Integral() < 12000 ): + print( "Effective counts at low energy below 12000!!") + print ( "Mid: " + str( histM.Integral() ) ) + exit(104) + +if( histH.Integral() < 14000 ): + print( "Effective counts at low energy below 14000!!") + print ( "High: " + str( histH.Integral() ) ) + exit(105) + + print ("All tests passed! [\033[92m OK \x1b[0m]") print ("") diff --git a/src/TRestAxionSolarFlux.cxx b/src/TRestAxionSolarFlux.cxx index f811c2d8..a0f08f81 100644 --- a/src/TRestAxionSolarFlux.cxx +++ b/src/TRestAxionSolarFlux.cxx @@ -290,7 +290,7 @@ void TRestAxionSolarFlux::LoadContinuumFluxTable() { RESTDebug << "File : " << fullPathName << RESTendl; std::vector> fluxTable; - if (TRestTools::GetFileNameExtension(fFluxDataFile) == "dat") { + if (TRestTools::GetFileNameExtension(fFluxDataFile) == ".dat") { std::vector> doubleTable; TRestTools::ReadASCIITable(fullPathName, doubleTable); for (const auto& row : doubleTable) { @@ -303,6 +303,7 @@ void TRestAxionSolarFlux::LoadContinuumFluxTable() { fluxTable.clear(); RESTError << "Filename extension was not recognized!" << RESTendl; RESTError << "Solar flux table will not be populated" << RESTendl; + RESTError << "Filename extension: " << TRestTools::GetFileNameExtension(fFluxDataFile) << RESTendl; } if (fluxTable.size() != 100 && fluxTable[0].size() != 200) { diff --git a/src/TRestAxionXrayWindow.cxx b/src/TRestAxionXrayWindow.cxx index 634fdbe1..ca112ad0 100644 --- a/src/TRestAxionXrayWindow.cxx +++ b/src/TRestAxionXrayWindow.cxx @@ -25,49 +25,33 @@ /// properties, such as material and thickness. This class will load the /// transmission data to calculate the transmission for a photon of a /// given energy and position. The window might be defined as a uniform -/// foil or using a particular structure. +/// `foil` or using a particular pattern using a TRestPatternMask definition. /// -/// For the moment, the window geometry is fixed to be a circular window. -/// Therefore, the following are the most basic parameters of any window -/// construction: +/// If we include the pattern definition using TRestPatternMask, then, the +/// limits for the window will be imposed by TRestPatternMask. In the +/// contrary, if no TRestPatternMask definition is included in the +/// TRestAxionXrayWindow definition, then the window will have no limits, +/// it will be just an infinite foil with a given material transmission. /// +/// The following parameters are used to define the window transmission: +/// +/// * **center**: It will emplace the window definition at a given position. /// * **material**: The material used by the window. The name must match /// the name of one of the files found at `data/transmission/` removing /// the extension. /// * **thickness**: The depth of the window that defines finally the total /// x-ray photon absorption. -/// * **radius**: The radius of the window where photons will be accepted. -/// -/// On top of that, we might define different types of windows that will -/// allow us to create different structures, such as a strong back where -/// photon opacity is only defined at a regular grid or stripped pattern. -/// We may define the window type using: -/// -/// - **type**: We may define different options that define the regions -/// of space where the window material will be effective. -/// -# **foil**: It defines a homogeneous region of material, all the -/// region inside the window radius will present the same efficiency. -/// -# **stripped**: It defines a stripped pattern where the absorption -/// will be effective, otherwise, if the photon is inside the window -/// but it doesn't hit the stripped pattern, the transmission will be -/// equal to 1. -/// -# **grid**: It defines a grid pattern where the absorption -/// will be effective, otherwise, if the photon is inside the window -/// but it doesn't hit the grid pattern, the transmission will be -/// equal to 1. -/// -/// In the case that the window type is defined to be *stripped* or -/// *grid*. Then, few additional parameters are necessary to define the -/// pattern structure, made of masking strips on one direction (stripped), -/// or masking strips on both directions (grid). -/// -/// * **patternGap**: The distance between 2 masking structures, or -/// periodicity. -/// * **patternWidth**: The width of the masking structure. -/// * **patternOffset**: If this parameter is 0, the first strip will -/// centered at the origin. If not, the pattern will be shifted. In the -/// case of the grid, it will be used to displace the grid on both -/// directions, X and Y. +/// +/// Then, as it was mentioned before, we might define different types of +/// window patterns, such as a strong back where photon opacity is only +/// defined at a regular grid or stripped pattern. The window transmission +/// will only be applied in the regions where the particle hits the +/// pattern. Otherwise, the particle will just go through the empty regions +/// and the transmission/efficiency will be equal to 1. +/// +/// We may define the window pattern using any of the classes inheriting +/// from TRestPatternMask, such as TRestGridMask, TRestStrippedMask, or +/// event TRestSpiderMask and TRestRingsMask. /// /// Once all the parameters have been defined inside an instance of this /// class, we will be able to recover the transmission at any given point @@ -77,14 +61,15 @@ /// file would be as follows. /// /// \code -/// -/// -/// -/// -/// -/// -/// -/// +/// +/// +/// +/// +/// +/// +/// /// \endcode /// /// The pipeline example found at `pipeline/transmission/windowPlot.py` will @@ -160,12 +145,14 @@ void TRestAxionXrayWindow::Initialize() { fEnergy.clear(); fTransmission.clear(); - if (fWindowType != "foil" && fPatternGap == 0) { - RESTError << "TRestAxionXrayWindow::Initialize. fPatternGap cannot be zero!" << RESTendl; - fPatternGap = 1; - } + /* +if (fWindowType != "foil" && fPatternGap == 0) { + RESTError << "TRestAxionXrayWindow::Initialize. fPatternGap cannot be zero!" << RESTendl; + fPatternGap = 1; +} - if (fPatternGap < 0) fPatternGap = -fPatternGap; +if (fPatternGap < 0) fPatternGap = -fPatternGap; + */ } /////////////////////////////////////////////// @@ -211,10 +198,12 @@ void TRestAxionXrayWindow::ReadMaterial() { Double_t TRestAxionXrayWindow::GetTransmission(Double_t energy, Double_t x, Double_t y) { if (fEnergy.size() == 0) ReadMaterial(); - if ((x - fCenter.X()) * (x - fCenter.X()) + (y - fCenter.Y()) * (y - fCenter.Y()) > fRadius * fRadius) - return 0; + Double_t xNew = x - fCenter.X(); + Double_t yNew = y - fCenter.Y(); + + if (fMask && xNew * xNew + yNew * yNew > fMask->GetMaskRadius() * fMask->GetMaskRadius()) return 0; - if (!HitsPattern(x, y)) return 1.; + if (fMask && !fMask->HitsPattern(xNew, yNew)) return 1.; Double_t energyIndex = GetEnergyIndex(energy); @@ -250,40 +239,44 @@ Double_t TRestAxionXrayWindow::GetTransmission(Double_t energy, Double_t x, Doub /// \brief It returns true if the window pattern is hitted. False otherwise. /// Bool_t TRestAxionXrayWindow::HitsPattern(Double_t x, Double_t y) { - if (fWindowType == "stripped") { - Double_t xEval = fPatternWidth / 2. + x - fPatternOffset; - - if (xEval > 0) { - while (xEval > fPatternGap) xEval -= fPatternGap; - } else { - while (xEval < 0) xEval += fPatternGap; - } - - if (xEval > fPatternWidth) { - return false; - } - } else if (fWindowType == "grid") { - Double_t xEval = fPatternWidth / 2. + x - fPatternOffset; - - if (xEval > 0) { - while (xEval > fPatternGap) xEval -= fPatternGap; - } else { - while (xEval < 0) xEval += fPatternGap; - } - - if (xEval < fPatternWidth) return true; - - Double_t yEval = fPatternWidth / 2. + y - fPatternOffset; - - if (yEval > 0) { - while (yEval > fPatternGap) yEval -= fPatternGap; - } else { - while (yEval < 0) yEval += fPatternGap; - } - - if (yEval < fPatternWidth) return true; + if (fMask) return fMask->HitsPattern(x, y); + + /* +if (fWindowType == "stripped") { + Double_t xEval = fPatternWidth / 2. + x - fPatternOffset; + + if (xEval > 0) { + while (xEval > fPatternGap) xEval -= fPatternGap; + } else { + while (xEval < 0) xEval += fPatternGap; + } + + if (xEval > fPatternWidth) { return false; } +} else if (fWindowType == "grid") { + Double_t xEval = fPatternWidth / 2. + x - fPatternOffset; + + if (xEval > 0) { + while (xEval > fPatternGap) xEval -= fPatternGap; + } else { + while (xEval < 0) xEval += fPatternGap; + } + + if (xEval < fPatternWidth) return true; + + Double_t yEval = fPatternWidth / 2. + y - fPatternOffset; + + if (yEval > 0) { + while (yEval > fPatternGap) yEval -= fPatternGap; + } else { + while (yEval < 0) yEval += fPatternGap; + } + + if (yEval < fPatternWidth) return true; + return false; +} + */ return true; } @@ -307,23 +300,34 @@ void TRestAxionXrayWindow::PrintTransmissionData() { cout << "Energy : " << fEnergy[n] << " Transmission : " << fTransmission[n] << endl; } +/////////////////////////////////////////////// +/// \brief +/// +void TRestAxionXrayWindow::InitFromConfigFile() { + TRestMetadata::InitFromConfigFile(); + + if (fMask) { + delete fMask; + fMask = nullptr; + } + fMask = (TRestPatternMask*)this->InstantiateChildMetadata("Mask", "mask"); +} + /////////////////////////////////////////////// /// \brief Prints on screen the information about the metadata members of TRestAxionXrayWindow /// void TRestAxionXrayWindow::PrintMetadata() { TRestMetadata::PrintMetadata(); - RESTMetadata << "X-ray window type: " << fWindowType << RESTendl; RESTMetadata << "Window center: ( " << fCenter.X() << ", " << fCenter.Y() << ", " << fCenter.Z() << ") mm" - << RESTendl; + << RESTendl; RESTMetadata << "Thickness: " << fThickness * units("um") << " um" << RESTendl; RESTMetadata << "Material: " << fMaterial << RESTendl; - RESTMetadata << "Window radius: " << fRadius << " mm" << RESTendl; - if (fWindowType != "foil") { - RESTMetadata << "------" << RESTendl; - RESTMetadata << "Pattern periodicity: " << fPatternGap << " mm" << RESTendl; - RESTMetadata << "Pattern width: " << fPatternWidth << " mm" << RESTendl; - RESTMetadata << "Pattern offset: " << fPatternOffset << " mm" << RESTendl; + RESTMetadata << "----" << RESTendl; + if (fMask) { + fMask->Print(); + } else { + RESTMetadata << " - Pattern type: foil" << RESTendl; } RESTMetadata << "+++++++++++++++++++++++++++++++++++++++++++++++++" << RESTendl;