From 8d7f724ee43a8485608ac9a2e1fb654c19e33614 Mon Sep 17 00:00:00 2001 From: tomasoshea Date: Tue, 20 Jun 2023 15:59:05 +0200 Subject: [PATCH 01/48] created hidden photon files and started work --- .gitignore | 1 + inc/TRestAxionSolarHiddenPhotonFlux.h | 125 +++++ src/TRestAxionSolarHiddenPhotonFlux.cxx | 700 ++++++++++++++++++++++++ 3 files changed, 826 insertions(+) create mode 100644 inc/TRestAxionSolarHiddenPhotonFlux.h create mode 100644 src/TRestAxionSolarHiddenPhotonFlux.cxx diff --git a/.gitignore b/.gitignore index f57a1172..58ad2261 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ build *.root **/.DS_Store +*.json \ No newline at end of file diff --git a/inc/TRestAxionSolarHiddenPhotonFlux.h b/inc/TRestAxionSolarHiddenPhotonFlux.h new file mode 100644 index 00000000..3a31e634 --- /dev/null +++ b/inc/TRestAxionSolarHiddenPhotonFlux.h @@ -0,0 +1,125 @@ +/************************************************************************* + * This file is part of the REST software framework. * + * * + * Copyright (C) 2016 GIFNA/TREX (University of Zaragoza) * + * For more information see http://gifna.unizar.es/trex * + * * + * REST 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. * + * * + * REST 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 a copy of the GNU General Public License along with * + * REST in $REST_PATH/LICENSE. * + * If not, see http://www.gnu.org/licenses/. * + * For the list of contributors see $REST_PATH/CREDITS. * + *************************************************************************/ + +#ifndef _TRestAxionSolarQCDFlux +#define _TRestAxionSolarQCDFlux + +#include +#include + + +//! A metadata class to load tabulated solar hidden photon fluxes. Mass and coupling set to 1. +class TRestAxionSolarHiddenPhotonFlux : public TRestAxionSolarFlux { + private: + /// The filename containing the solar flux table with continuum spectrum + std::string fFluxDataFile = ""; //< + + /// The filename containing the resonance width (wGamma) + std::string fWGammaDataFile = ""; //< + + /// The filename containing the plasma freqency (wp) table + std::string fWpDataFile = ""; //< + + /// It will be used when loading `.flux` files to define the input file energy binsize in eV. + Double_t fBinSize = 0; //< + + /// It will be used when loading `.flux` files to define the threshold for peak identification + Double_t fPeakSigma = 0; //< + + /// The tabulated solar flux continuum spectra TH1F(200,0,20)keV in cm-2 s-1 keV-1 versus solar radius + std::vector fFluxTable; //! + + /// The tabulated resonance width TH1F(200,0,20)keV in eV2 versus solar radius + std::vector fWGammaTable; //! + + /// The solar plasma frequency vector in eV versus solar radius + std::vector fWpTable; //! + + /// Accumulative integrated solar flux for each solar ring for continuum spectrum (renormalized to unity) + std::vector fFluxTableIntegrals; //! + + /// A pointer to the continuum spectrum histogram + TH1F* fContinuumHist = nullptr; //! + + /// A pointer to the superposed monochromatic and continuum spectrum histogram + TH1F* fTotalHist = nullptr; //! + + void ReadFluxFile(); + void LoadContinuumFluxTable(); + void LoadMonoChromaticFluxTable(); + void IntegrateSolarFluxes(); + + public: + /// It returns true if continuum flux spectra was loaded + Bool_t isSolarTableLoaded() { return fFluxTable.size() > 0; } + + /// It returns true if width table was loaded + Bool_t isWidthTableLoaded() { return fWGammaTable.size() > 0; } + + /// It returns true if plasma frequency table was loaded + Bool_t isPlasmaFreqLoaded() { return fWpTable.size() > 0; } + + /// It returns the integrated flux at earth in cm-2 s-1 for the given energy range + Double_t IntegrateFluxInRange(TVector2 eRange = TVector2(-1, -1), Double_t mass = 0) override; + + /// It defines how to generate Monte Carlo energy and radius values to reproduce the flux + std::pair GetRandomEnergyAndRadius(TVector2 eRange = TVector2(-1, -1), + Double_t mass = 0) override; + + /// It defines how to read the solar tables at the inhereted class + Bool_t LoadTables() override; + + /// It returns the total integrated flux at earth in cm-2 s-1 + Double_t GetTotalFlux(Double_t mass = 0) override { + return fTotalContinuumFlux + fTotalMonochromaticFlux; + } + + /// It returns an energy integrated spectrum in cm-2 s-1 keV-1 + TH1F* GetEnergySpectrum(Double_t m = 0) override { return GetTotalSpectrum(); } + + TH1F* GetContinuumSpectrum(); + TH1F* GetMonochromaticSpectrum(); + TH1F* GetTotalSpectrum(); + + virtual TCanvas* DrawSolarFlux() override; + + /// Tables might be loaded using a solar model description by TRestAxionSolarModel + void InitializeSolarTable(TRestAxionSolarModel* model) { + // TOBE implemented + // This method should initialize the tables fFluxTable and fFluxLines + } + + void ExportTables(Bool_t ascii = false) override; + + void PrintMetadata() override; + + void PrintContinuumSolarTable(); + void PrintIntegratedRingFlux(); + void PrintMonoChromaticFlux(); + + TRestAxionSolarQCDFlux(); + TRestAxionSolarQCDFlux(const char* cfgFileName, std::string name = ""); + ~TRestAxionSolarQCDFlux(); + + ClassDefOverride(TRestAxionSolarQCDFlux, 1); +}; +#endif diff --git a/src/TRestAxionSolarHiddenPhotonFlux.cxx b/src/TRestAxionSolarHiddenPhotonFlux.cxx new file mode 100644 index 00000000..0140f6fd --- /dev/null +++ b/src/TRestAxionSolarHiddenPhotonFlux.cxx @@ -0,0 +1,700 @@ +/******************** REST disclaimer *********************************** + * This file is part of the REST software framework. * + * * + * Copyright (C) 2016 GIFNA/TREX (University of Zaragoza) * + * For more information see http://gifna.unizar.es/trex * + * * + * REST 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. * + * * + * REST 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 a copy of the GNU General Public License along with * + * REST in $REST_PATH/LICENSE. * + * If not, see http://www.gnu.org/licenses/. * + * For the list of contributors see $REST_PATH/CREDITS. * + *************************************************************************/ + +////////////////////////////////////////////////////////////////////////// +/// TRestAxionSolarQCDFlux will use a file in ASCII or binary format to initialize +/// a solar flux table that will describe the solar flux spectrum as a function +/// of the solar radius. +/// +/// This class may serve to load any generic flux definition that is independent +/// from the axion mass. However, since the design of the class was motivated to +/// reproduce the standard QCD axion flux, therefore the name of the class. +/// +/// Another scenario arises when the axion or an axion-like particle production +/// mechanism depends on its mass, and we may need to introduce a flux description +/// as the given in the class TRestAxionSolarHiddenPhotonFlux. Both classes are +/// prototyped by a pure base class TRestAxionSolarFlux that defines common methods +/// used to evaluate the flux, and generate Monte-Carlo events inside +/// TRestAxionGeneratorProcess. +/// +/// ### Basic use +/// +/// Once the class has been initialized, the main use of this class will be provided +/// by the method TRestAxionSolarQCDFlux::GetRandomEnergyAndRadius. This method will +/// return a random axion energy and position inside the solar radius following the +/// distributions given by the solar flux tables. +/// +/// Description of the specific parameters accepted by this metadata class. +/// - *fluxDataFile:* A table with 100 rows representing the solar ring flux from the +/// center to the corona, and 200 columns representing the flux, measured in cm-2 s-1 keV-1, +/// for the range (0,20)keV in steps of 100eV. The table could be provided in ASCII format, +/// using `.dat` extension, or it might be a binary table using `.N200f` extension. +/// - *fluxSptFile:* A table where each column represents a monochromatic energy. The +/// column contains 101 rows, the first element is the energy of the monochromatic line +/// while the next 100 elements contain the flux, measured in cm-2 s-1, integrated to +/// each solar ring, being the second element the ring in the center of the sun. +/// +/// Additionally this class will be able to read `.flux` files that are the original files +/// produced in 3-columns format (inner radius [solar units] / energy [keV] / +/// flux [cm-2 s-1 keV-1]). The `.flux` files may contain the full information, +/// continuum and spectral components. Those components will be splited into two independent +/// contributions by TRestAxionSolarQCDFlux::ReadFluxFile to be managed internally. Two +/// additional parameters *will be required* to translate the `.flux` files into the tables +/// that are understood by this class. +/// - *binSize:* The energy binning used on the `.flux` file and inside the histogram used +/// for monochromatic lines identification. +/// - *peakSigma:* The ratio between the flux provided at the `.flux` file and the +/// average flux calculated in the peak surroundings. If the flux ratio is higher than +/// this value, the flux at that particular bin will be considered a peak. +/// +/// Optionally, if we want to consider a different binning on the monochromatic/continuum +/// histogram used internally for the calculation we may specify optionally a new parameter. +/// In that case, `fBinSize` will be the binning of the internal histogram, while the new +/// parameter will be the binning given inside the `.flux` file. +/// - *fluxBinSize:* The bin size used on the `.flux` table. +/// +/// Pre-generated solar axion flux tables will be available at the +/// [axionlib-data](https://github.com/rest-for-physics/axionlib-data/tree/master) +/// repository. The different RML flux definitions used to load those tables +/// will be found at the +/// [fluxes.rml](https://github.com/rest-for-physics/axionlib-data/blob/master/solarFlux/fluxes.rml) +/// file found at the axionlib-data repository. +/// +/// Inside a local REST installation, the `fluxes.rml` file will be found at the REST +/// installation directory, and it will be located automatically by the +/// TRestMetadata::SearchFile method. +/// +/// ### A basic RML definition +/// +/// The following definition integrates an axion-photon component with a continuum +/// spectrum using a Primakoff production model, and a dummy spectrum file that +/// includes two monocrhomatic lines at different solar disk radius positions. +/// +/// \code +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// \endcode +/// +/// \warning When the flux is loaded manually inside the `restRoot` interactive +/// shell, or inside a macro or script, after metadata initialization, it is necessary +/// to call the method TRestAxionSolarQCDFlux::LoadTables to trigger the tables +/// initialization. +/// +/// ### Performing MonteCarlo tests using pre-loaded tables +/// +/// In order to test the response of different solar flux definitions we may use the script +/// `solarPlot.py` found at `pipeline/metadata/solarFlux/`. This script will generate a +/// number of particles and it will assign to each particle an energy and solar disk +/// location with the help of the method TRestAxionSolarQCDFlux::GetRandomEnergyAndRadius. +/// +/// \code +/// python3 solarPlotQCD.py --fluxname LennertHoofABC --N 1000000 +/// \endcode +/// +/// By default, it will load the flux definition found at `fluxes.rml` from the +/// `axionlib-data` repository, and generate a `png` image with the resuts from the +/// Monte Carlo execution. +/// +/// \htmlonly \endhtmlonly +/// +/// ![Solar flux distributions MC-generated with TRestAxionSolarQCDFlux.](ABC_flux_MC.png) +/// +/// ### Reading solar flux tables from `.flux` files +/// +/// In a similar way we may initialize the class using a `.flux` file. The `.flux` described +/// previously will contain a high definition flux table measured in `cm-2 s-1 keV-1` as a +/// function of the energy (from 0 to 20keV) and the inner solar radius (from 0 to 1). The +/// binning of this table will be typically between 1eV and 10eV. +/// +/// The class TRestAxionSolarQCDFlux will be initialized directly using the `.flux` file +/// provided under the `fluxDataFile` parameter. During the initialization, the flux will be +/// splitted into two independent flux components. One smooth continuum component integrated +/// in 100 eV steps, and a monochromatic peak components. +/// +/// In order to help with the identification of peaks we need to define the `binSize` used in +/// the `.flux` table and the `peakSigma` defining the number of sigmas over the average for +/// a bin to be considered a peak. +/// +/// \code +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// \endcode +/// +/// We will be able to load this file as usual, using the following recipe inside +/// `restRoot`, +/// +/// \code +/// TRestAxionSolarQCDFlux *sFlux = new TRestAxionSolarQCDFlux("fluxes.rml", "LennertHoofABC") +/// sFlux->Initialize() +/// TCanvas *c = sFlux->DrawSolarFluxes() +/// c->Print("ABC_FluxTable.png" ) +/// \endcode +/// +/// will generate the following figure. +/// +/// \htmlonly \endhtmlonly +/// +/// ![Solar flux distributions generated with TRestAxionSolarQCDFlux::DrawSolarFlux.](ABC_FluxTable.png) +/// +/// ### Exporting the solar flux tables +/// +/// On top of that, we will be able to export those tables to the TRestAxionSolarQCDFlux standard +/// format to be used in later occasions. +/// +/// \code +/// TRestAxionSolarQCDFlux *sFlux = new TRestAxionSolarQCDFlux("fluxes.rml", "LennertHoofABC") +/// sFlux->Initialize() +/// sFlux->ExportTables() +/// \endcode +/// +/// which will produce two files, a binary table `.N200f` with the continuum flux, and an ASCII +/// table containning the `.spt` monochromatic lines. The filename root will be extracted from +/// the original `.flux` file. Optionally we may export the continuum flux to an ASCII file by +/// indicating it at the TRestAxionSolarQCDFlux::ExportTables method call. The files will be placed +/// at the REST user space, at `$HOME/.rest/export/` directory. +/// +/// TODO Implement the method TRestAxionSolarQCDFlux::InitializeSolarTable using +/// a solar model description by TRestAxionSolarModel. +/// +/// TODO Perhaps it would be interesting to replace fFluxTable for a TH2D +/// +///-------------------------------------------------------------------------- +/// +/// RESTsoft - Software for Rare Event Searches with TPCs +/// +/// History of developments: +/// +/// 2023-May: Specific methods extracted from TRestAxionSolarFlux +/// Javier Galan +/// +/// \class TRestAxionSolarQCDFlux +/// \author Javier Galan +/// +///
+/// + +#include "TRestAxionSolarHiddenPhotonFlux.h" +using namespace std; + +ClassImp(TRestAxionSolarHiddenPhotonFlux); + +/////////////////////////////////////////////// +/// \brief Default constructor +/// +TRestAxionSolarHiddenPhotonFlux::TRestAxionSolarHiddenPhotonFlux() : TRestAxionSolarFlux() {} + +/////////////////////////////////////////////// +/// \brief Constructor loading data from a config file +/// +/// If no configuration path is defined using TRestMetadata::SetConfigFilePath +/// the path to the config file must be specified using full path, absolute or +/// relative. +/// +/// The default behaviour is that the config file must be specified with +/// full path, absolute or relative. +/// +/// \param cfgFileName A const char* giving the path to an RML file. +/// \param name The name of the specific metadata. It will be used to find the +/// corresponding TRestAxionMagneticField section inside the RML. +/// +TRestAxionSolarHiddenPhotonFlux::TRestAxionSolarHiddenPhotonFlux(const char* cfgFileName, string name) + : TRestAxionSolarFlux(cfgFileName) { + LoadConfigFromFile(fConfigFileName, name); + + if (GetVerboseLevel() >= TRestStringOutput::REST_Verbose_Level::REST_Info) PrintMetadata(); +} + +/////////////////////////////////////////////// +/// \brief Default destructor +/// +TRestAxionSolarHiddenPhotonFlux::~TRestAxionSolarHiddenPhotonFlux() {} + +/////////////////////////////////////////////// +/// \brief It will load the tables in memory by using the filename information provided +/// inside the metadata members. +/// +Bool_t TRestAxionSolarHiddenPhotonFlux::LoadTables() { + if (fFluxDataFile == "" && fFluxSptFile == "") return false; + + if (TRestTools::GetFileNameExtension(fFluxDataFile) == "flux") { + ReadFluxFile(); + } else { + LoadContinuumFluxTable(); + LoadMonoChromaticFluxTable(); + } + + IntegrateSolarFluxes(); + + return true; +} + +/////////////////////////////////////////////// +/// \brief A helper method to load the data file containing continuum spectra as a +/// function of the solar radius. It will be called by TRestAxionSolarFlux::Initialize. +/// +void TRestAxionSolarHiddenPhotonFlux::LoadContinuumFluxTable() { + if (fFluxDataFile == "") { + RESTDebug << "TRestAxionSolarHiddenPhotonflux::LoadContinuumFluxTable. No solar flux table was defined" + << RESTendl; + return; + } + + string fullPathName = SearchFile((string)fFluxDataFile); + + RESTDebug << "Loading table from file : " << RESTendl; + RESTDebug << "File : " << fullPathName << RESTendl; + + std::vector> fluxTable; + if (TRestTools::GetFileNameExtension(fFluxDataFile) == "dat") { + std::vector> doubleTable; + if (!TRestTools::ReadASCIITable(fullPathName, doubleTable)) { + RESTError << "TRestAxionSolarHiddenPhotonFlux::LoadContinuumFluxTable. " << RESTendl; + RESTError << "Could not read solar flux table : " << fFluxDataFile << RESTendl; + return; + } + for (const auto& row : doubleTable) { + std::vector floatVec(row.begin(), row.end()); + fluxTable.push_back(floatVec); + } + } else if (TRestTools::IsBinaryFile(fFluxDataFile)) + TRestTools::ReadBinaryTable(fullPathName, fluxTable); + else { + 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() != 1000 && fluxTable[0].size() != 200) { + fluxTable.clear(); + RESTError << "LoadContinuumFluxTable. The table does not contain the right number of rows or columns" + << RESTendl; + RESTError << "Table will not be populated" << RESTendl; + } + + for (unsigned int n = 0; n < fluxTable.size(); n++) { + TH1F* h = new TH1F(Form("%s_ContinuumFluxAtRadius%d", GetName(), n), "", 200, 0, 20); + for (unsigned int m = 0; m < fluxTable[n].size(); m++) h->SetBinContent(m + 1, fluxTable[n][m]); + fFluxTable.push_back(h); + } +} + +/////////////////////////////////////////////// +/// \brief A helper method to load the data file containing the plasma frequency as a +/// function of the solar radius. It will be called by TRestAxionPhotonFlux::Initialize. +/// +void TRestAxionSolarHiddenPhotonFlux::LoadPlasmaFreqTable() { + if (fFluxDataFile == "") { + RESTDebug << "TRestAxionSolarHiddenPhotonFlux::LoadPlasmaFreqTable. No plasma frequency table was defined" + << RESTendl; + return; + } + + string fullPathName = SearchFile((string)fFluxDataFile); + + RESTDebug << "Loading table from file : " << RESTendl; + RESTDebug << "File : " << fullPathName << RESTendl; + + std::vector> fluxTable; + if (TRestTools::GetFileNameExtension(fFluxDataFile) == "dat") { + std::vector> doubleTable; + if (!TRestTools::ReadASCIITable(fullPathName, doubleTable)) { + RESTError << "TRestAxionSolarHiddenPhotonFlux::LoadPlasmaFreqTable. " << RESTendl; + RESTError << "Could not read solar flux table : " << fFluxDataFile << RESTendl; + return; + } + for (const auto& row : doubleTable) { + fluxTable.push_back(row); + } + } else if (TRestTools::IsBinaryFile(fFluxDataFile)) + TRestTools::ReadBinaryTable(fullPathName, fluxTable); + else { + 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() != 1000) { + fluxTable.clear(); + RESTError << "LoadContinuumFluxTable. The table does not contain the right number of rows" + << RESTendl; + RESTError << "Table will not be populated" << RESTendl; + } + + for (unsigned int n = 0; n < fluxTable.size(); n++) { + TH1F* h = new TH1F(Form("%s_PlasmaFreqAtRadius%d", GetName(), n), "", 1, 0, 20); + h->SetBinContent(1, fluxTable[n][0]); + fWpTable.push_back(h); + } +} + +/////////////////////////////////////////////// +/// \brief A helper method to load the data file containning monochromatic spectral +/// lines as a function of the solar radius. It will be called by TRestAxionSolarQCDFlux::Initialize. +/// +void TRestAxionSolarQCDFlux::LoadMonoChromaticFluxTable() { + if (fFluxSptFile == "") { + RESTDebug << "TRestAxionSolarflux::LoadMonoChromaticFluxTable. No solar flux monochromatic table was " + "defined" + << RESTendl; + return; + } + + string fullPathName = SearchFile((string)fFluxSptFile); + + RESTDebug << "Loading monochromatic lines from file : " << RESTendl; + RESTDebug << "File : " << fullPathName << RESTendl; + + std::vector> doubleTable; + if (!TRestTools::ReadASCIITable(fullPathName, doubleTable)) { + RESTError << "TRestAxionSolarQCDFlux::LoadMonoChromaticFluxTable." << RESTendl; + RESTError << "Could not read solar flux table : " << fFluxSptFile << RESTendl; + return; + } + + std::vector> asciiTable; + for (const auto& row : doubleTable) { + std::vector floatVec(row.begin(), row.end()); + asciiTable.push_back(floatVec); + } + + fFluxLines.clear(); + + if (asciiTable.size() != 101) { + RESTError << "LoadMonoChromaticFluxTable. The table does not contain the right number of rows" + << RESTendl; + RESTError << "Table will not be populated" << RESTendl; + return; + } + + for (unsigned int en = 0; en < asciiTable[0].size(); en++) { + Float_t energy = asciiTable[0][en]; + TH1F* h = new TH1F(Form("%s_MonochromeFluxAtEnergy%6.4lf", GetName(), energy), "", 100, 0, 1); + for (unsigned int r = 1; r < asciiTable.size(); r++) h->SetBinContent(r, asciiTable[r][en]); + fFluxLines[energy] = h; + } +} + + +/////////////////////////////////////////////// +/// \brief It builds a histogram with the continuum spectrum component. +/// The flux will be expressed in cm-2 s-1 keV-1. Binned in 100eV steps. +/// +TH1F* TRestAxionSolarQCDFlux::GetContinuumSpectrum() { + if (fContinuumHist != nullptr) { + delete fContinuumHist; + fContinuumHist = nullptr; + } + + fContinuumHist = new TH1F("ContinuumHist", "", 200, 0, 20); + for (const auto& x : fFluxTable) { + fContinuumHist->Add(x); + } + + fContinuumHist->SetStats(0); + fContinuumHist->GetXaxis()->SetTitle("Energy [keV]"); + fContinuumHist->GetXaxis()->SetTitleSize(0.05); + fContinuumHist->GetXaxis()->SetLabelSize(0.05); + fContinuumHist->GetYaxis()->SetTitle("Flux [cm-2 s-1 keV-1]"); + fContinuumHist->GetYaxis()->SetTitleSize(0.05); + fContinuumHist->GetYaxis()->SetLabelSize(0.05); + + return fContinuumHist; +} + +/////////////////////////////////////////////// +/// \brief It builds a histogram with the monochromatic spectrum component. +/// The flux will be expressed in cm-2 s-1 eV-1. Binned in 1eV steps. +/// +TH1F* TRestAxionSolarQCDFlux::GetMonochromaticSpectrum() { + if (fMonoHist != nullptr) { + delete fMonoHist; + fMonoHist = nullptr; + } + + fMonoHist = new TH1F("MonochromaticHist", "", 20000, 0, 20); + for (const auto& x : fFluxLines) { + fMonoHist->Fill(x.first, x.second->Integral()); // cm-2 s-1 eV-1 + } + + fMonoHist->SetStats(0); + fMonoHist->GetXaxis()->SetTitle("Energy [keV]"); + fMonoHist->GetXaxis()->SetTitleSize(0.05); + fMonoHist->GetXaxis()->SetLabelSize(0.05); + fMonoHist->GetYaxis()->SetTitle("Flux [cm-2 s-1 eV-1]"); + fMonoHist->GetYaxis()->SetTitleSize(0.05); + fMonoHist->GetYaxis()->SetLabelSize(0.05); + + return fMonoHist; +} + +/////////////////////////////////////////////// +/// \brief It builds a histogram adding the continuum and the monochromatic +/// spectrum component. The flux will be expressed in cm-2 s-1 keV-1. +/// Binned in 1eV steps. +/// +TH1F* TRestAxionSolarQCDFlux::GetTotalSpectrum() { + TH1F* hm = GetMonochromaticSpectrum(); + TH1F* hc = GetContinuumSpectrum(); + + if (fTotalHist != nullptr) { + delete fTotalHist; + fTotalHist = nullptr; + } + + fTotalHist = new TH1F("fTotalHist", "", 20000, 0, 20); + for (int n = 0; n < hc->GetNbinsX(); n++) { + for (int m = 0; m < 100; m++) { + fTotalHist->SetBinContent(n * 100 + 1 + m, hc->GetBinContent(n + 1)); + } + } + + for (int n = 0; n < hm->GetNbinsX(); n++) + // 1e-2 is the renormalization from 20000 bins to 200 bins + fTotalHist->SetBinContent(n + 1, fTotalHist->GetBinContent(n + 1) + 100 * hm->GetBinContent(n + 1)); + + fTotalHist->SetStats(0); + fTotalHist->GetXaxis()->SetTitle("Energy [keV]"); + fTotalHist->GetXaxis()->SetTitleSize(0.05); + fTotalHist->GetXaxis()->SetLabelSize(0.05); + fTotalHist->GetYaxis()->SetTitle("Flux [cm-2 s-1 keV-1]"); + fTotalHist->GetYaxis()->SetTitleSize(0.05); + fTotalHist->GetYaxis()->SetLabelSize(0.05); + + return fTotalHist; +} + +/////////////////////////////////////////////// +/// \brief A helper method to initialize the internal class data members with the +/// integrated flux for each solar ring. It will be called by TRestAxionSolarQCDFlux::Initialize. +/// +void TRestAxionSolarQCDFlux::IntegrateSolarFluxes() { + fFluxLineIntegrals.clear(); + fTotalMonochromaticFlux = 0; + + for (const auto& line : fFluxLines) { + fTotalMonochromaticFlux += line.second->Integral(); + fFluxLineIntegrals.push_back(fTotalMonochromaticFlux); + } + + for (unsigned int n = 0; n < fFluxLineIntegrals.size(); n++) + fFluxLineIntegrals[n] /= fTotalMonochromaticFlux; + + fTotalContinuumFlux = 0.0; + for (unsigned int n = 0; n < fFluxTable.size(); n++) { + fTotalContinuumFlux += fFluxTable[n]->Integral() * 0.1; // We integrate in 100eV steps + fFluxTableIntegrals.push_back(fTotalContinuumFlux); + } + + for (unsigned int n = 0; n < fFluxTableIntegrals.size(); n++) + fFluxTableIntegrals[n] /= fTotalContinuumFlux; + + fFluxRatio = fTotalMonochromaticFlux / (fTotalContinuumFlux + fTotalMonochromaticFlux); +} + +/////////////////////////////////////////////// +/// \brief It returns the integrated flux at earth in cm-2 s-1 for the given energy range +/// +Double_t TRestAxionSolarQCDFlux::IntegrateFluxInRange(TVector2 eRange, Double_t mass) { + if (eRange.X() == -1 && eRange.Y() == -1) { + if (GetTotalFlux() == 0) IntegrateSolarFluxes(); + return GetTotalFlux(); + } + + Double_t flux = 0; + for (const auto& line : fFluxLines) + if (line.first > eRange.X() && line.first < eRange.Y()) flux += line.second->Integral(); + + fTotalContinuumFlux = 0.0; + for (unsigned int n = 0; n < fFluxTable.size(); n++) { + flux += fFluxTable[n]->Integral(fFluxTable[n]->FindFixBin(eRange.X()), + fFluxTable[n]->FindFixBin(eRange.Y())) * + 0.1; // We integrate in 100eV steps + } + + return flux; +} + +/////////////////////////////////////////////// +/// \brief It returns a random solar radius position and energy according to the +/// flux distributions defined inside the solar tables loaded in the class +/// +std::pair TRestAxionSolarQCDFlux::GetRandomEnergyAndRadius(TVector2 eRange, + Double_t mass) { + std::pair result = {0, 0}; + if (!AreTablesLoaded()) return result; + Double_t rnd = fRandom->Rndm(); + if (fTotalMonochromaticFlux == 0 || fRandom->Rndm() > fFluxRatio) { + // Continuum + for (unsigned int r = 0; r < fFluxTableIntegrals.size(); r++) { + if (rnd < fFluxTableIntegrals[r]) { + Double_t energy = fFluxTable[r]->GetRandom(); + if (eRange.X() != -1 && eRange.Y() != -1) { + if (energy < eRange.X() || energy > eRange.Y()) return GetRandomEnergyAndRadius(eRange); + } + Double_t radius = ((Double_t)r + fRandom->Rndm()) * 0.01; + std::pair p = {energy, radius}; + return p; + } + } + } else { + // Monochromatic + int n = 0; + for (const auto& line : fFluxLines) { + if (rnd < fFluxLineIntegrals[n]) { + std::pair p = {line.first, line.second->GetRandom()}; + return p; + } + n++; + } + } + return result; +} + +/////////////////////////////////////////////// +/// \brief It prints on screen the table that has been loaded in memory +/// +void TRestAxionSolarQCDFlux::PrintContinuumSolarTable() { + cout << "Continuum solar flux table: " << endl; + cout << "--------------------------- " << endl; + for (unsigned int n = 0; n < fFluxTable.size(); n++) { + for (int m = 0; m < fFluxTable[n]->GetNbinsX(); m++) + cout << fFluxTable[n]->GetBinContent(m + 1) << "\t"; + cout << endl; + cout << endl; + } + cout << endl; +} + +/////////////////////////////////////////////// +/// \brief It prints on screen the integrated solar flux per solar ring +/// +void TRestAxionSolarQCDFlux::PrintIntegratedRingFlux() { + cout << "Integrated solar flux per solar ring: " << endl; + cout << "--------------------------- " << endl; + /* + for (int n = 0; n < fFluxPerRadius.size(); n++) + cout << "n : " << n << " flux : " << fFluxPerRadius[n] << endl; + cout << endl; + */ +} + +/////////////////////////////////////////////// +/// \brief It prints on screen the spectral lines loaded in memory +/// +void TRestAxionSolarQCDFlux::PrintMonoChromaticFlux() { + // cout << "Number of monochromatic lines: " << fFluxPerRadius.size() << endl; + cout << "+++++++++++++++++++++++++++++++++++" << endl; + for (auto const& line : fFluxLines) { + cout << "Energy : " << line.first << " keV" << endl; + cout << "-----------------" << endl; + for (int n = 0; n < line.second->GetNbinsX(); n++) + cout << "R : " << line.second->GetBinCenter(n + 1) + << " flux : " << line.second->GetBinContent(n + 1) << " cm-2 s-1" << endl; + } +} + +/////////////////////////////////////////////// +/// \brief Prints on screen the information about the metadata members of TRestAxionSolarQCDFlux +/// +void TRestAxionSolarQCDFlux::PrintMetadata() { + TRestAxionSolarFlux::PrintMetadata(); + + if (fFluxDataFile != "") + RESTMetadata << " - Solar axion flux datafile (continuum) : " << fFluxDataFile << RESTendl; + if (fFluxSptFile != "") + RESTMetadata << " - Solar axion flux datafile (monochromatic) : " << fFluxSptFile << RESTendl; + RESTMetadata << "-------" << RESTendl; + RESTMetadata << " - Total monochromatic flux : " << fTotalMonochromaticFlux << " cm-2 s-1" << RESTendl; + RESTMetadata << " - Total continuum flux : " << fTotalContinuumFlux << " cm-2 s-1" << RESTendl; + RESTMetadata << "++++++++++++++++++" << RESTendl; + + if (GetVerboseLevel() >= TRestStringOutput::REST_Verbose_Level::REST_Debug) { + PrintContinuumSolarTable(); + PrintMonoChromaticFlux(); + PrintIntegratedRingFlux(); + } +} + +/////////////////////////////////////////////// +/// \brief It will create files with the continuum and spectral flux components to be used +/// in a later ocasion. +/// +void TRestAxionSolarQCDFlux::ExportTables(Bool_t ascii) { + string rootFilename = TRestTools::GetFileNameRoot(fFluxDataFile); + + string path = REST_USER_PATH + "/export/"; + + if (!TRestTools::fileExists(path)) { + std::cout << "Creating path: " << path << std::endl; + int z = system(("mkdir -p " + path).c_str()); + if (z != 0) RESTError << "Could not create directory " << path << RESTendl; + } + + if (fFluxTable.size() > 0) { + std::vector> table; + for (const auto& x : fFluxTable) { + std::vector row; + for (int n = 0; n < x->GetNbinsX(); n++) row.push_back(x->GetBinContent(n + 1)); + + table.push_back(row); + } + + if (!ascii) + TRestTools::ExportBinaryTable(path + "/" + rootFilename + ".N200f", table); + else + TRestTools::ExportASCIITable(path + "/" + rootFilename + ".dat", table); + } + + if (fFluxLines.size() > 0) { + std::vector> table; + for (const auto& x : fFluxLines) { + std::vector row; + row.push_back(x.first); + for (int n = 0; n < x.second->GetNbinsX(); n++) row.push_back(x.second->GetBinContent(n + 1)); + + table.push_back(row); + } + + TRestTools::TransposeTable(table); + + TRestTools::ExportASCIITable(path + "/" + rootFilename + ".spt", table); + } +} From f1e5be3c9394e9ba010a533f5c4509491c1265b5 Mon Sep 17 00:00:00 2001 From: tomasoshea Date: Thu, 22 Jun 2023 09:53:53 +0200 Subject: [PATCH 02/48] Coded in HP flux calculation --- inc/TRestAxionSolarHiddenPhotonFlux.h | 17 +- src/TRestAxionSolarHiddenPhotonFlux.cxx | 323 ++++++++++++------------ 2 files changed, 170 insertions(+), 170 deletions(-) diff --git a/inc/TRestAxionSolarHiddenPhotonFlux.h b/inc/TRestAxionSolarHiddenPhotonFlux.h index 3a31e634..929859a1 100644 --- a/inc/TRestAxionSolarHiddenPhotonFlux.h +++ b/inc/TRestAxionSolarHiddenPhotonFlux.h @@ -30,14 +30,20 @@ //! A metadata class to load tabulated solar hidden photon fluxes. Mass and coupling set to 1. class TRestAxionSolarHiddenPhotonFlux : public TRestAxionSolarFlux { private: + /// The hidden photon mass used for calculation + double HiddenPhotonMass; + + /// The value of the kinetic mixing parameter used for calculation + double HiddenPhotonKineticMixing; + /// The filename containing the solar flux table with continuum spectrum std::string fFluxDataFile = ""; //< /// The filename containing the resonance width (wGamma) - std::string fWGammaDataFile = ""; //< + std::string fWidthDataFile = ""; //< /// The filename containing the plasma freqency (wp) table - std::string fWpDataFile = ""; //< + std::string fPlasmaFreqDataFile = ""; //< /// It will be used when loading `.flux` files to define the input file energy binsize in eV. Double_t fBinSize = 0; //< @@ -49,10 +55,13 @@ class TRestAxionSolarHiddenPhotonFlux : public TRestAxionSolarFlux { std::vector fFluxTable; //! /// The tabulated resonance width TH1F(200,0,20)keV in eV2 versus solar radius - std::vector fWGammaTable; //! + std::vector fWidthTable; //! /// The solar plasma frequency vector in eV versus solar radius - std::vector fWpTable; //! + std::vector fPlasmaFreqTable; //! + + /// The total solar flux TH1F(200,0,20)keV in cm-2 s-1 keV-1 versus solar radius + std::vector fFullFluxTable; //! /// Accumulative integrated solar flux for each solar ring for continuum spectrum (renormalized to unity) std::vector fFluxTableIntegrals; //! diff --git a/src/TRestAxionSolarHiddenPhotonFlux.cxx b/src/TRestAxionSolarHiddenPhotonFlux.cxx index 0140f6fd..5f4a00af 100644 --- a/src/TRestAxionSolarHiddenPhotonFlux.cxx +++ b/src/TRestAxionSolarHiddenPhotonFlux.cxx @@ -39,38 +39,22 @@ /// ### Basic use /// /// Once the class has been initialized, the main use of this class will be provided -/// by the method TRestAxionSolarQCDFlux::GetRandomEnergyAndRadius. This method will +/// by the method TRestAxionSolarHiddenPhotonFlux::GetRandomEnergyAndRadius. This method will /// return a random axion energy and position inside the solar radius following the /// distributions given by the solar flux tables. /// /// Description of the specific parameters accepted by this metadata class. -/// - *fluxDataFile:* A table with 100 rows representing the solar ring flux from the +/// - *fluxDataFile:* A table with 1000 rows representing the solar ring flux from the /// center to the corona, and 200 columns representing the flux, measured in cm-2 s-1 keV-1, -/// for the range (0,20)keV in steps of 100eV. The table could be provided in ASCII format, -/// using `.dat` extension, or it might be a binary table using `.N200f` extension. -/// - *fluxSptFile:* A table where each column represents a monochromatic energy. The -/// column contains 101 rows, the first element is the energy of the monochromatic line -/// while the next 100 elements contain the flux, measured in cm-2 s-1, integrated to -/// each solar ring, being the second element the ring in the center of the sun. -/// -/// Additionally this class will be able to read `.flux` files that are the original files -/// produced in 3-columns format (inner radius [solar units] / energy [keV] / -/// flux [cm-2 s-1 keV-1]). The `.flux` files may contain the full information, -/// continuum and spectral components. Those components will be splited into two independent -/// contributions by TRestAxionSolarQCDFlux::ReadFluxFile to be managed internally. Two -/// additional parameters *will be required* to translate the `.flux` files into the tables -/// that are understood by this class. -/// - *binSize:* The energy binning used on the `.flux` file and inside the histogram used -/// for monochromatic lines identification. -/// - *peakSigma:* The ratio between the flux provided at the `.flux` file and the -/// average flux calculated in the peak surroundings. If the flux ratio is higher than -/// this value, the flux at that particular bin will be considered a peak. -/// -/// Optionally, if we want to consider a different binning on the monochromatic/continuum -/// histogram used internally for the calculation we may specify optionally a new parameter. -/// In that case, `fBinSize` will be the binning of the internal histogram, while the new -/// parameter will be the binning given inside the `.flux` file. -/// - *fluxBinSize:* The bin size used on the `.flux` table. +/// for the range (0,20)keV in steps of 100eV. The table is provided as a binary table using +/// `.N200f` extension. +/// - *widthDataFile:* A table with 1000 rows representing the width of the hidden photon +/// resonant production for each solar ring from the center to the corona, and 200 columns +/// representing the width, measured in eV2, for the range (0,20)keV in steps of 100eV. The +/// table is provided as a binary table using `.N200f` extension. +/// - *plasmaFreqDataFile:* A table with 1000 rows and only 1 column representing the solar +/// plasma frequency for each solar ring from the center to the corona, measured in eV. The +/// table is provided as a binary table using `.N1f` extension. /// /// Pre-generated solar axion flux tables will be available at the /// [axionlib-data](https://github.com/rest-for-physics/axionlib-data/tree/master) @@ -105,7 +89,7 @@ /// /// \warning When the flux is loaded manually inside the `restRoot` interactive /// shell, or inside a macro or script, after metadata initialization, it is necessary -/// to call the method TRestAxionSolarQCDFlux::LoadTables to trigger the tables +/// to call the method TRestAxionSolarHiddenPhotonFlux::LoadTables to trigger the tables /// initialization. /// /// ### Performing MonteCarlo tests using pre-loaded tables @@ -113,10 +97,10 @@ /// In order to test the response of different solar flux definitions we may use the script /// `solarPlot.py` found at `pipeline/metadata/solarFlux/`. This script will generate a /// number of particles and it will assign to each particle an energy and solar disk -/// location with the help of the method TRestAxionSolarQCDFlux::GetRandomEnergyAndRadius. +/// location with the help of the method TRestAxionSolarHiddenPhotonFlux::GetRandomEnergyAndRadius. /// /// \code -/// python3 solarPlotQCD.py --fluxname LennertHoofABC --N 1000000 +/// python3 solarPlotHiddenPhoton.py --fluxname HiddenPhoton --N 1000000 /// \endcode /// /// By default, it will load the flux definition found at `fluxes.rml` from the @@ -127,67 +111,21 @@ /// /// ![Solar flux distributions MC-generated with TRestAxionSolarQCDFlux.](ABC_flux_MC.png) /// -/// ### Reading solar flux tables from `.flux` files -/// -/// In a similar way we may initialize the class using a `.flux` file. The `.flux` described -/// previously will contain a high definition flux table measured in `cm-2 s-1 keV-1` as a -/// function of the energy (from 0 to 20keV) and the inner solar radius (from 0 to 1). The -/// binning of this table will be typically between 1eV and 10eV. -/// -/// The class TRestAxionSolarQCDFlux will be initialized directly using the `.flux` file -/// provided under the `fluxDataFile` parameter. During the initialization, the flux will be -/// splitted into two independent flux components. One smooth continuum component integrated -/// in 100 eV steps, and a monochromatic peak components. -/// -/// In order to help with the identification of peaks we need to define the `binSize` used in -/// the `.flux` table and the `peakSigma` defining the number of sigmas over the average for -/// a bin to be considered a peak. -/// -/// \code -/// -/// -/// -/// -/// -/// -/// -/// -/// -/// -/// \endcode -/// -/// We will be able to load this file as usual, using the following recipe inside -/// `restRoot`, -/// -/// \code -/// TRestAxionSolarQCDFlux *sFlux = new TRestAxionSolarQCDFlux("fluxes.rml", "LennertHoofABC") -/// sFlux->Initialize() -/// TCanvas *c = sFlux->DrawSolarFluxes() -/// c->Print("ABC_FluxTable.png" ) -/// \endcode -/// -/// will generate the following figure. -/// -/// \htmlonly \endhtmlonly -/// -/// ![Solar flux distributions generated with TRestAxionSolarQCDFlux::DrawSolarFlux.](ABC_FluxTable.png) -/// /// ### Exporting the solar flux tables /// -/// On top of that, we will be able to export those tables to the TRestAxionSolarQCDFlux standard -/// format to be used in later occasions. +/// On top of that, we will be able to export those tables to the TRestAxionSolarHiddenPhotonFlux +/// standard format to be used in later occasions. /// /// \code -/// TRestAxionSolarQCDFlux *sFlux = new TRestAxionSolarQCDFlux("fluxes.rml", "LennertHoofABC") +/// TRestAxionSolarHiddenPhotonFlux *sFlux = new TRestAxionSolarHiddenPhotonFlux("fluxes.rml", "HiddenPhoton") /// sFlux->Initialize() /// sFlux->ExportTables() /// \endcode /// -/// which will produce two files, a binary table `.N200f` with the continuum flux, and an ASCII -/// table containning the `.spt` monochromatic lines. The filename root will be extracted from -/// the original `.flux` file. Optionally we may export the continuum flux to an ASCII file by -/// indicating it at the TRestAxionSolarQCDFlux::ExportTables method call. The files will be placed -/// at the REST user space, at `$HOME/.rest/export/` directory. +/// which will produce a binary table `.N200f` with the continuum flux. The filename root will be +/// extracted from the original `.flux` file. Optionally we may export the continuum flux to an +/// ASCII file by indicating it at the TRestAxionSolarHiddenPhotonFlux::ExportTables method call. +/// The files will be placed at the REST user space, at `$HOME/.rest/export/` directory. /// /// TODO Implement the method TRestAxionSolarQCDFlux::InitializeSolarTable using /// a solar model description by TRestAxionSolarModel. @@ -202,6 +140,8 @@ /// /// 2023-May: Specific methods extracted from TRestAxionSolarFlux /// Javier Galan +/// 2023-June: TRestAxionSolarHiddenPhotonFlux created by editing TRestAxionSolarQCDFlux +/// Tomas O'Shea /// /// \class TRestAxionSolarQCDFlux /// \author Javier Galan @@ -250,14 +190,12 @@ TRestAxionSolarHiddenPhotonFlux::~TRestAxionSolarHiddenPhotonFlux() {} /// inside the metadata members. /// Bool_t TRestAxionSolarHiddenPhotonFlux::LoadTables() { - if (fFluxDataFile == "" && fFluxSptFile == "") return false; + if (fFluxDataFile == "" || fWidthDataFile == "" || + fPlasmaFreqDataFile == "") return false; - if (TRestTools::GetFileNameExtension(fFluxDataFile) == "flux") { - ReadFluxFile(); - } else { - LoadContinuumFluxTable(); - LoadMonoChromaticFluxTable(); - } + LoadContinuumFluxTable(); + LoadWidthTable(); + LoadPlasmaFreqTable(); IntegrateSolarFluxes(); @@ -266,11 +204,11 @@ Bool_t TRestAxionSolarHiddenPhotonFlux::LoadTables() { /////////////////////////////////////////////// /// \brief A helper method to load the data file containing continuum spectra as a -/// function of the solar radius. It will be called by TRestAxionSolarFlux::Initialize. +/// function of the solar radius. It will be called by TRestAxionSolarHiddenPhotonFlux::Initialize. /// -void TRestAxionSolarHiddenPhotonFlux::LoadContinuumFluxTable() { +void TRestAxionSolarHiddenPhotonFlux::LoadContinuumTable() { if (fFluxDataFile == "") { - RESTDebug << "TRestAxionSolarHiddenPhotonflux::LoadContinuumFluxTable. No solar flux table was defined" + RESTDebug << "TRestAxionSolarHiddenPhotonFlux::LoadContinuumFluxTable. No solar flux table was defined" << RESTendl; return; } @@ -280,26 +218,14 @@ void TRestAxionSolarHiddenPhotonFlux::LoadContinuumFluxTable() { RESTDebug << "Loading table from file : " << RESTendl; RESTDebug << "File : " << fullPathName << RESTendl; - std::vector> fluxTable; - if (TRestTools::GetFileNameExtension(fFluxDataFile) == "dat") { - std::vector> doubleTable; - if (!TRestTools::ReadASCIITable(fullPathName, doubleTable)) { - RESTError << "TRestAxionSolarHiddenPhotonFlux::LoadContinuumFluxTable. " << RESTendl; - RESTError << "Could not read solar flux table : " << fFluxDataFile << RESTendl; - return; - } - for (const auto& row : doubleTable) { - std::vector floatVec(row.begin(), row.end()); - fluxTable.push_back(floatVec); - } - } else if (TRestTools::IsBinaryFile(fFluxDataFile)) - TRestTools::ReadBinaryTable(fullPathName, fluxTable); - else { + std::vector> fluxTable; + + if (!TRestTools::IsBinaryFile(fFluxDataFile)) { 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; + RESTError << "File is not in binary format!" << RESTendl; } + + TRestTools::ReadBinaryTable(fullPathName, fluxTable); if (fluxTable.size() != 1000 && fluxTable[0].size() != 200) { fluxTable.clear(); @@ -311,104 +237,125 @@ void TRestAxionSolarHiddenPhotonFlux::LoadContinuumFluxTable() { for (unsigned int n = 0; n < fluxTable.size(); n++) { TH1F* h = new TH1F(Form("%s_ContinuumFluxAtRadius%d", GetName(), n), "", 200, 0, 20); for (unsigned int m = 0; m < fluxTable[n].size(); m++) h->SetBinContent(m + 1, fluxTable[n][m]); - fFluxTable.push_back(h); + fContinuumTable.push_back(h); } } + /////////////////////////////////////////////// -/// \brief A helper method to load the data file containing the plasma frequency as a -/// function of the solar radius. It will be called by TRestAxionPhotonFlux::Initialize. +/// \brief A helper method to load the data file containing resonance width as a +/// function of the solar radius. It will be called by TRestAxionSolarHiddenPhotonFlux::Initialize. /// -void TRestAxionSolarHiddenPhotonFlux::LoadPlasmaFreqTable() { +void TRestAxionSolarHiddenPhotonFlux::LoadWidthTable() { if (fFluxDataFile == "") { - RESTDebug << "TRestAxionSolarHiddenPhotonFlux::LoadPlasmaFreqTable. No plasma frequency table was defined" + RESTDebug << "TRestAxionSolarHiddenPhotonFlux::LoadWidthTable. No width table was defined" << RESTendl; return; } - string fullPathName = SearchFile((string)fFluxDataFile); + string fullPathName = SearchFile((string)fWidthDataFile); RESTDebug << "Loading table from file : " << RESTendl; RESTDebug << "File : " << fullPathName << RESTendl; - std::vector> fluxTable; - if (TRestTools::GetFileNameExtension(fFluxDataFile) == "dat") { - std::vector> doubleTable; - if (!TRestTools::ReadASCIITable(fullPathName, doubleTable)) { - RESTError << "TRestAxionSolarHiddenPhotonFlux::LoadPlasmaFreqTable. " << RESTendl; - RESTError << "Could not read solar flux table : " << fFluxDataFile << RESTendl; - return; - } - for (const auto& row : doubleTable) { - fluxTable.push_back(row); - } - } else if (TRestTools::IsBinaryFile(fFluxDataFile)) - TRestTools::ReadBinaryTable(fullPathName, fluxTable); - else { + std::vector> fluxTable; + + if (!TRestTools::IsBinaryFile(fWidthDataFile)) { 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; + RESTError << "File is not in binary format!" << RESTendl; } + + TRestTools::ReadBinaryTable(fullPathName, fluxTable); - if (fluxTable.size() != 1000) { + if (fluxTable.size() != 1000 && fluxTable[0].size() != 200) { fluxTable.clear(); - RESTError << "LoadContinuumFluxTable. The table does not contain the right number of rows" + RESTError << "LoadWidthTable. The table does not contain the right number of rows or columns" << RESTendl; RESTError << "Table will not be populated" << RESTendl; } for (unsigned int n = 0; n < fluxTable.size(); n++) { - TH1F* h = new TH1F(Form("%s_PlasmaFreqAtRadius%d", GetName(), n), "", 1, 0, 20); - h->SetBinContent(1, fluxTable[n][0]); - fWpTable.push_back(h); + TH1F* h = new TH1F(Form("%s_ResonanceWidthAtRadius%d", GetName(), n), "", 200, 0, 20); + for (unsigned int m = 0; m < fluxTable[n].size(); m++) h->SetBinContent(m + 1, fluxTable[n][m]); + fWidthTable.push_back(h); } } + /////////////////////////////////////////////// -/// \brief A helper method to load the data file containning monochromatic spectral -/// lines as a function of the solar radius. It will be called by TRestAxionSolarQCDFlux::Initialize. +/// \brief A helper method to load the data file containing resonance width as a +/// function of the solar radius. It will be called by TRestAxionSolarHiddenPhotonFlux::Initialize. /// -void TRestAxionSolarQCDFlux::LoadMonoChromaticFluxTable() { - if (fFluxSptFile == "") { - RESTDebug << "TRestAxionSolarflux::LoadMonoChromaticFluxTable. No solar flux monochromatic table was " - "defined" +void TRestAxionSolarHiddenPhotonFlux::LoadPlasmaFreqTable() { + if (fFluxDataFile == "") { + RESTDebug << "TRestAxionSolarHiddenPhotonFlux::LoadPlasmaFreqTable. No plasma frequency table was defined" << RESTendl; return; } - string fullPathName = SearchFile((string)fFluxSptFile); + string fullPathName = SearchFile((string)fPlasmaFreqDataFile); - RESTDebug << "Loading monochromatic lines from file : " << RESTendl; + RESTDebug << "Loading table from file : " << RESTendl; RESTDebug << "File : " << fullPathName << RESTendl; - std::vector> doubleTable; - if (!TRestTools::ReadASCIITable(fullPathName, doubleTable)) { - RESTError << "TRestAxionSolarQCDFlux::LoadMonoChromaticFluxTable." << RESTendl; - RESTError << "Could not read solar flux table : " << fFluxSptFile << RESTendl; - return; - } + std::vector> fluxTable; - std::vector> asciiTable; - for (const auto& row : doubleTable) { - std::vector floatVec(row.begin(), row.end()); - asciiTable.push_back(floatVec); + if (!TRestTools::IsBinaryFile(fWidthDataFile)) { + fluxTable.clear(); + RESTError << "File is not in binary format!" << RESTendl; } + + TRestTools::ReadBinaryTable(fullPathName, fluxTable); - fFluxLines.clear(); - - if (asciiTable.size() != 101) { - RESTError << "LoadMonoChromaticFluxTable. The table does not contain the right number of rows" + if (fluxTable.size() != 1000 && fluxTable[0].size() != 1) { + fluxTable.clear(); + RESTError << "LoadWidthTable. The table does not contain the right number of rows or columns" << RESTendl; RESTError << "Table will not be populated" << RESTendl; + } + + for (unsigned int n = 0; n < fluxTable.size(); n++) { + TH1F* h = new TH1F(Form("%s_PlasmaFreqAtRadius%d", GetName(), n), "", 1, 0, 20); + for (unsigned int m = 0; m < fluxTable[n].size(); m++) h->SetBinContent(m + 1, fluxTable[n][m]); + fPlasmaFreqTable.push_back(h); + } +} + + +/////////////////////////////////////////////// +/// \brief A helper method to calculate the real solar flux spectrum from the 3 tables, the +/// kinetic mixing parameter and the hidden photon mass. +/// +void TRestAxionSolarHiddenPhotonFlux::CalculateSolarFlux() { + if (!LoadTables()) { + RESTError << "CalculateSolarFlux. The component tables cannot be loaded." << RESTendl; return; } - for (unsigned int en = 0; en < asciiTable[0].size(); en++) { - Float_t energy = asciiTable[0][en]; - TH1F* h = new TH1F(Form("%s_MonochromeFluxAtEnergy%6.4lf", GetName(), energy), "", 100, 0, 1); - for (unsigned int r = 1; r < asciiTable.size(); r++) h->SetBinContent(r, asciiTable[r][en]); - fFluxLines[energy] = h; + for (unsigned int n = 0; n < fluxTable.size(); n++) { + // m4 * chi2 * wG * flux / ( (m2 - wp2)^2 + (wG)^2 ) + + std::vector mass2Vector(200, pow(HiddenPhotonMass,2)); + float wp = fPlasmaFreqTable[n].GetBinContent(1); + std::vector wp2Vector(200, pow(wp,2)); + + TH1F* hMass = new TH1D("hMass", "hMass", 200, 0, 20) + TH1F* hWp = new TH1D("hWp", "hWp", 200, 0, 20) + TH1F* hWg2 = (TH1F*)fWidthTable[n]->Clone(); + + hMass->FillN(200, massVector); // m^2 hist + hWp->FillN(200, wpVector); // wp^2 hist + TH1F* hWg2 = fWidthTable[n] * fWidthTable[n]; // (omega Gamma)^2 + + hMass->Add(hWp, -1); // (m2 - wp2) + hMass->Multiply(hMass); // (m2 - wp2)^2 + hmass->Add(hWg2); // (m2 - wp2)^2 - (wG)^2 + + TH1F* h = fWidthTable[n] * fContinuumTable[n]; + h->Divide(hMass); + h->Scale(pow(HiddenPhotonMass,4) * pow(HiddenPhotonKineticMixing,2)); + + fFluxTable.push_back(h); } } @@ -501,6 +448,50 @@ TH1F* TRestAxionSolarQCDFlux::GetTotalSpectrum() { return fTotalHist; } +/////////////////////////////////////////////// +/// \brief It draws the contents of a .flux file. This method just receives the +/// +TCanvas* TRestAxionSolarQCDFlux::DrawSolarFlux() { + if (fCanvas != nullptr) { + delete fCanvas; + fCanvas = nullptr; + } + fCanvas = new TCanvas("canv", "This is the canvas title", 1200, 500); + fCanvas->Draw(); + + TPad* pad1 = new TPad("pad1", "This is pad1", 0.01, 0.02, 0.99, 0.97); + pad1->Divide(2, 1); + pad1->Draw(); + + pad1->cd(1); + pad1->cd(1)->SetLogy(); + pad1->cd(1)->SetRightMargin(0.09); + pad1->cd(1)->SetLeftMargin(0.15); + pad1->cd(1)->SetBottomMargin(0.15); + + TH1F* ht = GetTotalSpectrum(); + ht->SetLineColor(kBlack); + ht->SetFillStyle(4050); + ht->SetFillColor(kBlue - 10); + + TH1F* hm = GetMonochromaticSpectrum(); + hm->SetLineColor(kBlack); + hm->Scale(100); // renormalizing per 100eV-1 + + ht->Draw("hist"); + hm->Draw("hist same"); + + pad1->cd(2); + pad1->cd(2)->SetRightMargin(0.09); + pad1->cd(2)->SetLeftMargin(0.15); + pad1->cd(2)->SetBottomMargin(0.15); + + ht->Draw("hist"); + hm->Draw("hist same"); + + return fCanvas; +} + /////////////////////////////////////////////// /// \brief A helper method to initialize the internal class data members with the /// integrated flux for each solar ring. It will be called by TRestAxionSolarQCDFlux::Initialize. From b58c1f27d4513dba0e027ffa35813287025d996e Mon Sep 17 00:00:00 2001 From: tomasoshea Date: Thu, 22 Jun 2023 10:11:47 +0200 Subject: [PATCH 03/48] Changed comments to HP versions --- inc/TRestAxionSolarHiddenPhotonFlux.h | 12 +++---- src/TRestAxionSolarHiddenPhotonFlux.cxx | 47 +++++++++++-------------- 2 files changed, 27 insertions(+), 32 deletions(-) diff --git a/inc/TRestAxionSolarHiddenPhotonFlux.h b/inc/TRestAxionSolarHiddenPhotonFlux.h index 929859a1..aae9caff 100644 --- a/inc/TRestAxionSolarHiddenPhotonFlux.h +++ b/inc/TRestAxionSolarHiddenPhotonFlux.h @@ -20,8 +20,8 @@ * For the list of contributors see $REST_PATH/CREDITS. * *************************************************************************/ -#ifndef _TRestAxionSolarQCDFlux -#define _TRestAxionSolarQCDFlux +#ifndef _TRestAxionSolarHiddenPhotonFlux +#define _TRestAxionSolarHiddenPhotonFlux #include #include @@ -125,10 +125,10 @@ class TRestAxionSolarHiddenPhotonFlux : public TRestAxionSolarFlux { void PrintIntegratedRingFlux(); void PrintMonoChromaticFlux(); - TRestAxionSolarQCDFlux(); - TRestAxionSolarQCDFlux(const char* cfgFileName, std::string name = ""); - ~TRestAxionSolarQCDFlux(); + TRestAxionSolarHiddenPhotonFlux(); + TRestAxionSolarHiddenPhotonFlux(const char* cfgFileName, std::string name = ""); + ~TRestAxionSolarHiddenPhotonFlux(); - ClassDefOverride(TRestAxionSolarQCDFlux, 1); + ClassDefOverride(TRestAxionSolarHiddenPhotonFlux, 1); }; #endif diff --git a/src/TRestAxionSolarHiddenPhotonFlux.cxx b/src/TRestAxionSolarHiddenPhotonFlux.cxx index 5f4a00af..fc565499 100644 --- a/src/TRestAxionSolarHiddenPhotonFlux.cxx +++ b/src/TRestAxionSolarHiddenPhotonFlux.cxx @@ -21,19 +21,14 @@ *************************************************************************/ ////////////////////////////////////////////////////////////////////////// -/// TRestAxionSolarQCDFlux will use a file in ASCII or binary format to initialize -/// a solar flux table that will describe the solar flux spectrum as a function +/// TRestAxionSolarHiddenPhotonFlux will use a file in ASCII or binary format to initialize +/// a solar flux table that will describe the solar hidden photon flux spectrum as a function /// of the solar radius. /// -/// This class may serve to load any generic flux definition that is independent -/// from the axion mass. However, since the design of the class was motivated to -/// reproduce the standard QCD axion flux, therefore the name of the class. -/// -/// Another scenario arises when the axion or an axion-like particle production -/// mechanism depends on its mass, and we may need to introduce a flux description -/// as the given in the class TRestAxionSolarHiddenPhotonFlux. Both classes are -/// prototyped by a pure base class TRestAxionSolarFlux that defines common methods -/// used to evaluate the flux, and generate Monte-Carlo events inside +/// This class loads the hidden photon flux that depends on the mass and kinetic mixing parameter. +/// For axion-like particle prodution independent of mass there is the class +/// TRestAxionSolarQCDFlux. Both classes are prototyped by a pure base class TRestAxionSolarFlux +/// that defines common methods used to evaluate the flux, and generate Monte-Carlo events inside /// TRestAxionGeneratorProcess. /// /// ### Basic use @@ -143,7 +138,7 @@ /// 2023-June: TRestAxionSolarHiddenPhotonFlux created by editing TRestAxionSolarQCDFlux /// Tomas O'Shea /// -/// \class TRestAxionSolarQCDFlux +/// \class TRestAxionSolarHiddenPhotonFlux /// \author Javier Galan /// ///
@@ -364,7 +359,7 @@ void TRestAxionSolarHiddenPhotonFlux::CalculateSolarFlux() { /// \brief It builds a histogram with the continuum spectrum component. /// The flux will be expressed in cm-2 s-1 keV-1. Binned in 100eV steps. /// -TH1F* TRestAxionSolarQCDFlux::GetContinuumSpectrum() { +TH1F* TRestAxionSolarHiddenPhotonFlux::GetContinuumSpectrum() { if (fContinuumHist != nullptr) { delete fContinuumHist; fContinuumHist = nullptr; @@ -390,7 +385,7 @@ TH1F* TRestAxionSolarQCDFlux::GetContinuumSpectrum() { /// \brief It builds a histogram with the monochromatic spectrum component. /// The flux will be expressed in cm-2 s-1 eV-1. Binned in 1eV steps. /// -TH1F* TRestAxionSolarQCDFlux::GetMonochromaticSpectrum() { +TH1F* TRestAxionSolarHiddenPhotonFlux::GetMonochromaticSpectrum() { if (fMonoHist != nullptr) { delete fMonoHist; fMonoHist = nullptr; @@ -417,7 +412,7 @@ TH1F* TRestAxionSolarQCDFlux::GetMonochromaticSpectrum() { /// spectrum component. The flux will be expressed in cm-2 s-1 keV-1. /// Binned in 1eV steps. /// -TH1F* TRestAxionSolarQCDFlux::GetTotalSpectrum() { +TH1F* TRestAxionSolarHiddenPhotonFlux::GetTotalSpectrum() { TH1F* hm = GetMonochromaticSpectrum(); TH1F* hc = GetContinuumSpectrum(); @@ -451,7 +446,7 @@ TH1F* TRestAxionSolarQCDFlux::GetTotalSpectrum() { /////////////////////////////////////////////// /// \brief It draws the contents of a .flux file. This method just receives the /// -TCanvas* TRestAxionSolarQCDFlux::DrawSolarFlux() { +TCanvas* TRestAxionSolarHiddenPhotonFlux::DrawSolarFlux() { if (fCanvas != nullptr) { delete fCanvas; fCanvas = nullptr; @@ -494,9 +489,9 @@ TCanvas* TRestAxionSolarQCDFlux::DrawSolarFlux() { /////////////////////////////////////////////// /// \brief A helper method to initialize the internal class data members with the -/// integrated flux for each solar ring. It will be called by TRestAxionSolarQCDFlux::Initialize. +/// integrated flux for each solar ring. It will be called by TRestAxionSolarHiddenPhotonFlux::Initialize. /// -void TRestAxionSolarQCDFlux::IntegrateSolarFluxes() { +void TRestAxionSolarHiddenPhotonFlux::IntegrateSolarFluxes() { fFluxLineIntegrals.clear(); fTotalMonochromaticFlux = 0; @@ -523,7 +518,7 @@ void TRestAxionSolarQCDFlux::IntegrateSolarFluxes() { /////////////////////////////////////////////// /// \brief It returns the integrated flux at earth in cm-2 s-1 for the given energy range /// -Double_t TRestAxionSolarQCDFlux::IntegrateFluxInRange(TVector2 eRange, Double_t mass) { +Double_t TRestAxionSolarHiddenPhotonFlux::IntegrateFluxInRange(TVector2 eRange, Double_t mass) { if (eRange.X() == -1 && eRange.Y() == -1) { if (GetTotalFlux() == 0) IntegrateSolarFluxes(); return GetTotalFlux(); @@ -547,7 +542,7 @@ Double_t TRestAxionSolarQCDFlux::IntegrateFluxInRange(TVector2 eRange, Double_t /// \brief It returns a random solar radius position and energy according to the /// flux distributions defined inside the solar tables loaded in the class /// -std::pair TRestAxionSolarQCDFlux::GetRandomEnergyAndRadius(TVector2 eRange, +std::pair TRestAxionSolarHiddenPhotonFlux::GetRandomEnergyAndRadius(TVector2 eRange, Double_t mass) { std::pair result = {0, 0}; if (!AreTablesLoaded()) return result; @@ -582,7 +577,7 @@ std::pair TRestAxionSolarQCDFlux::GetRandomEnergyAndRadius(T /////////////////////////////////////////////// /// \brief It prints on screen the table that has been loaded in memory /// -void TRestAxionSolarQCDFlux::PrintContinuumSolarTable() { +void TRestAxionSolarHiddenPhotonFlux::PrintContinuumSolarTable() { cout << "Continuum solar flux table: " << endl; cout << "--------------------------- " << endl; for (unsigned int n = 0; n < fFluxTable.size(); n++) { @@ -597,7 +592,7 @@ void TRestAxionSolarQCDFlux::PrintContinuumSolarTable() { /////////////////////////////////////////////// /// \brief It prints on screen the integrated solar flux per solar ring /// -void TRestAxionSolarQCDFlux::PrintIntegratedRingFlux() { +void TRestAxionSolarHiddenPhotonFlux::PrintIntegratedRingFlux() { cout << "Integrated solar flux per solar ring: " << endl; cout << "--------------------------- " << endl; /* @@ -610,7 +605,7 @@ void TRestAxionSolarQCDFlux::PrintIntegratedRingFlux() { /////////////////////////////////////////////// /// \brief It prints on screen the spectral lines loaded in memory /// -void TRestAxionSolarQCDFlux::PrintMonoChromaticFlux() { +void TRestAxionSolarHiddenPhotonFlux::PrintMonoChromaticFlux() { // cout << "Number of monochromatic lines: " << fFluxPerRadius.size() << endl; cout << "+++++++++++++++++++++++++++++++++++" << endl; for (auto const& line : fFluxLines) { @@ -623,9 +618,9 @@ void TRestAxionSolarQCDFlux::PrintMonoChromaticFlux() { } /////////////////////////////////////////////// -/// \brief Prints on screen the information about the metadata members of TRestAxionSolarQCDFlux +/// \brief Prints on screen the information about the metadata members of TRestAxionSolarHiddenPhotonFlux /// -void TRestAxionSolarQCDFlux::PrintMetadata() { +void TRestAxionSolarHiddenPhotonFlux::PrintMetadata() { TRestAxionSolarFlux::PrintMetadata(); if (fFluxDataFile != "") @@ -648,7 +643,7 @@ void TRestAxionSolarQCDFlux::PrintMetadata() { /// \brief It will create files with the continuum and spectral flux components to be used /// in a later ocasion. /// -void TRestAxionSolarQCDFlux::ExportTables(Bool_t ascii) { +void TRestAxionSolarHiddenPhotonFlux::ExportTables(Bool_t ascii) { string rootFilename = TRestTools::GetFileNameRoot(fFluxDataFile); string path = REST_USER_PATH + "/export/"; From 17ac38fe97d11eb6d849b999c4f7afc64aae03a5 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 22 Jun 2023 08:15:14 +0000 Subject: [PATCH 04/48] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- .gitignore | 2 +- inc/TRestAxionSolarHiddenPhotonFlux.h | 1 - src/TRestAxionSolarHiddenPhotonFlux.cxx | 61 ++++++++++++------------- 3 files changed, 29 insertions(+), 35 deletions(-) diff --git a/.gitignore b/.gitignore index 58ad2261..9632e928 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ build *.root **/.DS_Store -*.json \ No newline at end of file +*.json diff --git a/inc/TRestAxionSolarHiddenPhotonFlux.h b/inc/TRestAxionSolarHiddenPhotonFlux.h index aae9caff..7551f2cf 100644 --- a/inc/TRestAxionSolarHiddenPhotonFlux.h +++ b/inc/TRestAxionSolarHiddenPhotonFlux.h @@ -26,7 +26,6 @@ #include #include - //! A metadata class to load tabulated solar hidden photon fluxes. Mass and coupling set to 1. class TRestAxionSolarHiddenPhotonFlux : public TRestAxionSolarFlux { private: diff --git a/src/TRestAxionSolarHiddenPhotonFlux.cxx b/src/TRestAxionSolarHiddenPhotonFlux.cxx index fc565499..97c9ccab 100644 --- a/src/TRestAxionSolarHiddenPhotonFlux.cxx +++ b/src/TRestAxionSolarHiddenPhotonFlux.cxx @@ -112,9 +112,8 @@ /// standard format to be used in later occasions. /// /// \code -/// TRestAxionSolarHiddenPhotonFlux *sFlux = new TRestAxionSolarHiddenPhotonFlux("fluxes.rml", "HiddenPhoton") -/// sFlux->Initialize() -/// sFlux->ExportTables() +/// TRestAxionSolarHiddenPhotonFlux *sFlux = new TRestAxionSolarHiddenPhotonFlux("fluxes.rml", +/// "HiddenPhoton") sFlux->Initialize() sFlux->ExportTables() /// \endcode /// /// which will produce a binary table `.N200f` with the continuum flux. The filename root will be @@ -185,8 +184,7 @@ TRestAxionSolarHiddenPhotonFlux::~TRestAxionSolarHiddenPhotonFlux() {} /// inside the metadata members. /// Bool_t TRestAxionSolarHiddenPhotonFlux::LoadTables() { - if (fFluxDataFile == "" || fWidthDataFile == "" || - fPlasmaFreqDataFile == "") return false; + if (fFluxDataFile == "" || fWidthDataFile == "" || fPlasmaFreqDataFile == "") return false; LoadContinuumFluxTable(); LoadWidthTable(); @@ -203,8 +201,9 @@ Bool_t TRestAxionSolarHiddenPhotonFlux::LoadTables() { /// void TRestAxionSolarHiddenPhotonFlux::LoadContinuumTable() { if (fFluxDataFile == "") { - RESTDebug << "TRestAxionSolarHiddenPhotonFlux::LoadContinuumFluxTable. No solar flux table was defined" - << RESTendl; + RESTDebug + << "TRestAxionSolarHiddenPhotonFlux::LoadContinuumFluxTable. No solar flux table was defined" + << RESTendl; return; } @@ -217,9 +216,9 @@ void TRestAxionSolarHiddenPhotonFlux::LoadContinuumTable() { if (!TRestTools::IsBinaryFile(fFluxDataFile)) { fluxTable.clear(); - RESTError << "File is not in binary format!" << RESTendl; + RESTError << "File is not in binary format!" << RESTendl; } - + TRestTools::ReadBinaryTable(fullPathName, fluxTable); if (fluxTable.size() != 1000 && fluxTable[0].size() != 200) { @@ -236,7 +235,6 @@ void TRestAxionSolarHiddenPhotonFlux::LoadContinuumTable() { } } - /////////////////////////////////////////////// /// \brief A helper method to load the data file containing resonance width as a /// function of the solar radius. It will be called by TRestAxionSolarHiddenPhotonFlux::Initialize. @@ -257,9 +255,9 @@ void TRestAxionSolarHiddenPhotonFlux::LoadWidthTable() { if (!TRestTools::IsBinaryFile(fWidthDataFile)) { fluxTable.clear(); - RESTError << "File is not in binary format!" << RESTendl; + RESTError << "File is not in binary format!" << RESTendl; } - + TRestTools::ReadBinaryTable(fullPathName, fluxTable); if (fluxTable.size() != 1000 && fluxTable[0].size() != 200) { @@ -276,15 +274,15 @@ void TRestAxionSolarHiddenPhotonFlux::LoadWidthTable() { } } - /////////////////////////////////////////////// /// \brief A helper method to load the data file containing resonance width as a /// function of the solar radius. It will be called by TRestAxionSolarHiddenPhotonFlux::Initialize. /// void TRestAxionSolarHiddenPhotonFlux::LoadPlasmaFreqTable() { if (fFluxDataFile == "") { - RESTDebug << "TRestAxionSolarHiddenPhotonFlux::LoadPlasmaFreqTable. No plasma frequency table was defined" - << RESTendl; + RESTDebug + << "TRestAxionSolarHiddenPhotonFlux::LoadPlasmaFreqTable. No plasma frequency table was defined" + << RESTendl; return; } @@ -297,9 +295,9 @@ void TRestAxionSolarHiddenPhotonFlux::LoadPlasmaFreqTable() { if (!TRestTools::IsBinaryFile(fWidthDataFile)) { fluxTable.clear(); - RESTError << "File is not in binary format!" << RESTendl; + RESTError << "File is not in binary format!" << RESTendl; } - + TRestTools::ReadBinaryTable(fullPathName, fluxTable); if (fluxTable.size() != 1000 && fluxTable[0].size() != 1) { @@ -316,9 +314,8 @@ void TRestAxionSolarHiddenPhotonFlux::LoadPlasmaFreqTable() { } } - /////////////////////////////////////////////// -/// \brief A helper method to calculate the real solar flux spectrum from the 3 tables, the +/// \brief A helper method to calculate the real solar flux spectrum from the 3 tables, the /// kinetic mixing parameter and the hidden photon mass. /// void TRestAxionSolarHiddenPhotonFlux::CalculateSolarFlux() { @@ -330,31 +327,29 @@ void TRestAxionSolarHiddenPhotonFlux::CalculateSolarFlux() { for (unsigned int n = 0; n < fluxTable.size(); n++) { // m4 * chi2 * wG * flux / ( (m2 - wp2)^2 + (wG)^2 ) - std::vector mass2Vector(200, pow(HiddenPhotonMass,2)); + std::vector mass2Vector(200, pow(HiddenPhotonMass, 2)); float wp = fPlasmaFreqTable[n].GetBinContent(1); - std::vector wp2Vector(200, pow(wp,2)); + std::vector wp2Vector(200, pow(wp, 2)); - TH1F* hMass = new TH1D("hMass", "hMass", 200, 0, 20) - TH1F* hWp = new TH1D("hWp", "hWp", 200, 0, 20) - TH1F* hWg2 = (TH1F*)fWidthTable[n]->Clone(); + TH1F* hMass = new TH1D("hMass", "hMass", 200, 0, 20) TH1F* hWp = + new TH1D("hWp", "hWp", 200, 0, 20) TH1F* hWg2 = (TH1F*)fWidthTable[n]->Clone(); - hMass->FillN(200, massVector); // m^2 hist - hWp->FillN(200, wpVector); // wp^2 hist - TH1F* hWg2 = fWidthTable[n] * fWidthTable[n]; // (omega Gamma)^2 + hMass->FillN(200, massVector); // m^2 hist + hWp->FillN(200, wpVector); // wp^2 hist + TH1F* hWg2 = fWidthTable[n] * fWidthTable[n]; // (omega Gamma)^2 - hMass->Add(hWp, -1); // (m2 - wp2) - hMass->Multiply(hMass); // (m2 - wp2)^2 - hmass->Add(hWg2); // (m2 - wp2)^2 - (wG)^2 + hMass->Add(hWp, -1); // (m2 - wp2) + hMass->Multiply(hMass); // (m2 - wp2)^2 + hmass->Add(hWg2); // (m2 - wp2)^2 - (wG)^2 TH1F* h = fWidthTable[n] * fContinuumTable[n]; h->Divide(hMass); - h->Scale(pow(HiddenPhotonMass,4) * pow(HiddenPhotonKineticMixing,2)); + h->Scale(pow(HiddenPhotonMass, 4) * pow(HiddenPhotonKineticMixing, 2)); fFluxTable.push_back(h); } } - /////////////////////////////////////////////// /// \brief It builds a histogram with the continuum spectrum component. /// The flux will be expressed in cm-2 s-1 keV-1. Binned in 100eV steps. @@ -543,7 +538,7 @@ Double_t TRestAxionSolarHiddenPhotonFlux::IntegrateFluxInRange(TVector2 eRange, /// flux distributions defined inside the solar tables loaded in the class /// std::pair TRestAxionSolarHiddenPhotonFlux::GetRandomEnergyAndRadius(TVector2 eRange, - Double_t mass) { + Double_t mass) { std::pair result = {0, 0}; if (!AreTablesLoaded()) return result; Double_t rnd = fRandom->Rndm(); From 76b0c6d29ac58d56139b36b57f9ecce348e5a5eb Mon Sep 17 00:00:00 2001 From: tomasoshea Date: Thu, 22 Jun 2023 10:37:29 +0200 Subject: [PATCH 05/48] Removed all monochromatic and .flux code --- inc/TRestAxionSolarHiddenPhotonFlux.h | 9 +- src/TRestAxionSolarHiddenPhotonFlux.cxx | 139 +----------------------- 2 files changed, 7 insertions(+), 141 deletions(-) diff --git a/inc/TRestAxionSolarHiddenPhotonFlux.h b/inc/TRestAxionSolarHiddenPhotonFlux.h index aae9caff..3e1d4ee3 100644 --- a/inc/TRestAxionSolarHiddenPhotonFlux.h +++ b/inc/TRestAxionSolarHiddenPhotonFlux.h @@ -42,15 +42,12 @@ class TRestAxionSolarHiddenPhotonFlux : public TRestAxionSolarFlux { /// The filename containing the resonance width (wGamma) std::string fWidthDataFile = ""; //< - /// The filename containing the plasma freqency (wp) table + /// The filename containing the plasma frequency (wp) table std::string fPlasmaFreqDataFile = ""; //< /// It will be used when loading `.flux` files to define the input file energy binsize in eV. Double_t fBinSize = 0; //< - /// It will be used when loading `.flux` files to define the threshold for peak identification - Double_t fPeakSigma = 0; //< - /// The tabulated solar flux continuum spectra TH1F(200,0,20)keV in cm-2 s-1 keV-1 versus solar radius std::vector fFluxTable; //! @@ -99,14 +96,13 @@ class TRestAxionSolarHiddenPhotonFlux : public TRestAxionSolarFlux { /// It returns the total integrated flux at earth in cm-2 s-1 Double_t GetTotalFlux(Double_t mass = 0) override { - return fTotalContinuumFlux + fTotalMonochromaticFlux; + return fTotalContinuumFlux; } /// It returns an energy integrated spectrum in cm-2 s-1 keV-1 TH1F* GetEnergySpectrum(Double_t m = 0) override { return GetTotalSpectrum(); } TH1F* GetContinuumSpectrum(); - TH1F* GetMonochromaticSpectrum(); TH1F* GetTotalSpectrum(); virtual TCanvas* DrawSolarFlux() override; @@ -123,7 +119,6 @@ class TRestAxionSolarHiddenPhotonFlux : public TRestAxionSolarFlux { void PrintContinuumSolarTable(); void PrintIntegratedRingFlux(); - void PrintMonoChromaticFlux(); TRestAxionSolarHiddenPhotonFlux(); TRestAxionSolarHiddenPhotonFlux(const char* cfgFileName, std::string name = ""); diff --git a/src/TRestAxionSolarHiddenPhotonFlux.cxx b/src/TRestAxionSolarHiddenPhotonFlux.cxx index fc565499..7fc73db6 100644 --- a/src/TRestAxionSolarHiddenPhotonFlux.cxx +++ b/src/TRestAxionSolarHiddenPhotonFlux.cxx @@ -356,7 +356,7 @@ void TRestAxionSolarHiddenPhotonFlux::CalculateSolarFlux() { /////////////////////////////////////////////// -/// \brief It builds a histogram with the continuum spectrum component. +/// \brief It builds a histogram with the continuum spectrum. /// The flux will be expressed in cm-2 s-1 keV-1. Binned in 100eV steps. /// TH1F* TRestAxionSolarHiddenPhotonFlux::GetContinuumSpectrum() { @@ -381,39 +381,12 @@ TH1F* TRestAxionSolarHiddenPhotonFlux::GetContinuumSpectrum() { return fContinuumHist; } -/////////////////////////////////////////////// -/// \brief It builds a histogram with the monochromatic spectrum component. -/// The flux will be expressed in cm-2 s-1 eV-1. Binned in 1eV steps. -/// -TH1F* TRestAxionSolarHiddenPhotonFlux::GetMonochromaticSpectrum() { - if (fMonoHist != nullptr) { - delete fMonoHist; - fMonoHist = nullptr; - } - - fMonoHist = new TH1F("MonochromaticHist", "", 20000, 0, 20); - for (const auto& x : fFluxLines) { - fMonoHist->Fill(x.first, x.second->Integral()); // cm-2 s-1 eV-1 - } - - fMonoHist->SetStats(0); - fMonoHist->GetXaxis()->SetTitle("Energy [keV]"); - fMonoHist->GetXaxis()->SetTitleSize(0.05); - fMonoHist->GetXaxis()->SetLabelSize(0.05); - fMonoHist->GetYaxis()->SetTitle("Flux [cm-2 s-1 eV-1]"); - fMonoHist->GetYaxis()->SetTitleSize(0.05); - fMonoHist->GetYaxis()->SetLabelSize(0.05); - - return fMonoHist; -} /////////////////////////////////////////////// -/// \brief It builds a histogram adding the continuum and the monochromatic -/// spectrum component. The flux will be expressed in cm-2 s-1 keV-1. -/// Binned in 1eV steps. +/// \brief Same as GetContinuumSpectrum, the flux will be +/// expressed in cm-2 s-1 keV-1. Binned in 1eV steps. /// TH1F* TRestAxionSolarHiddenPhotonFlux::GetTotalSpectrum() { - TH1F* hm = GetMonochromaticSpectrum(); TH1F* hc = GetContinuumSpectrum(); if (fTotalHist != nullptr) { @@ -428,10 +401,6 @@ TH1F* TRestAxionSolarHiddenPhotonFlux::GetTotalSpectrum() { } } - for (int n = 0; n < hm->GetNbinsX(); n++) - // 1e-2 is the renormalization from 20000 bins to 200 bins - fTotalHist->SetBinContent(n + 1, fTotalHist->GetBinContent(n + 1) + 100 * hm->GetBinContent(n + 1)); - fTotalHist->SetStats(0); fTotalHist->GetXaxis()->SetTitle("Energy [keV]"); fTotalHist->GetXaxis()->SetTitleSize(0.05); @@ -443,66 +412,12 @@ TH1F* TRestAxionSolarHiddenPhotonFlux::GetTotalSpectrum() { return fTotalHist; } -/////////////////////////////////////////////// -/// \brief It draws the contents of a .flux file. This method just receives the -/// -TCanvas* TRestAxionSolarHiddenPhotonFlux::DrawSolarFlux() { - if (fCanvas != nullptr) { - delete fCanvas; - fCanvas = nullptr; - } - fCanvas = new TCanvas("canv", "This is the canvas title", 1200, 500); - fCanvas->Draw(); - - TPad* pad1 = new TPad("pad1", "This is pad1", 0.01, 0.02, 0.99, 0.97); - pad1->Divide(2, 1); - pad1->Draw(); - - pad1->cd(1); - pad1->cd(1)->SetLogy(); - pad1->cd(1)->SetRightMargin(0.09); - pad1->cd(1)->SetLeftMargin(0.15); - pad1->cd(1)->SetBottomMargin(0.15); - - TH1F* ht = GetTotalSpectrum(); - ht->SetLineColor(kBlack); - ht->SetFillStyle(4050); - ht->SetFillColor(kBlue - 10); - - TH1F* hm = GetMonochromaticSpectrum(); - hm->SetLineColor(kBlack); - hm->Scale(100); // renormalizing per 100eV-1 - - ht->Draw("hist"); - hm->Draw("hist same"); - - pad1->cd(2); - pad1->cd(2)->SetRightMargin(0.09); - pad1->cd(2)->SetLeftMargin(0.15); - pad1->cd(2)->SetBottomMargin(0.15); - - ht->Draw("hist"); - hm->Draw("hist same"); - - return fCanvas; -} /////////////////////////////////////////////// /// \brief A helper method to initialize the internal class data members with the /// integrated flux for each solar ring. It will be called by TRestAxionSolarHiddenPhotonFlux::Initialize. /// void TRestAxionSolarHiddenPhotonFlux::IntegrateSolarFluxes() { - fFluxLineIntegrals.clear(); - fTotalMonochromaticFlux = 0; - - for (const auto& line : fFluxLines) { - fTotalMonochromaticFlux += line.second->Integral(); - fFluxLineIntegrals.push_back(fTotalMonochromaticFlux); - } - - for (unsigned int n = 0; n < fFluxLineIntegrals.size(); n++) - fFluxLineIntegrals[n] /= fTotalMonochromaticFlux; - fTotalContinuumFlux = 0.0; for (unsigned int n = 0; n < fFluxTable.size(); n++) { fTotalContinuumFlux += fFluxTable[n]->Integral() * 0.1; // We integrate in 100eV steps @@ -512,7 +427,6 @@ void TRestAxionSolarHiddenPhotonFlux::IntegrateSolarFluxes() { for (unsigned int n = 0; n < fFluxTableIntegrals.size(); n++) fFluxTableIntegrals[n] /= fTotalContinuumFlux; - fFluxRatio = fTotalMonochromaticFlux / (fTotalContinuumFlux + fTotalMonochromaticFlux); } /////////////////////////////////////////////// @@ -525,9 +439,6 @@ Double_t TRestAxionSolarHiddenPhotonFlux::IntegrateFluxInRange(TVector2 eRange, } Double_t flux = 0; - for (const auto& line : fFluxLines) - if (line.first > eRange.X() && line.first < eRange.Y()) flux += line.second->Integral(); - fTotalContinuumFlux = 0.0; for (unsigned int n = 0; n < fFluxTable.size(); n++) { flux += fFluxTable[n]->Integral(fFluxTable[n]->FindFixBin(eRange.X()), @@ -547,7 +458,7 @@ std::pair TRestAxionSolarHiddenPhotonFlux::GetRandomEnergyAn std::pair result = {0, 0}; if (!AreTablesLoaded()) return result; Double_t rnd = fRandom->Rndm(); - if (fTotalMonochromaticFlux == 0 || fRandom->Rndm() > fFluxRatio) { + if (fRandom->Rndm() > fFluxRatio) { // Continuum for (unsigned int r = 0; r < fFluxTableIntegrals.size(); r++) { if (rnd < fFluxTableIntegrals[r]) { @@ -560,16 +471,6 @@ std::pair TRestAxionSolarHiddenPhotonFlux::GetRandomEnergyAn return p; } } - } else { - // Monochromatic - int n = 0; - for (const auto& line : fFluxLines) { - if (rnd < fFluxLineIntegrals[n]) { - std::pair p = {line.first, line.second->GetRandom()}; - return p; - } - n++; - } } return result; } @@ -602,20 +503,6 @@ void TRestAxionSolarHiddenPhotonFlux::PrintIntegratedRingFlux() { */ } -/////////////////////////////////////////////// -/// \brief It prints on screen the spectral lines loaded in memory -/// -void TRestAxionSolarHiddenPhotonFlux::PrintMonoChromaticFlux() { - // cout << "Number of monochromatic lines: " << fFluxPerRadius.size() << endl; - cout << "+++++++++++++++++++++++++++++++++++" << endl; - for (auto const& line : fFluxLines) { - cout << "Energy : " << line.first << " keV" << endl; - cout << "-----------------" << endl; - for (int n = 0; n < line.second->GetNbinsX(); n++) - cout << "R : " << line.second->GetBinCenter(n + 1) - << " flux : " << line.second->GetBinContent(n + 1) << " cm-2 s-1" << endl; - } -} /////////////////////////////////////////////// /// \brief Prints on screen the information about the metadata members of TRestAxionSolarHiddenPhotonFlux @@ -634,13 +521,12 @@ void TRestAxionSolarHiddenPhotonFlux::PrintMetadata() { if (GetVerboseLevel() >= TRestStringOutput::REST_Verbose_Level::REST_Debug) { PrintContinuumSolarTable(); - PrintMonoChromaticFlux(); PrintIntegratedRingFlux(); } } /////////////////////////////////////////////// -/// \brief It will create files with the continuum and spectral flux components to be used +/// \brief It will create files with spectra to be used /// in a later ocasion. /// void TRestAxionSolarHiddenPhotonFlux::ExportTables(Bool_t ascii) { @@ -668,19 +554,4 @@ void TRestAxionSolarHiddenPhotonFlux::ExportTables(Bool_t ascii) { else TRestTools::ExportASCIITable(path + "/" + rootFilename + ".dat", table); } - - if (fFluxLines.size() > 0) { - std::vector> table; - for (const auto& x : fFluxLines) { - std::vector row; - row.push_back(x.first); - for (int n = 0; n < x.second->GetNbinsX(); n++) row.push_back(x.second->GetBinContent(n + 1)); - - table.push_back(row); - } - - TRestTools::TransposeTable(table); - - TRestTools::ExportASCIITable(path + "/" + rootFilename + ".spt", table); - } } From cd4b0e66994980310423b360f3f7dd3b0225f16b Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 22 Jun 2023 08:37:49 +0000 Subject: [PATCH 06/48] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- inc/TRestAxionSolarHiddenPhotonFlux.h | 4 +--- src/TRestAxionSolarHiddenPhotonFlux.cxx | 4 ---- 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/inc/TRestAxionSolarHiddenPhotonFlux.h b/inc/TRestAxionSolarHiddenPhotonFlux.h index 80059ddb..f41cb867 100644 --- a/inc/TRestAxionSolarHiddenPhotonFlux.h +++ b/inc/TRestAxionSolarHiddenPhotonFlux.h @@ -94,9 +94,7 @@ class TRestAxionSolarHiddenPhotonFlux : public TRestAxionSolarFlux { Bool_t LoadTables() override; /// It returns the total integrated flux at earth in cm-2 s-1 - Double_t GetTotalFlux(Double_t mass = 0) override { - return fTotalContinuumFlux; - } + Double_t GetTotalFlux(Double_t mass = 0) override { return fTotalContinuumFlux; } /// It returns an energy integrated spectrum in cm-2 s-1 keV-1 TH1F* GetEnergySpectrum(Double_t m = 0) override { return GetTotalSpectrum(); } diff --git a/src/TRestAxionSolarHiddenPhotonFlux.cxx b/src/TRestAxionSolarHiddenPhotonFlux.cxx index db100ef4..52caf875 100644 --- a/src/TRestAxionSolarHiddenPhotonFlux.cxx +++ b/src/TRestAxionSolarHiddenPhotonFlux.cxx @@ -376,7 +376,6 @@ TH1F* TRestAxionSolarHiddenPhotonFlux::GetContinuumSpectrum() { return fContinuumHist; } - /////////////////////////////////////////////// /// \brief Same as GetContinuumSpectrum, the flux will be /// expressed in cm-2 s-1 keV-1. Binned in 1eV steps. @@ -407,7 +406,6 @@ TH1F* TRestAxionSolarHiddenPhotonFlux::GetTotalSpectrum() { return fTotalHist; } - /////////////////////////////////////////////// /// \brief A helper method to initialize the internal class data members with the /// integrated flux for each solar ring. It will be called by TRestAxionSolarHiddenPhotonFlux::Initialize. @@ -421,7 +419,6 @@ void TRestAxionSolarHiddenPhotonFlux::IntegrateSolarFluxes() { for (unsigned int n = 0; n < fFluxTableIntegrals.size(); n++) fFluxTableIntegrals[n] /= fTotalContinuumFlux; - } /////////////////////////////////////////////// @@ -498,7 +495,6 @@ void TRestAxionSolarHiddenPhotonFlux::PrintIntegratedRingFlux() { */ } - /////////////////////////////////////////////// /// \brief Prints on screen the information about the metadata members of TRestAxionSolarHiddenPhotonFlux /// From 4d7b5481d78495991a718e8c37f0ccc3e9e4f1d9 Mon Sep 17 00:00:00 2001 From: tomasoshea Date: Tue, 27 Jun 2023 10:52:45 +0200 Subject: [PATCH 07/48] Inlcuded mass dependence and set chi=1 --- inc/TRestAxionSolarFlux.h | 6 +++++ src/TRestAxionSolarHiddenPhotonFlux.cxx | 30 ++++++++++++++++--------- 2 files changed, 25 insertions(+), 11 deletions(-) diff --git a/inc/TRestAxionSolarFlux.h b/inc/TRestAxionSolarFlux.h index 73bcc00d..f417d713 100644 --- a/inc/TRestAxionSolarFlux.h +++ b/inc/TRestAxionSolarFlux.h @@ -38,6 +38,9 @@ class TRestAxionSolarFlux : public TRestMetadata { /// Axion coupling strength Double_t fCouplingStrength = 0; //< + /// Mass parameter + Double_t fMass = 0; //! + /// Seed used in random generator Int_t fSeed = 0; //< @@ -83,6 +86,9 @@ class TRestAxionSolarFlux : public TRestMetadata { Bool_t AreTablesLoaded() { return fTablesLoaded; } + Double_t GetMass() { return fMass; } + void SetMass(const Double_t &m ){ fMass = m; } + TH1F* GetFluxHistogram(std::string fname, Double_t binSize = 0.01); TCanvas* DrawFluxFile(std::string fname, Double_t binSize = 0.01); diff --git a/src/TRestAxionSolarHiddenPhotonFlux.cxx b/src/TRestAxionSolarHiddenPhotonFlux.cxx index 52caf875..5b50bffd 100644 --- a/src/TRestAxionSolarHiddenPhotonFlux.cxx +++ b/src/TRestAxionSolarHiddenPhotonFlux.cxx @@ -84,7 +84,7 @@ /// /// \warning When the flux is loaded manually inside the `restRoot` interactive /// shell, or inside a macro or script, after metadata initialization, it is necessary -/// to call the method TRestAxionSolarHiddenPhotonFlux::LoadTables to trigger the tables +/// to call the method TRestAxionSolarHiddenPhotonFlux::LoadTables(mass) to trigger the tables /// initialization. /// /// ### Performing MonteCarlo tests using pre-loaded tables @@ -181,15 +181,19 @@ TRestAxionSolarHiddenPhotonFlux::~TRestAxionSolarHiddenPhotonFlux() {} /////////////////////////////////////////////// /// \brief It will load the tables in memory by using the filename information provided -/// inside the metadata members. +/// inside the metadata members, and calculate the solar flux for a given m. /// -Bool_t TRestAxionSolarHiddenPhotonFlux::LoadTables() { +Bool_t TRestAxionSolarHiddenPhotonFlux::LoadTables(Double_t mass) { if (fFluxDataFile == "" || fWidthDataFile == "" || fPlasmaFreqDataFile == "") return false; + SetMass(mass); + LoadContinuumFluxTable(); LoadWidthTable(); LoadPlasmaFreqTable(); + CalculateSolarFlux(); + IntegrateSolarFluxes(); return true; @@ -316,18 +320,18 @@ void TRestAxionSolarHiddenPhotonFlux::LoadPlasmaFreqTable() { /////////////////////////////////////////////// /// \brief A helper method to calculate the real solar flux spectrum from the 3 tables, the -/// kinetic mixing parameter and the hidden photon mass. +/// and the hidden photon mass for chi=1. /// void TRestAxionSolarHiddenPhotonFlux::CalculateSolarFlux() { - if (!LoadTables()) { - RESTError << "CalculateSolarFlux. The component tables cannot be loaded." << RESTendl; + if (fMass == 0) { + RESTError << "CalculateSolarFlux. The hidden photon mass is set to zero!" << RESTendl; return; } for (unsigned int n = 0; n < fluxTable.size(); n++) { - // m4 * chi2 * wG * flux / ( (m2 - wp2)^2 + (wG)^2 ) + // m4 * chi2 * wG * flux / ( (m2 - wp2)^2 + (w G)^2 ) - std::vector mass2Vector(200, pow(HiddenPhotonMass, 2)); + std::vector mass2Vector(200, pow(fMass, 2)); float wp = fPlasmaFreqTable[n].GetBinContent(1); std::vector wp2Vector(200, pow(wp, 2)); @@ -336,15 +340,15 @@ void TRestAxionSolarHiddenPhotonFlux::CalculateSolarFlux() { hMass->FillN(200, massVector); // m^2 hist hWp->FillN(200, wpVector); // wp^2 hist - TH1F* hWg2 = fWidthTable[n] * fWidthTable[n]; // (omega Gamma)^2 + TH1F* hWg2 = fWidthTable[n] * fWidthTable[n]; // (w G)^2 hMass->Add(hWp, -1); // (m2 - wp2) hMass->Multiply(hMass); // (m2 - wp2)^2 - hmass->Add(hWg2); // (m2 - wp2)^2 - (wG)^2 + hmass->Add(hWg2); // (m2 - wp2)^2 + (w G)^2 TH1F* h = fWidthTable[n] * fContinuumTable[n]; h->Divide(hMass); - h->Scale(pow(HiddenPhotonMass, 4) * pow(HiddenPhotonKineticMixing, 2)); + h->Scale(pow(fMass, 4)); fFluxTable.push_back(h); } @@ -425,6 +429,8 @@ void TRestAxionSolarHiddenPhotonFlux::IntegrateSolarFluxes() { /// \brief It returns the integrated flux at earth in cm-2 s-1 for the given energy range /// Double_t TRestAxionSolarHiddenPhotonFlux::IntegrateFluxInRange(TVector2 eRange, Double_t mass) { + SetMass(mass); + if (eRange.X() == -1 && eRange.Y() == -1) { if (GetTotalFlux() == 0) IntegrateSolarFluxes(); return GetTotalFlux(); @@ -447,6 +453,8 @@ Double_t TRestAxionSolarHiddenPhotonFlux::IntegrateFluxInRange(TVector2 eRange, /// std::pair TRestAxionSolarHiddenPhotonFlux::GetRandomEnergyAndRadius(TVector2 eRange, Double_t mass) { + SetMass(mass); + std::pair result = {0, 0}; if (!AreTablesLoaded()) return result; Double_t rnd = fRandom->Rndm(); From 712ca971f15294c4e4a98fb2a3252b3c80660be9 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 27 Jun 2023 08:53:24 +0000 Subject: [PATCH 08/48] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- inc/TRestAxionSolarFlux.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/inc/TRestAxionSolarFlux.h b/inc/TRestAxionSolarFlux.h index f417d713..e52656a1 100644 --- a/inc/TRestAxionSolarFlux.h +++ b/inc/TRestAxionSolarFlux.h @@ -39,7 +39,7 @@ class TRestAxionSolarFlux : public TRestMetadata { Double_t fCouplingStrength = 0; //< /// Mass parameter - Double_t fMass = 0; //! + Double_t fMass = 0; //! /// Seed used in random generator Int_t fSeed = 0; //< @@ -87,7 +87,7 @@ class TRestAxionSolarFlux : public TRestMetadata { Bool_t AreTablesLoaded() { return fTablesLoaded; } Double_t GetMass() { return fMass; } - void SetMass(const Double_t &m ){ fMass = m; } + void SetMass(const Double_t& m) { fMass = m; } TH1F* GetFluxHistogram(std::string fname, Double_t binSize = 0.01); TCanvas* DrawFluxFile(std::string fname, Double_t binSize = 0.01); From 43aee1683469108c186179b514b7f4e60f081a9f Mon Sep 17 00:00:00 2001 From: tomasoshea Date: Tue, 27 Jun 2023 11:50:58 +0200 Subject: [PATCH 09/48] Mass set only in loadtables --- inc/TRestAxionSolarHiddenPhotonFlux.h | 20 +++++++------------- src/TRestAxionSolarHiddenPhotonFlux.cxx | 17 ++++++----------- 2 files changed, 13 insertions(+), 24 deletions(-) diff --git a/inc/TRestAxionSolarHiddenPhotonFlux.h b/inc/TRestAxionSolarHiddenPhotonFlux.h index f41cb867..87f8d540 100644 --- a/inc/TRestAxionSolarHiddenPhotonFlux.h +++ b/inc/TRestAxionSolarHiddenPhotonFlux.h @@ -26,14 +26,9 @@ #include #include -//! A metadata class to load tabulated solar hidden photon fluxes. Mass and coupling set to 1. +//! A metadata class to load tabulated solar hidden photon fluxes. Kinetic mixing set to 1. class TRestAxionSolarHiddenPhotonFlux : public TRestAxionSolarFlux { private: - /// The hidden photon mass used for calculation - double HiddenPhotonMass; - - /// The value of the kinetic mixing parameter used for calculation - double HiddenPhotonKineticMixing; /// The filename containing the solar flux table with continuum spectrum std::string fFluxDataFile = ""; //< @@ -84,20 +79,19 @@ class TRestAxionSolarHiddenPhotonFlux : public TRestAxionSolarFlux { Bool_t isPlasmaFreqLoaded() { return fWpTable.size() > 0; } /// It returns the integrated flux at earth in cm-2 s-1 for the given energy range - Double_t IntegrateFluxInRange(TVector2 eRange = TVector2(-1, -1), Double_t mass = 0) override; + Double_t IntegrateFluxInRange(TVector2 eRange = TVector2(-1, -1)) override; /// It defines how to generate Monte Carlo energy and radius values to reproduce the flux - std::pair GetRandomEnergyAndRadius(TVector2 eRange = TVector2(-1, -1), - Double_t mass = 0) override; + std::pair GetRandomEnergyAndRadius(TVector2 eRange = TVector2(-1, -1)) override; - /// It defines how to read the solar tables at the inhereted class - Bool_t LoadTables() override; + /// It defines how to read the solar tables at the inhereted class for a given mass in eV + Bool_t LoadTables(Double_t mass) override; /// It returns the total integrated flux at earth in cm-2 s-1 - Double_t GetTotalFlux(Double_t mass = 0) override { return fTotalContinuumFlux; } + Double_t GetTotalFlux() override { return fTotalContinuumFlux; } /// It returns an energy integrated spectrum in cm-2 s-1 keV-1 - TH1F* GetEnergySpectrum(Double_t m = 0) override { return GetTotalSpectrum(); } + TH1F* GetEnergySpectrum() override { return GetTotalSpectrum(); } TH1F* GetContinuumSpectrum(); TH1F* GetTotalSpectrum(); diff --git a/src/TRestAxionSolarHiddenPhotonFlux.cxx b/src/TRestAxionSolarHiddenPhotonFlux.cxx index 5b50bffd..0ff58605 100644 --- a/src/TRestAxionSolarHiddenPhotonFlux.cxx +++ b/src/TRestAxionSolarHiddenPhotonFlux.cxx @@ -21,7 +21,7 @@ *************************************************************************/ ////////////////////////////////////////////////////////////////////////// -/// TRestAxionSolarHiddenPhotonFlux will use a file in ASCII or binary format to initialize +/// TRestAxionSolarHiddenPhotonFlux will use a file in binary format to initialize /// a solar flux table that will describe the solar hidden photon flux spectrum as a function /// of the solar radius. /// @@ -44,11 +44,11 @@ /// for the range (0,20)keV in steps of 100eV. The table is provided as a binary table using /// `.N200f` extension. /// - *widthDataFile:* A table with 1000 rows representing the width of the hidden photon -/// resonant production for each solar ring from the center to the corona, and 200 columns +/// resonant production (wG) for each solar ring from the center to the corona, and 200 columns /// representing the width, measured in eV2, for the range (0,20)keV in steps of 100eV. The /// table is provided as a binary table using `.N200f` extension. /// - *plasmaFreqDataFile:* A table with 1000 rows and only 1 column representing the solar -/// plasma frequency for each solar ring from the center to the corona, measured in eV. The +/// plasma frequency (wp) for each solar ring from the center to the corona, measured in eV. The /// table is provided as a binary table using `.N1f` extension. /// /// Pre-generated solar axion flux tables will be available at the @@ -428,9 +428,7 @@ void TRestAxionSolarHiddenPhotonFlux::IntegrateSolarFluxes() { /////////////////////////////////////////////// /// \brief It returns the integrated flux at earth in cm-2 s-1 for the given energy range /// -Double_t TRestAxionSolarHiddenPhotonFlux::IntegrateFluxInRange(TVector2 eRange, Double_t mass) { - SetMass(mass); - +Double_t TRestAxionSolarHiddenPhotonFlux::IntegrateFluxInRange(TVector2 eRange) { if (eRange.X() == -1 && eRange.Y() == -1) { if (GetTotalFlux() == 0) IntegrateSolarFluxes(); return GetTotalFlux(); @@ -451,11 +449,8 @@ Double_t TRestAxionSolarHiddenPhotonFlux::IntegrateFluxInRange(TVector2 eRange, /// \brief It returns a random solar radius position and energy according to the /// flux distributions defined inside the solar tables loaded in the class /// -std::pair TRestAxionSolarHiddenPhotonFlux::GetRandomEnergyAndRadius(TVector2 eRange, - Double_t mass) { - SetMass(mass); - - std::pair result = {0, 0}; +std::pair TRestAxionSolarHiddenPhotonFlux::GetRandomEnergyAndRadius(TVector2 eRange) { + std::pair result = {0, 0}; if (!AreTablesLoaded()) return result; Double_t rnd = fRandom->Rndm(); if (fRandom->Rndm() > fFluxRatio) { From d577a5d399b2bf1a17405740040ba4ffb4279c2f Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 27 Jun 2023 09:51:16 +0000 Subject: [PATCH 10/48] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- inc/TRestAxionSolarHiddenPhotonFlux.h | 1 - src/TRestAxionSolarHiddenPhotonFlux.cxx | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/inc/TRestAxionSolarHiddenPhotonFlux.h b/inc/TRestAxionSolarHiddenPhotonFlux.h index 87f8d540..2b6e51fb 100644 --- a/inc/TRestAxionSolarHiddenPhotonFlux.h +++ b/inc/TRestAxionSolarHiddenPhotonFlux.h @@ -29,7 +29,6 @@ //! A metadata class to load tabulated solar hidden photon fluxes. Kinetic mixing set to 1. class TRestAxionSolarHiddenPhotonFlux : public TRestAxionSolarFlux { private: - /// The filename containing the solar flux table with continuum spectrum std::string fFluxDataFile = ""; //< diff --git a/src/TRestAxionSolarHiddenPhotonFlux.cxx b/src/TRestAxionSolarHiddenPhotonFlux.cxx index 0ff58605..1f3ebf57 100644 --- a/src/TRestAxionSolarHiddenPhotonFlux.cxx +++ b/src/TRestAxionSolarHiddenPhotonFlux.cxx @@ -450,7 +450,7 @@ Double_t TRestAxionSolarHiddenPhotonFlux::IntegrateFluxInRange(TVector2 eRange) /// flux distributions defined inside the solar tables loaded in the class /// std::pair TRestAxionSolarHiddenPhotonFlux::GetRandomEnergyAndRadius(TVector2 eRange) { - std::pair result = {0, 0}; + std::pair result = {0, 0}; if (!AreTablesLoaded()) return result; Double_t rnd = fRandom->Rndm(); if (fRandom->Rndm() > fFluxRatio) { From ac0aa28aaf490f63ae9133da157f0f7a249ba8b8 Mon Sep 17 00:00:00 2001 From: Tomas OShea Date: Thu, 31 Aug 2023 12:52:21 +0100 Subject: [PATCH 11/48] created hidden photon plot code --- data | 2 +- .../solarFlux/solarPlotHiddenPhoton.py | 187 ++++++++++++++++++ src/TRestAxionSolarHiddenPhotonFlux.cxx | 3 +- 3 files changed, 190 insertions(+), 2 deletions(-) mode change 160000 => 120000 data create mode 100755 pipeline/metadata/solarFlux/solarPlotHiddenPhoton.py diff --git a/data b/data deleted file mode 160000 index 957d9fc5..00000000 --- a/data +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 957d9fc5e24d2e5aef97cfd1f99982f2c3a07a98 diff --git a/data b/data new file mode 120000 index 00000000..95fc0d20 --- /dev/null +++ b/data @@ -0,0 +1 @@ +../axionlib-data \ No newline at end of file diff --git a/pipeline/metadata/solarFlux/solarPlotHiddenPhoton.py b/pipeline/metadata/solarFlux/solarPlotHiddenPhoton.py new file mode 100755 index 00000000..bd68972e --- /dev/null +++ b/pipeline/metadata/solarFlux/solarPlotHiddenPhoton.py @@ -0,0 +1,187 @@ +#!/usr/bin/python3 + +import math +import ROOT +from ROOT import ( + TChain, + TFile, + TTree, + TCanvas, + TPad, + TRandom3, + TH1D, + TH2D, + TH3D, + TProfile, + TProfile2D, + TProfile3D, + TGraph, + TGraph2D, + TF1, + TF2, + TF3, + TFormula, + TLorentzVector, + TVector3, +) + +import argparse + +parser = argparse.ArgumentParser() +parser.add_argument("--rml", dest="rmlfile", type=str, help="The input RML file .rml") +parser.add_argument( + "--out", + dest="outfname", + type=str, + help="The output filename in png,pdf,C or any other ROOT accepted format", +) +parser.add_argument( + "--fluxname", + dest="fluxname", + type=str, + help="The name of the flux definition to be chosen from the RML", +) +parser.add_argument( + "--N", dest="samples", type=int, help="The number of generated particles" +) +parser.add_argument( + "--m", dest="mass", type=float, help="Hidden photon mass" +) +args = parser.parse_args() + +if mass == 0: + print("Hidden photon mass not specified!!") + print("Specify with argument --m") + quit() + +rmlfile = "fluxes.rml" +if args.rmlfile != None: + rmlfile = args.rmlfile + +outfname = "flux.png" +if args.outfname != None: + outfname = args.outfname + +fluxname = "combined" +if args.fluxname != None: + fluxname = args.fluxname + + +samples = 20000 +if args.samples != None: + samples = args.samples + +validation = True +if ( + rmlfile == "fluxes.rml" + and fluxname == "combined" + and outfname == "flux.png" + and samples == 20000 +): + validation = True + +ROOT.gSystem.Load("libRestFramework.so") +ROOT.gSystem.Load("libRestAxion.so") + +c1 = TCanvas("c1", "My canvas", 800, 700) +c1.GetFrame().SetBorderSize(6) +c1.GetFrame().SetBorderMode(-1) + +pad1 = TPad("pad1", "This is pad1", 0.01, 0.02, 0.99, 0.97) +pad1.Divide(2, 2) +pad1.Draw() + +combinedFlux = ROOT.TRestAxionSolarHiddenPhotonFlux(rmlfile, fluxname) +combinedFlux.Initialize() +combinedFlux.PrintMetadata() + +if combinedFlux.GetError(): + print(combinedFlux.GetErrorMessage()) + print("\nSolar flux initialization failed! Exit code : 101") + exit(101) + +comb_spt = TH2D("comb_spt", "Energy versus solar radius", 20000, 0, 20, 100, 0, 1) +for x in range(samples): + x = combinedFlux.GetRandomEnergyAndRadius(mass) + comb_spt.Fill(x[0], x[1]) + +rnd = TRandom3(0) +solarDisk = TH2D("solar_disk", "SolarDisk", 120, -1.2, 1.2, 120, -1.2, 1.2) +for x in range(samples): + angle = rnd.Rndm() * 2 * math.pi + x = combinedFlux.GetRandomEnergyAndRadius(mass) + + solarDisk.Fill(x[1] * math.cos(angle), x[1] * math.sin(angle)) + +pad1.cd(1) +pad1.cd(1).SetRightMargin(0.09) +pad1.cd(1).SetLeftMargin(0.15) +pad1.cd(1).SetBottomMargin(0.15) + +comb_spt.SetStats(0) +comb_spt.GetXaxis().SetTitle("Energy [keV]") +comb_spt.GetXaxis().SetTitleSize(0.05) +comb_spt.GetXaxis().SetLabelSize(0.05) +comb_spt.GetYaxis().SetTitle("Solar radius") +comb_spt.GetYaxis().SetTitleSize(0.05) +comb_spt.GetYaxis().SetLabelSize(0.05) +comb_spt.Draw("colz") + +pad1.cd(2) +pad1.cd(2).SetLogy() +pad1.cd(2).SetRightMargin(0.09) +pad1.cd(2).SetLeftMargin(0.15) +pad1.cd(2).SetBottomMargin(0.15) +enSpt = comb_spt.ProjectionX() +enSpt.SetTitle("Energy spectrum") +enSpt.GetYaxis().SetTitleSize(0.05) +enSpt.SetStats(0) +enSpt.SetFillStyle(4050) +enSpt.SetFillColor(ROOT.kBlue - 9) +enSpt.SetLineColor(ROOT.kBlack) +enSpt.Draw() + +pad1.cd(3) +pad1.cd(3).SetRightMargin(0.09) +pad1.cd(3).SetLeftMargin(0.15) +pad1.cd(3).SetBottomMargin(0.15) +rSpt = comb_spt.ProjectionY() +rSpt.SetTitle("Radial distribution") +rSpt.GetYaxis().SetTitleSize(0.05) +rSpt.SetStats(0) +rSpt.SetFillStyle(4050) +rSpt.SetFillColor(ROOT.kBlue - 9) +rSpt.SetLineColor(ROOT.kBlack) +rSpt.Draw() + +pad1.cd(4) +pad1.cd(4).SetRightMargin(0.09) +pad1.cd(4).SetLeftMargin(0.15) +pad1.cd(4).SetBottomMargin(0.15) +solarDisk.SetStats(0) +solarDisk.GetXaxis().SetTitle("X") +solarDisk.GetXaxis().SetTitleSize(0.05) +solarDisk.GetXaxis().SetLabelSize(0.05) +solarDisk.GetYaxis().SetTitle("Y") +solarDisk.GetYaxis().SetTitleOffset(1) +solarDisk.GetYaxis().SetTitleSize(0.05) +solarDisk.GetYaxis().SetLabelSize(0.05) +solarDisk.Draw("colz") + +c1.Print(outfname) +print("Generated file : " + outfname) + +print("\nMaximum energy bin is " + str(enSpt.GetMaximumBin())) +if validation: + if enSpt.GetMaximumBin() != 8001: + print("\nMaximum Bin is not the expected one (8001)! Exit code : 1") + exit(1) + +print("\nMaximum radius bin is " + str(rSpt.GetMaximumBin())) + +if validation: + if rSpt.GetMaximumBin() != 25: + print("\nMaximum Bin is not the expected one (25)! Exit code : 2") + exit(2) + +exit(0) diff --git a/src/TRestAxionSolarHiddenPhotonFlux.cxx b/src/TRestAxionSolarHiddenPhotonFlux.cxx index 1f3ebf57..15cd0b65 100644 --- a/src/TRestAxionSolarHiddenPhotonFlux.cxx +++ b/src/TRestAxionSolarHiddenPhotonFlux.cxx @@ -449,7 +449,8 @@ Double_t TRestAxionSolarHiddenPhotonFlux::IntegrateFluxInRange(TVector2 eRange) /// \brief It returns a random solar radius position and energy according to the /// flux distributions defined inside the solar tables loaded in the class /// -std::pair TRestAxionSolarHiddenPhotonFlux::GetRandomEnergyAndRadius(TVector2 eRange) { +std::pair TRestAxionSolarHiddenPhotonFlux::GetRandomEnergyAndRadius(TVector2 eRange, Double_t HPmass) { + LoadTables(HPmass); // load tables with specified hidden photon mass std::pair result = {0, 0}; if (!AreTablesLoaded()) return result; Double_t rnd = fRandom->Rndm(); From 8a7990f237f1238aff61e530f4e9ff530251da4f Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 31 Aug 2023 11:55:50 +0000 Subject: [PATCH 12/48] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- pipeline/metadata/solarFlux/solarPlotHiddenPhoton.py | 10 ++++------ src/TRestAxionSolarHiddenPhotonFlux.cxx | 5 +++-- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/pipeline/metadata/solarFlux/solarPlotHiddenPhoton.py b/pipeline/metadata/solarFlux/solarPlotHiddenPhoton.py index bd68972e..e80f742d 100755 --- a/pipeline/metadata/solarFlux/solarPlotHiddenPhoton.py +++ b/pipeline/metadata/solarFlux/solarPlotHiddenPhoton.py @@ -44,15 +44,13 @@ parser.add_argument( "--N", dest="samples", type=int, help="The number of generated particles" ) -parser.add_argument( - "--m", dest="mass", type=float, help="Hidden photon mass" -) +parser.add_argument("--m", dest="mass", type=float, help="Hidden photon mass") args = parser.parse_args() if mass == 0: - print("Hidden photon mass not specified!!") - print("Specify with argument --m") - quit() + print("Hidden photon mass not specified!!") + print("Specify with argument --m") + quit() rmlfile = "fluxes.rml" if args.rmlfile != None: diff --git a/src/TRestAxionSolarHiddenPhotonFlux.cxx b/src/TRestAxionSolarHiddenPhotonFlux.cxx index 15cd0b65..6acf83c7 100644 --- a/src/TRestAxionSolarHiddenPhotonFlux.cxx +++ b/src/TRestAxionSolarHiddenPhotonFlux.cxx @@ -449,8 +449,9 @@ Double_t TRestAxionSolarHiddenPhotonFlux::IntegrateFluxInRange(TVector2 eRange) /// \brief It returns a random solar radius position and energy according to the /// flux distributions defined inside the solar tables loaded in the class /// -std::pair TRestAxionSolarHiddenPhotonFlux::GetRandomEnergyAndRadius(TVector2 eRange, Double_t HPmass) { - LoadTables(HPmass); // load tables with specified hidden photon mass +std::pair TRestAxionSolarHiddenPhotonFlux::GetRandomEnergyAndRadius(TVector2 eRange, + Double_t HPmass) { + LoadTables(HPmass); // load tables with specified hidden photon mass std::pair result = {0, 0}; if (!AreTablesLoaded()) return result; Double_t rnd = fRandom->Rndm(); From f81afa57a67d04757d7021d6e7f9c94affe8629d Mon Sep 17 00:00:00 2001 From: Tomas OShea Date: Tue, 5 Sep 2023 07:35:35 +0100 Subject: [PATCH 13/48] fixed args error --- pipeline/metadata/solarFlux/solarPlotHiddenPhoton.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pipeline/metadata/solarFlux/solarPlotHiddenPhoton.py b/pipeline/metadata/solarFlux/solarPlotHiddenPhoton.py index e80f742d..ecf4bcb6 100755 --- a/pipeline/metadata/solarFlux/solarPlotHiddenPhoton.py +++ b/pipeline/metadata/solarFlux/solarPlotHiddenPhoton.py @@ -47,7 +47,9 @@ parser.add_argument("--m", dest="mass", type=float, help="Hidden photon mass") args = parser.parse_args() -if mass == 0: +if args.mass != None: + mass = args.mass +else: print("Hidden photon mass not specified!!") print("Specify with argument --m") quit() From a81dcb44699525a760283b2e547bfd44efd071d9 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 5 Sep 2023 06:59:21 +0000 Subject: [PATCH 14/48] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- pipeline/metadata/solarFlux/solarPlotHiddenPhoton.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pipeline/metadata/solarFlux/solarPlotHiddenPhoton.py b/pipeline/metadata/solarFlux/solarPlotHiddenPhoton.py index ecf4bcb6..88ceca53 100755 --- a/pipeline/metadata/solarFlux/solarPlotHiddenPhoton.py +++ b/pipeline/metadata/solarFlux/solarPlotHiddenPhoton.py @@ -48,7 +48,7 @@ args = parser.parse_args() if args.mass != None: - mass = args.mass + mass = args.mass else: print("Hidden photon mass not specified!!") print("Specify with argument --m") From fdedb14c7c101defac90e33c3912f6675c475126 Mon Sep 17 00:00:00 2001 From: Tomas OShea Date: Wed, 6 Sep 2023 12:02:04 +0100 Subject: [PATCH 15/48] fixing bugs --- inc/TRestAxionSolarFlux.h | 2 +- inc/TRestAxionSolarHiddenPhotonFlux.h | 14 ++++++++------ inc/TRestAxionSolarQCDFlux.h | 2 +- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/inc/TRestAxionSolarFlux.h b/inc/TRestAxionSolarFlux.h index e52656a1..1d068863 100644 --- a/inc/TRestAxionSolarFlux.h +++ b/inc/TRestAxionSolarFlux.h @@ -58,7 +58,7 @@ class TRestAxionSolarFlux : public TRestMetadata { TRestAxionSolarFlux(const char* cfgFileName, std::string name = ""); /// It defines how to read the solar tables at the inhereted class - virtual Bool_t LoadTables() = 0; + virtual Bool_t LoadTables(Double_t mass = 0) = 0; public: /// It is required in order to load solar flux tables into memory diff --git a/inc/TRestAxionSolarHiddenPhotonFlux.h b/inc/TRestAxionSolarHiddenPhotonFlux.h index 2b6e51fb..2cc4821b 100644 --- a/inc/TRestAxionSolarHiddenPhotonFlux.h +++ b/inc/TRestAxionSolarHiddenPhotonFlux.h @@ -45,16 +45,18 @@ class TRestAxionSolarHiddenPhotonFlux : public TRestAxionSolarFlux { std::vector fFluxTable; //! /// The tabulated resonance width TH1F(200,0,20)keV in eV2 versus solar radius - std::vector fWidthTable; //! + std::vector fWGammaTable; //! /// The solar plasma frequency vector in eV versus solar radius - std::vector fPlasmaFreqTable; //! + std::vector fWpTable; //! /// The total solar flux TH1F(200,0,20)keV in cm-2 s-1 keV-1 versus solar radius std::vector fFullFluxTable; //! /// Accumulative integrated solar flux for each solar ring for continuum spectrum (renormalized to unity) std::vector fFluxTableIntegrals; //! + + std::vector fTotalContinuumFlux; //! /// A pointer to the continuum spectrum histogram TH1F* fContinuumHist = nullptr; //! @@ -78,19 +80,19 @@ class TRestAxionSolarHiddenPhotonFlux : public TRestAxionSolarFlux { Bool_t isPlasmaFreqLoaded() { return fWpTable.size() > 0; } /// It returns the integrated flux at earth in cm-2 s-1 for the given energy range - Double_t IntegrateFluxInRange(TVector2 eRange = TVector2(-1, -1)) override; + Double_t IntegrateFluxInRange(TVector2 eRange = TVector2(-1, -1), Double_t mass = 0) override; /// It defines how to generate Monte Carlo energy and radius values to reproduce the flux - std::pair GetRandomEnergyAndRadius(TVector2 eRange = TVector2(-1, -1)) override; + std::pair GetRandomEnergyAndRadius(TVector2 eRange = TVector2(-1, -1), Double_t mass = 0) override; /// It defines how to read the solar tables at the inhereted class for a given mass in eV Bool_t LoadTables(Double_t mass) override; /// It returns the total integrated flux at earth in cm-2 s-1 - Double_t GetTotalFlux() override { return fTotalContinuumFlux; } + Double_t GetTotalFlux(Double_t mass = 0) override { return fTotalContinuumFlux; } /// It returns an energy integrated spectrum in cm-2 s-1 keV-1 - TH1F* GetEnergySpectrum() override { return GetTotalSpectrum(); } + TH1F* GetEnergySpectrum(Double_t m = 0) override { return GetTotalSpectrum(); } TH1F* GetContinuumSpectrum(); TH1F* GetTotalSpectrum(); diff --git a/inc/TRestAxionSolarQCDFlux.h b/inc/TRestAxionSolarQCDFlux.h index 373eab33..240fd395 100644 --- a/inc/TRestAxionSolarQCDFlux.h +++ b/inc/TRestAxionSolarQCDFlux.h @@ -91,7 +91,7 @@ class TRestAxionSolarQCDFlux : public TRestAxionSolarFlux { Double_t mass = 0) override; /// It defines how to read the solar tables at the inhereted class - Bool_t LoadTables() override; + Bool_t LoadTables(Double_t mass = 0) override; /// It returns the total integrated flux at earth in cm-2 s-1 Double_t GetTotalFlux(Double_t mass = 0) override { From 98136de1cba4aa97c220f246a6058ba5b8543039 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 6 Sep 2023 11:03:19 +0000 Subject: [PATCH 16/48] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- inc/TRestAxionSolarHiddenPhotonFlux.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/inc/TRestAxionSolarHiddenPhotonFlux.h b/inc/TRestAxionSolarHiddenPhotonFlux.h index 2cc4821b..eb1c18ea 100644 --- a/inc/TRestAxionSolarHiddenPhotonFlux.h +++ b/inc/TRestAxionSolarHiddenPhotonFlux.h @@ -55,7 +55,7 @@ class TRestAxionSolarHiddenPhotonFlux : public TRestAxionSolarFlux { /// Accumulative integrated solar flux for each solar ring for continuum spectrum (renormalized to unity) std::vector fFluxTableIntegrals; //! - + std::vector fTotalContinuumFlux; //! /// A pointer to the continuum spectrum histogram @@ -83,7 +83,8 @@ class TRestAxionSolarHiddenPhotonFlux : public TRestAxionSolarFlux { Double_t IntegrateFluxInRange(TVector2 eRange = TVector2(-1, -1), Double_t mass = 0) override; /// It defines how to generate Monte Carlo energy and radius values to reproduce the flux - std::pair GetRandomEnergyAndRadius(TVector2 eRange = TVector2(-1, -1), Double_t mass = 0) override; + std::pair GetRandomEnergyAndRadius(TVector2 eRange = TVector2(-1, -1), + Double_t mass = 0) override; /// It defines how to read the solar tables at the inhereted class for a given mass in eV Bool_t LoadTables(Double_t mass) override; From c0758b2cdd14c51582b7021905600613bc7fb947 Mon Sep 17 00:00:00 2001 From: Tomas OShea Date: Wed, 6 Sep 2023 12:12:50 +0100 Subject: [PATCH 17/48] fixing bugs again --- inc/TRestAxionSolarHiddenPhotonFlux.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/inc/TRestAxionSolarHiddenPhotonFlux.h b/inc/TRestAxionSolarHiddenPhotonFlux.h index eb1c18ea..5eaf7a9e 100644 --- a/inc/TRestAxionSolarHiddenPhotonFlux.h +++ b/inc/TRestAxionSolarHiddenPhotonFlux.h @@ -56,7 +56,8 @@ class TRestAxionSolarHiddenPhotonFlux : public TRestAxionSolarFlux { /// Accumulative integrated solar flux for each solar ring for continuum spectrum (renormalized to unity) std::vector fFluxTableIntegrals; //! - std::vector fTotalContinuumFlux; //! + /// Total solar flux for monochromatic contributions + Double_t fTotalContinuumFlux = 0; //! /// A pointer to the continuum spectrum histogram TH1F* fContinuumHist = nullptr; //! From 0a1f729aca99ce9ad4499d6d8a93465ff7e034ee Mon Sep 17 00:00:00 2001 From: Tomas OShea Date: Wed, 6 Sep 2023 12:44:04 +0100 Subject: [PATCH 18/48] fixing bugs again --- inc/TRestAxionSolarHiddenPhotonFlux.h | 8 +++++++- src/TRestAxionSolarHiddenPhotonFlux.cxx | 10 +--------- src/TRestAxionSolarQCDFlux.cxx | 2 +- 3 files changed, 9 insertions(+), 11 deletions(-) diff --git a/inc/TRestAxionSolarHiddenPhotonFlux.h b/inc/TRestAxionSolarHiddenPhotonFlux.h index 5eaf7a9e..8d8cec56 100644 --- a/inc/TRestAxionSolarHiddenPhotonFlux.h +++ b/inc/TRestAxionSolarHiddenPhotonFlux.h @@ -89,7 +89,13 @@ class TRestAxionSolarHiddenPhotonFlux : public TRestAxionSolarFlux { /// It defines how to read the solar tables at the inhereted class for a given mass in eV Bool_t LoadTables(Double_t mass) override; - + + void LoadContinuumTable(); + void LoadWidthTable(); + void LoadPlasmaFreqTable(); + + // calculate solar HP flux from the 3 tables and mass + void CalculateSolarFlux(); /// It returns the total integrated flux at earth in cm-2 s-1 Double_t GetTotalFlux(Double_t mass = 0) override { return fTotalContinuumFlux; } diff --git a/src/TRestAxionSolarHiddenPhotonFlux.cxx b/src/TRestAxionSolarHiddenPhotonFlux.cxx index 6acf83c7..2b3881f1 100644 --- a/src/TRestAxionSolarHiddenPhotonFlux.cxx +++ b/src/TRestAxionSolarHiddenPhotonFlux.cxx @@ -428,7 +428,7 @@ void TRestAxionSolarHiddenPhotonFlux::IntegrateSolarFluxes() { /////////////////////////////////////////////// /// \brief It returns the integrated flux at earth in cm-2 s-1 for the given energy range /// -Double_t TRestAxionSolarHiddenPhotonFlux::IntegrateFluxInRange(TVector2 eRange) { +Double_t TRestAxionSolarHiddenPhotonFlux::IntegrateFluxInRange(TVector2 eRange, Double_t mass) { if (eRange.X() == -1 && eRange.Y() == -1) { if (GetTotalFlux() == 0) IntegrateSolarFluxes(); return GetTotalFlux(); @@ -455,8 +455,6 @@ std::pair TRestAxionSolarHiddenPhotonFlux::GetRandomEnergyAn std::pair result = {0, 0}; if (!AreTablesLoaded()) return result; Double_t rnd = fRandom->Rndm(); - if (fRandom->Rndm() > fFluxRatio) { - // Continuum for (unsigned int r = 0; r < fFluxTableIntegrals.size(); r++) { if (rnd < fFluxTableIntegrals[r]) { Double_t energy = fFluxTable[r]->GetRandom(); @@ -466,7 +464,6 @@ std::pair TRestAxionSolarHiddenPhotonFlux::GetRandomEnergyAn Double_t radius = ((Double_t)r + fRandom->Rndm()) * 0.01; std::pair p = {energy, radius}; return p; - } } } return result; @@ -506,12 +503,7 @@ void TRestAxionSolarHiddenPhotonFlux::PrintIntegratedRingFlux() { void TRestAxionSolarHiddenPhotonFlux::PrintMetadata() { TRestAxionSolarFlux::PrintMetadata(); - if (fFluxDataFile != "") - RESTMetadata << " - Solar axion flux datafile (continuum) : " << fFluxDataFile << RESTendl; - if (fFluxSptFile != "") - RESTMetadata << " - Solar axion flux datafile (monochromatic) : " << fFluxSptFile << RESTendl; RESTMetadata << "-------" << RESTendl; - RESTMetadata << " - Total monochromatic flux : " << fTotalMonochromaticFlux << " cm-2 s-1" << RESTendl; RESTMetadata << " - Total continuum flux : " << fTotalContinuumFlux << " cm-2 s-1" << RESTendl; RESTMetadata << "++++++++++++++++++" << RESTendl; diff --git a/src/TRestAxionSolarQCDFlux.cxx b/src/TRestAxionSolarQCDFlux.cxx index 5cdd2d46..c64969df 100644 --- a/src/TRestAxionSolarQCDFlux.cxx +++ b/src/TRestAxionSolarQCDFlux.cxx @@ -249,7 +249,7 @@ TRestAxionSolarQCDFlux::~TRestAxionSolarQCDFlux() {} /// \brief It will load the tables in memory by using the filename information provided /// inside the metadata members. /// -Bool_t TRestAxionSolarQCDFlux::LoadTables() { +Bool_t TRestAxionSolarQCDFlux::LoadTables(Double_t mass) { if (fFluxDataFile == "" && fFluxSptFile == "") return false; if (TRestTools::GetFileNameExtension(fFluxDataFile) == "flux") { From 1b71f052b821f8d1eccf112f1e073943b71b11ed Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 6 Sep 2023 11:44:55 +0000 Subject: [PATCH 19/48] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- inc/TRestAxionSolarHiddenPhotonFlux.h | 4 ++-- src/TRestAxionSolarHiddenPhotonFlux.cxx | 18 +++++++++--------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/inc/TRestAxionSolarHiddenPhotonFlux.h b/inc/TRestAxionSolarHiddenPhotonFlux.h index 8d8cec56..548f914a 100644 --- a/inc/TRestAxionSolarHiddenPhotonFlux.h +++ b/inc/TRestAxionSolarHiddenPhotonFlux.h @@ -89,11 +89,11 @@ class TRestAxionSolarHiddenPhotonFlux : public TRestAxionSolarFlux { /// It defines how to read the solar tables at the inhereted class for a given mass in eV Bool_t LoadTables(Double_t mass) override; - + void LoadContinuumTable(); void LoadWidthTable(); void LoadPlasmaFreqTable(); - + // calculate solar HP flux from the 3 tables and mass void CalculateSolarFlux(); /// It returns the total integrated flux at earth in cm-2 s-1 diff --git a/src/TRestAxionSolarHiddenPhotonFlux.cxx b/src/TRestAxionSolarHiddenPhotonFlux.cxx index 2b3881f1..3520095e 100644 --- a/src/TRestAxionSolarHiddenPhotonFlux.cxx +++ b/src/TRestAxionSolarHiddenPhotonFlux.cxx @@ -455,15 +455,15 @@ std::pair TRestAxionSolarHiddenPhotonFlux::GetRandomEnergyAn std::pair result = {0, 0}; if (!AreTablesLoaded()) return result; Double_t rnd = fRandom->Rndm(); - for (unsigned int r = 0; r < fFluxTableIntegrals.size(); r++) { - if (rnd < fFluxTableIntegrals[r]) { - Double_t energy = fFluxTable[r]->GetRandom(); - if (eRange.X() != -1 && eRange.Y() != -1) { - if (energy < eRange.X() || energy > eRange.Y()) return GetRandomEnergyAndRadius(eRange); - } - Double_t radius = ((Double_t)r + fRandom->Rndm()) * 0.01; - std::pair p = {energy, radius}; - return p; + for (unsigned int r = 0; r < fFluxTableIntegrals.size(); r++) { + if (rnd < fFluxTableIntegrals[r]) { + Double_t energy = fFluxTable[r]->GetRandom(); + if (eRange.X() != -1 && eRange.Y() != -1) { + if (energy < eRange.X() || energy > eRange.Y()) return GetRandomEnergyAndRadius(eRange); + } + Double_t radius = ((Double_t)r + fRandom->Rndm()) * 0.01; + std::pair p = {energy, radius}; + return p; } } return result; From 3712ce27fd09c74770d4fbf276aaed4c3625f836 Mon Sep 17 00:00:00 2001 From: Tomas OShea Date: Wed, 6 Sep 2023 12:58:14 +0100 Subject: [PATCH 20/48] fixing bugs pt.4 --- inc/TRestAxionSolarHiddenPhotonFlux.h | 11 +++++++---- src/TRestAxionSolarHiddenPhotonFlux.cxx | 13 +++++++------ 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/inc/TRestAxionSolarHiddenPhotonFlux.h b/inc/TRestAxionSolarHiddenPhotonFlux.h index 548f914a..be3216ad 100644 --- a/inc/TRestAxionSolarHiddenPhotonFlux.h +++ b/inc/TRestAxionSolarHiddenPhotonFlux.h @@ -43,12 +43,15 @@ class TRestAxionSolarHiddenPhotonFlux : public TRestAxionSolarFlux { /// The tabulated solar flux continuum spectra TH1F(200,0,20)keV in cm-2 s-1 keV-1 versus solar radius std::vector fFluxTable; //! + + /// The tabulated solar flux continuum spectra TH1F(200,0,20)keV in cm-2 s-1 keV-1 versus solar radius + std::vector fContinuumTable; //! /// The tabulated resonance width TH1F(200,0,20)keV in eV2 versus solar radius - std::vector fWGammaTable; //! + std::vector fWidthTable; //! /// The solar plasma frequency vector in eV versus solar radius - std::vector fWpTable; //! + std::vector fPlasmaFreqTable; //! /// The total solar flux TH1F(200,0,20)keV in cm-2 s-1 keV-1 versus solar radius std::vector fFullFluxTable; //! @@ -75,10 +78,10 @@ class TRestAxionSolarHiddenPhotonFlux : public TRestAxionSolarFlux { Bool_t isSolarTableLoaded() { return fFluxTable.size() > 0; } /// It returns true if width table was loaded - Bool_t isWidthTableLoaded() { return fWGammaTable.size() > 0; } + Bool_t isWidthTableLoaded() { return fWidthTable.size() > 0; } /// It returns true if plasma frequency table was loaded - Bool_t isPlasmaFreqLoaded() { return fWpTable.size() > 0; } + Bool_t isPlasmaFreqLoaded() { return fPlasmaFreqTable.size() > 0; } /// It returns the integrated flux at earth in cm-2 s-1 for the given energy range Double_t IntegrateFluxInRange(TVector2 eRange = TVector2(-1, -1), Double_t mass = 0) override; diff --git a/src/TRestAxionSolarHiddenPhotonFlux.cxx b/src/TRestAxionSolarHiddenPhotonFlux.cxx index 3520095e..0a5ffdfc 100644 --- a/src/TRestAxionSolarHiddenPhotonFlux.cxx +++ b/src/TRestAxionSolarHiddenPhotonFlux.cxx @@ -323,20 +323,21 @@ void TRestAxionSolarHiddenPhotonFlux::LoadPlasmaFreqTable() { /// and the hidden photon mass for chi=1. /// void TRestAxionSolarHiddenPhotonFlux::CalculateSolarFlux() { - if (fMass == 0) { + if (GetMass() == 0) { RESTError << "CalculateSolarFlux. The hidden photon mass is set to zero!" << RESTendl; return; } - + Double_t mass = GetMass() for (unsigned int n = 0; n < fluxTable.size(); n++) { // m4 * chi2 * wG * flux / ( (m2 - wp2)^2 + (w G)^2 ) - std::vector mass2Vector(200, pow(fMass, 2)); + std::vector mass2Vector(200, pow(mass, 2)); float wp = fPlasmaFreqTable[n].GetBinContent(1); std::vector wp2Vector(200, pow(wp, 2)); - TH1F* hMass = new TH1D("hMass", "hMass", 200, 0, 20) TH1F* hWp = - new TH1D("hWp", "hWp", 200, 0, 20) TH1F* hWg2 = (TH1F*)fWidthTable[n]->Clone(); + TH1F* hMass = new TH1D("hMass", "hMass", 200, 0, 20); + TH1F* hWp = new TH1D("hWp", "hWp", 200, 0, 20); + TH1F* hWg2 = (TH1F*)fWidthTable[n]->Clone(); hMass->FillN(200, massVector); // m^2 hist hWp->FillN(200, wpVector); // wp^2 hist @@ -348,7 +349,7 @@ void TRestAxionSolarHiddenPhotonFlux::CalculateSolarFlux() { TH1F* h = fWidthTable[n] * fContinuumTable[n]; h->Divide(hMass); - h->Scale(pow(fMass, 4)); + h->Scale(pow(mass, 4)); fFluxTable.push_back(h); } From b261cc0cfc6d8e98daf94cea7fec5ab824d7845e Mon Sep 17 00:00:00 2001 From: Tomas OShea Date: Wed, 6 Sep 2023 13:08:43 +0100 Subject: [PATCH 21/48] fixing bugs pt.5 --- src/TRestAxionSolarHiddenPhotonFlux.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/TRestAxionSolarHiddenPhotonFlux.cxx b/src/TRestAxionSolarHiddenPhotonFlux.cxx index 0a5ffdfc..ed379a51 100644 --- a/src/TRestAxionSolarHiddenPhotonFlux.cxx +++ b/src/TRestAxionSolarHiddenPhotonFlux.cxx @@ -327,7 +327,7 @@ void TRestAxionSolarHiddenPhotonFlux::CalculateSolarFlux() { RESTError << "CalculateSolarFlux. The hidden photon mass is set to zero!" << RESTendl; return; } - Double_t mass = GetMass() + Double_t mass = GetMass(); for (unsigned int n = 0; n < fluxTable.size(); n++) { // m4 * chi2 * wG * flux / ( (m2 - wp2)^2 + (w G)^2 ) From 74e04fbc6c8b356a1cb035ca76c150e724eb2c20 Mon Sep 17 00:00:00 2001 From: Tomas OShea Date: Wed, 6 Sep 2023 13:16:11 +0100 Subject: [PATCH 22/48] fixing bugs pt.6 --- src/TRestAxionSolarHiddenPhotonFlux.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/TRestAxionSolarHiddenPhotonFlux.cxx b/src/TRestAxionSolarHiddenPhotonFlux.cxx index ed379a51..7b04589c 100644 --- a/src/TRestAxionSolarHiddenPhotonFlux.cxx +++ b/src/TRestAxionSolarHiddenPhotonFlux.cxx @@ -328,7 +328,7 @@ void TRestAxionSolarHiddenPhotonFlux::CalculateSolarFlux() { return; } Double_t mass = GetMass(); - for (unsigned int n = 0; n < fluxTable.size(); n++) { + for (unsigned int n = 0; n < fContinuumTable.size(); n++) { // m4 * chi2 * wG * flux / ( (m2 - wp2)^2 + (w G)^2 ) std::vector mass2Vector(200, pow(mass, 2)); From 3871b57b210903373f70e9381cf4664732854890 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 6 Sep 2023 12:16:40 +0000 Subject: [PATCH 23/48] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- inc/TRestAxionSolarHiddenPhotonFlux.h | 2 +- src/TRestAxionSolarHiddenPhotonFlux.cxx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/inc/TRestAxionSolarHiddenPhotonFlux.h b/inc/TRestAxionSolarHiddenPhotonFlux.h index be3216ad..502983af 100644 --- a/inc/TRestAxionSolarHiddenPhotonFlux.h +++ b/inc/TRestAxionSolarHiddenPhotonFlux.h @@ -43,7 +43,7 @@ class TRestAxionSolarHiddenPhotonFlux : public TRestAxionSolarFlux { /// The tabulated solar flux continuum spectra TH1F(200,0,20)keV in cm-2 s-1 keV-1 versus solar radius std::vector fFluxTable; //! - + /// The tabulated solar flux continuum spectra TH1F(200,0,20)keV in cm-2 s-1 keV-1 versus solar radius std::vector fContinuumTable; //! diff --git a/src/TRestAxionSolarHiddenPhotonFlux.cxx b/src/TRestAxionSolarHiddenPhotonFlux.cxx index 7b04589c..5fee2462 100644 --- a/src/TRestAxionSolarHiddenPhotonFlux.cxx +++ b/src/TRestAxionSolarHiddenPhotonFlux.cxx @@ -327,7 +327,7 @@ void TRestAxionSolarHiddenPhotonFlux::CalculateSolarFlux() { RESTError << "CalculateSolarFlux. The hidden photon mass is set to zero!" << RESTendl; return; } - Double_t mass = GetMass(); + Double_t mass = GetMass(); for (unsigned int n = 0; n < fContinuumTable.size(); n++) { // m4 * chi2 * wG * flux / ( (m2 - wp2)^2 + (w G)^2 ) From 1abf76653ab8e16a5089d2e7def12257b05178c1 Mon Sep 17 00:00:00 2001 From: Tomas OShea Date: Thu, 7 Sep 2023 11:25:58 +0200 Subject: [PATCH 24/48] fixed bugs, now compiles --- inc/TRestAxionSolarHiddenPhotonFlux.h | 6 +-- src/TRestAxionSolarHiddenPhotonFlux.cxx | 63 +++++++++++++++++++++---- 2 files changed, 56 insertions(+), 13 deletions(-) diff --git a/inc/TRestAxionSolarHiddenPhotonFlux.h b/inc/TRestAxionSolarHiddenPhotonFlux.h index 502983af..05dbc4eb 100644 --- a/inc/TRestAxionSolarHiddenPhotonFlux.h +++ b/inc/TRestAxionSolarHiddenPhotonFlux.h @@ -43,7 +43,7 @@ class TRestAxionSolarHiddenPhotonFlux : public TRestAxionSolarFlux { /// The tabulated solar flux continuum spectra TH1F(200,0,20)keV in cm-2 s-1 keV-1 versus solar radius std::vector fFluxTable; //! - + /// The tabulated solar flux continuum spectra TH1F(200,0,20)keV in cm-2 s-1 keV-1 versus solar radius std::vector fContinuumTable; //! @@ -92,11 +92,11 @@ class TRestAxionSolarHiddenPhotonFlux : public TRestAxionSolarFlux { /// It defines how to read the solar tables at the inhereted class for a given mass in eV Bool_t LoadTables(Double_t mass) override; - + void LoadContinuumTable(); void LoadWidthTable(); void LoadPlasmaFreqTable(); - + // calculate solar HP flux from the 3 tables and mass void CalculateSolarFlux(); /// It returns the total integrated flux at earth in cm-2 s-1 diff --git a/src/TRestAxionSolarHiddenPhotonFlux.cxx b/src/TRestAxionSolarHiddenPhotonFlux.cxx index 5fee2462..7984838f 100644 --- a/src/TRestAxionSolarHiddenPhotonFlux.cxx +++ b/src/TRestAxionSolarHiddenPhotonFlux.cxx @@ -331,23 +331,27 @@ void TRestAxionSolarHiddenPhotonFlux::CalculateSolarFlux() { for (unsigned int n = 0; n < fContinuumTable.size(); n++) { // m4 * chi2 * wG * flux / ( (m2 - wp2)^2 + (w G)^2 ) - std::vector mass2Vector(200, pow(mass, 2)); - float wp = fPlasmaFreqTable[n].GetBinContent(1); - std::vector wp2Vector(200, pow(wp, 2)); + vector mass2Vector(200, pow(mass, 2)); + double wp = fPlasmaFreqTable[n]->GetBinContent(1); + vector wp2Vector(200, pow(wp, 2)); + vector weights(200, 1); - TH1F* hMass = new TH1D("hMass", "hMass", 200, 0, 20); - TH1F* hWp = new TH1D("hWp", "hWp", 200, 0, 20); + TH1F* hMass = new TH1F("hMass", "hMass", 200, 0, 20); + TH1F* hWp = new TH1F("hWp", "hWp", 200, 0, 20); TH1F* hWg2 = (TH1F*)fWidthTable[n]->Clone(); + hWg2->Multiply(hWg2); // (w G)^2 - hMass->FillN(200, massVector); // m^2 hist - hWp->FillN(200, wpVector); // wp^2 hist - TH1F* hWg2 = fWidthTable[n] * fWidthTable[n]; // (w G)^2 + //hMass->FillN(200, mass2Vector); // m^2 hist + hMass->FillN(200, mass2Vector.data(), weights.data()); // m^2 hist + //hWp->FillN(200, wp2Vector); // wp^2 hist + hWp->FillN(200, wp2Vector.data(), weights.data()); // wp^2 hist hMass->Add(hWp, -1); // (m2 - wp2) hMass->Multiply(hMass); // (m2 - wp2)^2 - hmass->Add(hWg2); // (m2 - wp2)^2 + (w G)^2 + hMass->Add(hWg2); // (m2 - wp2)^2 + (w G)^2 - TH1F* h = fWidthTable[n] * fContinuumTable[n]; + TH1F* h = (TH1F*)fWidthTable[n]->Clone(); + h->Multiply(fContinuumTable[n]); h->Divide(hMass); h->Scale(pow(mass, 4)); @@ -544,3 +548,42 @@ void TRestAxionSolarHiddenPhotonFlux::ExportTables(Bool_t ascii) { TRestTools::ExportASCIITable(path + "/" + rootFilename + ".dat", table); } } + +/////////////////////////////////////////////// +/// \brief It draws the contents of a .flux file. This method just receives the +/// +TCanvas* TRestAxionSolarHiddenPhotonFlux::DrawSolarFlux() { + if (fCanvas != nullptr) { + delete fCanvas; + fCanvas = nullptr; + } + fCanvas = new TCanvas("canv", "This is the canvas title", 1200, 500); + fCanvas->Draw(); + + TPad* pad1 = new TPad("pad1", "This is pad1", 0.01, 0.02, 0.99, 0.97); + pad1->Divide(2, 1); + pad1->Draw(); + + pad1->cd(1); + pad1->cd(1)->SetLogy(); + pad1->cd(1)->SetRightMargin(0.09); + pad1->cd(1)->SetLeftMargin(0.15); + pad1->cd(1)->SetBottomMargin(0.15); + + TH1F* ht = GetTotalSpectrum(); + ht->SetLineColor(kBlack); + ht->SetFillStyle(4050); + ht->SetFillColor(kBlue - 10); + + ht->Draw("hist"); + + pad1->cd(2); + pad1->cd(2)->SetRightMargin(0.09); + pad1->cd(2)->SetLeftMargin(0.15); + pad1->cd(2)->SetBottomMargin(0.15); + + ht->Draw("hist"); + + return fCanvas; +} + From 18850772174817ff83c7f1e55bf4fe52937b33b4 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 7 Sep 2023 09:26:51 +0000 Subject: [PATCH 25/48] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- inc/TRestAxionSolarHiddenPhotonFlux.h | 6 +++--- src/TRestAxionSolarHiddenPhotonFlux.cxx | 11 +++++------ 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/inc/TRestAxionSolarHiddenPhotonFlux.h b/inc/TRestAxionSolarHiddenPhotonFlux.h index 05dbc4eb..502983af 100644 --- a/inc/TRestAxionSolarHiddenPhotonFlux.h +++ b/inc/TRestAxionSolarHiddenPhotonFlux.h @@ -43,7 +43,7 @@ class TRestAxionSolarHiddenPhotonFlux : public TRestAxionSolarFlux { /// The tabulated solar flux continuum spectra TH1F(200,0,20)keV in cm-2 s-1 keV-1 versus solar radius std::vector fFluxTable; //! - + /// The tabulated solar flux continuum spectra TH1F(200,0,20)keV in cm-2 s-1 keV-1 versus solar radius std::vector fContinuumTable; //! @@ -92,11 +92,11 @@ class TRestAxionSolarHiddenPhotonFlux : public TRestAxionSolarFlux { /// It defines how to read the solar tables at the inhereted class for a given mass in eV Bool_t LoadTables(Double_t mass) override; - + void LoadContinuumTable(); void LoadWidthTable(); void LoadPlasmaFreqTable(); - + // calculate solar HP flux from the 3 tables and mass void CalculateSolarFlux(); /// It returns the total integrated flux at earth in cm-2 s-1 diff --git a/src/TRestAxionSolarHiddenPhotonFlux.cxx b/src/TRestAxionSolarHiddenPhotonFlux.cxx index 7984838f..fe285b04 100644 --- a/src/TRestAxionSolarHiddenPhotonFlux.cxx +++ b/src/TRestAxionSolarHiddenPhotonFlux.cxx @@ -339,12 +339,12 @@ void TRestAxionSolarHiddenPhotonFlux::CalculateSolarFlux() { TH1F* hMass = new TH1F("hMass", "hMass", 200, 0, 20); TH1F* hWp = new TH1F("hWp", "hWp", 200, 0, 20); TH1F* hWg2 = (TH1F*)fWidthTable[n]->Clone(); - hWg2->Multiply(hWg2); // (w G)^2 + hWg2->Multiply(hWg2); // (w G)^2 - //hMass->FillN(200, mass2Vector); // m^2 hist - hMass->FillN(200, mass2Vector.data(), weights.data()); // m^2 hist - //hWp->FillN(200, wp2Vector); // wp^2 hist - hWp->FillN(200, wp2Vector.data(), weights.data()); // wp^2 hist + // hMass->FillN(200, mass2Vector); // m^2 hist + hMass->FillN(200, mass2Vector.data(), weights.data()); // m^2 hist + // hWp->FillN(200, wp2Vector); // wp^2 hist + hWp->FillN(200, wp2Vector.data(), weights.data()); // wp^2 hist hMass->Add(hWp, -1); // (m2 - wp2) hMass->Multiply(hMass); // (m2 - wp2)^2 @@ -586,4 +586,3 @@ TCanvas* TRestAxionSolarHiddenPhotonFlux::DrawSolarFlux() { return fCanvas; } - From b4984f9648cc0442c94efae675fb893358af9436 Mon Sep 17 00:00:00 2001 From: tomasoshea Date: Fri, 8 Sep 2023 15:54:37 +0200 Subject: [PATCH 26/48] changed how mass is set for hidden photon --- flux.png | Bin 0 -> 19725 bytes .../solarFlux/solarPlotHiddenPhoton.py | 27 ++++++------------ 2 files changed, 9 insertions(+), 18 deletions(-) create mode 100644 flux.png diff --git a/flux.png b/flux.png new file mode 100644 index 0000000000000000000000000000000000000000..26f7d1e50d09175a549d87940cce0bf89e8034df GIT binary patch literal 19725 zcmd43XIN8fyDdBc1w{cHf^-)k(m^RoR|KR<4LyL;ga`;2suY)EL5j2h7LX2+gdzb6 zRX|!0q=X(&>0NqHz9+igz2A55Kj*r>ALrnuV3;%WDR&w7xW|(hhPSks7&#ar2x8K{ zdBYfj=(r$=_WcoB@JcGj!X)@ce@9pA2KWxXcGN3FA&3vszH!ae|Lr2lu3cadK1T6* zUYz*6=;_NF5%*F!eVtQXoEMM1QftAQ(4P-#=!mSoJgVyKu4`1{XM1P4V`1rT?k&t# zj9)YJPrvf(5hs`j{LhY`JJxqf8Wt}2>8NqLf79g)rw(aEI6jF?61e1h^FX3T>Diho za?6AijNUaR?jfb;uvoMT>7X~o;GNH00(Rbt27>GrRg31S4xb{ex;b90m0sY^+A<%0qcxzU}7mgJkXzlm^+4y3s zmU5tzpGKZd3z@ebQ+P-d)?zeEqmwVcfQL*ri(`WC^=qj4dj=4!ec^}rj4v0gV{IzD zf7FNLv3~FqHy#-hGYvv_dnzSpY4^re$>VS~n&)hZJkHTewcOvV?5g}%wpYfxl|nWb zEVtrteX?&tzti!)3J*wKUS6IKSURh6u-@Y#8&Ht2`|X*^`eu18X>raZZP&DN5soK;BgE6{7dPv}kC7`sdv&}_ z*=H(J)EMQ2W%goyZakNto9aEk_lz=0NFuFPS1TjG=?Ml^dQa+P)<0Y*ZVuUR4jpk{ zQYBj1;UBavE_P?@9uwt?G>GEaub15a+j!1Fd=>q0t^1Cc)+Z%YyBB$Xr^&&ulwdO0 zus6C@gU6-?&IxZR+E#dfpn4eGReL5P664b4AW5tGr+R5N!s313YkfN zmS8MokoxdPI2%WH;*p=5YmKK3wks2JjhAg|9`3A85>`JQz=gA;xfOkX)E~}&L!A*S zP0C4J9`P3bXgs$wo#t7UM6h5{UVk+_9K1y`@84)v zC3|J}lKjRNDVheVU@Hw&#f=PVex>c^rv(zMM}LO!mAg>#6XXb&C|ZYd#D{d2UkIfd z>bz44#$)Hfdha#oe{jsAjcs1-9{lJsk4N$iq zJ^j{-)3c=yzs7EQCtBO_yjAq;7)w895p`)#z*IX}NWiF~`4l?q_1ZiRsSZOqc~k@) z*Rv>1Oy$j*!~4p@GJU;;oVz2YP`X(3{4RNKc`IoQOyg9MZOG1~W}f$a0W%Ey)b*jl zbz+`$4q9ttHT`8&>IJX)J`Av(ekf#Z>TCFL$T;WNtH*}haOW7M)fN|(wG=zbh8?9h zS0y_kaDSzlbC~K32Fe?~4656o$F`%!K6#Bd<(uS==$3nqZ4OT?k5u%8%wKltsM=p8 zbUz7M7${D%4Rjr3I5XYxE@*>jj_U(I3=a(0tA^~qwA;_9#RR>b z-uc+6^2RBp_SpyXLXqsO)nIU+c~awa$Ad)U{zAJ@Fp%1vub!j8P~ME~PXS}VB8=gkU3YC&yMAkwBgS*A29x0J zDP)kH7t%apg=C(3EDc*38XMcH+~M|nRbD}3oVL^MGBW-Ym^|r|m%8xAo7$Z>m#}$@ zAij7^d~S^wBCUeS4YxL>1ME4kb%l$MatGrBp1Lts~IBo2J8 zO@KkH*2#JaXQObpu7c@4+?h-w!JaJXcfM1c7AkT{3-(1G;C?Om!tJO72j+!-9IeWR zaUANTM_`QGYAsr;6Q*}!N$2VWG%RM}wIT4PkBZp7RnZi4yI|N;uD8lTn_zD|Ue&!g zE#zqN_xe`F?W1YijY4LjGT8|>^IHQBF|9rQwn2+6`ci?F9PP61gr<9KIH@+y*ChX; znen9XDCsvFpX)Tc*e5O$pK(@HyjtI_-v0TLd_A=BainqK{BHU)9)*C_EbHbp`OkLx zulq>Xky3`$U82(xSj){CviXmgeB)zE`W4{W|5HcJ;vG3UZ@ec6>aksp4tE14w{J zFr%f4$NMKAhhMHB4^&YOmMQPXcDT11v?UYg7n1US)okJl7t#LE2{Ycr)V^JiR^Bi* zA41*M318W%XRG1!S;h-uv9aM%G>0H5H`74&WAx~lZuy#(sNMI1Bc6za7t1InBZjb8 zM%&pgy>OLp2MknzB>sPnpG=Oy$O)AIXgy9b&AZgJfIkA62@|@l=2P7;QPN8-8+No| zT`4#7O8VR|AJ9X{Ymk^zq;^klsMQ$_OO%fAPSWsGh#jX*%4xECGrg0ba#BjV`>Y_v z?SN&&z!K$T$>G4UXaPw{cn% zzFsb2R6S8qI?-7m+Z5$Q_cl^<8%~#5rf_bbGoXC^=bNW4__cPN1tJ^!fXUSO+2(E^^p^`p zzeh&<)E8tZbm8`UX;>WgX@F$cUG}U+?&ptqQzNC3@V#7%Qd1gsT!?yN`vd#Pe6$GR z5>hI$7y4?Nb|{h_0LwiC;(6urSk*OT=EpAFvE!=E4l1? zM$f>W`OB(2`LSW&e<~FO^5)gt-xuZ=f}py_bx!ntW#G{ii}ZeZ*5jsNa@MG)NhVAD z(FBIOIc`;+W1b9<3di`Pb92G(cd>XS{sp(gQm03d49U6al@!Q+i2X8SyP0IVPT)aX z$vrzPFhKr(eQgJM*QS4S!LR)%G3Dl9wr+<=Dy}oD?D@ zd6eejSJTzPH1ft-d}C7KbXpb)O(wd=|GW zW)8c_?l4i>Cdd+cG46Gvh7SS1&u-4xe$CFDvcsAkDgJ82q#v0&4d3J=V(o^_V7OmV zL)J9Uqu%cKBH?GkWkd*rNt}-cFXxKII$V3vid1AAO#!Yu`}WaY>yH(dfAwIuyrQl_;RiZ-lvP zKP_`|V1Q+x_>)tl_Q#^Ux#vt=bG=GU7fyOF?Yh@R#P1krJz6*~f zIb8{n)$*o&x*l3vR=XhBYK{G9&<%6omgl`z7`{N9yFtA2HS=%U3;AP)+00mJU-vx{ zLxwMx*rZ+ELMIm;pNRJnLYIh(<)t&N8?VI?jj!pA&qy&SCQqezWtINjH#8|lDUS3{ z#9z@jkynol;+kG(t;=h@y|EP<=uKi8`?dLIsV*TkumWu!ZF$tf!@e$$^8+efllJeI zYejR_dY29n?S7(r`O6a(%y}y35xqac1Wh;z-sRR8D2M(YRx!=j=x_dd`{F6tQzu5a z)DyEZ#0ZXN56+d>m~mjwc}4eZKXwKt|qbE-{AEd0v@hDCvU3l?~}vW!RXdT!V|gdSAOOWKgj*0-WZz-Z-Y)Ri!j;rU(KYJ02 zk9XX!K7MVKR*j8P{mE}oH?F(@xAf~?=g>576(nU`ZII6=o3DEPa_5=^%q5fGbMOM$ zZKU=b`$<1df&SNkD2RkFn^PtOBr1foPo0x0?rRb1&qytq5L5MOr@_2}RnrT~H`F@{p`K=%|*6K%f zsEL*X!m3?i<&WX+F&_rNTYNol^d%tvl6@}-&GZ~5#Ap>b+UVT$XtMP+?prrQwjR~G zKN*t^8@%eBGJ)+E<~YOlQdaSANF%khHL;DMJMnm zOlwptAndt%#Bci)G-bN)#{ns>EH01X=Kq4!vYsXzUz^I0Yfkqtqyy+65o8MoU|yyk z`XJ=?1t!~Mvv7Xrrh)3-ZiKvfjYfl*e^qH7FA-5+TdWtF%t{YI$Md%giOGpNJU+vw z5F{l{N6MjxrXsa%!>-N*FNtB0aRMG(iF!Dxx;MryG`B(gz>S6agZQzsmiF$y{D8Qp zwvll$!FcwOfOg;R*#evu!lAvMN8KUPBQ}XWj~RlV_6BW@l_>RkS)ZGh`1sgsyzYmyH?xi z%&Dx24eL(ecBDidIn z3Y`_Dc#xP3C?kc~E70_-yq{H@ob0$OEFahjy+!w1dfmK2`s?yG&Y-8l{urm*A$il( zeM>QbNWw-L&~$YLpS-pzC60uppF~4^MI~aK{XJ0f@ndSPF5bDbhgQUW_Y-r2{3?t z{PDjkUg%}R+w>U?P_)j75>n`H5uA;o?m>dntO3)q$6V2!`*>TASAWs5*E?FH*|iSa z`xCCS%AS&9h7U2zU6P2sULW6{GJ7j3!5A=rCC{OvcU~-} zNf86M>`KIas8Q1@;ot}{^>TcZGn6T}WSCtgaXmYsZzzffF75WH%nt-*+cDhzo!rnq zo(hc2jh%|Nl>J%5OwEk5v=?00(?zsT^-m@_S*A{(Lg#%9J0H9+>N}__;pt>qw(z!@ zbfqw@dy$8_ge%ecZjsSe7Q>hRW@LZq>+IH^a&^)0us!onCRjb3DdAticLr&Ga&I1b z9`Tm8wZPl^ZQI+Fxa=#}Xr*WrrZi_u#Cl{Bo5_3+@)HC-EfFMEb&q$x)7RU1PqQD! zAmRNnl+QzKGr_wqixG79nO{TzOS|Qk1y9NlZn`8ZGi7E`7G3)XK`4i#ufG42);T__ zZAiEj$E)^$SQ`5>SPy{Yx{H74WcF)YW6sHLEPrr8^1Zx_4%!neZUXkq7dX+-`j1Wu zSqt#A(DO46zv<`Xd%CRr?BM=a;P*F;K*YTn&jf=`uncuPx(c{ywdI>ebzD-0+G;)-Yl{vaRH;8~nJQcANlML*!z#hwC#lhGy^7=}IwP z=$_ErQZ2u>#@ig%H~|=JGJxl{$Km%?Wf!+RVKDDLM@*tQ2xzbs$UbNskZhW$T=J_; z*2g_ZZR?uI3(KJoeynmX2WJtcyq}Z}FDAiXTslWhWS?i$6ICB56E5`!tGzpXe6|;n zX1N(RA?{c25b5f-)>^Fe<1VQ3+OJhPpgGuf#S7dCCHKUVt`$Oe#&@^5=+yu!Q;gfG@R`ORK_~a`XV|l zWkefetRv#oYJDjQ=J0Ma44tfcL5lIxiMdosN-k2qYGqVwgl3?_z~`o^m+c-?q}AJJ zut+DjyX}~wd)%SnS85UVy?;MJ2W0%8n-JJI*OK&zGr-86$_yGFe$NuRMv`9!74!*V z(9Kwnra4;2r6*@<6i)M;0d@jJ9VVFRZK?(7orU zb-Lj!Q{B^jl!NOtxu%vLr{*hA$7VP>vUV}n<$d8qbL4(JhOj=THEC-lH^W%hQE_c1AeGSdPT+-%O>1qG zr4eNR;6b~%g4MhjAuDx*m(UWaIkzh6gvlh^)UgA^(U7(`hvy_OsxPm`X!ZXELuJdz zi7wYC9F;LkbP{Hb-4pw#hFGyZ$W0K5_^Z<=rMf50_PU z*KIB6Rfx&6ZlsZYorA+i^ubA&u)~_-rn*GEZH&ji-Y7cXJ6VE8?H-4_QTJtciF7+w z2LT$-=rE0s)S#gTE4{scB+cQednM^0{nb!H$%ELJC*C!QZ_<(*Xg=Xn+?dB8sVtDYTgyx} z0Hu;#M9j>e0h!GnJOlc9ErNC`tW^~>+Wu*`oe26(_?VCUN*B|`AcMGr2c)tOhlNvX zspkr&=Nwj*BqOdbl@dFEIpny$cCs`&qa#f5u-Uk+ewGvB_~$wpOz=gU)f)lrAll>- zF{cVdj+LDD@vwK7o7f#n`<4!A4<(b3K3uhsrucv7I}5EM0EVfO1Nc7D(%FJf%L4Y(Th9a7-G07SwzH%&uZyOvvyn~Q{G>uG|6H9 z>WTMp_fw}ms=_%Ro%fOWl(?qkqQ`nd2!Y{Bw?bS+VQ{Xmbx=QB4olHUk4_B6y5>z3 zE9S#=w6nzm2)v4ueXcBd5jzgFnS8;%eg~`leWYI-G1U#+VT=1R&u)P5d8nU9#RJLRD}+jC5l17d&?1+Aj=ah|$Ekt(K%PASyf z8I^Z~8q@eGL~tM{*Im4ena7j6Vo1Q#Jt?aztPJ0|P9;7>R!SU}5(ZR>G%7z` zy8JrZZxhj;RA>8_7T`Z1I~`Fd^enZsvOfeOK@(Q`!uk5k_n=`=^8bN0Ac1+=9{H2v zG=7(uukYp2etWjN@ufVU25MBw?p||HOq)aA#jXYdc9vcbhUgyCQ2 zsO&U0Twk}F${fpKdpZ!jsr4G==K;lOP#3<6iY(x8V3ck$g-s3(WEu1XbICuTspD!? z$w3~8$KA9$_v()+c}O&p&-5r-2wI6((XZGol>VAu%i$7SCorqc zGi+tB=0l?>@QhenMKJ&Y$J%cDMFn?El(UGN0N*E&G`s*i9dj4GxvdI@( z0Z^NoJR%hSVc0;N07fBCA%>dg+nnzicX;KH;IXU%RO>w#^B zA7d)(O!ZY9Pzf4ZY=4RGJF0F_`K768wfXWUM}98JnBV>s)w=sSJ>n%I>=E+njEw_v#E_rnvh>d- zRr%LCQtug`r$|3tnT2xP8`E`cz$)>8H8=(Y1*M=M;jY^CH5Wh3YmdM%1uaR8sSRY% zQ??hM+626G5Bb!jl5OO;cSjQ8BiD4VYIsxS@xGgA%_F87qSM%DQ*8pLVKz=8;tpvw z@{H^$*|_(b5g5%mU1evmz_0iCmLEjw|w(*(peS=p5+OJ3v zMYVtLeK+nEBb1HhCVUJ2FuZIMlG9|}A}{87(l>4RA?qS3!kv6-Xz%!{U(iH3zRx4+ z;HxJ^_bVfKm~l{A@68@;Y{tb#6lgT!K(`TtMNs_W#`s#u2c$Mh4#)D1&%8GVxOX*} zR++Zl^SAr=$iGC&(plvyx6l# z@f@!8vfXE{C*FNnOEb?w@nigCo$p9DHD5&hFiy#)--$_Ii5)hO_kY=RYogI<@B` zliop~H0_bwF^VBnCgY>nG2?srObuo~SJP6YHA7?rxEwnJQgs{DQBH3T#!hc~^4vD! zr~c8n`+Cjvun_W^(V1)HDo3G7n(PFe@18?D`#7(?_qs=g!PUCC$0|Y8TI4pOcoW8% z-cdFAV$1?t&_{~@kk-9dcJ9d{Vl89tLFG}Bw@GmE{mn8;wsSa`wYDKY@ne4M1LcZ0 z#@d|rykF}bx|-#s>dHCFZa;hwxcf9{*CBaL5+~s%;Fcwwp*hrkNS(@G{K~mZB^m6W z{Sn7W8L$>5ZX&A`7f4&pqW4rg)Hds0@!8+Vi}k(N&p-L-q_w|MC$r@BSlX7uilmsO z@T4=XUv4b@e9ex9(HC*Zc6Ue{au2*!q#O3S%6u2|^6|N6INR}=O?jJ7AO0GV`341E zk1F+v%%=@JzhMPxI!~_i#}4qFB%Z9|=v8!!CVa4Z?q0!Q$X3&V{-oDiJLLw+X5 zW^t#wWK8mX16yN;@;Jk1E+5wHHrUXQo!ti;Wv2*kbH9#%Su8huHqGY2=KZ6xU+b%1 z!CxNt7`_|wFLI?b4vf^FJnmh(CqMZrLY-%i^_jH<%RXnIj0kstuy!1=T-nw9_F`M! z!P2qvjroG)4^j{_n2Fa0ZxN=c`ic!FPLcm!sg=A3c8RBQY6*=VQQ?$7@pWwk7tb4@ z7+CS+Zl!;eUsCz2P2XAWyGiHjEWl$=fXC{@36NqoeTg4`wR@jKxTj99z8`;TiOP1h z>feZ6_5clIQ!{J-kK)iurshyFTt1P8zbx?3<1uz@Rg-V1tZSo3d60bB#_$gk_wukO z`fQZ_FL}G|r6_r~<%fgAG|w6Tj8aO*&w1+B7mgCK_%&4`UQcsqn5Yo-L&InyVAP}A zvoujQ6UFHaqOt zYASo!-{J3Fp?knD&d{Uj6pQc* zuYRQAZg? zylNVDez&Y8P&QJfn5h5Pm74z(eEz3+lz3);z9D2bDZ~}?mDm3}O@Mu*W$};!dBOlY z+R32uizd5QOJy}S=HUcCf>lizxm>-~_Sk2-15=5qy&Co+00^^q1835KmP&d3o4OYE zp`+}i4bU7FO#l4yaw(gb2#oX5VYkRMNC~-ALZ4H?u5Rp!Mp3RdkL&@ z0+z*T3_SkdPXk>|iF+DQk1Pq+0(Bt}g6)5$(QALqqLP;Y6fzUw2mjTHR-#s5l3UwV zpqn(F8=wgglf>j5UsK90`^;Ess^3_>HM;ke4ha{{?sG5P#o6uQYPVn34%7%ZSz-q| z`)kP?;e_mVLC<7-kZeJ z#_*~x*#c2$J5Xblh*8CLo+LbRV8m)(#{-iXZZ$8I>VN%go3L=0G~R3cX(^Cjs{DGy zQi_n9UKsp{6}b-&@(kS@R$WhL*}+9EgSY9&!cCruHfRb?1$}?SkhOArTdUIjqWTG) z{GjD(a~{>r0f$R1BjLIY z{?%FV>S7<{r@c;hQQ0A&Ae&qSJNO8X6_k?QUC!ED2AbEUmCKzcJw$lNn%)-67=I(&X@>mfh^ht&EMM)aXzgDF z3=aFOBTCI!2VV2AVx?{xPr=&N*6aqu+1>Q$b%7|&in@T!)EtMq1~C~DNc#WreZeq&*iQY4;?Hmld)9wB$-_EL|pa0 z(%!;Hf*jCQZUgjuRL`4@HO+x z*o)nxqp4#Ye!#;t8(70mRy>%EGj2;uZ6opk^(M9>_Ob${Y6-~dx+`;|(T#6`9vi4W zo81L%1UI{NC4rb&j|1BXbcaB0eJ(GW9*pQOi8^-bP{Q z0T3N_=PW9;yah5~J0Rf02E++ZtcX?mdG&7IcE9`^)=OQ=*Hs|nr%I&#VC^*9Pz#;`)Codu>N zoPX22bk`x8o~t&T)Kb#Udus`31(u$EC~qZ(k{`3~*{#e`-3YJh@?#>6$-B!gQ)w~o zAC>j|*`sxzlt6@{hN=1_Gp+^ijj>Izdneq?la=6?5q|+_)b~$H`u}}8AUU%{41-(B z2Ryt(WNa>3mm730p}GZjhi;h-Kp+^QvW<19G$bjw=Dfu$$S|52U7(mtECoHi-z52x zO71yyX&(^tOI<_4K`$T^5OeG4*!kt)Wo)=)^{jqj;pqL1R6$dB``76@MtgMW`j^fn zQ28XIGahF&3;=UlWY&K(bjwe*Y9X5#pxe@dX3Ag%rF46eG>{|7=*zRmGTH;c;zfrB zP_XDliP+1GmNgqhwbvWfu;Pz>Ij$m>ZsR!!vodwt_D|Rx|og)ELBp>elgq>@fA4|bCNG<++q{j_95)`$he3!O`!bg-ef;Qf1+ff^J z{ewcY=;Dt0$_eD>WH5?wy@H~7W5_~{Ha@Z-PH~(&VE%{1T`HHn_E!?QHTcQP3`1QH zWzb*-^-1zOJoaGk2;oZ@`P6UXPr-HUy$?9^(ha&E)rj`I4hvEHI56vPic|sG0}5Es ze@^w-gUDN;D%I*L#mkXl$d>^k~I1M$_}Ev%??>h919JMI&2xy&egF(J+*rqCG|^37;1 z3@+>9k7$zsw@6`vH>pV^2k2v<%=P}Uptbr*PulpQZQOas3j9Yh*{`+naHL;F7RM8f<8V zj^@cid(77oz1ItJOAO%U0nG;vXlfs&wb%NRZ2_?Lzrl#|;-sCT3&e&`QDfh&8*J!a zg*C6%!>_<)CbfG8OGcRqZg$n}PFDb-{AmVHaa570_3P|szcR^D{Dil{HXs|NNbD64 zKFbS?)-+Na#?;Lv*mGYy&ux80)@(pun8vF%tJf$Hp>I-I2F4giGeaK5h(+tyZEZ+erEY;<1%w1=N{qA#9qRw?f)1j3M zf~uZ73Hw#PsQU(&c@f%6_q2BK*47LZcv-}ciR+Nnp&E>&zlyS zGjHD3fMTu-EWm|Wm$b+K1>fXMW7hZ4QJ_je9q0*BD@2;lpi!G$xL=8sS32;i#e>YV z8u^?`1VhIL8+T7Bz0RH_`Y~Igk4?;HbH5a>8TWBwfR(eK8VoGj>lvK|7WA9Yr0GXqk;L)D5T zb5q4W2skQRtPAKgBc(mUkz3kS@#Y#hu4aj%YAVEkw6cTdAU{4Q*4J)gn=Z-O*S87Pc`x!7#@U*t+NM#jW8fg)kDN(%SE52 zIuPBeQ@D(NqH*7l7-7PC;5+S2Xy(mtX8c!7KtniFz`_th?rwgBhaQohZgn!qNCyO? z#ut{)9~ljl5Jd5Y*?s3;Nh-gm`Z=ZY?nq9P)*^_?f4`JAMe@E{{_WhKfIb#zRe>MM zvA-I#xc&Zbuqyr;h@v@&09F}Sa;?#^-8G46B8K=}-{x1~`IV!-)>XE)??z#aCHnmu4I$BCa%DP3uG z0${A~{ebxXe{DTSd4BpLV8+(nO2lD>RmOyOZgcnxMl|eC0rgF)S)u#g#H0;-^rvfG z&mNy6T)~*k39{A`qknZ9m&&Z5zp_|9wKhx^2jM@T*8}}eC=1?J7!3|R+zu#8q2f2{ zUw9I&`pvi-^hYWlmtSNI5Tj~mmsErle{*x^U+7cMKA6D-g*1TTL6%U0^wXtwQe~Y@ zx4Z=PO-HwzmcbM)8qy99VkB%r#;ao<4BB9YyR77y8=@F)fROv%kJ?nqwcTqkNfPj^ z(0wqu8`q?8sl@H^-7g@j9jS}TIc2lU(Ad7QautxoG%%`wP1&!)Fm;;qcnc(T{J%6Z zXsSl$tMBlF)?0cEu6=)JCbMThtnSxP1M@dSl+){+)q!^#A~g!{8N4k>Ym=1HrKj?v zd(RblhId@w+{nJbh33$`up|BGeC%-rw|2~XfCqUF9ff_?_kFJbPMG-KdDCM9Wr8;N ze;?V^D+2-RXBYcSYtf;9%l1?cl+yV}9rFw{bEvJzKkev$cTPRu_q&-fVxj%8;<|(CQ{{CKzB`b;P=^#P@p+)+5Asvn}K{Z<{!}BH-y~!EwuKTSdCYb zh{zDr%}&?{M^o^MSzvHbdo-?(1t>0CO%RwT0ABX}L06I8V-L5m;RMQNx*vCiJN4ws zZbe(D>&MkbPIM``dGJJOA5~S_>556ztjM@HF@LuJxT5oXTIeQAQnf$;K~_hb4#uxU z#p|auvK-LS3sVW7Q(a$+WK-d;_UMSc#W@gLSP__ca(rmKfS0zzxFM^9E)h?9+x>TL z0uT^DVf+=zu>vmy7^s`rJ&*H3JqOOWJe6Q$2}@Mkkaq=6*}TyXr0D?_^#BawcvW-0 z9rVvk-K)hHoz&eOGV53j!wjKl>{^#QNzRgPD4RP1xT^z!16OKVzJ-^XK;7RzF zU9-n6OMQBC&>J_Wz+f8cXTpvc$%xHZa2Mc?WjX~-Hz&sBbifOTC$03Vec~k0+N$| zbpXMW{`<7InmJ$_and=#494j!)@2-jk{T^!kYg>CuFJdngvaPz` z?#vPtRHEKGS;d@iC2$E=pJteBCjsgTY(pdd!tuO z^+9VLpyGkB<3)ER7fLXpq*un^Jd*skM3E!UBWzlM=n4ip%K48~4g|D&&jxRSL)F{bPtE86LEwGw7KZf1!h z&ul1lrWn&ax7<5IT1^(DE;f~+mY_?I6Ih``{WlN*iW#cE*Lzpf&Hb7!P;IK?ol&?q z3oY<~1?c-GC?1;^7LY-8x_@~)fb(k09Ptk?5s#f{WT_!Prh-2Z0%o{@jEU}d-9Srq z@juBJ2n~LM6b%G(|GNzMw+{hG=5~nutvE^ijq)q~a;-IJYnS)q!wIzqgl2Qki#z#Z zx(IipGg0Q80Us)7t|uypD2Zfq{4hF|ZQRDLoRJ;nET zKDKB9s?S7(Z*2Mv*Vh-cGvx3~1~v3?lJ2L4$xJ4$kUPk45~ORCN9N1+xL9Fm(LcZ?#Rr z=)O6{oupqw)Vj({mFoOXmRVpf6F`M)pzR1dJ*f)lcvQ;x~gnRm4Suek38h&m;mk0hx9dp_7(YQ=FP_a^L zamsfVvVFf3FbMwd_3DTQ$nNQF0MN~{N6wm^@-?{4H#3)5hWq;6l~IeNCQ z*ip=Iy60X7UNsCy4g}hiOOYiJI&W3Ac(rz=t{-f5#jk`EyT|U&;(wheIbD=`;#{%q z84Z-v>ihnKn`K{1#9El0%st-mRU!q&BCeY;8=H1jzvcFuj}W=Ocv(9RM;5?8{7@qR zq!~wTd-(~2#d%S+A0#T_2LK$>(0tkPS@+6f;qMLQRX(@OHhgwE&EsPHu01);Dv2^z zHW;Iu4LAN0t9Wn!S%2{_xbM8=g7HxFSUN&%ksYlNk`4DI2B#U{+%iSK;nQ$0s69~O z429CkSdL@y0<+se;$oxgw;D7>rqVKF_=DNg$$K-c{q3MN2l6v4{5>LP`@!%r?t3Vba73VD}iS?>*rj)!yQX;b4UH5|J&iY<8S}GZC zVkw;rWgRX@o_~KNG+HHk{q~dHyzYOHx3rFU^h8!a2d&CJPXf)sHDmh*O%!lWV_pT_%$lHxivKry@A!l8kjG1D1Gv z-ii5QWB9ovB;`1spg&OwVW#a+^e_-Ak|~9p@d76w9?8mzz+;^T-ZRRG163lnRmjv7 z*)4-4y$2r-VZ(vCeqh}8GBFPQc;WPbrh%5i_8ord@K)8_bTNXAezxC*?G8b`mM?+U z^v8s=7H(Ln0KtsHh*@p|IL~;q=$Cb`V_Ld*;zXh$5tU`j2Ado{5@!S2R54r=F7@^W zxJ6Y6;eMQAA|Yy>@|&Ra zz&C~2JU%7i*DoUX={XP=UM_)C2rBX|f~3%31V(kndoOtR!#RiOf)k2MWn#Kp48RYY zFF8!#xmCwaI6HBZSM!&fYJm#caNX&bk&UwPsH_QkE!>r~)l>7ZVEpDHzu$~R5`5lm zfZwn3v#b+IHK@9S=vXO&Ue$c)w;w;V&6J0fz%PxD`we1L-y`>m%X@fi6%@S4T*?Re zEPVgV9-$<6thZHJ+Gg6URZ=Zx;I`s|uW)FR_hzv{ZcyG_i8ZB4#MJ2EX-ahHDY$Q? zhuZA;xM$JulJNa>SM%`9)6<<@J!!kpe>s#FdG=|>d@E`8a<6?-(PQV`f!oa_k6$%l zgjN*hq~L{*;~xFE4;h>52wKAWdag=X3kwQ(;+phlD(@zx^qcJapPx!}!Xn`Pc-sNW zxpnx9+-Vl56qB4Fdh3Y@p8y6KsD=oh_$;|K$C2U4;M2a#0`WP!zLvZ2X3@BC2?!C6 zXfDZ(Ul4085$jmE6M59X|2jB;MwJUyo&lZGE$x@5!8JKR|NoR7feF=8Mc${YA(kh& z7VyOkTZ5`yLgtvfAHlq8wj}q1?lCAh{xa;UVj^B*lf%{gV>E5gxQBdih_=D@;J4rJ4d5oq*~{tdw7Gp^QEJ4WWu5rFZzP# z!{2x+ZP!_eeua0>on0$3gnFi|MqrKQP7jWN`xX%g9CXBY;B>3*s#213`q!mr`1?K% zkrYjYlUUNRk75MS+F6CvPPo2yw!F|U_Wx}=yPr$?^s^}kwrJ$DRMlQMtrqDX)&J*d z-sD9Ze^kF7v^{tCaqIi1<^Q*u=kvFGFTbtlkbGFwn!VxR57YEo1Ea+Dr2bac% zhc4ycA*@q+!Rv|sck?Ny+fplbUyF)+d++77dwW)C-Hds5YSQ;uizhL9;dyHk)|SdI ziH%~AXb5rnx1=g)?a@1&D_%E$4rg%OaqZ=|iTe7ws|Ejro4;U*+4%F-UR~|0uP!k$ zNC8LJfgLI684$qM1-#jfT$K;XQ?-EZMp-C~yjG*(zx;~ML`lKd`$1cv89ZJ6T-G@y GGywp@_)F{n literal 0 HcmV?d00001 diff --git a/pipeline/metadata/solarFlux/solarPlotHiddenPhoton.py b/pipeline/metadata/solarFlux/solarPlotHiddenPhoton.py index 88ceca53..7743f843 100755 --- a/pipeline/metadata/solarFlux/solarPlotHiddenPhoton.py +++ b/pipeline/metadata/solarFlux/solarPlotHiddenPhoton.py @@ -44,15 +44,15 @@ parser.add_argument( "--N", dest="samples", type=int, help="The number of generated particles" ) -parser.add_argument("--m", dest="mass", type=float, help="Hidden photon mass") +parser.add_argument( + "--mass", dest="mass", type=float, help="Hidden photon mass [eV]" +) + args = parser.parse_args() +mass = 10 # eV if args.mass != None: mass = args.mass -else: - print("Hidden photon mass not specified!!") - print("Specify with argument --m") - quit() rmlfile = "fluxes.rml" if args.rmlfile != None: @@ -62,23 +62,15 @@ if args.outfname != None: outfname = args.outfname -fluxname = "combined" +fluxname = "HiddenPhoton" if args.fluxname != None: fluxname = args.fluxname - samples = 20000 if args.samples != None: samples = args.samples validation = True -if ( - rmlfile == "fluxes.rml" - and fluxname == "combined" - and outfname == "flux.png" - and samples == 20000 -): - validation = True ROOT.gSystem.Load("libRestFramework.so") ROOT.gSystem.Load("libRestAxion.so") @@ -92,7 +84,7 @@ pad1.Draw() combinedFlux = ROOT.TRestAxionSolarHiddenPhotonFlux(rmlfile, fluxname) -combinedFlux.Initialize() +combinedFlux.Initialize(mass) combinedFlux.PrintMetadata() if combinedFlux.GetError(): @@ -102,15 +94,14 @@ comb_spt = TH2D("comb_spt", "Energy versus solar radius", 20000, 0, 20, 100, 0, 1) for x in range(samples): - x = combinedFlux.GetRandomEnergyAndRadius(mass) + x = combinedFlux.GetRandomEnergyAndRadius((-1,-1)) comb_spt.Fill(x[0], x[1]) rnd = TRandom3(0) solarDisk = TH2D("solar_disk", "SolarDisk", 120, -1.2, 1.2, 120, -1.2, 1.2) for x in range(samples): angle = rnd.Rndm() * 2 * math.pi - x = combinedFlux.GetRandomEnergyAndRadius(mass) - + x = combinedFlux.GetRandomEnergyAndRadius((-1,-1)) solarDisk.Fill(x[1] * math.cos(angle), x[1] * math.sin(angle)) pad1.cd(1) From 55492be454907f32b8b2179f799ac27d0fda4729 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 8 Sep 2023 13:55:58 +0000 Subject: [PATCH 27/48] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- pipeline/metadata/solarFlux/solarPlotHiddenPhoton.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/pipeline/metadata/solarFlux/solarPlotHiddenPhoton.py b/pipeline/metadata/solarFlux/solarPlotHiddenPhoton.py index 7743f843..d24dfcc1 100755 --- a/pipeline/metadata/solarFlux/solarPlotHiddenPhoton.py +++ b/pipeline/metadata/solarFlux/solarPlotHiddenPhoton.py @@ -44,13 +44,11 @@ parser.add_argument( "--N", dest="samples", type=int, help="The number of generated particles" ) -parser.add_argument( - "--mass", dest="mass", type=float, help="Hidden photon mass [eV]" -) +parser.add_argument("--mass", dest="mass", type=float, help="Hidden photon mass [eV]") args = parser.parse_args() -mass = 10 # eV +mass = 10 # eV if args.mass != None: mass = args.mass @@ -94,14 +92,14 @@ comb_spt = TH2D("comb_spt", "Energy versus solar radius", 20000, 0, 20, 100, 0, 1) for x in range(samples): - x = combinedFlux.GetRandomEnergyAndRadius((-1,-1)) + x = combinedFlux.GetRandomEnergyAndRadius((-1, -1)) comb_spt.Fill(x[0], x[1]) rnd = TRandom3(0) solarDisk = TH2D("solar_disk", "SolarDisk", 120, -1.2, 1.2, 120, -1.2, 1.2) for x in range(samples): angle = rnd.Rndm() * 2 * math.pi - x = combinedFlux.GetRandomEnergyAndRadius((-1,-1)) + x = combinedFlux.GetRandomEnergyAndRadius((-1, -1)) solarDisk.Fill(x[1] * math.cos(angle), x[1] * math.sin(angle)) pad1.cd(1) From 3950fa13fedf6cf16e816186292e4e6d26e44ff9 Mon Sep 17 00:00:00 2001 From: Javier Galan Date: Mon, 11 Sep 2023 12:51:52 +0200 Subject: [PATCH 28/48] Revert "created hidden photon plot code" This reverts commit ac0aa28aaf490f63ae9133da157f0f7a249ba8b8. --- data | 1 - src/TRestAxionSolarHiddenPhotonFlux.cxx | 4 +--- 2 files changed, 1 insertion(+), 4 deletions(-) delete mode 120000 data diff --git a/data b/data deleted file mode 120000 index 95fc0d20..00000000 --- a/data +++ /dev/null @@ -1 +0,0 @@ -../axionlib-data \ No newline at end of file diff --git a/src/TRestAxionSolarHiddenPhotonFlux.cxx b/src/TRestAxionSolarHiddenPhotonFlux.cxx index fe285b04..77abd9b8 100644 --- a/src/TRestAxionSolarHiddenPhotonFlux.cxx +++ b/src/TRestAxionSolarHiddenPhotonFlux.cxx @@ -454,9 +454,7 @@ Double_t TRestAxionSolarHiddenPhotonFlux::IntegrateFluxInRange(TVector2 eRange, /// \brief It returns a random solar radius position and energy according to the /// flux distributions defined inside the solar tables loaded in the class /// -std::pair TRestAxionSolarHiddenPhotonFlux::GetRandomEnergyAndRadius(TVector2 eRange, - Double_t HPmass) { - LoadTables(HPmass); // load tables with specified hidden photon mass +std::pair TRestAxionSolarHiddenPhotonFlux::GetRandomEnergyAndRadius(TVector2 eRange) { std::pair result = {0, 0}; if (!AreTablesLoaded()) return result; Double_t rnd = fRandom->Rndm(); From ee57b39a1064684847bfe43688d2ae1b5072d491 Mon Sep 17 00:00:00 2001 From: Javier Galan Date: Mon, 11 Sep 2023 12:58:39 +0200 Subject: [PATCH 29/48] Readding data submodule? --- .gitmodules | 2 +- data | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) create mode 160000 data diff --git a/.gitmodules b/.gitmodules index 29be5f3e..7fe95128 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,6 +1,6 @@ [submodule "data"] path = data - url = https://github.com/rest-for-physics/axionlib-data.git + url = https://github.com/rest-for-physics/axionlib-data [submodule "external/solarAxionFlux"] path = external/solarAxionFlux url = https://github.com/sebhoof/SolarAxionFlux.git diff --git a/data b/data new file mode 160000 index 00000000..957d9fc5 --- /dev/null +++ b/data @@ -0,0 +1 @@ +Subproject commit 957d9fc5e24d2e5aef97cfd1f99982f2c3a07a98 From d2e3d9b929dd076dd0cb27f0197acbf1e0902d2b Mon Sep 17 00:00:00 2001 From: Javier Galan Date: Mon, 11 Sep 2023 13:08:24 +0200 Subject: [PATCH 30/48] TRestAxionSolarXYZFlux. Fixing compilation issues --- inc/TRestAxionSolarFlux.h | 3 +-- inc/TRestAxionSolarHiddenPhotonFlux.h | 3 +-- inc/TRestAxionSolarQCDFlux.h | 3 +-- src/TRestAxionSolarQCDFlux.cxx | 3 +-- 4 files changed, 4 insertions(+), 8 deletions(-) diff --git a/inc/TRestAxionSolarFlux.h b/inc/TRestAxionSolarFlux.h index 1d068863..30c49340 100644 --- a/inc/TRestAxionSolarFlux.h +++ b/inc/TRestAxionSolarFlux.h @@ -71,8 +71,7 @@ class TRestAxionSolarFlux : public TRestMetadata { virtual Double_t GetTotalFlux(Double_t mass = 0) = 0; /// It defines how to generate Monte Carlo energy and radius values to reproduce the flux - virtual std::pair GetRandomEnergyAndRadius(TVector2 eRange = TVector2(-1, -1), - Double_t mass = 0) = 0; + virtual std::pair GetRandomEnergyAndRadius(TVector2 eRange = TVector2(-1, -1)) = 0; /// It returns an energy integrated spectrum in cm-2 s-1 keV-1 virtual TH1F* GetEnergySpectrum(Double_t m = 0) = 0; diff --git a/inc/TRestAxionSolarHiddenPhotonFlux.h b/inc/TRestAxionSolarHiddenPhotonFlux.h index 502983af..876a29ef 100644 --- a/inc/TRestAxionSolarHiddenPhotonFlux.h +++ b/inc/TRestAxionSolarHiddenPhotonFlux.h @@ -87,8 +87,7 @@ class TRestAxionSolarHiddenPhotonFlux : public TRestAxionSolarFlux { Double_t IntegrateFluxInRange(TVector2 eRange = TVector2(-1, -1), Double_t mass = 0) override; /// It defines how to generate Monte Carlo energy and radius values to reproduce the flux - std::pair GetRandomEnergyAndRadius(TVector2 eRange = TVector2(-1, -1), - Double_t mass = 0) override; + std::pair GetRandomEnergyAndRadius(TVector2 eRange = TVector2(-1, -1)) override; /// It defines how to read the solar tables at the inhereted class for a given mass in eV Bool_t LoadTables(Double_t mass) override; diff --git a/inc/TRestAxionSolarQCDFlux.h b/inc/TRestAxionSolarQCDFlux.h index 240fd395..13246023 100644 --- a/inc/TRestAxionSolarQCDFlux.h +++ b/inc/TRestAxionSolarQCDFlux.h @@ -87,8 +87,7 @@ class TRestAxionSolarQCDFlux : public TRestAxionSolarFlux { Double_t IntegrateFluxInRange(TVector2 eRange = TVector2(-1, -1), Double_t mass = 0) override; /// It defines how to generate Monte Carlo energy and radius values to reproduce the flux - std::pair GetRandomEnergyAndRadius(TVector2 eRange = TVector2(-1, -1), - Double_t mass = 0) override; + std::pair GetRandomEnergyAndRadius(TVector2 eRange = TVector2(-1, -1)) override; /// It defines how to read the solar tables at the inhereted class Bool_t LoadTables(Double_t mass = 0) override; diff --git a/src/TRestAxionSolarQCDFlux.cxx b/src/TRestAxionSolarQCDFlux.cxx index c64969df..457bd31f 100644 --- a/src/TRestAxionSolarQCDFlux.cxx +++ b/src/TRestAxionSolarQCDFlux.cxx @@ -658,8 +658,7 @@ Double_t TRestAxionSolarQCDFlux::IntegrateFluxInRange(TVector2 eRange, Double_t /// \brief It returns a random solar radius position and energy according to the /// flux distributions defined inside the solar tables loaded in the class /// -std::pair TRestAxionSolarQCDFlux::GetRandomEnergyAndRadius(TVector2 eRange, - Double_t mass) { +std::pair TRestAxionSolarQCDFlux::GetRandomEnergyAndRadius(TVector2 eRange) { std::pair result = {0, 0}; if (!AreTablesLoaded()) return result; Double_t rnd = fRandom->Rndm(); From 56f58d2669f586816e6224b64427308bb06b9da0 Mon Sep 17 00:00:00 2001 From: tomasoshea Date: Tue, 12 Sep 2023 10:28:40 +0200 Subject: [PATCH 31/48] fixing hidden photon solar plot --- inc/TRestAxionSolarFlux.h | 21 +- inc/TRestAxionSolarHiddenPhotonFlux.h | 36 +- inc/TRestAxionSolarHiddenPhotonFlux.h.new | 131 ++++ inc/TRestAxionSolarHiddenPhotonFlux.h.old | 131 ++++ inc/TRestAxionSolarQCDFlux.h | 26 +- .../solarFlux/solarPlotHiddenPhoton.py | 31 +- src/TRestAxionSolarFlux.cxx | 22 +- src/TRestAxionSolarHiddenPhotonFlux.cxx | 163 +++-- src/TRestAxionSolarHiddenPhotonFlux.cxx.new | 583 +++++++++++++++++ src/TRestAxionSolarHiddenPhotonFlux.cxx.old | 613 ++++++++++++++++++ src/TRestAxionSolarQCDFlux.cxx | 82 +-- 11 files changed, 1646 insertions(+), 193 deletions(-) create mode 100644 inc/TRestAxionSolarHiddenPhotonFlux.h.new create mode 100644 inc/TRestAxionSolarHiddenPhotonFlux.h.old create mode 100644 src/TRestAxionSolarHiddenPhotonFlux.cxx.new create mode 100644 src/TRestAxionSolarHiddenPhotonFlux.cxx.old diff --git a/inc/TRestAxionSolarFlux.h b/inc/TRestAxionSolarFlux.h index 30c49340..9a917211 100644 --- a/inc/TRestAxionSolarFlux.h +++ b/inc/TRestAxionSolarFlux.h @@ -24,8 +24,8 @@ #define _TRestAxionSolarFlux #include -#include -#include +#include +#include #include #include @@ -58,23 +58,29 @@ class TRestAxionSolarFlux : public TRestMetadata { TRestAxionSolarFlux(const char* cfgFileName, std::string name = ""); /// It defines how to read the solar tables at the inhereted class - virtual Bool_t LoadTables(Double_t mass = 0) = 0; + virtual Bool_t LoadTables() = 0; public: /// It is required in order to load solar flux tables into memory void Initialize(); + /// It is required in order to load solar flux tables into memory for specific mass + void InitializeMass( Double_t mass ) { SetMass(mass); Initialize(); } + + /// Set mass and reinitialise + void SetMass( Double_t m ) { fMass = m; } //Initialize(); } + /// It returns the integrated flux at earth in cm-2 s-1 for the given energy range - virtual Double_t IntegrateFluxInRange(TVector2 eRange = TVector2(-1, -1), Double_t mass = 0) = 0; + virtual Double_t IntegrateFluxInRange(TVector2 eRange = TVector2(-1, -1)) = 0; /// It returns the total integrated flux at earth in cm-2 s-1 - virtual Double_t GetTotalFlux(Double_t mass = 0) = 0; + virtual Double_t GetTotalFlux() = 0; /// It defines how to generate Monte Carlo energy and radius values to reproduce the flux virtual std::pair GetRandomEnergyAndRadius(TVector2 eRange = TVector2(-1, -1)) = 0; /// It returns an energy integrated spectrum in cm-2 s-1 keV-1 - virtual TH1F* GetEnergySpectrum(Double_t m = 0) = 0; + virtual TH1D* GetEnergySpectrum() = 0; virtual TCanvas* DrawSolarFlux(); @@ -86,9 +92,8 @@ class TRestAxionSolarFlux : public TRestMetadata { Bool_t AreTablesLoaded() { return fTablesLoaded; } Double_t GetMass() { return fMass; } - void SetMass(const Double_t& m) { fMass = m; } - TH1F* GetFluxHistogram(std::string fname, Double_t binSize = 0.01); + TH1D* GetFluxHistogram(std::string fname, Double_t binSize = 0.01); TCanvas* DrawFluxFile(std::string fname, Double_t binSize = 0.01); void PrintMetadata(); diff --git a/inc/TRestAxionSolarHiddenPhotonFlux.h b/inc/TRestAxionSolarHiddenPhotonFlux.h index 876a29ef..2df02f96 100644 --- a/inc/TRestAxionSolarHiddenPhotonFlux.h +++ b/inc/TRestAxionSolarHiddenPhotonFlux.h @@ -41,20 +41,20 @@ class TRestAxionSolarHiddenPhotonFlux : public TRestAxionSolarFlux { /// It will be used when loading `.flux` files to define the input file energy binsize in eV. Double_t fBinSize = 0; //< - /// The tabulated solar flux continuum spectra TH1F(200,0,20)keV in cm-2 s-1 keV-1 versus solar radius - std::vector fFluxTable; //! + /// The tabulated solar flux continuum spectra TH1D(200,0,20)keV in cm-2 s-1 keV-1 versus solar radius + std::vector fFluxTable; //! - /// The tabulated solar flux continuum spectra TH1F(200,0,20)keV in cm-2 s-1 keV-1 versus solar radius - std::vector fContinuumTable; //! + /// The tabulated solar flux continuum spectra TH1D(200,0,20)keV in cm-2 s-1 keV-1 versus solar radius + std::vector> fContinuumTable; //! - /// The tabulated resonance width TH1F(200,0,20)keV in eV2 versus solar radius - std::vector fWidthTable; //! + /// The tabulated resonance width TH1D(200,0,20)keV in eV2 versus solar radius + std::vector> fWidthTable; //! /// The solar plasma frequency vector in eV versus solar radius - std::vector fPlasmaFreqTable; //! + std::vector> fPlasmaFreqTable; //! - /// The total solar flux TH1F(200,0,20)keV in cm-2 s-1 keV-1 versus solar radius - std::vector fFullFluxTable; //! + /// The total solar flux TH1D(200,0,20)keV in cm-2 s-1 keV-1 versus solar radius + std::vector fFullFluxTable; //! /// Accumulative integrated solar flux for each solar ring for continuum spectrum (renormalized to unity) std::vector fFluxTableIntegrals; //! @@ -63,17 +63,17 @@ class TRestAxionSolarHiddenPhotonFlux : public TRestAxionSolarFlux { Double_t fTotalContinuumFlux = 0; //! /// A pointer to the continuum spectrum histogram - TH1F* fContinuumHist = nullptr; //! + TH1D* fContinuumHist = nullptr; //! /// A pointer to the superposed monochromatic and continuum spectrum histogram - TH1F* fTotalHist = nullptr; //! + TH1D* fTotalHist = nullptr; //! void ReadFluxFile(); void LoadContinuumFluxTable(); void LoadMonoChromaticFluxTable(); void IntegrateSolarFluxes(); - public: + public: /// It returns true if continuum flux spectra was loaded Bool_t isSolarTableLoaded() { return fFluxTable.size() > 0; } @@ -84,13 +84,13 @@ class TRestAxionSolarHiddenPhotonFlux : public TRestAxionSolarFlux { Bool_t isPlasmaFreqLoaded() { return fPlasmaFreqTable.size() > 0; } /// It returns the integrated flux at earth in cm-2 s-1 for the given energy range - Double_t IntegrateFluxInRange(TVector2 eRange = TVector2(-1, -1), Double_t mass = 0) override; + Double_t IntegrateFluxInRange(TVector2 eRange = TVector2(-1, -1)) override; /// It defines how to generate Monte Carlo energy and radius values to reproduce the flux std::pair GetRandomEnergyAndRadius(TVector2 eRange = TVector2(-1, -1)) override; /// It defines how to read the solar tables at the inhereted class for a given mass in eV - Bool_t LoadTables(Double_t mass) override; + Bool_t LoadTables() override; void LoadContinuumTable(); void LoadWidthTable(); @@ -99,13 +99,13 @@ class TRestAxionSolarHiddenPhotonFlux : public TRestAxionSolarFlux { // calculate solar HP flux from the 3 tables and mass void CalculateSolarFlux(); /// It returns the total integrated flux at earth in cm-2 s-1 - Double_t GetTotalFlux(Double_t mass = 0) override { return fTotalContinuumFlux; } + Double_t GetTotalFlux() override { return fTotalContinuumFlux; } /// It returns an energy integrated spectrum in cm-2 s-1 keV-1 - TH1F* GetEnergySpectrum(Double_t m = 0) override { return GetTotalSpectrum(); } + TH1D* GetEnergySpectrum() override { return GetTotalSpectrum(); } - TH1F* GetContinuumSpectrum(); - TH1F* GetTotalSpectrum(); + TH1D* GetContinuumSpectrum(); + TH1D* GetTotalSpectrum(); virtual TCanvas* DrawSolarFlux() override; diff --git a/inc/TRestAxionSolarHiddenPhotonFlux.h.new b/inc/TRestAxionSolarHiddenPhotonFlux.h.new new file mode 100644 index 00000000..2df02f96 --- /dev/null +++ b/inc/TRestAxionSolarHiddenPhotonFlux.h.new @@ -0,0 +1,131 @@ +/************************************************************************* + * This file is part of the REST software framework. * + * * + * Copyright (C) 2016 GIFNA/TREX (University of Zaragoza) * + * For more information see http://gifna.unizar.es/trex * + * * + * REST 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. * + * * + * REST 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 a copy of the GNU General Public License along with * + * REST in $REST_PATH/LICENSE. * + * If not, see http://www.gnu.org/licenses/. * + * For the list of contributors see $REST_PATH/CREDITS. * + *************************************************************************/ + +#ifndef _TRestAxionSolarHiddenPhotonFlux +#define _TRestAxionSolarHiddenPhotonFlux + +#include +#include + +//! A metadata class to load tabulated solar hidden photon fluxes. Kinetic mixing set to 1. +class TRestAxionSolarHiddenPhotonFlux : public TRestAxionSolarFlux { + private: + /// The filename containing the solar flux table with continuum spectrum + std::string fFluxDataFile = ""; //< + + /// The filename containing the resonance width (wGamma) + std::string fWidthDataFile = ""; //< + + /// The filename containing the plasma frequency (wp) table + std::string fPlasmaFreqDataFile = ""; //< + + /// It will be used when loading `.flux` files to define the input file energy binsize in eV. + Double_t fBinSize = 0; //< + + /// The tabulated solar flux continuum spectra TH1D(200,0,20)keV in cm-2 s-1 keV-1 versus solar radius + std::vector fFluxTable; //! + + /// The tabulated solar flux continuum spectra TH1D(200,0,20)keV in cm-2 s-1 keV-1 versus solar radius + std::vector> fContinuumTable; //! + + /// The tabulated resonance width TH1D(200,0,20)keV in eV2 versus solar radius + std::vector> fWidthTable; //! + + /// The solar plasma frequency vector in eV versus solar radius + std::vector> fPlasmaFreqTable; //! + + /// The total solar flux TH1D(200,0,20)keV in cm-2 s-1 keV-1 versus solar radius + std::vector fFullFluxTable; //! + + /// Accumulative integrated solar flux for each solar ring for continuum spectrum (renormalized to unity) + std::vector fFluxTableIntegrals; //! + + /// Total solar flux for monochromatic contributions + Double_t fTotalContinuumFlux = 0; //! + + /// A pointer to the continuum spectrum histogram + TH1D* fContinuumHist = nullptr; //! + + /// A pointer to the superposed monochromatic and continuum spectrum histogram + TH1D* fTotalHist = nullptr; //! + + void ReadFluxFile(); + void LoadContinuumFluxTable(); + void LoadMonoChromaticFluxTable(); + void IntegrateSolarFluxes(); + + public: + /// It returns true if continuum flux spectra was loaded + Bool_t isSolarTableLoaded() { return fFluxTable.size() > 0; } + + /// It returns true if width table was loaded + Bool_t isWidthTableLoaded() { return fWidthTable.size() > 0; } + + /// It returns true if plasma frequency table was loaded + Bool_t isPlasmaFreqLoaded() { return fPlasmaFreqTable.size() > 0; } + + /// It returns the integrated flux at earth in cm-2 s-1 for the given energy range + Double_t IntegrateFluxInRange(TVector2 eRange = TVector2(-1, -1)) override; + + /// It defines how to generate Monte Carlo energy and radius values to reproduce the flux + std::pair GetRandomEnergyAndRadius(TVector2 eRange = TVector2(-1, -1)) override; + + /// It defines how to read the solar tables at the inhereted class for a given mass in eV + Bool_t LoadTables() override; + + void LoadContinuumTable(); + void LoadWidthTable(); + void LoadPlasmaFreqTable(); + + // calculate solar HP flux from the 3 tables and mass + void CalculateSolarFlux(); + /// It returns the total integrated flux at earth in cm-2 s-1 + Double_t GetTotalFlux() override { return fTotalContinuumFlux; } + + /// It returns an energy integrated spectrum in cm-2 s-1 keV-1 + TH1D* GetEnergySpectrum() override { return GetTotalSpectrum(); } + + TH1D* GetContinuumSpectrum(); + TH1D* GetTotalSpectrum(); + + virtual TCanvas* DrawSolarFlux() override; + + /// Tables might be loaded using a solar model description by TRestAxionSolarModel + void InitializeSolarTable(TRestAxionSolarModel* model) { + // TOBE implemented + // This method should initialize the tables fFluxTable and fFluxLines + } + + void ExportTables(Bool_t ascii = false) override; + + void PrintMetadata() override; + + void PrintContinuumSolarTable(); + void PrintIntegratedRingFlux(); + + TRestAxionSolarHiddenPhotonFlux(); + TRestAxionSolarHiddenPhotonFlux(const char* cfgFileName, std::string name = ""); + ~TRestAxionSolarHiddenPhotonFlux(); + + ClassDefOverride(TRestAxionSolarHiddenPhotonFlux, 1); +}; +#endif diff --git a/inc/TRestAxionSolarHiddenPhotonFlux.h.old b/inc/TRestAxionSolarHiddenPhotonFlux.h.old new file mode 100644 index 00000000..bdc44040 --- /dev/null +++ b/inc/TRestAxionSolarHiddenPhotonFlux.h.old @@ -0,0 +1,131 @@ +/************************************************************************* + * This file is part of the REST software framework. * + * * + * Copyright (C) 2016 GIFNA/TREX (University of Zaragoza) * + * For more information see http://gifna.unizar.es/trex * + * * + * REST 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. * + * * + * REST 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 a copy of the GNU General Public License along with * + * REST in $REST_PATH/LICENSE. * + * If not, see http://www.gnu.org/licenses/. * + * For the list of contributors see $REST_PATH/CREDITS. * + *************************************************************************/ + +#ifndef _TRestAxionSolarHiddenPhotonFlux +#define _TRestAxionSolarHiddenPhotonFlux + +#include +#include + +//! A metadata class to load tabulated solar hidden photon fluxes. Kinetic mixing set to 1. +class TRestAxionSolarHiddenPhotonFlux : public TRestAxionSolarFlux { + private: + /// The filename containing the solar flux table with continuum spectrum + std::string fFluxDataFile = ""; //< + + /// The filename containing the resonance width (wGamma) + std::string fWidthDataFile = ""; //< + + /// The filename containing the plasma frequency (wp) table + std::string fPlasmaFreqDataFile = ""; //< + + /// It will be used when loading `.flux` files to define the input file energy binsize in eV. + Double_t fBinSize = 0; //< + + /// The tabulated solar flux continuum spectra TH1D(200,0,20)keV in cm-2 s-1 keV-1 versus solar radius + std::vector fFluxTable; //! + + /// The tabulated solar flux continuum spectra TH1D(200,0,20)keV in cm-2 s-1 keV-1 versus solar radius + std::vector fContinuumTable; //! + + /// The tabulated resonance width TH1D(200,0,20)keV in eV2 versus solar radius + std::vector fWidthTable; //! + + /// The solar plasma frequency vector in eV versus solar radius + std::vector fPlasmaFreqTable; //! + + /// The total solar flux TH1D(200,0,20)keV in cm-2 s-1 keV-1 versus solar radius + std::vector fFullFluxTable; //! + + /// Accumulative integrated solar flux for each solar ring for continuum spectrum (renormalized to unity) + std::vector fFluxTableIntegrals; //! + + /// Total solar flux for monochromatic contributions + Double_t fTotalContinuumFlux = 0; //! + + /// A pointer to the continuum spectrum histogram + TH1D* fContinuumHist = nullptr; //! + + /// A pointer to the superposed monochromatic and continuum spectrum histogram + TH1D* fTotalHist = nullptr; //! + + void ReadFluxFile(); + void LoadContinuumFluxTable(); + void LoadMonoChromaticFluxTable(); + void IntegrateSolarFluxes(); + + public: + /// It returns true if continuum flux spectra was loaded + Bool_t isSolarTableLoaded() { return fFluxTable.size() > 0; } + + /// It returns true if width table was loaded + Bool_t isWidthTableLoaded() { return fWidthTable.size() > 0; } + + /// It returns true if plasma frequency table was loaded + Bool_t isPlasmaFreqLoaded() { return fPlasmaFreqTable.size() > 0; } + + /// It returns the integrated flux at earth in cm-2 s-1 for the given energy range + Double_t IntegrateFluxInRange(TVector2 eRange = TVector2(-1, -1)) override; + + /// It defines how to generate Monte Carlo energy and radius values to reproduce the flux + std::pair GetRandomEnergyAndRadius(TVector2 eRange = TVector2(-1, -1)) override; + + /// It defines how to read the solar tables at the inhereted class for a given mass in eV + Bool_t LoadTables() override; + + void LoadContinuumTable(); + void LoadWidthTable(); + void LoadPlasmaFreqTable(); + + // calculate solar HP flux from the 3 tables and mass + void CalculateSolarFlux(); + /// It returns the total integrated flux at earth in cm-2 s-1 + Double_t GetTotalFlux() override { return fTotalContinuumFlux; } + + /// It returns an energy integrated spectrum in cm-2 s-1 keV-1 + TH1D* GetEnergySpectrum() override { return GetTotalSpectrum(); } + + TH1D* GetContinuumSpectrum(); + TH1D* GetTotalSpectrum(); + + virtual TCanvas* DrawSolarFlux() override; + + /// Tables might be loaded using a solar model description by TRestAxionSolarModel + void InitializeSolarTable(TRestAxionSolarModel* model) { + // TOBE implemented + // This method should initialize the tables fFluxTable and fFluxLines + } + + void ExportTables(Bool_t ascii = false) override; + + void PrintMetadata() override; + + void PrintContinuumSolarTable(); + void PrintIntegratedRingFlux(); + + TRestAxionSolarHiddenPhotonFlux(); + TRestAxionSolarHiddenPhotonFlux(const char* cfgFileName, std::string name = ""); + ~TRestAxionSolarHiddenPhotonFlux(); + + ClassDefOverride(TRestAxionSolarHiddenPhotonFlux, 1); +}; +#endif diff --git a/inc/TRestAxionSolarQCDFlux.h b/inc/TRestAxionSolarQCDFlux.h index 13246023..10db402e 100644 --- a/inc/TRestAxionSolarQCDFlux.h +++ b/inc/TRestAxionSolarQCDFlux.h @@ -41,11 +41,11 @@ class TRestAxionSolarQCDFlux : public TRestAxionSolarFlux { /// It will be used when loading `.flux` files to define the threshold for peak identification Double_t fPeakSigma = 0; //< - /// The tabulated solar flux continuum spectra TH1F(200,0,20)keV in cm-2 s-1 keV-1 versus solar radius - std::vector fFluxTable; //! + /// The tabulated solar flux continuum spectra TH1D(200,0,20)keV in cm-2 s-1 keV-1 versus solar radius + std::vector fFluxTable; //! /// The tabulated solar flux in cm-2 s-1 for a number of monochromatic energies versus solar radius - std::map fFluxLines; //! + std::map fFluxLines; //! /// Accumulative integrated solar flux for each solar ring for continuum spectrum (renormalized to unity) std::vector fFluxTableIntegrals; //! @@ -63,13 +63,13 @@ class TRestAxionSolarQCDFlux : public TRestAxionSolarFlux { Double_t fFluxRatio = 0; //! /// A pointer to the continuum spectrum histogram - TH1F* fContinuumHist = nullptr; //! + TH1D* fContinuumHist = nullptr; //! /// A pointer to the monochromatic spectrum histogram - TH1F* fMonoHist = nullptr; //! + TH1D* fMonoHist = nullptr; //! /// A pointer to the superposed monochromatic and continuum spectrum histogram - TH1F* fTotalHist = nullptr; //! + TH1D* fTotalHist = nullptr; //! void ReadFluxFile(); void LoadContinuumFluxTable(); @@ -84,25 +84,25 @@ class TRestAxionSolarQCDFlux : public TRestAxionSolarFlux { Bool_t isSolarSpectrumLoaded() { return fFluxLines.size() > 0; } /// It returns the integrated flux at earth in cm-2 s-1 for the given energy range - Double_t IntegrateFluxInRange(TVector2 eRange = TVector2(-1, -1), Double_t mass = 0) override; + Double_t IntegrateFluxInRange(TVector2 eRange = TVector2(-1, -1)) override; /// It defines how to generate Monte Carlo energy and radius values to reproduce the flux std::pair GetRandomEnergyAndRadius(TVector2 eRange = TVector2(-1, -1)) override; /// It defines how to read the solar tables at the inhereted class - Bool_t LoadTables(Double_t mass = 0) override; + Bool_t LoadTables() override; /// It returns the total integrated flux at earth in cm-2 s-1 - Double_t GetTotalFlux(Double_t mass = 0) override { + Double_t GetTotalFlux() override { return fTotalContinuumFlux + fTotalMonochromaticFlux; } /// It returns an energy integrated spectrum in cm-2 s-1 keV-1 - TH1F* GetEnergySpectrum(Double_t m = 0) override { return GetTotalSpectrum(); } + TH1D* GetEnergySpectrum() override { return GetTotalSpectrum(); } - TH1F* GetContinuumSpectrum(); - TH1F* GetMonochromaticSpectrum(); - TH1F* GetTotalSpectrum(); + TH1D* GetContinuumSpectrum(); + TH1D* GetMonochromaticSpectrum(); + TH1D* GetTotalSpectrum(); virtual TCanvas* DrawSolarFlux() override; diff --git a/pipeline/metadata/solarFlux/solarPlotHiddenPhoton.py b/pipeline/metadata/solarFlux/solarPlotHiddenPhoton.py index d24dfcc1..c07ac580 100755 --- a/pipeline/metadata/solarFlux/solarPlotHiddenPhoton.py +++ b/pipeline/metadata/solarFlux/solarPlotHiddenPhoton.py @@ -44,11 +44,12 @@ parser.add_argument( "--N", dest="samples", type=int, help="The number of generated particles" ) -parser.add_argument("--mass", dest="mass", type=float, help="Hidden photon mass [eV]") - +parser.add_argument( + "--m", dest="mass", type=float, help="Hidden photon mass [eV]" +) args = parser.parse_args() -mass = 10 # eV +mass = 10. # eV if args.mass != None: mass = args.mass @@ -68,7 +69,7 @@ if args.samples != None: samples = args.samples -validation = True +validation = False ROOT.gSystem.Load("libRestFramework.so") ROOT.gSystem.Load("libRestAxion.so") @@ -82,7 +83,9 @@ pad1.Draw() combinedFlux = ROOT.TRestAxionSolarHiddenPhotonFlux(rmlfile, fluxname) -combinedFlux.Initialize(mass) +combinedFlux.SetMass(mass) +print(combinedFlux.GetMass()) +combinedFlux.Initialize() combinedFlux.PrintMetadata() if combinedFlux.GetError(): @@ -91,8 +94,9 @@ exit(101) comb_spt = TH2D("comb_spt", "Energy versus solar radius", 20000, 0, 20, 100, 0, 1) -for x in range(samples): +for i in range(samples): x = combinedFlux.GetRandomEnergyAndRadius((-1, -1)) + #print(x) comb_spt.Fill(x[0], x[1]) rnd = TRandom3(0) @@ -160,17 +164,4 @@ c1.Print(outfname) print("Generated file : " + outfname) -print("\nMaximum energy bin is " + str(enSpt.GetMaximumBin())) -if validation: - if enSpt.GetMaximumBin() != 8001: - print("\nMaximum Bin is not the expected one (8001)! Exit code : 1") - exit(1) - -print("\nMaximum radius bin is " + str(rSpt.GetMaximumBin())) - -if validation: - if rSpt.GetMaximumBin() != 25: - print("\nMaximum Bin is not the expected one (25)! Exit code : 2") - exit(2) - -exit(0) +#exit(0) diff --git a/src/TRestAxionSolarFlux.cxx b/src/TRestAxionSolarFlux.cxx index a2e0ccd6..f82d9e34 100644 --- a/src/TRestAxionSolarFlux.cxx +++ b/src/TRestAxionSolarFlux.cxx @@ -64,7 +64,7 @@ /// on the flux distribution initialized. /// - **LoadTables**: It is called by TRestAxionSolarFlux::Initialize to allow the inherited /// class to load all the necessary tables in memory. -/// - **GetEnergySpectrum**: It should return a TH1F pointer with a energy spectrum histogram. +/// - **GetEnergySpectrum**: It should return a TH1D pointer with a energy spectrum histogram. /// ///-------------------------------------------------------------------------- /// @@ -125,12 +125,7 @@ void TRestAxionSolarFlux::Initialize() { fTablesLoaded = false; if (LoadTables()) fTablesLoaded = true; - if (!fRandom) { - delete fRandom; - fRandom = nullptr; - } - - if (fRandom != nullptr) { + if (fRandom) { delete fRandom; fRandom = nullptr; } @@ -139,11 +134,18 @@ void TRestAxionSolarFlux::Initialize() { fSeed = fRandom->TRandom::GetSeed(); } + +/////////////////////////////////////////////// +/// \brief Initialization of TRestAxionSolarFlux members with specific mass +/// +//void TRestAxionSolarFlux::InitializeMass( Double_t mass ) { SetMass(mass); RESTMetadata << GetMass() << RESTendl; } // SetMass calls Initialize + + /////////////////////////////////////////////// /// \brief It builds a histogram using the contents of the .flux file given /// in the argument. /// -TH1F* TRestAxionSolarFlux::GetFluxHistogram(string fname, Double_t binSize) { +TH1D* TRestAxionSolarFlux::GetFluxHistogram(string fname, Double_t binSize) { string fullPathName = SearchFile(fname); std::vector> fluxData; @@ -160,7 +162,7 @@ TH1F* TRestAxionSolarFlux::GetFluxHistogram(string fname, Double_t binSize) { originalHist->Fill(r, en, flux); } - return (TH1F*)originalHist->ProjectionY(); + return (TH1D*)originalHist->ProjectionY(); } /////////////////////////////////////////////// @@ -206,7 +208,7 @@ TCanvas* TRestAxionSolarFlux::DrawSolarFlux() { pad1->SetLeftMargin(0.15); pad1->SetBottomMargin(0.15); - TH1F* ht = GetEnergySpectrum(); + TH1D* ht = GetEnergySpectrum(); ht->SetLineColor(kBlack); ht->SetFillStyle(4050); ht->SetFillColor(kBlue - 10); diff --git a/src/TRestAxionSolarHiddenPhotonFlux.cxx b/src/TRestAxionSolarHiddenPhotonFlux.cxx index 77abd9b8..01f443fa 100644 --- a/src/TRestAxionSolarHiddenPhotonFlux.cxx +++ b/src/TRestAxionSolarHiddenPhotonFlux.cxx @@ -183,10 +183,25 @@ TRestAxionSolarHiddenPhotonFlux::~TRestAxionSolarHiddenPhotonFlux() {} /// \brief It will load the tables in memory by using the filename information provided /// inside the metadata members, and calculate the solar flux for a given m. /// -Bool_t TRestAxionSolarHiddenPhotonFlux::LoadTables(Double_t mass) { - if (fFluxDataFile == "" || fWidthDataFile == "" || fPlasmaFreqDataFile == "") return false; +Bool_t TRestAxionSolarHiddenPhotonFlux::LoadTables() { - SetMass(mass); + if (GetMass() <= 0 ) { + RESTWarning << "TRestAxionSolarHiddenPhotonFlux::LoadTables - hidden photon mass not yet defined" << RESTendl; + RESTWarning << "TRestAxionSolarHiddenPhotonFlux::LoadTables - mass given as " << GetMass() << " eV" << RESTendl; + return false; + } + if ( fFluxDataFile == "" ){ + RESTWarning << "TRestAxionSolarHiddenPhotonFlux::LoadTables - flux table not found!!\n " << fFluxDataFile << RESTendl; + return false; + } + if ( fWidthDataFile == "") { + RESTWarning << "TRestAxionSolarHiddenPhotonFlux::LoadTables - width table not found!!\n " << fWidthDataFile << RESTendl; + return false; + } + if ( fPlasmaFreqDataFile == "" ) { + RESTWarning << "TRestAxionSolarHiddenPhotonFlux::LoadTables - plasma frequency table not found!!\n " << fPlasmaFreqDataFile << RESTendl; + return false; + } LoadContinuumFluxTable(); LoadWidthTable(); @@ -195,7 +210,6 @@ Bool_t TRestAxionSolarHiddenPhotonFlux::LoadTables(Double_t mass) { CalculateSolarFlux(); IntegrateSolarFluxes(); - return true; } @@ -203,9 +217,9 @@ Bool_t TRestAxionSolarHiddenPhotonFlux::LoadTables(Double_t mass) { /// \brief A helper method to load the data file containing continuum spectra as a /// function of the solar radius. It will be called by TRestAxionSolarHiddenPhotonFlux::Initialize. /// -void TRestAxionSolarHiddenPhotonFlux::LoadContinuumTable() { +void TRestAxionSolarHiddenPhotonFlux::LoadContinuumFluxTable() { if (fFluxDataFile == "") { - RESTDebug + RESTError << "TRestAxionSolarHiddenPhotonFlux::LoadContinuumFluxTable. No solar flux table was defined" << RESTendl; return; @@ -216,26 +230,18 @@ void TRestAxionSolarHiddenPhotonFlux::LoadContinuumTable() { RESTDebug << "Loading table from file : " << RESTendl; RESTDebug << "File : " << fullPathName << RESTendl; - std::vector> fluxTable; - if (!TRestTools::IsBinaryFile(fFluxDataFile)) { - fluxTable.clear(); + fContinuumTable.clear(); RESTError << "File is not in binary format!" << RESTendl; } - TRestTools::ReadBinaryTable(fullPathName, fluxTable); + TRestTools::ReadBinaryTable(fullPathName, fContinuumTable); - if (fluxTable.size() != 1000 && fluxTable[0].size() != 200) { - fluxTable.clear(); + if (fContinuumTable.size() != 1000 || fContinuumTable[0].size() != 200) { RESTError << "LoadContinuumFluxTable. The table does not contain the right number of rows or columns" << RESTendl; RESTError << "Table will not be populated" << RESTendl; - } - - for (unsigned int n = 0; n < fluxTable.size(); n++) { - TH1F* h = new TH1F(Form("%s_ContinuumFluxAtRadius%d", GetName(), n), "", 200, 0, 20); - for (unsigned int m = 0; m < fluxTable[n].size(); m++) h->SetBinContent(m + 1, fluxTable[n][m]); - fContinuumTable.push_back(h); + fContinuumTable.clear(); } } @@ -245,7 +251,7 @@ void TRestAxionSolarHiddenPhotonFlux::LoadContinuumTable() { /// void TRestAxionSolarHiddenPhotonFlux::LoadWidthTable() { if (fFluxDataFile == "") { - RESTDebug << "TRestAxionSolarHiddenPhotonFlux::LoadWidthTable. No width table was defined" + RESTError << "TRestAxionSolarHiddenPhotonFlux::LoadWidthTable. No width table was defined" << RESTendl; return; } @@ -255,26 +261,18 @@ void TRestAxionSolarHiddenPhotonFlux::LoadWidthTable() { RESTDebug << "Loading table from file : " << RESTendl; RESTDebug << "File : " << fullPathName << RESTendl; - std::vector> fluxTable; - if (!TRestTools::IsBinaryFile(fWidthDataFile)) { - fluxTable.clear(); + fWidthTable.clear(); RESTError << "File is not in binary format!" << RESTendl; } - TRestTools::ReadBinaryTable(fullPathName, fluxTable); - - if (fluxTable.size() != 1000 && fluxTable[0].size() != 200) { - fluxTable.clear(); + TRestTools::ReadBinaryTable(fullPathName, fWidthTable); + + if (fWidthTable.size() != 1000 || fWidthTable[0].size() != 200) { RESTError << "LoadWidthTable. The table does not contain the right number of rows or columns" << RESTendl; RESTError << "Table will not be populated" << RESTendl; - } - - for (unsigned int n = 0; n < fluxTable.size(); n++) { - TH1F* h = new TH1F(Form("%s_ResonanceWidthAtRadius%d", GetName(), n), "", 200, 0, 20); - for (unsigned int m = 0; m < fluxTable[n].size(); m++) h->SetBinContent(m + 1, fluxTable[n][m]); - fWidthTable.push_back(h); + fWidthTable.clear(); } } @@ -284,7 +282,7 @@ void TRestAxionSolarHiddenPhotonFlux::LoadWidthTable() { /// void TRestAxionSolarHiddenPhotonFlux::LoadPlasmaFreqTable() { if (fFluxDataFile == "") { - RESTDebug + RESTError << "TRestAxionSolarHiddenPhotonFlux::LoadPlasmaFreqTable. No plasma frequency table was defined" << RESTendl; return; @@ -295,26 +293,18 @@ void TRestAxionSolarHiddenPhotonFlux::LoadPlasmaFreqTable() { RESTDebug << "Loading table from file : " << RESTendl; RESTDebug << "File : " << fullPathName << RESTendl; - std::vector> fluxTable; - if (!TRestTools::IsBinaryFile(fWidthDataFile)) { - fluxTable.clear(); RESTError << "File is not in binary format!" << RESTendl; + fPlasmaFreqTable.clear(); } - TRestTools::ReadBinaryTable(fullPathName, fluxTable); - - if (fluxTable.size() != 1000 && fluxTable[0].size() != 1) { - fluxTable.clear(); - RESTError << "LoadWidthTable. The table does not contain the right number of rows or columns" + TRestTools::ReadBinaryTable(fullPathName, fPlasmaFreqTable); + + if (fPlasmaFreqTable.size() != 1000 || fPlasmaFreqTable[0].size() != 1) { + RESTError << "LoadPlasmaFreqTable. The table does not contain the right number of rows or columns" << RESTendl; RESTError << "Table will not be populated" << RESTendl; - } - - for (unsigned int n = 0; n < fluxTable.size(); n++) { - TH1F* h = new TH1F(Form("%s_PlasmaFreqAtRadius%d", GetName(), n), "", 1, 0, 20); - for (unsigned int m = 0; m < fluxTable[n].size(); m++) h->SetBinContent(m + 1, fluxTable[n][m]); - fPlasmaFreqTable.push_back(h); + fPlasmaFreqTable.clear(); } } @@ -326,35 +316,37 @@ void TRestAxionSolarHiddenPhotonFlux::CalculateSolarFlux() { if (GetMass() == 0) { RESTError << "CalculateSolarFlux. The hidden photon mass is set to zero!" << RESTendl; return; + } + if (fContinuumTable.size() == 0 ) { + RESTError << "TRestAxionSolarHiddenPhotonFlux::CalculateSolarFlux - empty flux table!" << RESTendl; + return; } + if (fPlasmaFreqTable.size() == 0 ) { + RESTError << "TRestAxionSolarHiddenPhotonFlux::CalculateSolarFlux - empty plasma freq table!" << RESTendl; + return; + } + if (fWidthTable.size() == 0 ) { + RESTError << "TRestAxionSolarHiddenPhotonFlux::CalculateSolarFlux - empty width table!" << RESTendl; + return; + } + Double_t mass = GetMass(); for (unsigned int n = 0; n < fContinuumTable.size(); n++) { // m4 * chi2 * wG * flux / ( (m2 - wp2)^2 + (w G)^2 ) - vector mass2Vector(200, pow(mass, 2)); - double wp = fPlasmaFreqTable[n]->GetBinContent(1); - vector wp2Vector(200, pow(wp, 2)); - vector weights(200, 1); - - TH1F* hMass = new TH1F("hMass", "hMass", 200, 0, 20); - TH1F* hWp = new TH1F("hWp", "hWp", 200, 0, 20); - TH1F* hWg2 = (TH1F*)fWidthTable[n]->Clone(); - hWg2->Multiply(hWg2); // (w G)^2 - - // hMass->FillN(200, mass2Vector); // m^2 hist - hMass->FillN(200, mass2Vector.data(), weights.data()); // m^2 hist - // hWp->FillN(200, wp2Vector); // wp^2 hist - hWp->FillN(200, wp2Vector.data(), weights.data()); // wp^2 hist - - hMass->Add(hWp, -1); // (m2 - wp2) - hMass->Multiply(hMass); // (m2 - wp2)^2 - hMass->Add(hWg2); // (m2 - wp2)^2 + (w G)^2 - - TH1F* h = (TH1F*)fWidthTable[n]->Clone(); - h->Multiply(fContinuumTable[n]); - h->Divide(hMass); - h->Scale(pow(mass, 4)); - + Double_t wp = fPlasmaFreqTable[n][0]; + vector wG = fWidthTable[n]; + vector flux = fContinuumTable[n]; + vector v; + for( unsigned int c; c < wG.size(); c++ ) { + Double_t d1 = ( wG[c] * flux[c] * pow(mass,4) ); // m4 * wG * flux + Double_t d2 = ( pow( pow(mass,2) - pow(wp,2) , 2 ) + pow(wG[c],2) ); // m4 * wG * flux / ( (m2 - wp2)^2 + (w G)^2 ) + v.push_back(d1/d2); + } + + TH1D* h = new TH1D(Form("%s_TotalFluxTable%d", GetName(), n), "", 200, 0, 20); + for (unsigned int c = 0; c < v.size(); c++) { h->SetBinContent(c + 1, v[c]); } + //for (unsigned int c = 0; c < v.size(); c++) { h->Fill(v[c]); } fFluxTable.push_back(h); } } @@ -363,13 +355,13 @@ void TRestAxionSolarHiddenPhotonFlux::CalculateSolarFlux() { /// \brief It builds a histogram with the continuum spectrum. /// The flux will be expressed in cm-2 s-1 keV-1. Binned in 100eV steps. /// -TH1F* TRestAxionSolarHiddenPhotonFlux::GetContinuumSpectrum() { +TH1D* TRestAxionSolarHiddenPhotonFlux::GetContinuumSpectrum() { if (fContinuumHist != nullptr) { delete fContinuumHist; fContinuumHist = nullptr; } - fContinuumHist = new TH1F("ContinuumHist", "", 200, 0, 20); + fContinuumHist = new TH1D("ContinuumHist", "", 200, 0, 20); for (const auto& x : fFluxTable) { fContinuumHist->Add(x); } @@ -389,15 +381,15 @@ TH1F* TRestAxionSolarHiddenPhotonFlux::GetContinuumSpectrum() { /// \brief Same as GetContinuumSpectrum, the flux will be /// expressed in cm-2 s-1 keV-1. Binned in 1eV steps. /// -TH1F* TRestAxionSolarHiddenPhotonFlux::GetTotalSpectrum() { - TH1F* hc = GetContinuumSpectrum(); +TH1D* TRestAxionSolarHiddenPhotonFlux::GetTotalSpectrum() { + TH1D* hc = GetContinuumSpectrum(); if (fTotalHist != nullptr) { delete fTotalHist; fTotalHist = nullptr; } - fTotalHist = new TH1F("fTotalHist", "", 20000, 0, 20); + fTotalHist = new TH1D("fTotalHist", "", 20000, 0, 20); for (int n = 0; n < hc->GetNbinsX(); n++) { for (int m = 0; m < 100; m++) { fTotalHist->SetBinContent(n * 100 + 1 + m, hc->GetBinContent(n + 1)); @@ -433,7 +425,7 @@ void TRestAxionSolarHiddenPhotonFlux::IntegrateSolarFluxes() { /////////////////////////////////////////////// /// \brief It returns the integrated flux at earth in cm-2 s-1 for the given energy range /// -Double_t TRestAxionSolarHiddenPhotonFlux::IntegrateFluxInRange(TVector2 eRange, Double_t mass) { +Double_t TRestAxionSolarHiddenPhotonFlux::IntegrateFluxInRange(TVector2 eRange) { if (eRange.X() == -1 && eRange.Y() == -1) { if (GetTotalFlux() == 0) IntegrateSolarFluxes(); return GetTotalFlux(); @@ -455,8 +447,9 @@ Double_t TRestAxionSolarHiddenPhotonFlux::IntegrateFluxInRange(TVector2 eRange, /// flux distributions defined inside the solar tables loaded in the class /// std::pair TRestAxionSolarHiddenPhotonFlux::GetRandomEnergyAndRadius(TVector2 eRange) { + std::pair result = {0, 0}; - if (!AreTablesLoaded()) return result; + if (!AreTablesLoaded()) { RESTWarning << "Tables not loaded!!" << RESTendl; return result; } Double_t rnd = fRandom->Rndm(); for (unsigned int r = 0; r < fFluxTableIntegrals.size(); r++) { if (rnd < fFluxTableIntegrals[r]) { @@ -464,7 +457,7 @@ std::pair TRestAxionSolarHiddenPhotonFlux::GetRandomEnergyAn if (eRange.X() != -1 && eRange.Y() != -1) { if (energy < eRange.X() || energy > eRange.Y()) return GetRandomEnergyAndRadius(eRange); } - Double_t radius = ((Double_t)r + fRandom->Rndm()) * 0.01; + Double_t radius = ((Double_t)r + fRandom->Rndm()) * 0.001; std::pair p = {energy, radius}; return p; } @@ -473,7 +466,7 @@ std::pair TRestAxionSolarHiddenPhotonFlux::GetRandomEnergyAn } /////////////////////////////////////////////// -/// \brief It prints on screen the table that has been loaded in memory +/// \brief It prints on screen the flux table that has been read from file /// void TRestAxionSolarHiddenPhotonFlux::PrintContinuumSolarTable() { cout << "Continuum solar flux table: " << endl; @@ -506,6 +499,9 @@ void TRestAxionSolarHiddenPhotonFlux::PrintIntegratedRingFlux() { void TRestAxionSolarHiddenPhotonFlux::PrintMetadata() { TRestAxionSolarFlux::PrintMetadata(); + RESTMetadata << " - Solar hidden photon datafile (flux) : " << fFluxDataFile << RESTendl; + RESTMetadata << " - Solar hidden photon datafile (width) : " << fWidthDataFile << RESTendl; + RESTMetadata << " - Solar hidden photon datafile (plasma freq) : " << fPlasmaFreqDataFile << RESTendl; RESTMetadata << "-------" << RESTendl; RESTMetadata << " - Total continuum flux : " << fTotalContinuumFlux << " cm-2 s-1" << RESTendl; RESTMetadata << "++++++++++++++++++" << RESTendl; @@ -532,9 +528,9 @@ void TRestAxionSolarHiddenPhotonFlux::ExportTables(Bool_t ascii) { } if (fFluxTable.size() > 0) { - std::vector> table; + std::vector> table; for (const auto& x : fFluxTable) { - std::vector row; + std::vector row; for (int n = 0; n < x->GetNbinsX(); n++) row.push_back(x->GetBinContent(n + 1)); table.push_back(row); @@ -568,7 +564,7 @@ TCanvas* TRestAxionSolarHiddenPhotonFlux::DrawSolarFlux() { pad1->cd(1)->SetLeftMargin(0.15); pad1->cd(1)->SetBottomMargin(0.15); - TH1F* ht = GetTotalSpectrum(); + TH1D* ht = GetTotalSpectrum(); ht->SetLineColor(kBlack); ht->SetFillStyle(4050); ht->SetFillColor(kBlue - 10); @@ -584,3 +580,4 @@ TCanvas* TRestAxionSolarHiddenPhotonFlux::DrawSolarFlux() { return fCanvas; } + diff --git a/src/TRestAxionSolarHiddenPhotonFlux.cxx.new b/src/TRestAxionSolarHiddenPhotonFlux.cxx.new new file mode 100644 index 00000000..26c782c1 --- /dev/null +++ b/src/TRestAxionSolarHiddenPhotonFlux.cxx.new @@ -0,0 +1,583 @@ +/******************** REST disclaimer *********************************** + * This file is part of the REST software framework. * + * * + * Copyright (C) 2016 GIFNA/TREX (University of Zaragoza) * + * For more information see http://gifna.unizar.es/trex * + * * + * REST 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. * + * * + * REST 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 a copy of the GNU General Public License along with * + * REST in $REST_PATH/LICENSE. * + * If not, see http://www.gnu.org/licenses/. * + * For the list of contributors see $REST_PATH/CREDITS. * + *************************************************************************/ + +////////////////////////////////////////////////////////////////////////// +/// TRestAxionSolarHiddenPhotonFlux will use a file in binary format to initialize +/// a solar flux table that will describe the solar hidden photon flux spectrum as a function +/// of the solar radius. +/// +/// This class loads the hidden photon flux that depends on the mass and kinetic mixing parameter. +/// For axion-like particle prodution independent of mass there is the class +/// TRestAxionSolarQCDFlux. Both classes are prototyped by a pure base class TRestAxionSolarFlux +/// that defines common methods used to evaluate the flux, and generate Monte-Carlo events inside +/// TRestAxionGeneratorProcess. +/// +/// ### Basic use +/// +/// Once the class has been initialized, the main use of this class will be provided +/// by the method TRestAxionSolarHiddenPhotonFlux::GetRandomEnergyAndRadius. This method will +/// return a random axion energy and position inside the solar radius following the +/// distributions given by the solar flux tables. +/// +/// Description of the specific parameters accepted by this metadata class. +/// - *fluxDataFile:* A table with 1000 rows representing the solar ring flux from the +/// center to the corona, and 200 columns representing the flux, measured in cm-2 s-1 keV-1, +/// for the range (0,20)keV in steps of 100eV. The table is provided as a binary table using +/// `.N200f` extension. +/// - *widthDataFile:* A table with 1000 rows representing the width of the hidden photon +/// resonant production (wG) for each solar ring from the center to the corona, and 200 columns +/// representing the width, measured in eV2, for the range (0,20)keV in steps of 100eV. The +/// table is provided as a binary table using `.N200f` extension. +/// - *plasmaFreqDataFile:* A table with 1000 rows and only 1 column representing the solar +/// plasma frequency (wp) for each solar ring from the center to the corona, measured in eV. The +/// table is provided as a binary table using `.N1f` extension. +/// +/// Pre-generated solar axion flux tables will be available at the +/// [axionlib-data](https://github.com/rest-for-physics/axionlib-data/tree/master) +/// repository. The different RML flux definitions used to load those tables +/// will be found at the +/// [fluxes.rml](https://github.com/rest-for-physics/axionlib-data/blob/master/solarFlux/fluxes.rml) +/// file found at the axionlib-data repository. +/// +/// Inside a local REST installation, the `fluxes.rml` file will be found at the REST +/// installation directory, and it will be located automatically by the +/// TRestMetadata::SearchFile method. +/// +/// ### A basic RML definition +/// +/// The following definition integrates an axion-photon component with a continuum +/// spectrum using a Primakoff production model, and a dummy spectrum file that +/// includes two monocrhomatic lines at different solar disk radius positions. +/// +/// \code +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// \endcode +/// +/// \warning When the flux is loaded manually inside the `restRoot` interactive +/// shell, or inside a macro or script, after metadata initialization, it is necessary +/// to call the method TRestAxionSolarHiddenPhotonFlux::LoadTables(mass) to trigger the tables +/// initialization. +/// +/// ### Performing MonteCarlo tests using pre-loaded tables +/// +/// In order to test the response of different solar flux definitions we may use the script +/// `solarPlot.py` found at `pipeline/metadata/solarFlux/`. This script will generate a +/// number of particles and it will assign to each particle an energy and solar disk +/// location with the help of the method TRestAxionSolarHiddenPhotonFlux::GetRandomEnergyAndRadius. +/// +/// \code +/// python3 solarPlotHiddenPhoton.py --fluxname HiddenPhoton --N 1000000 +/// \endcode +/// +/// By default, it will load the flux definition found at `fluxes.rml` from the +/// `axionlib-data` repository, and generate a `png` image with the resuts from the +/// Monte Carlo execution. +/// +/// \htmlonly \endhtmlonly +/// +/// ![Solar flux distributions MC-generated with TRestAxionSolarQCDFlux.](ABC_flux_MC.png) +/// +/// ### Exporting the solar flux tables +/// +/// On top of that, we will be able to export those tables to the TRestAxionSolarHiddenPhotonFlux +/// standard format to be used in later occasions. +/// +/// \code +/// TRestAxionSolarHiddenPhotonFlux *sFlux = new TRestAxionSolarHiddenPhotonFlux("fluxes.rml", +/// "HiddenPhoton") sFlux->Initialize() sFlux->ExportTables() +/// \endcode +/// +/// which will produce a binary table `.N200f` with the continuum flux. The filename root will be +/// extracted from the original `.flux` file. Optionally we may export the continuum flux to an +/// ASCII file by indicating it at the TRestAxionSolarHiddenPhotonFlux::ExportTables method call. +/// The files will be placed at the REST user space, at `$HOME/.rest/export/` directory. +/// +/// TODO Implement the method TRestAxionSolarQCDFlux::InitializeSolarTable using +/// a solar model description by TRestAxionSolarModel. +/// +/// TODO Perhaps it would be interesting to replace fFluxTable for a TH2D +/// +///-------------------------------------------------------------------------- +/// +/// RESTsoft - Software for Rare Event Searches with TPCs +/// +/// History of developments: +/// +/// 2023-May: Specific methods extracted from TRestAxionSolarFlux +/// Javier Galan +/// 2023-June: TRestAxionSolarHiddenPhotonFlux created by editing TRestAxionSolarQCDFlux +/// Tomas O'Shea +/// +/// \class TRestAxionSolarHiddenPhotonFlux +/// \author Javier Galan +/// +///
+/// + +#include "TRestAxionSolarHiddenPhotonFlux.h" +using namespace std; + +ClassImp(TRestAxionSolarHiddenPhotonFlux); + +/////////////////////////////////////////////// +/// \brief Default constructor +/// +TRestAxionSolarHiddenPhotonFlux::TRestAxionSolarHiddenPhotonFlux() : TRestAxionSolarFlux() {} + +/////////////////////////////////////////////// +/// \brief Constructor loading data from a config file +/// +/// If no configuration path is defined using TRestMetadata::SetConfigFilePath +/// the path to the config file must be specified using full path, absolute or +/// relative. +/// +/// The default behaviour is that the config file must be specified with +/// full path, absolute or relative. +/// +/// \param cfgFileName A const char* giving the path to an RML file. +/// \param name The name of the specific metadata. It will be used to find the +/// corresponding TRestAxionMagneticField section inside the RML. +/// +TRestAxionSolarHiddenPhotonFlux::TRestAxionSolarHiddenPhotonFlux(const char* cfgFileName, string name) + : TRestAxionSolarFlux(cfgFileName) { + LoadConfigFromFile(fConfigFileName, name); + + if (GetVerboseLevel() >= TRestStringOutput::REST_Verbose_Level::REST_Info) PrintMetadata(); +} + +/////////////////////////////////////////////// +/// \brief Default destructor +/// +TRestAxionSolarHiddenPhotonFlux::~TRestAxionSolarHiddenPhotonFlux() {} + +/////////////////////////////////////////////// +/// \brief It will load the tables in memory by using the filename information provided +/// inside the metadata members, and calculate the solar flux for a given m. +/// +Bool_t TRestAxionSolarHiddenPhotonFlux::LoadTables() { + + if (GetMass() <= 0 ) { + RESTWarning << "TRestAxionSolarHiddenPhotonFlux::LoadTables - hidden photon mass not yet defined" << RESTendl; + RESTWarning << "TRestAxionSolarHiddenPhotonFlux::LoadTables - mass given as " << GetMass() << " eV" << RESTendl; + return false; + } + if ( fFluxDataFile == "" ){ + RESTWarning << "TRestAxionSolarHiddenPhotonFlux::LoadTables - flux table not found!!\n " << fFluxDataFile << RESTendl; + return false; + } + if ( fWidthDataFile == "") { + RESTWarning << "TRestAxionSolarHiddenPhotonFlux::LoadTables - width table not found!!\n " << fWidthDataFile << RESTendl; + return false; + } + if ( fPlasmaFreqDataFile == "" ) { + RESTWarning << "TRestAxionSolarHiddenPhotonFlux::LoadTables - plasma frequency table not found!!\n " << fPlasmaFreqDataFile << RESTendl; + return false; + } + + LoadContinuumFluxTable(); + LoadWidthTable(); + LoadPlasmaFreqTable(); + + CalculateSolarFlux(); + + IntegrateSolarFluxes(); + return true; +} + +/////////////////////////////////////////////// +/// \brief A helper method to load the data file containing continuum spectra as a +/// function of the solar radius. It will be called by TRestAxionSolarHiddenPhotonFlux::Initialize. +/// +void TRestAxionSolarHiddenPhotonFlux::LoadContinuumFluxTable() { + if (fFluxDataFile == "") { + RESTError + << "TRestAxionSolarHiddenPhotonFlux::LoadContinuumFluxTable. No solar flux table was defined" + << RESTendl; + return; + } + + string fullPathName = SearchFile((string)fFluxDataFile); + + RESTDebug << "Loading table from file : " << RESTendl; + RESTDebug << "File : " << fullPathName << RESTendl; + + if (!TRestTools::IsBinaryFile(fFluxDataFile)) { + fContinuumTable.clear(); + RESTError << "File is not in binary format!" << RESTendl; + } + + TRestTools::ReadBinaryTable(fullPathName, fContinuumTable); + + if (fContinuumTable.size() != 1000 || fContinuumTable[0].size() != 200) { + RESTError << "LoadContinuumFluxTable. The table does not contain the right number of rows or columns" + << RESTendl; + RESTError << "Table will not be populated" << RESTendl; + fContinuumTable.clear(); + } +} + +/////////////////////////////////////////////// +/// \brief A helper method to load the data file containing resonance width as a +/// function of the solar radius. It will be called by TRestAxionSolarHiddenPhotonFlux::Initialize. +/// +void TRestAxionSolarHiddenPhotonFlux::LoadWidthTable() { + if (fFluxDataFile == "") { + RESTError << "TRestAxionSolarHiddenPhotonFlux::LoadWidthTable. No width table was defined" + << RESTendl; + return; + } + + string fullPathName = SearchFile((string)fWidthDataFile); + + RESTDebug << "Loading table from file : " << RESTendl; + RESTDebug << "File : " << fullPathName << RESTendl; + + if (!TRestTools::IsBinaryFile(fWidthDataFile)) { + fWidthTable.clear(); + RESTError << "File is not in binary format!" << RESTendl; + } + + TRestTools::ReadBinaryTable(fullPathName, fWidthTable); + + if (fWidthTable.size() != 1000 || fWidthTable[0].size() != 200) { + RESTError << "LoadWidthTable. The table does not contain the right number of rows or columns" + << RESTendl; + RESTError << "Table will not be populated" << RESTendl; + fWidthTable.clear(); + } +} + +/////////////////////////////////////////////// +/// \brief A helper method to load the data file containing resonance width as a +/// function of the solar radius. It will be called by TRestAxionSolarHiddenPhotonFlux::Initialize. +/// +void TRestAxionSolarHiddenPhotonFlux::LoadPlasmaFreqTable() { + if (fFluxDataFile == "") { + RESTError + << "TRestAxionSolarHiddenPhotonFlux::LoadPlasmaFreqTable. No plasma frequency table was defined" + << RESTendl; + return; + } + + string fullPathName = SearchFile((string)fPlasmaFreqDataFile); + + RESTDebug << "Loading table from file : " << RESTendl; + RESTDebug << "File : " << fullPathName << RESTendl; + + if (!TRestTools::IsBinaryFile(fWidthDataFile)) { + RESTError << "File is not in binary format!" << RESTendl; + fPlasmaFreqTable.clear(); + } + + TRestTools::ReadBinaryTable(fullPathName, fPlasmaFreqTable); + + if (fPlasmaFreqTable.size() != 1000 || fPlasmaFreqTable[0].size() != 1) { + RESTError << "LoadPlasmaFreqTable. The table does not contain the right number of rows or columns" + << RESTendl; + RESTError << "Table will not be populated" << RESTendl; + fPlasmaFreqTable.clear(); + } +} + +/////////////////////////////////////////////// +/// \brief A helper method to calculate the real solar flux spectrum from the 3 tables, the +/// and the hidden photon mass for chi=1. +/// +void TRestAxionSolarHiddenPhotonFlux::CalculateSolarFlux() { + if (GetMass() == 0) { + RESTError << "CalculateSolarFlux. The hidden photon mass is set to zero!" << RESTendl; + return; + } + if (fContinuumTable.size() == 0 ) { + RESTError << "TRestAxionSolarHiddenPhotonFlux::CalculateSolarFlux - empty flux table!" << RESTendl; + return; + } + if (fPlasmaFreqTable.size() == 0 ) { + RESTError << "TRestAxionSolarHiddenPhotonFlux::CalculateSolarFlux - empty plasma freq table!" << RESTendl; + return; + } + if (fWidthTable.size() == 0 ) { + RESTError << "TRestAxionSolarHiddenPhotonFlux::CalculateSolarFlux - empty width table!" << RESTendl; + return; + } + fFluxTable.clear(); + Double_t mass = GetMass(); + for (unsigned int n = 0; n < fContinuumTable.size(); n++) { + // m4 * chi2 * wG * flux / ( (m2 - wp2)^2 + (w G)^2 ) + + Double_t wp = fPlasmaFreqTable[n][0]; + vector wG = fWidthTable[n]; + vector flux = fContinuumTable[n]; + vector v; + for( unsigned int c; c < wG.size(); c++ ) { + Double_t d1 = ( wG[c] * flux[c] * pow(mass,4) ); // m4 * wG * flux + Double_t d2 = ( pow( pow(mass,2) - pow(wp,2) , 2 ) + pow(wG[c],2) ); // m4 * wG * flux / ( (m2 - wp2)^2 + (w G)^2 ) + v.push_back(d1/d2); + } + + TH1D* h = new TH1D(Form("%s_TotalFluxTable%d", GetName(), n), "", 200, 0, 20); + for (unsigned int c = 0; c < v.size(); c++) { h->SetBinContent(c + 1, v[c]); } + //for (unsigned int c = 0; c < v.size(); c++) { h->Fill(v[c]); } + fFluxTable.push_back(h); + } +} + +/////////////////////////////////////////////// +/// \brief It builds a histogram with the continuum spectrum. +/// The flux will be expressed in cm-2 s-1 keV-1. Binned in 100eV steps. +/// +TH1D* TRestAxionSolarHiddenPhotonFlux::GetContinuumSpectrum() { + if (fContinuumHist != nullptr) { + delete fContinuumHist; + fContinuumHist = nullptr; + } + + fContinuumHist = new TH1D("ContinuumHist", "", 200, 0, 20); + for (const auto& x : fFluxTable) { + fContinuumHist->Add(x); + } + + fContinuumHist->SetStats(0); + fContinuumHist->GetXaxis()->SetTitle("Energy [keV]"); + fContinuumHist->GetXaxis()->SetTitleSize(0.05); + fContinuumHist->GetXaxis()->SetLabelSize(0.05); + fContinuumHist->GetYaxis()->SetTitle("Flux [cm-2 s-1 keV-1]"); + fContinuumHist->GetYaxis()->SetTitleSize(0.05); + fContinuumHist->GetYaxis()->SetLabelSize(0.05); + + return fContinuumHist; +} + +/////////////////////////////////////////////// +/// \brief Same as GetContinuumSpectrum, the flux will be +/// expressed in cm-2 s-1 keV-1. Binned in 1eV steps. +/// +TH1D* TRestAxionSolarHiddenPhotonFlux::GetTotalSpectrum() { + TH1D* hc = GetContinuumSpectrum(); + + if (fTotalHist != nullptr) { + delete fTotalHist; + fTotalHist = nullptr; + } + + fTotalHist = new TH1D("fTotalHist", "", 20000, 0, 20); + for (int n = 0; n < hc->GetNbinsX(); n++) { + for (int m = 0; m < 100; m++) { + fTotalHist->SetBinContent(n * 100 + 1 + m, hc->GetBinContent(n + 1)); + } + } + + fTotalHist->SetStats(0); + fTotalHist->GetXaxis()->SetTitle("Energy [keV]"); + fTotalHist->GetXaxis()->SetTitleSize(0.05); + fTotalHist->GetXaxis()->SetLabelSize(0.05); + fTotalHist->GetYaxis()->SetTitle("Flux [cm-2 s-1 keV-1]"); + fTotalHist->GetYaxis()->SetTitleSize(0.05); + fTotalHist->GetYaxis()->SetLabelSize(0.05); + + return fTotalHist; +} + +/////////////////////////////////////////////// +/// \brief A helper method to initialize the internal class data members with the +/// integrated flux for each solar ring. It will be called by TRestAxionSolarHiddenPhotonFlux::Initialize. +/// +void TRestAxionSolarHiddenPhotonFlux::IntegrateSolarFluxes() { + fTotalContinuumFlux = 0.0; + for (unsigned int n = 0; n < fFluxTable.size(); n++) { + fTotalContinuumFlux += fFluxTable[n]->Integral() * 0.1; // We integrate in 100eV steps + fFluxTableIntegrals.push_back(fTotalContinuumFlux); + } + + for (unsigned int n = 0; n < fFluxTableIntegrals.size(); n++) + fFluxTableIntegrals[n] /= fTotalContinuumFlux; +} + +/////////////////////////////////////////////// +/// \brief It returns the integrated flux at earth in cm-2 s-1 for the given energy range +/// +Double_t TRestAxionSolarHiddenPhotonFlux::IntegrateFluxInRange(TVector2 eRange) { + if (eRange.X() == -1 && eRange.Y() == -1) { + if (GetTotalFlux() == 0) IntegrateSolarFluxes(); + return GetTotalFlux(); + } + + Double_t flux = 0; + fTotalContinuumFlux = 0.0; + for (unsigned int n = 0; n < fFluxTable.size(); n++) { + flux += fFluxTable[n]->Integral(fFluxTable[n]->FindFixBin(eRange.X()), + fFluxTable[n]->FindFixBin(eRange.Y())) * + 0.1; // We integrate in 100eV steps + } + + return flux; +} + +/////////////////////////////////////////////// +/// \brief It returns a random solar radius position and energy according to the +/// flux distributions defined inside the solar tables loaded in the class +/// +std::pair TRestAxionSolarHiddenPhotonFlux::GetRandomEnergyAndRadius(TVector2 eRange) { + + std::pair result = {0, 0}; + if (!AreTablesLoaded()) { RESTWarning << "Tables not loaded!!" << RESTendl; return result; } + Double_t rnd = fRandom->Rndm(); + for (unsigned int r = 0; r < fFluxTableIntegrals.size(); r++) { + if (rnd < fFluxTableIntegrals[r]) { + Double_t energy = fFluxTable[r]->GetRandom(); + if (eRange.X() != -1 && eRange.Y() != -1) { + if (energy < eRange.X() || energy > eRange.Y()) return GetRandomEnergyAndRadius(eRange); + } + Double_t radius = ((Double_t)r + fRandom->Rndm()) * 0.001; + std::pair p = {energy, radius}; + return p; + } + } + return result; +} + +/////////////////////////////////////////////// +/// \brief It prints on screen the flux table that has been read from file +/// +void TRestAxionSolarHiddenPhotonFlux::PrintContinuumSolarTable() { + cout << "Continuum solar flux table: " << endl; + cout << "--------------------------- " << endl; + for (unsigned int n = 0; n < fFluxTable.size(); n++) { + for (int m = 0; m < fFluxTable[n]->GetNbinsX(); m++) + cout << fFluxTable[n]->GetBinContent(m + 1) << "\t"; + cout << endl; + cout << endl; + } + cout << endl; +} + +/////////////////////////////////////////////// +/// \brief It prints on screen the integrated solar flux per solar ring +/// +void TRestAxionSolarHiddenPhotonFlux::PrintIntegratedRingFlux() { + cout << "Integrated solar flux per solar ring: " << endl; + cout << "--------------------------- " << endl; + /* + for (int n = 0; n < fFluxPerRadius.size(); n++) + cout << "n : " << n << " flux : " << fFluxPerRadius[n] << endl; + cout << endl; + */ +} + +/////////////////////////////////////////////// +/// \brief Prints on screen the information about the metadata members of TRestAxionSolarHiddenPhotonFlux +/// +void TRestAxionSolarHiddenPhotonFlux::PrintMetadata() { + TRestAxionSolarFlux::PrintMetadata(); + + RESTMetadata << " - Solar hidden photon datafile (flux) : " << fFluxDataFile << RESTendl; + RESTMetadata << " - Solar hidden photon datafile (width) : " << fWidthDataFile << RESTendl; + RESTMetadata << " - Solar hidden photon datafile (plasma freq) : " << fPlasmaFreqDataFile << RESTendl; + RESTMetadata << "-------" << RESTendl; + RESTMetadata << " - Total continuum flux : " << fTotalContinuumFlux << " cm-2 s-1" << RESTendl; + RESTMetadata << "++++++++++++++++++" << RESTendl; + + if (GetVerboseLevel() >= TRestStringOutput::REST_Verbose_Level::REST_Debug) { + PrintContinuumSolarTable(); + PrintIntegratedRingFlux(); + } +} + +/////////////////////////////////////////////// +/// \brief It will create files with spectra to be used +/// in a later ocasion. +/// +void TRestAxionSolarHiddenPhotonFlux::ExportTables(Bool_t ascii) { + string rootFilename = TRestTools::GetFileNameRoot(fFluxDataFile); + + string path = REST_USER_PATH + "/export/"; + + if (!TRestTools::fileExists(path)) { + std::cout << "Creating path: " << path << std::endl; + int z = system(("mkdir -p " + path).c_str()); + if (z != 0) RESTError << "Could not create directory " << path << RESTendl; + } + + if (fFluxTable.size() > 0) { + std::vector> table; + for (const auto& x : fFluxTable) { + std::vector row; + for (int n = 0; n < x->GetNbinsX(); n++) row.push_back(x->GetBinContent(n + 1)); + + table.push_back(row); + } + + if (!ascii) + TRestTools::ExportBinaryTable(path + "/" + rootFilename + ".N200f", table); + else + TRestTools::ExportASCIITable(path + "/" + rootFilename + ".dat", table); + } +} + +/////////////////////////////////////////////// +/// \brief It draws the contents of a .flux file. This method just receives the +/// +TCanvas* TRestAxionSolarHiddenPhotonFlux::DrawSolarFlux() { + if (fCanvas != nullptr) { + delete fCanvas; + fCanvas = nullptr; + } + fCanvas = new TCanvas("canv", "This is the canvas title", 1200, 500); + fCanvas->Draw(); + + TPad* pad1 = new TPad("pad1", "This is pad1", 0.01, 0.02, 0.99, 0.97); + pad1->Divide(2, 1); + pad1->Draw(); + + pad1->cd(1); + pad1->cd(1)->SetLogy(); + pad1->cd(1)->SetRightMargin(0.09); + pad1->cd(1)->SetLeftMargin(0.15); + pad1->cd(1)->SetBottomMargin(0.15); + + TH1D* ht = GetTotalSpectrum(); + ht->SetLineColor(kBlack); + ht->SetFillStyle(4050); + ht->SetFillColor(kBlue - 10); + + ht->Draw("hist"); + + pad1->cd(2); + pad1->cd(2)->SetRightMargin(0.09); + pad1->cd(2)->SetLeftMargin(0.15); + pad1->cd(2)->SetBottomMargin(0.15); + + ht->Draw("hist"); + + return fCanvas; +} + diff --git a/src/TRestAxionSolarHiddenPhotonFlux.cxx.old b/src/TRestAxionSolarHiddenPhotonFlux.cxx.old new file mode 100644 index 00000000..e61f0630 --- /dev/null +++ b/src/TRestAxionSolarHiddenPhotonFlux.cxx.old @@ -0,0 +1,613 @@ +/******************** REST disclaimer *********************************** + * This file is part of the REST software framework. * + * * + * Copyright (C) 2016 GIFNA/TREX (University of Zaragoza) * + * For more information see http://gifna.unizar.es/trex * + * * + * REST 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. * + * * + * REST 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 a copy of the GNU General Public License along with * + * REST in $REST_PATH/LICENSE. * + * If not, see http://www.gnu.org/licenses/. * + * For the list of contributors see $REST_PATH/CREDITS. * + *************************************************************************/ + +////////////////////////////////////////////////////////////////////////// +/// TRestAxionSolarHiddenPhotonFlux will use a file in binary format to initialize +/// a solar flux table that will describe the solar hidden photon flux spectrum as a function +/// of the solar radius. +/// +/// This class loads the hidden photon flux that depends on the mass and kinetic mixing parameter. +/// For axion-like particle prodution independent of mass there is the class +/// TRestAxionSolarQCDFlux. Both classes are prototyped by a pure base class TRestAxionSolarFlux +/// that defines common methods used to evaluate the flux, and generate Monte-Carlo events inside +/// TRestAxionGeneratorProcess. +/// +/// ### Basic use +/// +/// Once the class has been initialized, the main use of this class will be provided +/// by the method TRestAxionSolarHiddenPhotonFlux::GetRandomEnergyAndRadius. This method will +/// return a random axion energy and position inside the solar radius following the +/// distributions given by the solar flux tables. +/// +/// Description of the specific parameters accepted by this metadata class. +/// - *fluxDataFile:* A table with 1000 rows representing the solar ring flux from the +/// center to the corona, and 200 columns representing the flux, measured in cm-2 s-1 keV-1, +/// for the range (0,20)keV in steps of 100eV. The table is provided as a binary table using +/// `.N200f` extension. +/// - *widthDataFile:* A table with 1000 rows representing the width of the hidden photon +/// resonant production (wG) for each solar ring from the center to the corona, and 200 columns +/// representing the width, measured in eV2, for the range (0,20)keV in steps of 100eV. The +/// table is provided as a binary table using `.N200f` extension. +/// - *plasmaFreqDataFile:* A table with 1000 rows and only 1 column representing the solar +/// plasma frequency (wp) for each solar ring from the center to the corona, measured in eV. The +/// table is provided as a binary table using `.N1f` extension. +/// +/// Pre-generated solar axion flux tables will be available at the +/// [axionlib-data](https://github.com/rest-for-physics/axionlib-data/tree/master) +/// repository. The different RML flux definitions used to load those tables +/// will be found at the +/// [fluxes.rml](https://github.com/rest-for-physics/axionlib-data/blob/master/solarFlux/fluxes.rml) +/// file found at the axionlib-data repository. +/// +/// Inside a local REST installation, the `fluxes.rml` file will be found at the REST +/// installation directory, and it will be located automatically by the +/// TRestMetadata::SearchFile method. +/// +/// ### A basic RML definition +/// +/// The following definition integrates an axion-photon component with a continuum +/// spectrum using a Primakoff production model, and a dummy spectrum file that +/// includes two monocrhomatic lines at different solar disk radius positions. +/// +/// \code +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// \endcode +/// +/// \warning When the flux is loaded manually inside the `restRoot` interactive +/// shell, or inside a macro or script, after metadata initialization, it is necessary +/// to call the method TRestAxionSolarHiddenPhotonFlux::LoadTables(mass) to trigger the tables +/// initialization. +/// +/// ### Performing MonteCarlo tests using pre-loaded tables +/// +/// In order to test the response of different solar flux definitions we may use the script +/// `solarPlot.py` found at `pipeline/metadata/solarFlux/`. This script will generate a +/// number of particles and it will assign to each particle an energy and solar disk +/// location with the help of the method TRestAxionSolarHiddenPhotonFlux::GetRandomEnergyAndRadius. +/// +/// \code +/// python3 solarPlotHiddenPhoton.py --fluxname HiddenPhoton --N 1000000 +/// \endcode +/// +/// By default, it will load the flux definition found at `fluxes.rml` from the +/// `axionlib-data` repository, and generate a `png` image with the resuts from the +/// Monte Carlo execution. +/// +/// \htmlonly \endhtmlonly +/// +/// ![Solar flux distributions MC-generated with TRestAxionSolarQCDFlux.](ABC_flux_MC.png) +/// +/// ### Exporting the solar flux tables +/// +/// On top of that, we will be able to export those tables to the TRestAxionSolarHiddenPhotonFlux +/// standard format to be used in later occasions. +/// +/// \code +/// TRestAxionSolarHiddenPhotonFlux *sFlux = new TRestAxionSolarHiddenPhotonFlux("fluxes.rml", +/// "HiddenPhoton") sFlux->Initialize() sFlux->ExportTables() +/// \endcode +/// +/// which will produce a binary table `.N200f` with the continuum flux. The filename root will be +/// extracted from the original `.flux` file. Optionally we may export the continuum flux to an +/// ASCII file by indicating it at the TRestAxionSolarHiddenPhotonFlux::ExportTables method call. +/// The files will be placed at the REST user space, at `$HOME/.rest/export/` directory. +/// +/// TODO Implement the method TRestAxionSolarQCDFlux::InitializeSolarTable using +/// a solar model description by TRestAxionSolarModel. +/// +/// TODO Perhaps it would be interesting to replace fFluxTable for a TH2D +/// +///-------------------------------------------------------------------------- +/// +/// RESTsoft - Software for Rare Event Searches with TPCs +/// +/// History of developments: +/// +/// 2023-May: Specific methods extracted from TRestAxionSolarFlux +/// Javier Galan +/// 2023-June: TRestAxionSolarHiddenPhotonFlux created by editing TRestAxionSolarQCDFlux +/// Tomas O'Shea +/// +/// \class TRestAxionSolarHiddenPhotonFlux +/// \author Javier Galan +/// +///
+/// + +#include "TRestAxionSolarHiddenPhotonFlux.h" +using namespace std; + +ClassImp(TRestAxionSolarHiddenPhotonFlux); + +/////////////////////////////////////////////// +/// \brief Default constructor +/// +TRestAxionSolarHiddenPhotonFlux::TRestAxionSolarHiddenPhotonFlux() : TRestAxionSolarFlux() {} + +/////////////////////////////////////////////// +/// \brief Constructor loading data from a config file +/// +/// If no configuration path is defined using TRestMetadata::SetConfigFilePath +/// the path to the config file must be specified using full path, absolute or +/// relative. +/// +/// The default behaviour is that the config file must be specified with +/// full path, absolute or relative. +/// +/// \param cfgFileName A const char* giving the path to an RML file. +/// \param name The name of the specific metadata. It will be used to find the +/// corresponding TRestAxionMagneticField section inside the RML. +/// +TRestAxionSolarHiddenPhotonFlux::TRestAxionSolarHiddenPhotonFlux(const char* cfgFileName, string name) + : TRestAxionSolarFlux(cfgFileName) { + LoadConfigFromFile(fConfigFileName, name); + + if (GetVerboseLevel() >= TRestStringOutput::REST_Verbose_Level::REST_Info) PrintMetadata(); +} + +/////////////////////////////////////////////// +/// \brief Default destructor +/// +TRestAxionSolarHiddenPhotonFlux::~TRestAxionSolarHiddenPhotonFlux() {} + +/////////////////////////////////////////////// +/// \brief It will load the tables in memory by using the filename information provided +/// inside the metadata members, and calculate the solar flux for a given m. +/// +Bool_t TRestAxionSolarHiddenPhotonFlux::LoadTables() { + + if (GetMass() <= 0 ) { + RESTWarning << "TRestAxionSolarHiddenPhotonFlux::LoadTables - hidden photon mass not yet defined" << RESTendl; + RESTWarning << "TRestAxionSolarHiddenPhotonFlux::LoadTables - mass given as " << GetMass() << " eV" << RESTendl; + return false; + } + if ( fFluxDataFile == "" ){ + RESTWarning << "TRestAxionSolarHiddenPhotonFlux::LoadTables - flux table not found!!\n " << fFluxDataFile << RESTendl; + return false; + } + if ( fWidthDataFile == "") { + RESTWarning << "TRestAxionSolarHiddenPhotonFlux::LoadTables - width table not found!!\n " << fWidthDataFile << RESTendl; + return false; + } + if ( fPlasmaFreqDataFile == "" ) { + RESTWarning << "TRestAxionSolarHiddenPhotonFlux::LoadTables - plasma frequency table not found!!\n " << fPlasmaFreqDataFile << RESTendl; + return false; + } + + LoadContinuumFluxTable(); + LoadWidthTable(); + LoadPlasmaFreqTable(); + + CalculateSolarFlux(); + + IntegrateSolarFluxes(); + return true; +} + +/////////////////////////////////////////////// +/// \brief A helper method to load the data file containing continuum spectra as a +/// function of the solar radius. It will be called by TRestAxionSolarHiddenPhotonFlux::Initialize. +/// +void TRestAxionSolarHiddenPhotonFlux::LoadContinuumFluxTable() { + if (fFluxDataFile == "") { + RESTError + << "TRestAxionSolarHiddenPhotonFlux::LoadContinuumFluxTable. No solar flux table was defined" + << RESTendl; + return; + } + + string fullPathName = SearchFile((string)fFluxDataFile); + + RESTDebug << "Loading table from file : " << RESTendl; + RESTDebug << "File : " << fullPathName << RESTendl; + + std::vector> fluxTable; + + if (!TRestTools::IsBinaryFile(fFluxDataFile)) { + fluxTable.clear(); + RESTError << "File is not in binary format!" << RESTendl; + } + + TRestTools::ReadBinaryTable(fullPathName, fluxTable); + + if (fluxTable.size() != 1000 || fluxTable[0].size() != 200) { + fluxTable.clear(); + RESTError << "LoadContinuumFluxTable. The table does not contain the right number of rows or columns" + << RESTendl; + RESTError << "Table will not be populated" << RESTendl; + } + + for (unsigned int n = 0; n < fluxTable.size(); n++) { + TH1D* h = new TH1D(Form("%s_ContinuumFluxAtRadius%d", GetName(), n), "", 200, 0, 20); + for (unsigned int m = 0; m < fluxTable[n].size(); m++) { h->SetBinContent(m + 1, fluxTable[n][m]); } + fContinuumTable.push_back(h); + } +} + +/////////////////////////////////////////////// +/// \brief A helper method to load the data file containing resonance width as a +/// function of the solar radius. It will be called by TRestAxionSolarHiddenPhotonFlux::Initialize. +/// +void TRestAxionSolarHiddenPhotonFlux::LoadWidthTable() { + if (fFluxDataFile == "") { + RESTError << "TRestAxionSolarHiddenPhotonFlux::LoadWidthTable. No width table was defined" + << RESTendl; + return; + } + + string fullPathName = SearchFile((string)fWidthDataFile); + + RESTDebug << "Loading table from file : " << RESTendl; + RESTDebug << "File : " << fullPathName << RESTendl; + + std::vector> fluxTable; + + if (!TRestTools::IsBinaryFile(fWidthDataFile)) { + fluxTable.clear(); + RESTError << "File is not in binary format!" << RESTendl; + } + + TRestTools::ReadBinaryTable(fullPathName, fluxTable); + //RESTMetadata << "Width table rows / columns: " << fluxTable.size() << " " << fluxTable[0].size() << RESTendl; + + if (fluxTable.size() != 1000 || fluxTable[0].size() != 200) { + fluxTable.clear(); + RESTError << "LoadWidthTable. The table does not contain the right number of rows or columns" + << RESTendl; + RESTError << "Table will not be populated" << RESTendl; + } + + for (unsigned int n = 0; n < fluxTable.size(); n++) { + TH1D* h = new TH1D(Form("%s_ResonanceWidthAtRadius%d", GetName(), n), "", 200, 0, 20); + for (unsigned int m = 0; m < fluxTable[n].size(); m++) { h->SetBinContent(m + 1, fluxTable[n][m]); } + fWidthTable.push_back(h); + } +} + +/////////////////////////////////////////////// +/// \brief A helper method to load the data file containing resonance width as a +/// function of the solar radius. It will be called by TRestAxionSolarHiddenPhotonFlux::Initialize. +/// +void TRestAxionSolarHiddenPhotonFlux::LoadPlasmaFreqTable() { + if (fFluxDataFile == "") { + RESTError + << "TRestAxionSolarHiddenPhotonFlux::LoadPlasmaFreqTable. No plasma frequency table was defined" + << RESTendl; + return; + } + + string fullPathName = SearchFile((string)fPlasmaFreqDataFile); + + RESTDebug << "Loading table from file : " << RESTendl; + RESTDebug << "File : " << fullPathName << RESTendl; + + std::vector> fluxTable; + + if (!TRestTools::IsBinaryFile(fWidthDataFile)) { + fluxTable.clear(); + RESTError << "File is not in binary format!" << RESTendl; + } + + TRestTools::ReadBinaryTable(fullPathName, fluxTable); + + if (fluxTable.size() != 1000 || fluxTable[0].size() != 1) { + fluxTable.clear(); + RESTError << "LoadPlasmaFreqTable. The table does not contain the right number of rows or columns" + << RESTendl; + RESTError << "Table will not be populated" << RESTendl; + } + + for (unsigned int n = 0; n < fluxTable.size(); n++) { + TH1D* h = new TH1D(Form("%s_PlasmaFreqAtRadius%d", GetName(), n), "", 1, 0, 20); + for (unsigned int m = 0; m < fluxTable[n].size(); m++) { h->SetBinContent(m + 1, fluxTable[n][m]); } + fPlasmaFreqTable.push_back(h); + } +} + +/////////////////////////////////////////////// +/// \brief A helper method to calculate the real solar flux spectrum from the 3 tables, the +/// and the hidden photon mass for chi=1. +/// +void TRestAxionSolarHiddenPhotonFlux::CalculateSolarFlux() { + if (GetMass() == 0) { + RESTError << "CalculateSolarFlux. The hidden photon mass is set to zero!" << RESTendl; + return; + } + if (fContinuumTable.size() == 0 ) { + RESTError << "TRestAxionSolarHiddenPhotonFlux::CalculateSolarFlux - empty flux table!" << RESTendl; + return; + } + if (fPlasmaFreqTable.size() == 0 ) { + RESTError << "TRestAxionSolarHiddenPhotonFlux::CalculateSolarFlux - empty plasma freq table!" << RESTendl; + return; + } + if (fWidthTable.size() == 0 ) { + RESTError << "TRestAxionSolarHiddenPhotonFlux::CalculateSolarFlux - empty width table!" << RESTendl; + return; + } + + Double_t mass = GetMass(); + cout << mass << endl; + for (unsigned int n = 0; n < fContinuumTable.size(); n++) { + // m4 * chi2 * wG * flux / ( (m2 - wp2)^2 + (w G)^2 ) + + Double_t wp = fPlasmaFreqTable[n]->GetBinContent(1); + TH1D* hMass = new TH1D(Form("%s_hMass%d", GetName(), n), "hMass", 200, 0, 20); + TH1D* hWg2 = (TH1D*)fWidthTable[n]->Clone(); + hWg2->Multiply(hWg2); // (w G)^2 + + for ( unsigned int c; c < 200; c++ ) { + Double_t wG = fWidthTable[n]->GetBinContent(c+1); + hMass->SetBinContent( c+1, pow(mass,-4) * ( pow( pow(mass,2) - pow(wp,2) , 2 )));// + pow(wG,2) ) ); // m2 + } + + hMass->Add(hWg2); // (m2 - wp2)^2 + (w G)^2 + + TH1D* h = (TH1D*)fWidthTable[n]->Clone(); // wG + h->Multiply(fContinuumTable[n]); // wG * flux + h->Divide(hMass); // wG * flux / ( (m2 - wp2)^2 + (w G)^2 ) + //h->Scale(pow(mass, 4)); // m4 * wG * flux / ( (m2 - wp2)^2 + (w G)^2 ) + + fFluxTable.push_back(h); + } +} + +/////////////////////////////////////////////// +/// \brief It builds a histogram with the continuum spectrum. +/// The flux will be expressed in cm-2 s-1 keV-1. Binned in 100eV steps. +/// +TH1D* TRestAxionSolarHiddenPhotonFlux::GetContinuumSpectrum() { + if (fContinuumHist != nullptr) { + delete fContinuumHist; + fContinuumHist = nullptr; + } + + fContinuumHist = new TH1D("ContinuumHist", "", 200, 0, 20); + for (const auto& x : fFluxTable) { + fContinuumHist->Add(x); + } + + fContinuumHist->SetStats(0); + fContinuumHist->GetXaxis()->SetTitle("Energy [keV]"); + fContinuumHist->GetXaxis()->SetTitleSize(0.05); + fContinuumHist->GetXaxis()->SetLabelSize(0.05); + fContinuumHist->GetYaxis()->SetTitle("Flux [cm-2 s-1 keV-1]"); + fContinuumHist->GetYaxis()->SetTitleSize(0.05); + fContinuumHist->GetYaxis()->SetLabelSize(0.05); + + return fContinuumHist; +} + +/////////////////////////////////////////////// +/// \brief Same as GetContinuumSpectrum, the flux will be +/// expressed in cm-2 s-1 keV-1. Binned in 1eV steps. +/// +TH1D* TRestAxionSolarHiddenPhotonFlux::GetTotalSpectrum() { + TH1D* hc = GetContinuumSpectrum(); + + if (fTotalHist != nullptr) { + delete fTotalHist; + fTotalHist = nullptr; + } + + fTotalHist = new TH1D("fTotalHist", "", 20000, 0, 20); + for (int n = 0; n < hc->GetNbinsX(); n++) { + for (int m = 0; m < 100; m++) { + fTotalHist->SetBinContent(n * 100 + 1 + m, hc->GetBinContent(n + 1)); + } + } + + fTotalHist->SetStats(0); + fTotalHist->GetXaxis()->SetTitle("Energy [keV]"); + fTotalHist->GetXaxis()->SetTitleSize(0.05); + fTotalHist->GetXaxis()->SetLabelSize(0.05); + fTotalHist->GetYaxis()->SetTitle("Flux [cm-2 s-1 keV-1]"); + fTotalHist->GetYaxis()->SetTitleSize(0.05); + fTotalHist->GetYaxis()->SetLabelSize(0.05); + + return fTotalHist; +} + +/////////////////////////////////////////////// +/// \brief A helper method to initialize the internal class data members with the +/// integrated flux for each solar ring. It will be called by TRestAxionSolarHiddenPhotonFlux::Initialize. +/// +void TRestAxionSolarHiddenPhotonFlux::IntegrateSolarFluxes() { + fTotalContinuumFlux = 0.0; + for (unsigned int n = 0; n < fFluxTable.size(); n++) { + fTotalContinuumFlux += fFluxTable[n]->Integral() * 0.1; // We integrate in 100eV steps + fFluxTableIntegrals.push_back(fTotalContinuumFlux); + } + + for (unsigned int n = 0; n < fFluxTableIntegrals.size(); n++) + fFluxTableIntegrals[n] /= fTotalContinuumFlux; +} + +/////////////////////////////////////////////// +/// \brief It returns the integrated flux at earth in cm-2 s-1 for the given energy range +/// +Double_t TRestAxionSolarHiddenPhotonFlux::IntegrateFluxInRange(TVector2 eRange) { + if (eRange.X() == -1 && eRange.Y() == -1) { + if (GetTotalFlux() == 0) IntegrateSolarFluxes(); + return GetTotalFlux(); + } + + Double_t flux = 0; + fTotalContinuumFlux = 0.0; + for (unsigned int n = 0; n < fFluxTable.size(); n++) { + flux += fFluxTable[n]->Integral(fFluxTable[n]->FindFixBin(eRange.X()), + fFluxTable[n]->FindFixBin(eRange.Y())) * + 0.1; // We integrate in 100eV steps + } + + return flux; +} + +/////////////////////////////////////////////// +/// \brief It returns a random solar radius position and energy according to the +/// flux distributions defined inside the solar tables loaded in the class +/// +std::pair TRestAxionSolarHiddenPhotonFlux::GetRandomEnergyAndRadius(TVector2 eRange) { + + std::pair result = {0, 0}; + if (!AreTablesLoaded()) { RESTWarning << "Tables not loaded!!" << RESTendl; return result; } + Double_t rnd = fRandom->Rndm(); + for (unsigned int r = 0; r < fFluxTableIntegrals.size(); r++) { + if (rnd < fFluxTableIntegrals[r]) { + Double_t energy = fFluxTable[r]->GetRandom(); + if (eRange.X() != -1 && eRange.Y() != -1) { + if (energy < eRange.X() || energy > eRange.Y()) return GetRandomEnergyAndRadius(eRange); + } + Double_t radius = ((Double_t)r + fRandom->Rndm()) * 0.001; + std::pair p = {energy, radius}; + return p; + } + } + return result; +} + +/////////////////////////////////////////////// +/// \brief It prints on screen the flux table that has been read from file +/// +void TRestAxionSolarHiddenPhotonFlux::PrintContinuumSolarTable() { + cout << "Continuum solar flux table: " << endl; + cout << "--------------------------- " << endl; + for (unsigned int n = 0; n < fFluxTable.size(); n++) { + for (int m = 0; m < fFluxTable[n]->GetNbinsX(); m++) + cout << fFluxTable[n]->GetBinContent(m + 1) << "\t"; + cout << endl; + cout << endl; + } + cout << endl; +} + +/////////////////////////////////////////////// +/// \brief It prints on screen the integrated solar flux per solar ring +/// +void TRestAxionSolarHiddenPhotonFlux::PrintIntegratedRingFlux() { + cout << "Integrated solar flux per solar ring: " << endl; + cout << "--------------------------- " << endl; + /* + for (int n = 0; n < fFluxPerRadius.size(); n++) + cout << "n : " << n << " flux : " << fFluxPerRadius[n] << endl; + cout << endl; + */ +} + +/////////////////////////////////////////////// +/// \brief Prints on screen the information about the metadata members of TRestAxionSolarHiddenPhotonFlux +/// +void TRestAxionSolarHiddenPhotonFlux::PrintMetadata() { + TRestAxionSolarFlux::PrintMetadata(); + + RESTMetadata << " - Solar hidden photon datafile (flux) : " << fFluxDataFile << RESTendl; + RESTMetadata << " - Solar hidden photon datafile (width) : " << fWidthDataFile << RESTendl; + RESTMetadata << " - Solar hidden photon datafile (plasma freq) : " << fPlasmaFreqDataFile << RESTendl; + RESTMetadata << "-------" << RESTendl; + RESTMetadata << " - Total continuum flux : " << fTotalContinuumFlux << " cm-2 s-1" << RESTendl; + RESTMetadata << "++++++++++++++++++" << RESTendl; + + if (GetVerboseLevel() >= TRestStringOutput::REST_Verbose_Level::REST_Debug) { + PrintContinuumSolarTable(); + PrintIntegratedRingFlux(); + } +} + +/////////////////////////////////////////////// +/// \brief It will create files with spectra to be used +/// in a later ocasion. +/// +void TRestAxionSolarHiddenPhotonFlux::ExportTables(Bool_t ascii) { + string rootFilename = TRestTools::GetFileNameRoot(fFluxDataFile); + + string path = REST_USER_PATH + "/export/"; + + if (!TRestTools::fileExists(path)) { + std::cout << "Creating path: " << path << std::endl; + int z = system(("mkdir -p " + path).c_str()); + if (z != 0) RESTError << "Could not create directory " << path << RESTendl; + } + + if (fFluxTable.size() > 0) { + std::vector> table; + for (const auto& x : fFluxTable) { + std::vector row; + for (int n = 0; n < x->GetNbinsX(); n++) row.push_back(x->GetBinContent(n + 1)); + + table.push_back(row); + } + + if (!ascii) + TRestTools::ExportBinaryTable(path + "/" + rootFilename + ".N200f", table); + else + TRestTools::ExportASCIITable(path + "/" + rootFilename + ".dat", table); + } +} + +/////////////////////////////////////////////// +/// \brief It draws the contents of a .flux file. This method just receives the +/// +TCanvas* TRestAxionSolarHiddenPhotonFlux::DrawSolarFlux() { + if (fCanvas != nullptr) { + delete fCanvas; + fCanvas = nullptr; + } + fCanvas = new TCanvas("canv", "This is the canvas title", 1200, 500); + fCanvas->Draw(); + + TPad* pad1 = new TPad("pad1", "This is pad1", 0.01, 0.02, 0.99, 0.97); + pad1->Divide(2, 1); + pad1->Draw(); + + pad1->cd(1); + pad1->cd(1)->SetLogy(); + pad1->cd(1)->SetRightMargin(0.09); + pad1->cd(1)->SetLeftMargin(0.15); + pad1->cd(1)->SetBottomMargin(0.15); + + TH1D* ht = GetTotalSpectrum(); + ht->SetLineColor(kBlack); + ht->SetFillStyle(4050); + ht->SetFillColor(kBlue - 10); + + ht->Draw("hist"); + + pad1->cd(2); + pad1->cd(2)->SetRightMargin(0.09); + pad1->cd(2)->SetLeftMargin(0.15); + pad1->cd(2)->SetBottomMargin(0.15); + + ht->Draw("hist"); + + return fCanvas; +} + diff --git a/src/TRestAxionSolarQCDFlux.cxx b/src/TRestAxionSolarQCDFlux.cxx index 457bd31f..79b5452e 100644 --- a/src/TRestAxionSolarQCDFlux.cxx +++ b/src/TRestAxionSolarQCDFlux.cxx @@ -249,7 +249,7 @@ TRestAxionSolarQCDFlux::~TRestAxionSolarQCDFlux() {} /// \brief It will load the tables in memory by using the filename information provided /// inside the metadata members. /// -Bool_t TRestAxionSolarQCDFlux::LoadTables(Double_t mass) { +Bool_t TRestAxionSolarQCDFlux::LoadTables() { if (fFluxDataFile == "" && fFluxSptFile == "") return false; if (TRestTools::GetFileNameExtension(fFluxDataFile) == "flux") { @@ -265,7 +265,7 @@ Bool_t TRestAxionSolarQCDFlux::LoadTables(Double_t mass) { } /////////////////////////////////////////////// -/// \brief A helper method to load the data file containning continuum spectra as a +/// \brief A helper method to load the data file containing continuum spectra as a /// function of the solar radius. It will be called by TRestAxionSolarQCDFlux::Initialize. /// void TRestAxionSolarQCDFlux::LoadContinuumFluxTable() { @@ -280,7 +280,7 @@ void TRestAxionSolarQCDFlux::LoadContinuumFluxTable() { RESTDebug << "Loading table from file : " << RESTendl; RESTDebug << "File : " << fullPathName << RESTendl; - std::vector> fluxTable; + std::vector> fluxTable; if (TRestTools::GetFileNameExtension(fFluxDataFile) == "dat") { std::vector> doubleTable; if (!TRestTools::ReadASCIITable(fullPathName, doubleTable)) { @@ -289,8 +289,8 @@ void TRestAxionSolarQCDFlux::LoadContinuumFluxTable() { return; } for (const auto& row : doubleTable) { - std::vector floatVec(row.begin(), row.end()); - fluxTable.push_back(floatVec); + std::vector doubleVec(row.begin(), row.end()); + fluxTable.push_back(doubleVec); } } else if (TRestTools::IsBinaryFile(fFluxDataFile)) TRestTools::ReadBinaryTable(fullPathName, fluxTable); @@ -309,14 +309,14 @@ void TRestAxionSolarQCDFlux::LoadContinuumFluxTable() { } for (unsigned int n = 0; n < fluxTable.size(); n++) { - TH1F* h = new TH1F(Form("%s_ContinuumFluxAtRadius%d", GetName(), n), "", 200, 0, 20); + TH1D* h = new TH1D(Form("%s_ContinuumFluxAtRadius%d", GetName(), n), "", 200, 0, 20); for (unsigned int m = 0; m < fluxTable[n].size(); m++) h->SetBinContent(m + 1, fluxTable[n][m]); fFluxTable.push_back(h); } } /////////////////////////////////////////////// -/// \brief A helper method to load the data file containning monochromatic spectral +/// \brief A helper method to load the data file containing monochromatic spectral /// lines as a function of the solar radius. It will be called by TRestAxionSolarQCDFlux::Initialize. /// void TRestAxionSolarQCDFlux::LoadMonoChromaticFluxTable() { @@ -339,10 +339,10 @@ void TRestAxionSolarQCDFlux::LoadMonoChromaticFluxTable() { return; } - std::vector> asciiTable; + std::vector> asciiTable; for (const auto& row : doubleTable) { - std::vector floatVec(row.begin(), row.end()); - asciiTable.push_back(floatVec); + std::vector doubleVec(row.begin(), row.end()); + asciiTable.push_back(doubleVec); } fFluxLines.clear(); @@ -355,8 +355,8 @@ void TRestAxionSolarQCDFlux::LoadMonoChromaticFluxTable() { } for (unsigned int en = 0; en < asciiTable[0].size(); en++) { - Float_t energy = asciiTable[0][en]; - TH1F* h = new TH1F(Form("%s_MonochromeFluxAtEnergy%6.4lf", GetName(), energy), "", 100, 0, 1); + Double_t energy = asciiTable[0][en]; + TH1D* h = new TH1D(Form("%s_MonochromeFluxAtEnergy%6.4lf", GetName(), energy), "", 100, 0, 1); for (unsigned int r = 1; r < asciiTable.size(); r++) h->SetBinContent(r, asciiTable[r][en]); fFluxLines[energy] = h; } @@ -399,12 +399,12 @@ void TRestAxionSolarQCDFlux::ReadFluxFile() { Double_t fluxBinSize = TRestTools::GetLowestIncreaseFromTable(fluxData, 1); for (const auto& data : fluxData) { - Float_t r = 0.005 + data[0]; - Float_t en = data[1] - 0.005; - Float_t flux = data[2] * fluxBinSize; // flux in cm-2 s-1 bin-1 + Double_t r = 0.005 + data[0]; + Double_t en = data[1] - 0.005; + Double_t flux = data[2] * fluxBinSize; // flux in cm-2 s-1 bin-1 - originalHist->Fill(r, en, (Float_t)flux); - continuumHist->Fill(r, en, (Float_t)flux); + originalHist->Fill(r, en, (Double_t)flux); + continuumHist->Fill(r, en, (Double_t)flux); } RESTDebug << "Histograms filled" << RESTendl; @@ -415,8 +415,8 @@ void TRestAxionSolarQCDFlux::ReadFluxFile() { const int smearPoints = (Int_t)(5 / (fBinSize * 100)); const int excludePoints = smearPoints / 5; for (const auto& data : fluxData) { - Float_t r = 0.005 + data[0]; - Float_t en = data[1] - 0.005; + Double_t r = 0.005 + data[0]; + Double_t en = data[1] - 0.005; Int_t binR = continuumHist->GetXaxis()->FindBin(r); Int_t binE = continuumHist->GetYaxis()->FindBin(en); @@ -430,8 +430,8 @@ void TRestAxionSolarQCDFlux::ReadFluxFile() { } avgFlux /= n; - Float_t targetBinFlux = continuumHist->GetBinContent(binR, binE); - Float_t thrFlux = avgFlux + fPeakSigma * TMath::Sqrt(avgFlux); + Double_t targetBinFlux = continuumHist->GetBinContent(binR, binE); + Double_t thrFlux = avgFlux + fPeakSigma * TMath::Sqrt(avgFlux); if (targetBinFlux > 0 && targetBinFlux > thrFlux) { continuumHist->SetBinContent(binR, binE, avgFlux); peaks++; @@ -441,8 +441,8 @@ void TRestAxionSolarQCDFlux::ReadFluxFile() { for (int n = 0; n < originalHist->GetNbinsX(); n++) for (int m = 0; m < originalHist->GetNbinsY(); m++) { - Float_t orig = originalHist->GetBinContent(n + 1, m + 1); - Float_t cont = continuumHist->GetBinContent(n + 1, m + 1); + Double_t orig = originalHist->GetBinContent(n + 1, m + 1); + Double_t cont = continuumHist->GetBinContent(n + 1, m + 1); spectrumHist->SetBinContent(n + 1, m + 1, orig - cont); } @@ -453,8 +453,8 @@ void TRestAxionSolarQCDFlux::ReadFluxFile() { fFluxTable.clear(); for (int n = 0; n < continuumHist->GetNbinsX(); n++) { - TH1F* hc = - (TH1F*)continuumHist->ProjectionY(Form("%s_ContinuumFluxAtRadius%d", GetName(), n), n + 1, n + 1); + TH1D* hc = + (TH1D*)continuumHist->ProjectionY(Form("%s_ContinuumFluxAtRadius%d", GetName(), n), n + 1, n + 1); fFluxTable.push_back(hc); } @@ -462,7 +462,7 @@ void TRestAxionSolarQCDFlux::ReadFluxFile() { for (int n = 0; n < spectrumHist->GetNbinsY(); n++) { if (spectrumHist->ProjectionX("", n + 1, n + 1)->Integral() > 0) { Double_t energy = spectrumHist->ProjectionY()->GetBinCenter(n + 1); - TH1F* hm = (TH1F*)spectrumHist->ProjectionX( + TH1D* hm = (TH1D*)spectrumHist->ProjectionX( Form("%s_MonochromeFluxAtEnergy%5.3lf", GetName(), energy), n + 1, n + 1); fFluxLines[energy] = hm; } @@ -475,13 +475,13 @@ void TRestAxionSolarQCDFlux::ReadFluxFile() { /// \brief It builds a histogram with the continuum spectrum component. /// The flux will be expressed in cm-2 s-1 keV-1. Binned in 100eV steps. /// -TH1F* TRestAxionSolarQCDFlux::GetContinuumSpectrum() { +TH1D* TRestAxionSolarQCDFlux::GetContinuumSpectrum() { if (fContinuumHist != nullptr) { delete fContinuumHist; fContinuumHist = nullptr; } - fContinuumHist = new TH1F("ContinuumHist", "", 200, 0, 20); + fContinuumHist = new TH1D("ContinuumHist", "", 200, 0, 20); for (const auto& x : fFluxTable) { fContinuumHist->Add(x); } @@ -501,13 +501,13 @@ TH1F* TRestAxionSolarQCDFlux::GetContinuumSpectrum() { /// \brief It builds a histogram with the monochromatic spectrum component. /// The flux will be expressed in cm-2 s-1 eV-1. Binned in 1eV steps. /// -TH1F* TRestAxionSolarQCDFlux::GetMonochromaticSpectrum() { +TH1D* TRestAxionSolarQCDFlux::GetMonochromaticSpectrum() { if (fMonoHist != nullptr) { delete fMonoHist; fMonoHist = nullptr; } - fMonoHist = new TH1F("MonochromaticHist", "", 20000, 0, 20); + fMonoHist = new TH1D("MonochromaticHist", "", 20000, 0, 20); for (const auto& x : fFluxLines) { fMonoHist->Fill(x.first, x.second->Integral()); // cm-2 s-1 eV-1 } @@ -528,16 +528,16 @@ TH1F* TRestAxionSolarQCDFlux::GetMonochromaticSpectrum() { /// spectrum component. The flux will be expressed in cm-2 s-1 keV-1. /// Binned in 1eV steps. /// -TH1F* TRestAxionSolarQCDFlux::GetTotalSpectrum() { - TH1F* hm = GetMonochromaticSpectrum(); - TH1F* hc = GetContinuumSpectrum(); +TH1D* TRestAxionSolarQCDFlux::GetTotalSpectrum() { + TH1D* hm = GetMonochromaticSpectrum(); + TH1D* hc = GetContinuumSpectrum(); if (fTotalHist != nullptr) { delete fTotalHist; fTotalHist = nullptr; } - fTotalHist = new TH1F("fTotalHist", "", 20000, 0, 20); + fTotalHist = new TH1D("fTotalHist", "", 20000, 0, 20); for (int n = 0; n < hc->GetNbinsX(); n++) { for (int m = 0; m < 100; m++) { fTotalHist->SetBinContent(n * 100 + 1 + m, hc->GetBinContent(n + 1)); @@ -580,12 +580,12 @@ TCanvas* TRestAxionSolarQCDFlux::DrawSolarFlux() { pad1->cd(1)->SetLeftMargin(0.15); pad1->cd(1)->SetBottomMargin(0.15); - TH1F* ht = GetTotalSpectrum(); + TH1D* ht = GetTotalSpectrum(); ht->SetLineColor(kBlack); ht->SetFillStyle(4050); ht->SetFillColor(kBlue - 10); - TH1F* hm = GetMonochromaticSpectrum(); + TH1D* hm = GetMonochromaticSpectrum(); hm->SetLineColor(kBlack); hm->Scale(100); // renormalizing per 100eV-1 @@ -634,7 +634,7 @@ void TRestAxionSolarQCDFlux::IntegrateSolarFluxes() { /////////////////////////////////////////////// /// \brief It returns the integrated flux at earth in cm-2 s-1 for the given energy range /// -Double_t TRestAxionSolarQCDFlux::IntegrateFluxInRange(TVector2 eRange, Double_t mass) { +Double_t TRestAxionSolarQCDFlux::IntegrateFluxInRange(TVector2 eRange) { if (eRange.X() == -1 && eRange.Y() == -1) { if (GetTotalFlux() == 0) IntegrateSolarFluxes(); return GetTotalFlux(); @@ -770,9 +770,9 @@ void TRestAxionSolarQCDFlux::ExportTables(Bool_t ascii) { } if (fFluxTable.size() > 0) { - std::vector> table; + std::vector> table; for (const auto& x : fFluxTable) { - std::vector row; + std::vector row; for (int n = 0; n < x->GetNbinsX(); n++) row.push_back(x->GetBinContent(n + 1)); table.push_back(row); @@ -785,9 +785,9 @@ void TRestAxionSolarQCDFlux::ExportTables(Bool_t ascii) { } if (fFluxLines.size() > 0) { - std::vector> table; + std::vector> table; for (const auto& x : fFluxLines) { - std::vector row; + std::vector row; row.push_back(x.first); for (int n = 0; n < x.second->GetNbinsX(); n++) row.push_back(x.second->GetBinContent(n + 1)); From 6e94816681a7854ffb1875b48f8d667bb5716776 Mon Sep 17 00:00:00 2001 From: tomasoshea Date: Fri, 15 Sep 2023 12:24:50 +0200 Subject: [PATCH 32/48] fixed unspecified int c = 0 --- inc/TRestAxionSolarHiddenPhotonFlux.h | 6 +- inc/TRestAxionSolarHiddenPhotonFlux.h.new | 131 ----- inc/TRestAxionSolarHiddenPhotonFlux.h.old | 131 ----- src/TRestAxionSolarHiddenPhotonFlux.cxx | 76 ++- src/TRestAxionSolarHiddenPhotonFlux.cxx.new | 583 ------------------- src/TRestAxionSolarHiddenPhotonFlux.cxx.old | 613 -------------------- 6 files changed, 56 insertions(+), 1484 deletions(-) delete mode 100644 inc/TRestAxionSolarHiddenPhotonFlux.h.new delete mode 100644 inc/TRestAxionSolarHiddenPhotonFlux.h.old delete mode 100644 src/TRestAxionSolarHiddenPhotonFlux.cxx.new delete mode 100644 src/TRestAxionSolarHiddenPhotonFlux.cxx.old diff --git a/inc/TRestAxionSolarHiddenPhotonFlux.h b/inc/TRestAxionSolarHiddenPhotonFlux.h index 2df02f96..bdc44040 100644 --- a/inc/TRestAxionSolarHiddenPhotonFlux.h +++ b/inc/TRestAxionSolarHiddenPhotonFlux.h @@ -45,13 +45,13 @@ class TRestAxionSolarHiddenPhotonFlux : public TRestAxionSolarFlux { std::vector fFluxTable; //! /// The tabulated solar flux continuum spectra TH1D(200,0,20)keV in cm-2 s-1 keV-1 versus solar radius - std::vector> fContinuumTable; //! + std::vector fContinuumTable; //! /// The tabulated resonance width TH1D(200,0,20)keV in eV2 versus solar radius - std::vector> fWidthTable; //! + std::vector fWidthTable; //! /// The solar plasma frequency vector in eV versus solar radius - std::vector> fPlasmaFreqTable; //! + std::vector fPlasmaFreqTable; //! /// The total solar flux TH1D(200,0,20)keV in cm-2 s-1 keV-1 versus solar radius std::vector fFullFluxTable; //! diff --git a/inc/TRestAxionSolarHiddenPhotonFlux.h.new b/inc/TRestAxionSolarHiddenPhotonFlux.h.new deleted file mode 100644 index 2df02f96..00000000 --- a/inc/TRestAxionSolarHiddenPhotonFlux.h.new +++ /dev/null @@ -1,131 +0,0 @@ -/************************************************************************* - * This file is part of the REST software framework. * - * * - * Copyright (C) 2016 GIFNA/TREX (University of Zaragoza) * - * For more information see http://gifna.unizar.es/trex * - * * - * REST 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. * - * * - * REST 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 a copy of the GNU General Public License along with * - * REST in $REST_PATH/LICENSE. * - * If not, see http://www.gnu.org/licenses/. * - * For the list of contributors see $REST_PATH/CREDITS. * - *************************************************************************/ - -#ifndef _TRestAxionSolarHiddenPhotonFlux -#define _TRestAxionSolarHiddenPhotonFlux - -#include -#include - -//! A metadata class to load tabulated solar hidden photon fluxes. Kinetic mixing set to 1. -class TRestAxionSolarHiddenPhotonFlux : public TRestAxionSolarFlux { - private: - /// The filename containing the solar flux table with continuum spectrum - std::string fFluxDataFile = ""; //< - - /// The filename containing the resonance width (wGamma) - std::string fWidthDataFile = ""; //< - - /// The filename containing the plasma frequency (wp) table - std::string fPlasmaFreqDataFile = ""; //< - - /// It will be used when loading `.flux` files to define the input file energy binsize in eV. - Double_t fBinSize = 0; //< - - /// The tabulated solar flux continuum spectra TH1D(200,0,20)keV in cm-2 s-1 keV-1 versus solar radius - std::vector fFluxTable; //! - - /// The tabulated solar flux continuum spectra TH1D(200,0,20)keV in cm-2 s-1 keV-1 versus solar radius - std::vector> fContinuumTable; //! - - /// The tabulated resonance width TH1D(200,0,20)keV in eV2 versus solar radius - std::vector> fWidthTable; //! - - /// The solar plasma frequency vector in eV versus solar radius - std::vector> fPlasmaFreqTable; //! - - /// The total solar flux TH1D(200,0,20)keV in cm-2 s-1 keV-1 versus solar radius - std::vector fFullFluxTable; //! - - /// Accumulative integrated solar flux for each solar ring for continuum spectrum (renormalized to unity) - std::vector fFluxTableIntegrals; //! - - /// Total solar flux for monochromatic contributions - Double_t fTotalContinuumFlux = 0; //! - - /// A pointer to the continuum spectrum histogram - TH1D* fContinuumHist = nullptr; //! - - /// A pointer to the superposed monochromatic and continuum spectrum histogram - TH1D* fTotalHist = nullptr; //! - - void ReadFluxFile(); - void LoadContinuumFluxTable(); - void LoadMonoChromaticFluxTable(); - void IntegrateSolarFluxes(); - - public: - /// It returns true if continuum flux spectra was loaded - Bool_t isSolarTableLoaded() { return fFluxTable.size() > 0; } - - /// It returns true if width table was loaded - Bool_t isWidthTableLoaded() { return fWidthTable.size() > 0; } - - /// It returns true if plasma frequency table was loaded - Bool_t isPlasmaFreqLoaded() { return fPlasmaFreqTable.size() > 0; } - - /// It returns the integrated flux at earth in cm-2 s-1 for the given energy range - Double_t IntegrateFluxInRange(TVector2 eRange = TVector2(-1, -1)) override; - - /// It defines how to generate Monte Carlo energy and radius values to reproduce the flux - std::pair GetRandomEnergyAndRadius(TVector2 eRange = TVector2(-1, -1)) override; - - /// It defines how to read the solar tables at the inhereted class for a given mass in eV - Bool_t LoadTables() override; - - void LoadContinuumTable(); - void LoadWidthTable(); - void LoadPlasmaFreqTable(); - - // calculate solar HP flux from the 3 tables and mass - void CalculateSolarFlux(); - /// It returns the total integrated flux at earth in cm-2 s-1 - Double_t GetTotalFlux() override { return fTotalContinuumFlux; } - - /// It returns an energy integrated spectrum in cm-2 s-1 keV-1 - TH1D* GetEnergySpectrum() override { return GetTotalSpectrum(); } - - TH1D* GetContinuumSpectrum(); - TH1D* GetTotalSpectrum(); - - virtual TCanvas* DrawSolarFlux() override; - - /// Tables might be loaded using a solar model description by TRestAxionSolarModel - void InitializeSolarTable(TRestAxionSolarModel* model) { - // TOBE implemented - // This method should initialize the tables fFluxTable and fFluxLines - } - - void ExportTables(Bool_t ascii = false) override; - - void PrintMetadata() override; - - void PrintContinuumSolarTable(); - void PrintIntegratedRingFlux(); - - TRestAxionSolarHiddenPhotonFlux(); - TRestAxionSolarHiddenPhotonFlux(const char* cfgFileName, std::string name = ""); - ~TRestAxionSolarHiddenPhotonFlux(); - - ClassDefOverride(TRestAxionSolarHiddenPhotonFlux, 1); -}; -#endif diff --git a/inc/TRestAxionSolarHiddenPhotonFlux.h.old b/inc/TRestAxionSolarHiddenPhotonFlux.h.old deleted file mode 100644 index bdc44040..00000000 --- a/inc/TRestAxionSolarHiddenPhotonFlux.h.old +++ /dev/null @@ -1,131 +0,0 @@ -/************************************************************************* - * This file is part of the REST software framework. * - * * - * Copyright (C) 2016 GIFNA/TREX (University of Zaragoza) * - * For more information see http://gifna.unizar.es/trex * - * * - * REST 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. * - * * - * REST 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 a copy of the GNU General Public License along with * - * REST in $REST_PATH/LICENSE. * - * If not, see http://www.gnu.org/licenses/. * - * For the list of contributors see $REST_PATH/CREDITS. * - *************************************************************************/ - -#ifndef _TRestAxionSolarHiddenPhotonFlux -#define _TRestAxionSolarHiddenPhotonFlux - -#include -#include - -//! A metadata class to load tabulated solar hidden photon fluxes. Kinetic mixing set to 1. -class TRestAxionSolarHiddenPhotonFlux : public TRestAxionSolarFlux { - private: - /// The filename containing the solar flux table with continuum spectrum - std::string fFluxDataFile = ""; //< - - /// The filename containing the resonance width (wGamma) - std::string fWidthDataFile = ""; //< - - /// The filename containing the plasma frequency (wp) table - std::string fPlasmaFreqDataFile = ""; //< - - /// It will be used when loading `.flux` files to define the input file energy binsize in eV. - Double_t fBinSize = 0; //< - - /// The tabulated solar flux continuum spectra TH1D(200,0,20)keV in cm-2 s-1 keV-1 versus solar radius - std::vector fFluxTable; //! - - /// The tabulated solar flux continuum spectra TH1D(200,0,20)keV in cm-2 s-1 keV-1 versus solar radius - std::vector fContinuumTable; //! - - /// The tabulated resonance width TH1D(200,0,20)keV in eV2 versus solar radius - std::vector fWidthTable; //! - - /// The solar plasma frequency vector in eV versus solar radius - std::vector fPlasmaFreqTable; //! - - /// The total solar flux TH1D(200,0,20)keV in cm-2 s-1 keV-1 versus solar radius - std::vector fFullFluxTable; //! - - /// Accumulative integrated solar flux for each solar ring for continuum spectrum (renormalized to unity) - std::vector fFluxTableIntegrals; //! - - /// Total solar flux for monochromatic contributions - Double_t fTotalContinuumFlux = 0; //! - - /// A pointer to the continuum spectrum histogram - TH1D* fContinuumHist = nullptr; //! - - /// A pointer to the superposed monochromatic and continuum spectrum histogram - TH1D* fTotalHist = nullptr; //! - - void ReadFluxFile(); - void LoadContinuumFluxTable(); - void LoadMonoChromaticFluxTable(); - void IntegrateSolarFluxes(); - - public: - /// It returns true if continuum flux spectra was loaded - Bool_t isSolarTableLoaded() { return fFluxTable.size() > 0; } - - /// It returns true if width table was loaded - Bool_t isWidthTableLoaded() { return fWidthTable.size() > 0; } - - /// It returns true if plasma frequency table was loaded - Bool_t isPlasmaFreqLoaded() { return fPlasmaFreqTable.size() > 0; } - - /// It returns the integrated flux at earth in cm-2 s-1 for the given energy range - Double_t IntegrateFluxInRange(TVector2 eRange = TVector2(-1, -1)) override; - - /// It defines how to generate Monte Carlo energy and radius values to reproduce the flux - std::pair GetRandomEnergyAndRadius(TVector2 eRange = TVector2(-1, -1)) override; - - /// It defines how to read the solar tables at the inhereted class for a given mass in eV - Bool_t LoadTables() override; - - void LoadContinuumTable(); - void LoadWidthTable(); - void LoadPlasmaFreqTable(); - - // calculate solar HP flux from the 3 tables and mass - void CalculateSolarFlux(); - /// It returns the total integrated flux at earth in cm-2 s-1 - Double_t GetTotalFlux() override { return fTotalContinuumFlux; } - - /// It returns an energy integrated spectrum in cm-2 s-1 keV-1 - TH1D* GetEnergySpectrum() override { return GetTotalSpectrum(); } - - TH1D* GetContinuumSpectrum(); - TH1D* GetTotalSpectrum(); - - virtual TCanvas* DrawSolarFlux() override; - - /// Tables might be loaded using a solar model description by TRestAxionSolarModel - void InitializeSolarTable(TRestAxionSolarModel* model) { - // TOBE implemented - // This method should initialize the tables fFluxTable and fFluxLines - } - - void ExportTables(Bool_t ascii = false) override; - - void PrintMetadata() override; - - void PrintContinuumSolarTable(); - void PrintIntegratedRingFlux(); - - TRestAxionSolarHiddenPhotonFlux(); - TRestAxionSolarHiddenPhotonFlux(const char* cfgFileName, std::string name = ""); - ~TRestAxionSolarHiddenPhotonFlux(); - - ClassDefOverride(TRestAxionSolarHiddenPhotonFlux, 1); -}; -#endif diff --git a/src/TRestAxionSolarHiddenPhotonFlux.cxx b/src/TRestAxionSolarHiddenPhotonFlux.cxx index 01f443fa..0c213f20 100644 --- a/src/TRestAxionSolarHiddenPhotonFlux.cxx +++ b/src/TRestAxionSolarHiddenPhotonFlux.cxx @@ -230,18 +230,26 @@ void TRestAxionSolarHiddenPhotonFlux::LoadContinuumFluxTable() { RESTDebug << "Loading table from file : " << RESTendl; RESTDebug << "File : " << fullPathName << RESTendl; + std::vector> fluxTable; + if (!TRestTools::IsBinaryFile(fFluxDataFile)) { - fContinuumTable.clear(); + fluxTable.clear(); RESTError << "File is not in binary format!" << RESTendl; } - TRestTools::ReadBinaryTable(fullPathName, fContinuumTable); + TRestTools::ReadBinaryTable(fullPathName, fluxTable); - if (fContinuumTable.size() != 1000 || fContinuumTable[0].size() != 200) { + if (fluxTable.size() != 1000 || fluxTable[0].size() != 200) { + fluxTable.clear(); RESTError << "LoadContinuumFluxTable. The table does not contain the right number of rows or columns" << RESTendl; RESTError << "Table will not be populated" << RESTendl; - fContinuumTable.clear(); + } + + for (unsigned int n = 0; n < fluxTable.size(); n++) { + TH1D* h = new TH1D(Form("%s_ContinuumFluxAtRadius%d", GetName(), n), "", 200, 0, 20); + for (unsigned int m = 0; m < fluxTable[n].size(); m++) { h->SetBinContent(m + 1, fluxTable[n][m]); } + fContinuumTable.push_back(h); } } @@ -261,18 +269,27 @@ void TRestAxionSolarHiddenPhotonFlux::LoadWidthTable() { RESTDebug << "Loading table from file : " << RESTendl; RESTDebug << "File : " << fullPathName << RESTendl; + std::vector> fluxTable; + if (!TRestTools::IsBinaryFile(fWidthDataFile)) { - fWidthTable.clear(); + fluxTable.clear(); RESTError << "File is not in binary format!" << RESTendl; } - TRestTools::ReadBinaryTable(fullPathName, fWidthTable); + TRestTools::ReadBinaryTable(fullPathName, fluxTable); + //RESTMetadata << "Width table rows / columns: " << fluxTable.size() << " " << fluxTable[0].size() << RESTendl; - if (fWidthTable.size() != 1000 || fWidthTable[0].size() != 200) { + if (fluxTable.size() != 1000 || fluxTable[0].size() != 200) { + fluxTable.clear(); RESTError << "LoadWidthTable. The table does not contain the right number of rows or columns" << RESTendl; RESTError << "Table will not be populated" << RESTendl; - fWidthTable.clear(); + } + + for (unsigned int n = 0; n < fluxTable.size(); n++) { + TH1D* h = new TH1D(Form("%s_ResonanceWidthAtRadius%d", GetName(), n), "", 200, 0, 20); + for (unsigned int m = 0; m < fluxTable[n].size(); m++) { h->SetBinContent(m + 1, fluxTable[n][m]); } + fWidthTable.push_back(h); } } @@ -293,18 +310,26 @@ void TRestAxionSolarHiddenPhotonFlux::LoadPlasmaFreqTable() { RESTDebug << "Loading table from file : " << RESTendl; RESTDebug << "File : " << fullPathName << RESTendl; + std::vector> fluxTable; + if (!TRestTools::IsBinaryFile(fWidthDataFile)) { + fluxTable.clear(); RESTError << "File is not in binary format!" << RESTendl; - fPlasmaFreqTable.clear(); } - TRestTools::ReadBinaryTable(fullPathName, fPlasmaFreqTable); + TRestTools::ReadBinaryTable(fullPathName, fluxTable); - if (fPlasmaFreqTable.size() != 1000 || fPlasmaFreqTable[0].size() != 1) { + if (fluxTable.size() != 1000 || fluxTable[0].size() != 1) { + fluxTable.clear(); RESTError << "LoadPlasmaFreqTable. The table does not contain the right number of rows or columns" << RESTendl; RESTError << "Table will not be populated" << RESTendl; - fPlasmaFreqTable.clear(); + } + + for (unsigned int n = 0; n < fluxTable.size(); n++) { + TH1D* h = new TH1D(Form("%s_PlasmaFreqAtRadius%d", GetName(), n), "", 1, 0, 20); + for (unsigned int m = 0; m < fluxTable[n].size(); m++) { h->SetBinContent(m + 1, fluxTable[n][m]); } + fPlasmaFreqTable.push_back(h); } } @@ -331,22 +356,27 @@ void TRestAxionSolarHiddenPhotonFlux::CalculateSolarFlux() { } Double_t mass = GetMass(); + cout << mass << endl; for (unsigned int n = 0; n < fContinuumTable.size(); n++) { // m4 * chi2 * wG * flux / ( (m2 - wp2)^2 + (w G)^2 ) - Double_t wp = fPlasmaFreqTable[n][0]; - vector wG = fWidthTable[n]; - vector flux = fContinuumTable[n]; - vector v; - for( unsigned int c; c < wG.size(); c++ ) { - Double_t d1 = ( wG[c] * flux[c] * pow(mass,4) ); // m4 * wG * flux - Double_t d2 = ( pow( pow(mass,2) - pow(wp,2) , 2 ) + pow(wG[c],2) ); // m4 * wG * flux / ( (m2 - wp2)^2 + (w G)^2 ) - v.push_back(d1/d2); + Double_t wp = fPlasmaFreqTable[n]->GetBinContent(1); + TH1D* hMass = new TH1D(Form("%s_hMass%d", GetName(), n), "hMass", 200, 0, 20); + TH1D* hWg2 = (TH1D*)fWidthTable[n]->Clone(); + hWg2->Multiply(hWg2); // (w G)^2 + + for ( unsigned int c = 0; c < 200; c++ ) { + Double_t wG = fWidthTable[n]->GetBinContent(c+1); + hMass->SetBinContent( c+1, pow(mass,-4) * ( pow( pow(mass,2) - pow(wp,2) , 2 )));// + pow(wG,2) ) ); // m2 } + + hMass->Add(hWg2); // (m2 - wp2)^2 + (w G)^2 + + TH1D* h = (TH1D*)fWidthTable[n]->Clone(); // wG + h->Multiply(fContinuumTable[n]); // wG * flux + h->Divide(hMass); // wG * flux / ( (m2 - wp2)^2 + (w G)^2 ) + //h->Scale(pow(mass, 4)); // m4 * wG * flux / ( (m2 - wp2)^2 + (w G)^2 ) - TH1D* h = new TH1D(Form("%s_TotalFluxTable%d", GetName(), n), "", 200, 0, 20); - for (unsigned int c = 0; c < v.size(); c++) { h->SetBinContent(c + 1, v[c]); } - //for (unsigned int c = 0; c < v.size(); c++) { h->Fill(v[c]); } fFluxTable.push_back(h); } } diff --git a/src/TRestAxionSolarHiddenPhotonFlux.cxx.new b/src/TRestAxionSolarHiddenPhotonFlux.cxx.new deleted file mode 100644 index 26c782c1..00000000 --- a/src/TRestAxionSolarHiddenPhotonFlux.cxx.new +++ /dev/null @@ -1,583 +0,0 @@ -/******************** REST disclaimer *********************************** - * This file is part of the REST software framework. * - * * - * Copyright (C) 2016 GIFNA/TREX (University of Zaragoza) * - * For more information see http://gifna.unizar.es/trex * - * * - * REST 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. * - * * - * REST 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 a copy of the GNU General Public License along with * - * REST in $REST_PATH/LICENSE. * - * If not, see http://www.gnu.org/licenses/. * - * For the list of contributors see $REST_PATH/CREDITS. * - *************************************************************************/ - -////////////////////////////////////////////////////////////////////////// -/// TRestAxionSolarHiddenPhotonFlux will use a file in binary format to initialize -/// a solar flux table that will describe the solar hidden photon flux spectrum as a function -/// of the solar radius. -/// -/// This class loads the hidden photon flux that depends on the mass and kinetic mixing parameter. -/// For axion-like particle prodution independent of mass there is the class -/// TRestAxionSolarQCDFlux. Both classes are prototyped by a pure base class TRestAxionSolarFlux -/// that defines common methods used to evaluate the flux, and generate Monte-Carlo events inside -/// TRestAxionGeneratorProcess. -/// -/// ### Basic use -/// -/// Once the class has been initialized, the main use of this class will be provided -/// by the method TRestAxionSolarHiddenPhotonFlux::GetRandomEnergyAndRadius. This method will -/// return a random axion energy and position inside the solar radius following the -/// distributions given by the solar flux tables. -/// -/// Description of the specific parameters accepted by this metadata class. -/// - *fluxDataFile:* A table with 1000 rows representing the solar ring flux from the -/// center to the corona, and 200 columns representing the flux, measured in cm-2 s-1 keV-1, -/// for the range (0,20)keV in steps of 100eV. The table is provided as a binary table using -/// `.N200f` extension. -/// - *widthDataFile:* A table with 1000 rows representing the width of the hidden photon -/// resonant production (wG) for each solar ring from the center to the corona, and 200 columns -/// representing the width, measured in eV2, for the range (0,20)keV in steps of 100eV. The -/// table is provided as a binary table using `.N200f` extension. -/// - *plasmaFreqDataFile:* A table with 1000 rows and only 1 column representing the solar -/// plasma frequency (wp) for each solar ring from the center to the corona, measured in eV. The -/// table is provided as a binary table using `.N1f` extension. -/// -/// Pre-generated solar axion flux tables will be available at the -/// [axionlib-data](https://github.com/rest-for-physics/axionlib-data/tree/master) -/// repository. The different RML flux definitions used to load those tables -/// will be found at the -/// [fluxes.rml](https://github.com/rest-for-physics/axionlib-data/blob/master/solarFlux/fluxes.rml) -/// file found at the axionlib-data repository. -/// -/// Inside a local REST installation, the `fluxes.rml` file will be found at the REST -/// installation directory, and it will be located automatically by the -/// TRestMetadata::SearchFile method. -/// -/// ### A basic RML definition -/// -/// The following definition integrates an axion-photon component with a continuum -/// spectrum using a Primakoff production model, and a dummy spectrum file that -/// includes two monocrhomatic lines at different solar disk radius positions. -/// -/// \code -/// -/// -/// -/// -/// -/// -/// -/// -/// -/// -/// -/// \endcode -/// -/// \warning When the flux is loaded manually inside the `restRoot` interactive -/// shell, or inside a macro or script, after metadata initialization, it is necessary -/// to call the method TRestAxionSolarHiddenPhotonFlux::LoadTables(mass) to trigger the tables -/// initialization. -/// -/// ### Performing MonteCarlo tests using pre-loaded tables -/// -/// In order to test the response of different solar flux definitions we may use the script -/// `solarPlot.py` found at `pipeline/metadata/solarFlux/`. This script will generate a -/// number of particles and it will assign to each particle an energy and solar disk -/// location with the help of the method TRestAxionSolarHiddenPhotonFlux::GetRandomEnergyAndRadius. -/// -/// \code -/// python3 solarPlotHiddenPhoton.py --fluxname HiddenPhoton --N 1000000 -/// \endcode -/// -/// By default, it will load the flux definition found at `fluxes.rml` from the -/// `axionlib-data` repository, and generate a `png` image with the resuts from the -/// Monte Carlo execution. -/// -/// \htmlonly \endhtmlonly -/// -/// ![Solar flux distributions MC-generated with TRestAxionSolarQCDFlux.](ABC_flux_MC.png) -/// -/// ### Exporting the solar flux tables -/// -/// On top of that, we will be able to export those tables to the TRestAxionSolarHiddenPhotonFlux -/// standard format to be used in later occasions. -/// -/// \code -/// TRestAxionSolarHiddenPhotonFlux *sFlux = new TRestAxionSolarHiddenPhotonFlux("fluxes.rml", -/// "HiddenPhoton") sFlux->Initialize() sFlux->ExportTables() -/// \endcode -/// -/// which will produce a binary table `.N200f` with the continuum flux. The filename root will be -/// extracted from the original `.flux` file. Optionally we may export the continuum flux to an -/// ASCII file by indicating it at the TRestAxionSolarHiddenPhotonFlux::ExportTables method call. -/// The files will be placed at the REST user space, at `$HOME/.rest/export/` directory. -/// -/// TODO Implement the method TRestAxionSolarQCDFlux::InitializeSolarTable using -/// a solar model description by TRestAxionSolarModel. -/// -/// TODO Perhaps it would be interesting to replace fFluxTable for a TH2D -/// -///-------------------------------------------------------------------------- -/// -/// RESTsoft - Software for Rare Event Searches with TPCs -/// -/// History of developments: -/// -/// 2023-May: Specific methods extracted from TRestAxionSolarFlux -/// Javier Galan -/// 2023-June: TRestAxionSolarHiddenPhotonFlux created by editing TRestAxionSolarQCDFlux -/// Tomas O'Shea -/// -/// \class TRestAxionSolarHiddenPhotonFlux -/// \author Javier Galan -/// -///
-/// - -#include "TRestAxionSolarHiddenPhotonFlux.h" -using namespace std; - -ClassImp(TRestAxionSolarHiddenPhotonFlux); - -/////////////////////////////////////////////// -/// \brief Default constructor -/// -TRestAxionSolarHiddenPhotonFlux::TRestAxionSolarHiddenPhotonFlux() : TRestAxionSolarFlux() {} - -/////////////////////////////////////////////// -/// \brief Constructor loading data from a config file -/// -/// If no configuration path is defined using TRestMetadata::SetConfigFilePath -/// the path to the config file must be specified using full path, absolute or -/// relative. -/// -/// The default behaviour is that the config file must be specified with -/// full path, absolute or relative. -/// -/// \param cfgFileName A const char* giving the path to an RML file. -/// \param name The name of the specific metadata. It will be used to find the -/// corresponding TRestAxionMagneticField section inside the RML. -/// -TRestAxionSolarHiddenPhotonFlux::TRestAxionSolarHiddenPhotonFlux(const char* cfgFileName, string name) - : TRestAxionSolarFlux(cfgFileName) { - LoadConfigFromFile(fConfigFileName, name); - - if (GetVerboseLevel() >= TRestStringOutput::REST_Verbose_Level::REST_Info) PrintMetadata(); -} - -/////////////////////////////////////////////// -/// \brief Default destructor -/// -TRestAxionSolarHiddenPhotonFlux::~TRestAxionSolarHiddenPhotonFlux() {} - -/////////////////////////////////////////////// -/// \brief It will load the tables in memory by using the filename information provided -/// inside the metadata members, and calculate the solar flux for a given m. -/// -Bool_t TRestAxionSolarHiddenPhotonFlux::LoadTables() { - - if (GetMass() <= 0 ) { - RESTWarning << "TRestAxionSolarHiddenPhotonFlux::LoadTables - hidden photon mass not yet defined" << RESTendl; - RESTWarning << "TRestAxionSolarHiddenPhotonFlux::LoadTables - mass given as " << GetMass() << " eV" << RESTendl; - return false; - } - if ( fFluxDataFile == "" ){ - RESTWarning << "TRestAxionSolarHiddenPhotonFlux::LoadTables - flux table not found!!\n " << fFluxDataFile << RESTendl; - return false; - } - if ( fWidthDataFile == "") { - RESTWarning << "TRestAxionSolarHiddenPhotonFlux::LoadTables - width table not found!!\n " << fWidthDataFile << RESTendl; - return false; - } - if ( fPlasmaFreqDataFile == "" ) { - RESTWarning << "TRestAxionSolarHiddenPhotonFlux::LoadTables - plasma frequency table not found!!\n " << fPlasmaFreqDataFile << RESTendl; - return false; - } - - LoadContinuumFluxTable(); - LoadWidthTable(); - LoadPlasmaFreqTable(); - - CalculateSolarFlux(); - - IntegrateSolarFluxes(); - return true; -} - -/////////////////////////////////////////////// -/// \brief A helper method to load the data file containing continuum spectra as a -/// function of the solar radius. It will be called by TRestAxionSolarHiddenPhotonFlux::Initialize. -/// -void TRestAxionSolarHiddenPhotonFlux::LoadContinuumFluxTable() { - if (fFluxDataFile == "") { - RESTError - << "TRestAxionSolarHiddenPhotonFlux::LoadContinuumFluxTable. No solar flux table was defined" - << RESTendl; - return; - } - - string fullPathName = SearchFile((string)fFluxDataFile); - - RESTDebug << "Loading table from file : " << RESTendl; - RESTDebug << "File : " << fullPathName << RESTendl; - - if (!TRestTools::IsBinaryFile(fFluxDataFile)) { - fContinuumTable.clear(); - RESTError << "File is not in binary format!" << RESTendl; - } - - TRestTools::ReadBinaryTable(fullPathName, fContinuumTable); - - if (fContinuumTable.size() != 1000 || fContinuumTable[0].size() != 200) { - RESTError << "LoadContinuumFluxTable. The table does not contain the right number of rows or columns" - << RESTendl; - RESTError << "Table will not be populated" << RESTendl; - fContinuumTable.clear(); - } -} - -/////////////////////////////////////////////// -/// \brief A helper method to load the data file containing resonance width as a -/// function of the solar radius. It will be called by TRestAxionSolarHiddenPhotonFlux::Initialize. -/// -void TRestAxionSolarHiddenPhotonFlux::LoadWidthTable() { - if (fFluxDataFile == "") { - RESTError << "TRestAxionSolarHiddenPhotonFlux::LoadWidthTable. No width table was defined" - << RESTendl; - return; - } - - string fullPathName = SearchFile((string)fWidthDataFile); - - RESTDebug << "Loading table from file : " << RESTendl; - RESTDebug << "File : " << fullPathName << RESTendl; - - if (!TRestTools::IsBinaryFile(fWidthDataFile)) { - fWidthTable.clear(); - RESTError << "File is not in binary format!" << RESTendl; - } - - TRestTools::ReadBinaryTable(fullPathName, fWidthTable); - - if (fWidthTable.size() != 1000 || fWidthTable[0].size() != 200) { - RESTError << "LoadWidthTable. The table does not contain the right number of rows or columns" - << RESTendl; - RESTError << "Table will not be populated" << RESTendl; - fWidthTable.clear(); - } -} - -/////////////////////////////////////////////// -/// \brief A helper method to load the data file containing resonance width as a -/// function of the solar radius. It will be called by TRestAxionSolarHiddenPhotonFlux::Initialize. -/// -void TRestAxionSolarHiddenPhotonFlux::LoadPlasmaFreqTable() { - if (fFluxDataFile == "") { - RESTError - << "TRestAxionSolarHiddenPhotonFlux::LoadPlasmaFreqTable. No plasma frequency table was defined" - << RESTendl; - return; - } - - string fullPathName = SearchFile((string)fPlasmaFreqDataFile); - - RESTDebug << "Loading table from file : " << RESTendl; - RESTDebug << "File : " << fullPathName << RESTendl; - - if (!TRestTools::IsBinaryFile(fWidthDataFile)) { - RESTError << "File is not in binary format!" << RESTendl; - fPlasmaFreqTable.clear(); - } - - TRestTools::ReadBinaryTable(fullPathName, fPlasmaFreqTable); - - if (fPlasmaFreqTable.size() != 1000 || fPlasmaFreqTable[0].size() != 1) { - RESTError << "LoadPlasmaFreqTable. The table does not contain the right number of rows or columns" - << RESTendl; - RESTError << "Table will not be populated" << RESTendl; - fPlasmaFreqTable.clear(); - } -} - -/////////////////////////////////////////////// -/// \brief A helper method to calculate the real solar flux spectrum from the 3 tables, the -/// and the hidden photon mass for chi=1. -/// -void TRestAxionSolarHiddenPhotonFlux::CalculateSolarFlux() { - if (GetMass() == 0) { - RESTError << "CalculateSolarFlux. The hidden photon mass is set to zero!" << RESTendl; - return; - } - if (fContinuumTable.size() == 0 ) { - RESTError << "TRestAxionSolarHiddenPhotonFlux::CalculateSolarFlux - empty flux table!" << RESTendl; - return; - } - if (fPlasmaFreqTable.size() == 0 ) { - RESTError << "TRestAxionSolarHiddenPhotonFlux::CalculateSolarFlux - empty plasma freq table!" << RESTendl; - return; - } - if (fWidthTable.size() == 0 ) { - RESTError << "TRestAxionSolarHiddenPhotonFlux::CalculateSolarFlux - empty width table!" << RESTendl; - return; - } - fFluxTable.clear(); - Double_t mass = GetMass(); - for (unsigned int n = 0; n < fContinuumTable.size(); n++) { - // m4 * chi2 * wG * flux / ( (m2 - wp2)^2 + (w G)^2 ) - - Double_t wp = fPlasmaFreqTable[n][0]; - vector wG = fWidthTable[n]; - vector flux = fContinuumTable[n]; - vector v; - for( unsigned int c; c < wG.size(); c++ ) { - Double_t d1 = ( wG[c] * flux[c] * pow(mass,4) ); // m4 * wG * flux - Double_t d2 = ( pow( pow(mass,2) - pow(wp,2) , 2 ) + pow(wG[c],2) ); // m4 * wG * flux / ( (m2 - wp2)^2 + (w G)^2 ) - v.push_back(d1/d2); - } - - TH1D* h = new TH1D(Form("%s_TotalFluxTable%d", GetName(), n), "", 200, 0, 20); - for (unsigned int c = 0; c < v.size(); c++) { h->SetBinContent(c + 1, v[c]); } - //for (unsigned int c = 0; c < v.size(); c++) { h->Fill(v[c]); } - fFluxTable.push_back(h); - } -} - -/////////////////////////////////////////////// -/// \brief It builds a histogram with the continuum spectrum. -/// The flux will be expressed in cm-2 s-1 keV-1. Binned in 100eV steps. -/// -TH1D* TRestAxionSolarHiddenPhotonFlux::GetContinuumSpectrum() { - if (fContinuumHist != nullptr) { - delete fContinuumHist; - fContinuumHist = nullptr; - } - - fContinuumHist = new TH1D("ContinuumHist", "", 200, 0, 20); - for (const auto& x : fFluxTable) { - fContinuumHist->Add(x); - } - - fContinuumHist->SetStats(0); - fContinuumHist->GetXaxis()->SetTitle("Energy [keV]"); - fContinuumHist->GetXaxis()->SetTitleSize(0.05); - fContinuumHist->GetXaxis()->SetLabelSize(0.05); - fContinuumHist->GetYaxis()->SetTitle("Flux [cm-2 s-1 keV-1]"); - fContinuumHist->GetYaxis()->SetTitleSize(0.05); - fContinuumHist->GetYaxis()->SetLabelSize(0.05); - - return fContinuumHist; -} - -/////////////////////////////////////////////// -/// \brief Same as GetContinuumSpectrum, the flux will be -/// expressed in cm-2 s-1 keV-1. Binned in 1eV steps. -/// -TH1D* TRestAxionSolarHiddenPhotonFlux::GetTotalSpectrum() { - TH1D* hc = GetContinuumSpectrum(); - - if (fTotalHist != nullptr) { - delete fTotalHist; - fTotalHist = nullptr; - } - - fTotalHist = new TH1D("fTotalHist", "", 20000, 0, 20); - for (int n = 0; n < hc->GetNbinsX(); n++) { - for (int m = 0; m < 100; m++) { - fTotalHist->SetBinContent(n * 100 + 1 + m, hc->GetBinContent(n + 1)); - } - } - - fTotalHist->SetStats(0); - fTotalHist->GetXaxis()->SetTitle("Energy [keV]"); - fTotalHist->GetXaxis()->SetTitleSize(0.05); - fTotalHist->GetXaxis()->SetLabelSize(0.05); - fTotalHist->GetYaxis()->SetTitle("Flux [cm-2 s-1 keV-1]"); - fTotalHist->GetYaxis()->SetTitleSize(0.05); - fTotalHist->GetYaxis()->SetLabelSize(0.05); - - return fTotalHist; -} - -/////////////////////////////////////////////// -/// \brief A helper method to initialize the internal class data members with the -/// integrated flux for each solar ring. It will be called by TRestAxionSolarHiddenPhotonFlux::Initialize. -/// -void TRestAxionSolarHiddenPhotonFlux::IntegrateSolarFluxes() { - fTotalContinuumFlux = 0.0; - for (unsigned int n = 0; n < fFluxTable.size(); n++) { - fTotalContinuumFlux += fFluxTable[n]->Integral() * 0.1; // We integrate in 100eV steps - fFluxTableIntegrals.push_back(fTotalContinuumFlux); - } - - for (unsigned int n = 0; n < fFluxTableIntegrals.size(); n++) - fFluxTableIntegrals[n] /= fTotalContinuumFlux; -} - -/////////////////////////////////////////////// -/// \brief It returns the integrated flux at earth in cm-2 s-1 for the given energy range -/// -Double_t TRestAxionSolarHiddenPhotonFlux::IntegrateFluxInRange(TVector2 eRange) { - if (eRange.X() == -1 && eRange.Y() == -1) { - if (GetTotalFlux() == 0) IntegrateSolarFluxes(); - return GetTotalFlux(); - } - - Double_t flux = 0; - fTotalContinuumFlux = 0.0; - for (unsigned int n = 0; n < fFluxTable.size(); n++) { - flux += fFluxTable[n]->Integral(fFluxTable[n]->FindFixBin(eRange.X()), - fFluxTable[n]->FindFixBin(eRange.Y())) * - 0.1; // We integrate in 100eV steps - } - - return flux; -} - -/////////////////////////////////////////////// -/// \brief It returns a random solar radius position and energy according to the -/// flux distributions defined inside the solar tables loaded in the class -/// -std::pair TRestAxionSolarHiddenPhotonFlux::GetRandomEnergyAndRadius(TVector2 eRange) { - - std::pair result = {0, 0}; - if (!AreTablesLoaded()) { RESTWarning << "Tables not loaded!!" << RESTendl; return result; } - Double_t rnd = fRandom->Rndm(); - for (unsigned int r = 0; r < fFluxTableIntegrals.size(); r++) { - if (rnd < fFluxTableIntegrals[r]) { - Double_t energy = fFluxTable[r]->GetRandom(); - if (eRange.X() != -1 && eRange.Y() != -1) { - if (energy < eRange.X() || energy > eRange.Y()) return GetRandomEnergyAndRadius(eRange); - } - Double_t radius = ((Double_t)r + fRandom->Rndm()) * 0.001; - std::pair p = {energy, radius}; - return p; - } - } - return result; -} - -/////////////////////////////////////////////// -/// \brief It prints on screen the flux table that has been read from file -/// -void TRestAxionSolarHiddenPhotonFlux::PrintContinuumSolarTable() { - cout << "Continuum solar flux table: " << endl; - cout << "--------------------------- " << endl; - for (unsigned int n = 0; n < fFluxTable.size(); n++) { - for (int m = 0; m < fFluxTable[n]->GetNbinsX(); m++) - cout << fFluxTable[n]->GetBinContent(m + 1) << "\t"; - cout << endl; - cout << endl; - } - cout << endl; -} - -/////////////////////////////////////////////// -/// \brief It prints on screen the integrated solar flux per solar ring -/// -void TRestAxionSolarHiddenPhotonFlux::PrintIntegratedRingFlux() { - cout << "Integrated solar flux per solar ring: " << endl; - cout << "--------------------------- " << endl; - /* - for (int n = 0; n < fFluxPerRadius.size(); n++) - cout << "n : " << n << " flux : " << fFluxPerRadius[n] << endl; - cout << endl; - */ -} - -/////////////////////////////////////////////// -/// \brief Prints on screen the information about the metadata members of TRestAxionSolarHiddenPhotonFlux -/// -void TRestAxionSolarHiddenPhotonFlux::PrintMetadata() { - TRestAxionSolarFlux::PrintMetadata(); - - RESTMetadata << " - Solar hidden photon datafile (flux) : " << fFluxDataFile << RESTendl; - RESTMetadata << " - Solar hidden photon datafile (width) : " << fWidthDataFile << RESTendl; - RESTMetadata << " - Solar hidden photon datafile (plasma freq) : " << fPlasmaFreqDataFile << RESTendl; - RESTMetadata << "-------" << RESTendl; - RESTMetadata << " - Total continuum flux : " << fTotalContinuumFlux << " cm-2 s-1" << RESTendl; - RESTMetadata << "++++++++++++++++++" << RESTendl; - - if (GetVerboseLevel() >= TRestStringOutput::REST_Verbose_Level::REST_Debug) { - PrintContinuumSolarTable(); - PrintIntegratedRingFlux(); - } -} - -/////////////////////////////////////////////// -/// \brief It will create files with spectra to be used -/// in a later ocasion. -/// -void TRestAxionSolarHiddenPhotonFlux::ExportTables(Bool_t ascii) { - string rootFilename = TRestTools::GetFileNameRoot(fFluxDataFile); - - string path = REST_USER_PATH + "/export/"; - - if (!TRestTools::fileExists(path)) { - std::cout << "Creating path: " << path << std::endl; - int z = system(("mkdir -p " + path).c_str()); - if (z != 0) RESTError << "Could not create directory " << path << RESTendl; - } - - if (fFluxTable.size() > 0) { - std::vector> table; - for (const auto& x : fFluxTable) { - std::vector row; - for (int n = 0; n < x->GetNbinsX(); n++) row.push_back(x->GetBinContent(n + 1)); - - table.push_back(row); - } - - if (!ascii) - TRestTools::ExportBinaryTable(path + "/" + rootFilename + ".N200f", table); - else - TRestTools::ExportASCIITable(path + "/" + rootFilename + ".dat", table); - } -} - -/////////////////////////////////////////////// -/// \brief It draws the contents of a .flux file. This method just receives the -/// -TCanvas* TRestAxionSolarHiddenPhotonFlux::DrawSolarFlux() { - if (fCanvas != nullptr) { - delete fCanvas; - fCanvas = nullptr; - } - fCanvas = new TCanvas("canv", "This is the canvas title", 1200, 500); - fCanvas->Draw(); - - TPad* pad1 = new TPad("pad1", "This is pad1", 0.01, 0.02, 0.99, 0.97); - pad1->Divide(2, 1); - pad1->Draw(); - - pad1->cd(1); - pad1->cd(1)->SetLogy(); - pad1->cd(1)->SetRightMargin(0.09); - pad1->cd(1)->SetLeftMargin(0.15); - pad1->cd(1)->SetBottomMargin(0.15); - - TH1D* ht = GetTotalSpectrum(); - ht->SetLineColor(kBlack); - ht->SetFillStyle(4050); - ht->SetFillColor(kBlue - 10); - - ht->Draw("hist"); - - pad1->cd(2); - pad1->cd(2)->SetRightMargin(0.09); - pad1->cd(2)->SetLeftMargin(0.15); - pad1->cd(2)->SetBottomMargin(0.15); - - ht->Draw("hist"); - - return fCanvas; -} - diff --git a/src/TRestAxionSolarHiddenPhotonFlux.cxx.old b/src/TRestAxionSolarHiddenPhotonFlux.cxx.old deleted file mode 100644 index e61f0630..00000000 --- a/src/TRestAxionSolarHiddenPhotonFlux.cxx.old +++ /dev/null @@ -1,613 +0,0 @@ -/******************** REST disclaimer *********************************** - * This file is part of the REST software framework. * - * * - * Copyright (C) 2016 GIFNA/TREX (University of Zaragoza) * - * For more information see http://gifna.unizar.es/trex * - * * - * REST 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. * - * * - * REST 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 a copy of the GNU General Public License along with * - * REST in $REST_PATH/LICENSE. * - * If not, see http://www.gnu.org/licenses/. * - * For the list of contributors see $REST_PATH/CREDITS. * - *************************************************************************/ - -////////////////////////////////////////////////////////////////////////// -/// TRestAxionSolarHiddenPhotonFlux will use a file in binary format to initialize -/// a solar flux table that will describe the solar hidden photon flux spectrum as a function -/// of the solar radius. -/// -/// This class loads the hidden photon flux that depends on the mass and kinetic mixing parameter. -/// For axion-like particle prodution independent of mass there is the class -/// TRestAxionSolarQCDFlux. Both classes are prototyped by a pure base class TRestAxionSolarFlux -/// that defines common methods used to evaluate the flux, and generate Monte-Carlo events inside -/// TRestAxionGeneratorProcess. -/// -/// ### Basic use -/// -/// Once the class has been initialized, the main use of this class will be provided -/// by the method TRestAxionSolarHiddenPhotonFlux::GetRandomEnergyAndRadius. This method will -/// return a random axion energy and position inside the solar radius following the -/// distributions given by the solar flux tables. -/// -/// Description of the specific parameters accepted by this metadata class. -/// - *fluxDataFile:* A table with 1000 rows representing the solar ring flux from the -/// center to the corona, and 200 columns representing the flux, measured in cm-2 s-1 keV-1, -/// for the range (0,20)keV in steps of 100eV. The table is provided as a binary table using -/// `.N200f` extension. -/// - *widthDataFile:* A table with 1000 rows representing the width of the hidden photon -/// resonant production (wG) for each solar ring from the center to the corona, and 200 columns -/// representing the width, measured in eV2, for the range (0,20)keV in steps of 100eV. The -/// table is provided as a binary table using `.N200f` extension. -/// - *plasmaFreqDataFile:* A table with 1000 rows and only 1 column representing the solar -/// plasma frequency (wp) for each solar ring from the center to the corona, measured in eV. The -/// table is provided as a binary table using `.N1f` extension. -/// -/// Pre-generated solar axion flux tables will be available at the -/// [axionlib-data](https://github.com/rest-for-physics/axionlib-data/tree/master) -/// repository. The different RML flux definitions used to load those tables -/// will be found at the -/// [fluxes.rml](https://github.com/rest-for-physics/axionlib-data/blob/master/solarFlux/fluxes.rml) -/// file found at the axionlib-data repository. -/// -/// Inside a local REST installation, the `fluxes.rml` file will be found at the REST -/// installation directory, and it will be located automatically by the -/// TRestMetadata::SearchFile method. -/// -/// ### A basic RML definition -/// -/// The following definition integrates an axion-photon component with a continuum -/// spectrum using a Primakoff production model, and a dummy spectrum file that -/// includes two monocrhomatic lines at different solar disk radius positions. -/// -/// \code -/// -/// -/// -/// -/// -/// -/// -/// -/// -/// -/// -/// \endcode -/// -/// \warning When the flux is loaded manually inside the `restRoot` interactive -/// shell, or inside a macro or script, after metadata initialization, it is necessary -/// to call the method TRestAxionSolarHiddenPhotonFlux::LoadTables(mass) to trigger the tables -/// initialization. -/// -/// ### Performing MonteCarlo tests using pre-loaded tables -/// -/// In order to test the response of different solar flux definitions we may use the script -/// `solarPlot.py` found at `pipeline/metadata/solarFlux/`. This script will generate a -/// number of particles and it will assign to each particle an energy and solar disk -/// location with the help of the method TRestAxionSolarHiddenPhotonFlux::GetRandomEnergyAndRadius. -/// -/// \code -/// python3 solarPlotHiddenPhoton.py --fluxname HiddenPhoton --N 1000000 -/// \endcode -/// -/// By default, it will load the flux definition found at `fluxes.rml` from the -/// `axionlib-data` repository, and generate a `png` image with the resuts from the -/// Monte Carlo execution. -/// -/// \htmlonly \endhtmlonly -/// -/// ![Solar flux distributions MC-generated with TRestAxionSolarQCDFlux.](ABC_flux_MC.png) -/// -/// ### Exporting the solar flux tables -/// -/// On top of that, we will be able to export those tables to the TRestAxionSolarHiddenPhotonFlux -/// standard format to be used in later occasions. -/// -/// \code -/// TRestAxionSolarHiddenPhotonFlux *sFlux = new TRestAxionSolarHiddenPhotonFlux("fluxes.rml", -/// "HiddenPhoton") sFlux->Initialize() sFlux->ExportTables() -/// \endcode -/// -/// which will produce a binary table `.N200f` with the continuum flux. The filename root will be -/// extracted from the original `.flux` file. Optionally we may export the continuum flux to an -/// ASCII file by indicating it at the TRestAxionSolarHiddenPhotonFlux::ExportTables method call. -/// The files will be placed at the REST user space, at `$HOME/.rest/export/` directory. -/// -/// TODO Implement the method TRestAxionSolarQCDFlux::InitializeSolarTable using -/// a solar model description by TRestAxionSolarModel. -/// -/// TODO Perhaps it would be interesting to replace fFluxTable for a TH2D -/// -///-------------------------------------------------------------------------- -/// -/// RESTsoft - Software for Rare Event Searches with TPCs -/// -/// History of developments: -/// -/// 2023-May: Specific methods extracted from TRestAxionSolarFlux -/// Javier Galan -/// 2023-June: TRestAxionSolarHiddenPhotonFlux created by editing TRestAxionSolarQCDFlux -/// Tomas O'Shea -/// -/// \class TRestAxionSolarHiddenPhotonFlux -/// \author Javier Galan -/// -///
-/// - -#include "TRestAxionSolarHiddenPhotonFlux.h" -using namespace std; - -ClassImp(TRestAxionSolarHiddenPhotonFlux); - -/////////////////////////////////////////////// -/// \brief Default constructor -/// -TRestAxionSolarHiddenPhotonFlux::TRestAxionSolarHiddenPhotonFlux() : TRestAxionSolarFlux() {} - -/////////////////////////////////////////////// -/// \brief Constructor loading data from a config file -/// -/// If no configuration path is defined using TRestMetadata::SetConfigFilePath -/// the path to the config file must be specified using full path, absolute or -/// relative. -/// -/// The default behaviour is that the config file must be specified with -/// full path, absolute or relative. -/// -/// \param cfgFileName A const char* giving the path to an RML file. -/// \param name The name of the specific metadata. It will be used to find the -/// corresponding TRestAxionMagneticField section inside the RML. -/// -TRestAxionSolarHiddenPhotonFlux::TRestAxionSolarHiddenPhotonFlux(const char* cfgFileName, string name) - : TRestAxionSolarFlux(cfgFileName) { - LoadConfigFromFile(fConfigFileName, name); - - if (GetVerboseLevel() >= TRestStringOutput::REST_Verbose_Level::REST_Info) PrintMetadata(); -} - -/////////////////////////////////////////////// -/// \brief Default destructor -/// -TRestAxionSolarHiddenPhotonFlux::~TRestAxionSolarHiddenPhotonFlux() {} - -/////////////////////////////////////////////// -/// \brief It will load the tables in memory by using the filename information provided -/// inside the metadata members, and calculate the solar flux for a given m. -/// -Bool_t TRestAxionSolarHiddenPhotonFlux::LoadTables() { - - if (GetMass() <= 0 ) { - RESTWarning << "TRestAxionSolarHiddenPhotonFlux::LoadTables - hidden photon mass not yet defined" << RESTendl; - RESTWarning << "TRestAxionSolarHiddenPhotonFlux::LoadTables - mass given as " << GetMass() << " eV" << RESTendl; - return false; - } - if ( fFluxDataFile == "" ){ - RESTWarning << "TRestAxionSolarHiddenPhotonFlux::LoadTables - flux table not found!!\n " << fFluxDataFile << RESTendl; - return false; - } - if ( fWidthDataFile == "") { - RESTWarning << "TRestAxionSolarHiddenPhotonFlux::LoadTables - width table not found!!\n " << fWidthDataFile << RESTendl; - return false; - } - if ( fPlasmaFreqDataFile == "" ) { - RESTWarning << "TRestAxionSolarHiddenPhotonFlux::LoadTables - plasma frequency table not found!!\n " << fPlasmaFreqDataFile << RESTendl; - return false; - } - - LoadContinuumFluxTable(); - LoadWidthTable(); - LoadPlasmaFreqTable(); - - CalculateSolarFlux(); - - IntegrateSolarFluxes(); - return true; -} - -/////////////////////////////////////////////// -/// \brief A helper method to load the data file containing continuum spectra as a -/// function of the solar radius. It will be called by TRestAxionSolarHiddenPhotonFlux::Initialize. -/// -void TRestAxionSolarHiddenPhotonFlux::LoadContinuumFluxTable() { - if (fFluxDataFile == "") { - RESTError - << "TRestAxionSolarHiddenPhotonFlux::LoadContinuumFluxTable. No solar flux table was defined" - << RESTendl; - return; - } - - string fullPathName = SearchFile((string)fFluxDataFile); - - RESTDebug << "Loading table from file : " << RESTendl; - RESTDebug << "File : " << fullPathName << RESTendl; - - std::vector> fluxTable; - - if (!TRestTools::IsBinaryFile(fFluxDataFile)) { - fluxTable.clear(); - RESTError << "File is not in binary format!" << RESTendl; - } - - TRestTools::ReadBinaryTable(fullPathName, fluxTable); - - if (fluxTable.size() != 1000 || fluxTable[0].size() != 200) { - fluxTable.clear(); - RESTError << "LoadContinuumFluxTable. The table does not contain the right number of rows or columns" - << RESTendl; - RESTError << "Table will not be populated" << RESTendl; - } - - for (unsigned int n = 0; n < fluxTable.size(); n++) { - TH1D* h = new TH1D(Form("%s_ContinuumFluxAtRadius%d", GetName(), n), "", 200, 0, 20); - for (unsigned int m = 0; m < fluxTable[n].size(); m++) { h->SetBinContent(m + 1, fluxTable[n][m]); } - fContinuumTable.push_back(h); - } -} - -/////////////////////////////////////////////// -/// \brief A helper method to load the data file containing resonance width as a -/// function of the solar radius. It will be called by TRestAxionSolarHiddenPhotonFlux::Initialize. -/// -void TRestAxionSolarHiddenPhotonFlux::LoadWidthTable() { - if (fFluxDataFile == "") { - RESTError << "TRestAxionSolarHiddenPhotonFlux::LoadWidthTable. No width table was defined" - << RESTendl; - return; - } - - string fullPathName = SearchFile((string)fWidthDataFile); - - RESTDebug << "Loading table from file : " << RESTendl; - RESTDebug << "File : " << fullPathName << RESTendl; - - std::vector> fluxTable; - - if (!TRestTools::IsBinaryFile(fWidthDataFile)) { - fluxTable.clear(); - RESTError << "File is not in binary format!" << RESTendl; - } - - TRestTools::ReadBinaryTable(fullPathName, fluxTable); - //RESTMetadata << "Width table rows / columns: " << fluxTable.size() << " " << fluxTable[0].size() << RESTendl; - - if (fluxTable.size() != 1000 || fluxTable[0].size() != 200) { - fluxTable.clear(); - RESTError << "LoadWidthTable. The table does not contain the right number of rows or columns" - << RESTendl; - RESTError << "Table will not be populated" << RESTendl; - } - - for (unsigned int n = 0; n < fluxTable.size(); n++) { - TH1D* h = new TH1D(Form("%s_ResonanceWidthAtRadius%d", GetName(), n), "", 200, 0, 20); - for (unsigned int m = 0; m < fluxTable[n].size(); m++) { h->SetBinContent(m + 1, fluxTable[n][m]); } - fWidthTable.push_back(h); - } -} - -/////////////////////////////////////////////// -/// \brief A helper method to load the data file containing resonance width as a -/// function of the solar radius. It will be called by TRestAxionSolarHiddenPhotonFlux::Initialize. -/// -void TRestAxionSolarHiddenPhotonFlux::LoadPlasmaFreqTable() { - if (fFluxDataFile == "") { - RESTError - << "TRestAxionSolarHiddenPhotonFlux::LoadPlasmaFreqTable. No plasma frequency table was defined" - << RESTendl; - return; - } - - string fullPathName = SearchFile((string)fPlasmaFreqDataFile); - - RESTDebug << "Loading table from file : " << RESTendl; - RESTDebug << "File : " << fullPathName << RESTendl; - - std::vector> fluxTable; - - if (!TRestTools::IsBinaryFile(fWidthDataFile)) { - fluxTable.clear(); - RESTError << "File is not in binary format!" << RESTendl; - } - - TRestTools::ReadBinaryTable(fullPathName, fluxTable); - - if (fluxTable.size() != 1000 || fluxTable[0].size() != 1) { - fluxTable.clear(); - RESTError << "LoadPlasmaFreqTable. The table does not contain the right number of rows or columns" - << RESTendl; - RESTError << "Table will not be populated" << RESTendl; - } - - for (unsigned int n = 0; n < fluxTable.size(); n++) { - TH1D* h = new TH1D(Form("%s_PlasmaFreqAtRadius%d", GetName(), n), "", 1, 0, 20); - for (unsigned int m = 0; m < fluxTable[n].size(); m++) { h->SetBinContent(m + 1, fluxTable[n][m]); } - fPlasmaFreqTable.push_back(h); - } -} - -/////////////////////////////////////////////// -/// \brief A helper method to calculate the real solar flux spectrum from the 3 tables, the -/// and the hidden photon mass for chi=1. -/// -void TRestAxionSolarHiddenPhotonFlux::CalculateSolarFlux() { - if (GetMass() == 0) { - RESTError << "CalculateSolarFlux. The hidden photon mass is set to zero!" << RESTendl; - return; - } - if (fContinuumTable.size() == 0 ) { - RESTError << "TRestAxionSolarHiddenPhotonFlux::CalculateSolarFlux - empty flux table!" << RESTendl; - return; - } - if (fPlasmaFreqTable.size() == 0 ) { - RESTError << "TRestAxionSolarHiddenPhotonFlux::CalculateSolarFlux - empty plasma freq table!" << RESTendl; - return; - } - if (fWidthTable.size() == 0 ) { - RESTError << "TRestAxionSolarHiddenPhotonFlux::CalculateSolarFlux - empty width table!" << RESTendl; - return; - } - - Double_t mass = GetMass(); - cout << mass << endl; - for (unsigned int n = 0; n < fContinuumTable.size(); n++) { - // m4 * chi2 * wG * flux / ( (m2 - wp2)^2 + (w G)^2 ) - - Double_t wp = fPlasmaFreqTable[n]->GetBinContent(1); - TH1D* hMass = new TH1D(Form("%s_hMass%d", GetName(), n), "hMass", 200, 0, 20); - TH1D* hWg2 = (TH1D*)fWidthTable[n]->Clone(); - hWg2->Multiply(hWg2); // (w G)^2 - - for ( unsigned int c; c < 200; c++ ) { - Double_t wG = fWidthTable[n]->GetBinContent(c+1); - hMass->SetBinContent( c+1, pow(mass,-4) * ( pow( pow(mass,2) - pow(wp,2) , 2 )));// + pow(wG,2) ) ); // m2 - } - - hMass->Add(hWg2); // (m2 - wp2)^2 + (w G)^2 - - TH1D* h = (TH1D*)fWidthTable[n]->Clone(); // wG - h->Multiply(fContinuumTable[n]); // wG * flux - h->Divide(hMass); // wG * flux / ( (m2 - wp2)^2 + (w G)^2 ) - //h->Scale(pow(mass, 4)); // m4 * wG * flux / ( (m2 - wp2)^2 + (w G)^2 ) - - fFluxTable.push_back(h); - } -} - -/////////////////////////////////////////////// -/// \brief It builds a histogram with the continuum spectrum. -/// The flux will be expressed in cm-2 s-1 keV-1. Binned in 100eV steps. -/// -TH1D* TRestAxionSolarHiddenPhotonFlux::GetContinuumSpectrum() { - if (fContinuumHist != nullptr) { - delete fContinuumHist; - fContinuumHist = nullptr; - } - - fContinuumHist = new TH1D("ContinuumHist", "", 200, 0, 20); - for (const auto& x : fFluxTable) { - fContinuumHist->Add(x); - } - - fContinuumHist->SetStats(0); - fContinuumHist->GetXaxis()->SetTitle("Energy [keV]"); - fContinuumHist->GetXaxis()->SetTitleSize(0.05); - fContinuumHist->GetXaxis()->SetLabelSize(0.05); - fContinuumHist->GetYaxis()->SetTitle("Flux [cm-2 s-1 keV-1]"); - fContinuumHist->GetYaxis()->SetTitleSize(0.05); - fContinuumHist->GetYaxis()->SetLabelSize(0.05); - - return fContinuumHist; -} - -/////////////////////////////////////////////// -/// \brief Same as GetContinuumSpectrum, the flux will be -/// expressed in cm-2 s-1 keV-1. Binned in 1eV steps. -/// -TH1D* TRestAxionSolarHiddenPhotonFlux::GetTotalSpectrum() { - TH1D* hc = GetContinuumSpectrum(); - - if (fTotalHist != nullptr) { - delete fTotalHist; - fTotalHist = nullptr; - } - - fTotalHist = new TH1D("fTotalHist", "", 20000, 0, 20); - for (int n = 0; n < hc->GetNbinsX(); n++) { - for (int m = 0; m < 100; m++) { - fTotalHist->SetBinContent(n * 100 + 1 + m, hc->GetBinContent(n + 1)); - } - } - - fTotalHist->SetStats(0); - fTotalHist->GetXaxis()->SetTitle("Energy [keV]"); - fTotalHist->GetXaxis()->SetTitleSize(0.05); - fTotalHist->GetXaxis()->SetLabelSize(0.05); - fTotalHist->GetYaxis()->SetTitle("Flux [cm-2 s-1 keV-1]"); - fTotalHist->GetYaxis()->SetTitleSize(0.05); - fTotalHist->GetYaxis()->SetLabelSize(0.05); - - return fTotalHist; -} - -/////////////////////////////////////////////// -/// \brief A helper method to initialize the internal class data members with the -/// integrated flux for each solar ring. It will be called by TRestAxionSolarHiddenPhotonFlux::Initialize. -/// -void TRestAxionSolarHiddenPhotonFlux::IntegrateSolarFluxes() { - fTotalContinuumFlux = 0.0; - for (unsigned int n = 0; n < fFluxTable.size(); n++) { - fTotalContinuumFlux += fFluxTable[n]->Integral() * 0.1; // We integrate in 100eV steps - fFluxTableIntegrals.push_back(fTotalContinuumFlux); - } - - for (unsigned int n = 0; n < fFluxTableIntegrals.size(); n++) - fFluxTableIntegrals[n] /= fTotalContinuumFlux; -} - -/////////////////////////////////////////////// -/// \brief It returns the integrated flux at earth in cm-2 s-1 for the given energy range -/// -Double_t TRestAxionSolarHiddenPhotonFlux::IntegrateFluxInRange(TVector2 eRange) { - if (eRange.X() == -1 && eRange.Y() == -1) { - if (GetTotalFlux() == 0) IntegrateSolarFluxes(); - return GetTotalFlux(); - } - - Double_t flux = 0; - fTotalContinuumFlux = 0.0; - for (unsigned int n = 0; n < fFluxTable.size(); n++) { - flux += fFluxTable[n]->Integral(fFluxTable[n]->FindFixBin(eRange.X()), - fFluxTable[n]->FindFixBin(eRange.Y())) * - 0.1; // We integrate in 100eV steps - } - - return flux; -} - -/////////////////////////////////////////////// -/// \brief It returns a random solar radius position and energy according to the -/// flux distributions defined inside the solar tables loaded in the class -/// -std::pair TRestAxionSolarHiddenPhotonFlux::GetRandomEnergyAndRadius(TVector2 eRange) { - - std::pair result = {0, 0}; - if (!AreTablesLoaded()) { RESTWarning << "Tables not loaded!!" << RESTendl; return result; } - Double_t rnd = fRandom->Rndm(); - for (unsigned int r = 0; r < fFluxTableIntegrals.size(); r++) { - if (rnd < fFluxTableIntegrals[r]) { - Double_t energy = fFluxTable[r]->GetRandom(); - if (eRange.X() != -1 && eRange.Y() != -1) { - if (energy < eRange.X() || energy > eRange.Y()) return GetRandomEnergyAndRadius(eRange); - } - Double_t radius = ((Double_t)r + fRandom->Rndm()) * 0.001; - std::pair p = {energy, radius}; - return p; - } - } - return result; -} - -/////////////////////////////////////////////// -/// \brief It prints on screen the flux table that has been read from file -/// -void TRestAxionSolarHiddenPhotonFlux::PrintContinuumSolarTable() { - cout << "Continuum solar flux table: " << endl; - cout << "--------------------------- " << endl; - for (unsigned int n = 0; n < fFluxTable.size(); n++) { - for (int m = 0; m < fFluxTable[n]->GetNbinsX(); m++) - cout << fFluxTable[n]->GetBinContent(m + 1) << "\t"; - cout << endl; - cout << endl; - } - cout << endl; -} - -/////////////////////////////////////////////// -/// \brief It prints on screen the integrated solar flux per solar ring -/// -void TRestAxionSolarHiddenPhotonFlux::PrintIntegratedRingFlux() { - cout << "Integrated solar flux per solar ring: " << endl; - cout << "--------------------------- " << endl; - /* - for (int n = 0; n < fFluxPerRadius.size(); n++) - cout << "n : " << n << " flux : " << fFluxPerRadius[n] << endl; - cout << endl; - */ -} - -/////////////////////////////////////////////// -/// \brief Prints on screen the information about the metadata members of TRestAxionSolarHiddenPhotonFlux -/// -void TRestAxionSolarHiddenPhotonFlux::PrintMetadata() { - TRestAxionSolarFlux::PrintMetadata(); - - RESTMetadata << " - Solar hidden photon datafile (flux) : " << fFluxDataFile << RESTendl; - RESTMetadata << " - Solar hidden photon datafile (width) : " << fWidthDataFile << RESTendl; - RESTMetadata << " - Solar hidden photon datafile (plasma freq) : " << fPlasmaFreqDataFile << RESTendl; - RESTMetadata << "-------" << RESTendl; - RESTMetadata << " - Total continuum flux : " << fTotalContinuumFlux << " cm-2 s-1" << RESTendl; - RESTMetadata << "++++++++++++++++++" << RESTendl; - - if (GetVerboseLevel() >= TRestStringOutput::REST_Verbose_Level::REST_Debug) { - PrintContinuumSolarTable(); - PrintIntegratedRingFlux(); - } -} - -/////////////////////////////////////////////// -/// \brief It will create files with spectra to be used -/// in a later ocasion. -/// -void TRestAxionSolarHiddenPhotonFlux::ExportTables(Bool_t ascii) { - string rootFilename = TRestTools::GetFileNameRoot(fFluxDataFile); - - string path = REST_USER_PATH + "/export/"; - - if (!TRestTools::fileExists(path)) { - std::cout << "Creating path: " << path << std::endl; - int z = system(("mkdir -p " + path).c_str()); - if (z != 0) RESTError << "Could not create directory " << path << RESTendl; - } - - if (fFluxTable.size() > 0) { - std::vector> table; - for (const auto& x : fFluxTable) { - std::vector row; - for (int n = 0; n < x->GetNbinsX(); n++) row.push_back(x->GetBinContent(n + 1)); - - table.push_back(row); - } - - if (!ascii) - TRestTools::ExportBinaryTable(path + "/" + rootFilename + ".N200f", table); - else - TRestTools::ExportASCIITable(path + "/" + rootFilename + ".dat", table); - } -} - -/////////////////////////////////////////////// -/// \brief It draws the contents of a .flux file. This method just receives the -/// -TCanvas* TRestAxionSolarHiddenPhotonFlux::DrawSolarFlux() { - if (fCanvas != nullptr) { - delete fCanvas; - fCanvas = nullptr; - } - fCanvas = new TCanvas("canv", "This is the canvas title", 1200, 500); - fCanvas->Draw(); - - TPad* pad1 = new TPad("pad1", "This is pad1", 0.01, 0.02, 0.99, 0.97); - pad1->Divide(2, 1); - pad1->Draw(); - - pad1->cd(1); - pad1->cd(1)->SetLogy(); - pad1->cd(1)->SetRightMargin(0.09); - pad1->cd(1)->SetLeftMargin(0.15); - pad1->cd(1)->SetBottomMargin(0.15); - - TH1D* ht = GetTotalSpectrum(); - ht->SetLineColor(kBlack); - ht->SetFillStyle(4050); - ht->SetFillColor(kBlue - 10); - - ht->Draw("hist"); - - pad1->cd(2); - pad1->cd(2)->SetRightMargin(0.09); - pad1->cd(2)->SetLeftMargin(0.15); - pad1->cd(2)->SetBottomMargin(0.15); - - ht->Draw("hist"); - - return fCanvas; -} - From 5f91092171b0a7810cbde0cd04a3fd3e75ff6f98 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 15 Sep 2023 11:02:57 +0000 Subject: [PATCH 33/48] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- inc/TRestAxionSolarFlux.h | 9 +- inc/TRestAxionSolarHiddenPhotonFlux.h | 2 +- inc/TRestAxionSolarQCDFlux.h | 4 +- .../solarFlux/solarPlotHiddenPhoton.py | 10 +- src/TRestAxionSolarFlux.cxx | 5 +- src/TRestAxionSolarHiddenPhotonFlux.cxx | 114 ++++++++++-------- 6 files changed, 79 insertions(+), 65 deletions(-) diff --git a/inc/TRestAxionSolarFlux.h b/inc/TRestAxionSolarFlux.h index 9a917211..6c740852 100644 --- a/inc/TRestAxionSolarFlux.h +++ b/inc/TRestAxionSolarFlux.h @@ -65,10 +65,13 @@ class TRestAxionSolarFlux : public TRestMetadata { void Initialize(); /// It is required in order to load solar flux tables into memory for specific mass - void InitializeMass( Double_t mass ) { SetMass(mass); Initialize(); } - + void InitializeMass(Double_t mass) { + SetMass(mass); + Initialize(); + } + /// Set mass and reinitialise - void SetMass( Double_t m ) { fMass = m; } //Initialize(); } + void SetMass(Double_t m) { fMass = m; } // Initialize(); } /// It returns the integrated flux at earth in cm-2 s-1 for the given energy range virtual Double_t IntegrateFluxInRange(TVector2 eRange = TVector2(-1, -1)) = 0; diff --git a/inc/TRestAxionSolarHiddenPhotonFlux.h b/inc/TRestAxionSolarHiddenPhotonFlux.h index bdc44040..5a6b0398 100644 --- a/inc/TRestAxionSolarHiddenPhotonFlux.h +++ b/inc/TRestAxionSolarHiddenPhotonFlux.h @@ -73,7 +73,7 @@ class TRestAxionSolarHiddenPhotonFlux : public TRestAxionSolarFlux { void LoadMonoChromaticFluxTable(); void IntegrateSolarFluxes(); - public: + public: /// It returns true if continuum flux spectra was loaded Bool_t isSolarTableLoaded() { return fFluxTable.size() > 0; } diff --git a/inc/TRestAxionSolarQCDFlux.h b/inc/TRestAxionSolarQCDFlux.h index 10db402e..fb99ebb0 100644 --- a/inc/TRestAxionSolarQCDFlux.h +++ b/inc/TRestAxionSolarQCDFlux.h @@ -93,9 +93,7 @@ class TRestAxionSolarQCDFlux : public TRestAxionSolarFlux { Bool_t LoadTables() override; /// It returns the total integrated flux at earth in cm-2 s-1 - Double_t GetTotalFlux() override { - return fTotalContinuumFlux + fTotalMonochromaticFlux; - } + Double_t GetTotalFlux() override { return fTotalContinuumFlux + fTotalMonochromaticFlux; } /// It returns an energy integrated spectrum in cm-2 s-1 keV-1 TH1D* GetEnergySpectrum() override { return GetTotalSpectrum(); } diff --git a/pipeline/metadata/solarFlux/solarPlotHiddenPhoton.py b/pipeline/metadata/solarFlux/solarPlotHiddenPhoton.py index c07ac580..5b83b758 100755 --- a/pipeline/metadata/solarFlux/solarPlotHiddenPhoton.py +++ b/pipeline/metadata/solarFlux/solarPlotHiddenPhoton.py @@ -44,12 +44,10 @@ parser.add_argument( "--N", dest="samples", type=int, help="The number of generated particles" ) -parser.add_argument( - "--m", dest="mass", type=float, help="Hidden photon mass [eV]" -) +parser.add_argument("--m", dest="mass", type=float, help="Hidden photon mass [eV]") args = parser.parse_args() -mass = 10. # eV +mass = 10.0 # eV if args.mass != None: mass = args.mass @@ -96,7 +94,7 @@ comb_spt = TH2D("comb_spt", "Energy versus solar radius", 20000, 0, 20, 100, 0, 1) for i in range(samples): x = combinedFlux.GetRandomEnergyAndRadius((-1, -1)) - #print(x) + # print(x) comb_spt.Fill(x[0], x[1]) rnd = TRandom3(0) @@ -164,4 +162,4 @@ c1.Print(outfname) print("Generated file : " + outfname) -#exit(0) +# exit(0) diff --git a/src/TRestAxionSolarFlux.cxx b/src/TRestAxionSolarFlux.cxx index f82d9e34..62549922 100644 --- a/src/TRestAxionSolarFlux.cxx +++ b/src/TRestAxionSolarFlux.cxx @@ -134,12 +134,11 @@ void TRestAxionSolarFlux::Initialize() { fSeed = fRandom->TRandom::GetSeed(); } - /////////////////////////////////////////////// /// \brief Initialization of TRestAxionSolarFlux members with specific mass /// -//void TRestAxionSolarFlux::InitializeMass( Double_t mass ) { SetMass(mass); RESTMetadata << GetMass() << RESTendl; } // SetMass calls Initialize - +// void TRestAxionSolarFlux::InitializeMass( Double_t mass ) { SetMass(mass); RESTMetadata << GetMass() << +// RESTendl; } // SetMass calls Initialize /////////////////////////////////////////////// /// \brief It builds a histogram using the contents of the .flux file given diff --git a/src/TRestAxionSolarHiddenPhotonFlux.cxx b/src/TRestAxionSolarHiddenPhotonFlux.cxx index 0c213f20..f824fd5c 100644 --- a/src/TRestAxionSolarHiddenPhotonFlux.cxx +++ b/src/TRestAxionSolarHiddenPhotonFlux.cxx @@ -184,23 +184,28 @@ TRestAxionSolarHiddenPhotonFlux::~TRestAxionSolarHiddenPhotonFlux() {} /// inside the metadata members, and calculate the solar flux for a given m. /// Bool_t TRestAxionSolarHiddenPhotonFlux::LoadTables() { - - if (GetMass() <= 0 ) { - RESTWarning << "TRestAxionSolarHiddenPhotonFlux::LoadTables - hidden photon mass not yet defined" << RESTendl; - RESTWarning << "TRestAxionSolarHiddenPhotonFlux::LoadTables - mass given as " << GetMass() << " eV" << RESTendl; - return false; + if (GetMass() <= 0) { + RESTWarning << "TRestAxionSolarHiddenPhotonFlux::LoadTables - hidden photon mass not yet defined" + << RESTendl; + RESTWarning << "TRestAxionSolarHiddenPhotonFlux::LoadTables - mass given as " << GetMass() << " eV" + << RESTendl; + return false; + } + if (fFluxDataFile == "") { + RESTWarning << "TRestAxionSolarHiddenPhotonFlux::LoadTables - flux table not found!!\n " + << fFluxDataFile << RESTendl; + return false; } - if ( fFluxDataFile == "" ){ - RESTWarning << "TRestAxionSolarHiddenPhotonFlux::LoadTables - flux table not found!!\n " << fFluxDataFile << RESTendl; - return false; + if (fWidthDataFile == "") { + RESTWarning << "TRestAxionSolarHiddenPhotonFlux::LoadTables - width table not found!!\n " + << fWidthDataFile << RESTendl; + return false; } - if ( fWidthDataFile == "") { - RESTWarning << "TRestAxionSolarHiddenPhotonFlux::LoadTables - width table not found!!\n " << fWidthDataFile << RESTendl; - return false; - } - if ( fPlasmaFreqDataFile == "" ) { - RESTWarning << "TRestAxionSolarHiddenPhotonFlux::LoadTables - plasma frequency table not found!!\n " << fPlasmaFreqDataFile << RESTendl; - return false; + if (fPlasmaFreqDataFile == "") { + RESTWarning + << "TRestAxionSolarHiddenPhotonFlux::LoadTables - plasma frequency table not found!!\n " + << fPlasmaFreqDataFile << RESTendl; + return false; } LoadContinuumFluxTable(); @@ -248,7 +253,9 @@ void TRestAxionSolarHiddenPhotonFlux::LoadContinuumFluxTable() { for (unsigned int n = 0; n < fluxTable.size(); n++) { TH1D* h = new TH1D(Form("%s_ContinuumFluxAtRadius%d", GetName(), n), "", 200, 0, 20); - for (unsigned int m = 0; m < fluxTable[n].size(); m++) { h->SetBinContent(m + 1, fluxTable[n][m]); } + for (unsigned int m = 0; m < fluxTable[n].size(); m++) { + h->SetBinContent(m + 1, fluxTable[n][m]); + } fContinuumTable.push_back(h); } } @@ -277,8 +284,9 @@ void TRestAxionSolarHiddenPhotonFlux::LoadWidthTable() { } TRestTools::ReadBinaryTable(fullPathName, fluxTable); - //RESTMetadata << "Width table rows / columns: " << fluxTable.size() << " " << fluxTable[0].size() << RESTendl; - + // RESTMetadata << "Width table rows / columns: " << fluxTable.size() << " " << fluxTable[0].size() << + // RESTendl; + if (fluxTable.size() != 1000 || fluxTable[0].size() != 200) { fluxTable.clear(); RESTError << "LoadWidthTable. The table does not contain the right number of rows or columns" @@ -288,7 +296,9 @@ void TRestAxionSolarHiddenPhotonFlux::LoadWidthTable() { for (unsigned int n = 0; n < fluxTable.size(); n++) { TH1D* h = new TH1D(Form("%s_ResonanceWidthAtRadius%d", GetName(), n), "", 200, 0, 20); - for (unsigned int m = 0; m < fluxTable[n].size(); m++) { h->SetBinContent(m + 1, fluxTable[n][m]); } + for (unsigned int m = 0; m < fluxTable[n].size(); m++) { + h->SetBinContent(m + 1, fluxTable[n][m]); + } fWidthTable.push_back(h); } } @@ -318,7 +328,7 @@ void TRestAxionSolarHiddenPhotonFlux::LoadPlasmaFreqTable() { } TRestTools::ReadBinaryTable(fullPathName, fluxTable); - + if (fluxTable.size() != 1000 || fluxTable[0].size() != 1) { fluxTable.clear(); RESTError << "LoadPlasmaFreqTable. The table does not contain the right number of rows or columns" @@ -328,7 +338,9 @@ void TRestAxionSolarHiddenPhotonFlux::LoadPlasmaFreqTable() { for (unsigned int n = 0; n < fluxTable.size(); n++) { TH1D* h = new TH1D(Form("%s_PlasmaFreqAtRadius%d", GetName(), n), "", 1, 0, 20); - for (unsigned int m = 0; m < fluxTable[n].size(); m++) { h->SetBinContent(m + 1, fluxTable[n][m]); } + for (unsigned int m = 0; m < fluxTable[n].size(); m++) { + h->SetBinContent(m + 1, fluxTable[n][m]); + } fPlasmaFreqTable.push_back(h); } } @@ -341,20 +353,21 @@ void TRestAxionSolarHiddenPhotonFlux::CalculateSolarFlux() { if (GetMass() == 0) { RESTError << "CalculateSolarFlux. The hidden photon mass is set to zero!" << RESTendl; return; - } - if (fContinuumTable.size() == 0 ) { - RESTError << "TRestAxionSolarHiddenPhotonFlux::CalculateSolarFlux - empty flux table!" << RESTendl; - return; } - if (fPlasmaFreqTable.size() == 0 ) { - RESTError << "TRestAxionSolarHiddenPhotonFlux::CalculateSolarFlux - empty plasma freq table!" << RESTendl; - return; + if (fContinuumTable.size() == 0) { + RESTError << "TRestAxionSolarHiddenPhotonFlux::CalculateSolarFlux - empty flux table!" << RESTendl; + return; } - if (fWidthTable.size() == 0 ) { - RESTError << "TRestAxionSolarHiddenPhotonFlux::CalculateSolarFlux - empty width table!" << RESTendl; - return; + if (fPlasmaFreqTable.size() == 0) { + RESTError << "TRestAxionSolarHiddenPhotonFlux::CalculateSolarFlux - empty plasma freq table!" + << RESTendl; + return; + } + if (fWidthTable.size() == 0) { + RESTError << "TRestAxionSolarHiddenPhotonFlux::CalculateSolarFlux - empty width table!" << RESTendl; + return; } - + Double_t mass = GetMass(); cout << mass << endl; for (unsigned int n = 0; n < fContinuumTable.size(); n++) { @@ -363,19 +376,21 @@ void TRestAxionSolarHiddenPhotonFlux::CalculateSolarFlux() { Double_t wp = fPlasmaFreqTable[n]->GetBinContent(1); TH1D* hMass = new TH1D(Form("%s_hMass%d", GetName(), n), "hMass", 200, 0, 20); TH1D* hWg2 = (TH1D*)fWidthTable[n]->Clone(); - hWg2->Multiply(hWg2); // (w G)^2 + hWg2->Multiply(hWg2); // (w G)^2 - for ( unsigned int c = 0; c < 200; c++ ) { - Double_t wG = fWidthTable[n]->GetBinContent(c+1); - hMass->SetBinContent( c+1, pow(mass,-4) * ( pow( pow(mass,2) - pow(wp,2) , 2 )));// + pow(wG,2) ) ); // m2 - } - - hMass->Add(hWg2); // (m2 - wp2)^2 + (w G)^2 + for (unsigned int c = 0; c < 200; c++) { + Double_t wG = fWidthTable[n]->GetBinContent(c + 1); + hMass->SetBinContent( + c + 1, pow(mass, -4) * (pow(pow(mass, 2) - pow(wp, 2), 2))); // + pow(wG,2) ) ); // m2 + } - TH1D* h = (TH1D*)fWidthTable[n]->Clone(); // wG - h->Multiply(fContinuumTable[n]); // wG * flux - h->Divide(hMass); // wG * flux / ( (m2 - wp2)^2 + (w G)^2 ) - //h->Scale(pow(mass, 4)); // m4 * wG * flux / ( (m2 - wp2)^2 + (w G)^2 ) + hMass->Add(hWg2); // (m2 - wp2)^2 + (w G)^2 + + TH1D* h = (TH1D*)fWidthTable[n]->Clone(); // wG + h->Multiply(fContinuumTable[n]); // wG * flux + h->Divide(hMass); // wG * flux / ( (m2 - wp2)^2 + (w G)^2 ) + // h->Scale(pow(mass, 4)); // m4 * wG * flux / ( (m2 - wp2)^2 + (w G)^2 + // ) fFluxTable.push_back(h); } @@ -477,9 +492,11 @@ Double_t TRestAxionSolarHiddenPhotonFlux::IntegrateFluxInRange(TVector2 eRange) /// flux distributions defined inside the solar tables loaded in the class /// std::pair TRestAxionSolarHiddenPhotonFlux::GetRandomEnergyAndRadius(TVector2 eRange) { - std::pair result = {0, 0}; - if (!AreTablesLoaded()) { RESTWarning << "Tables not loaded!!" << RESTendl; return result; } + if (!AreTablesLoaded()) { + RESTWarning << "Tables not loaded!!" << RESTendl; + return result; + } Double_t rnd = fRandom->Rndm(); for (unsigned int r = 0; r < fFluxTableIntegrals.size(); r++) { if (rnd < fFluxTableIntegrals[r]) { @@ -529,9 +546,9 @@ void TRestAxionSolarHiddenPhotonFlux::PrintIntegratedRingFlux() { void TRestAxionSolarHiddenPhotonFlux::PrintMetadata() { TRestAxionSolarFlux::PrintMetadata(); - RESTMetadata << " - Solar hidden photon datafile (flux) : " << fFluxDataFile << RESTendl; - RESTMetadata << " - Solar hidden photon datafile (width) : " << fWidthDataFile << RESTendl; - RESTMetadata << " - Solar hidden photon datafile (plasma freq) : " << fPlasmaFreqDataFile << RESTendl; + RESTMetadata << " - Solar hidden photon datafile (flux) : " << fFluxDataFile << RESTendl; + RESTMetadata << " - Solar hidden photon datafile (width) : " << fWidthDataFile << RESTendl; + RESTMetadata << " - Solar hidden photon datafile (plasma freq) : " << fPlasmaFreqDataFile << RESTendl; RESTMetadata << "-------" << RESTendl; RESTMetadata << " - Total continuum flux : " << fTotalContinuumFlux << " cm-2 s-1" << RESTendl; RESTMetadata << "++++++++++++++++++" << RESTendl; @@ -610,4 +627,3 @@ TCanvas* TRestAxionSolarHiddenPhotonFlux::DrawSolarFlux() { return fCanvas; } - From f2ea3420d0d8831de1622ce7fc384c5e879a59f6 Mon Sep 17 00:00:00 2001 From: tomasoshea Date: Fri, 15 Sep 2023 15:18:08 +0200 Subject: [PATCH 34/48] commented out redundant 'wG' in calculation --- src/TRestAxionSolarHiddenPhotonFlux.cxx | 114 ++++++++++-------------- 1 file changed, 49 insertions(+), 65 deletions(-) diff --git a/src/TRestAxionSolarHiddenPhotonFlux.cxx b/src/TRestAxionSolarHiddenPhotonFlux.cxx index f824fd5c..a59cbc95 100644 --- a/src/TRestAxionSolarHiddenPhotonFlux.cxx +++ b/src/TRestAxionSolarHiddenPhotonFlux.cxx @@ -184,28 +184,23 @@ TRestAxionSolarHiddenPhotonFlux::~TRestAxionSolarHiddenPhotonFlux() {} /// inside the metadata members, and calculate the solar flux for a given m. /// Bool_t TRestAxionSolarHiddenPhotonFlux::LoadTables() { - if (GetMass() <= 0) { - RESTWarning << "TRestAxionSolarHiddenPhotonFlux::LoadTables - hidden photon mass not yet defined" - << RESTendl; - RESTWarning << "TRestAxionSolarHiddenPhotonFlux::LoadTables - mass given as " << GetMass() << " eV" - << RESTendl; - return false; - } - if (fFluxDataFile == "") { - RESTWarning << "TRestAxionSolarHiddenPhotonFlux::LoadTables - flux table not found!!\n " - << fFluxDataFile << RESTendl; - return false; + + if (GetMass() <= 0 ) { + RESTWarning << "TRestAxionSolarHiddenPhotonFlux::LoadTables - hidden photon mass not yet defined" << RESTendl; + RESTWarning << "TRestAxionSolarHiddenPhotonFlux::LoadTables - mass given as " << GetMass() << " eV" << RESTendl; + return false; } - if (fWidthDataFile == "") { - RESTWarning << "TRestAxionSolarHiddenPhotonFlux::LoadTables - width table not found!!\n " - << fWidthDataFile << RESTendl; - return false; + if ( fFluxDataFile == "" ){ + RESTWarning << "TRestAxionSolarHiddenPhotonFlux::LoadTables - flux table not found!!\n " << fFluxDataFile << RESTendl; + return false; } - if (fPlasmaFreqDataFile == "") { - RESTWarning - << "TRestAxionSolarHiddenPhotonFlux::LoadTables - plasma frequency table not found!!\n " - << fPlasmaFreqDataFile << RESTendl; - return false; + if ( fWidthDataFile == "") { + RESTWarning << "TRestAxionSolarHiddenPhotonFlux::LoadTables - width table not found!!\n " << fWidthDataFile << RESTendl; + return false; + } + if ( fPlasmaFreqDataFile == "" ) { + RESTWarning << "TRestAxionSolarHiddenPhotonFlux::LoadTables - plasma frequency table not found!!\n " << fPlasmaFreqDataFile << RESTendl; + return false; } LoadContinuumFluxTable(); @@ -253,9 +248,7 @@ void TRestAxionSolarHiddenPhotonFlux::LoadContinuumFluxTable() { for (unsigned int n = 0; n < fluxTable.size(); n++) { TH1D* h = new TH1D(Form("%s_ContinuumFluxAtRadius%d", GetName(), n), "", 200, 0, 20); - for (unsigned int m = 0; m < fluxTable[n].size(); m++) { - h->SetBinContent(m + 1, fluxTable[n][m]); - } + for (unsigned int m = 0; m < fluxTable[n].size(); m++) { h->SetBinContent(m + 1, fluxTable[n][m]); } fContinuumTable.push_back(h); } } @@ -284,9 +277,8 @@ void TRestAxionSolarHiddenPhotonFlux::LoadWidthTable() { } TRestTools::ReadBinaryTable(fullPathName, fluxTable); - // RESTMetadata << "Width table rows / columns: " << fluxTable.size() << " " << fluxTable[0].size() << - // RESTendl; - + //RESTMetadata << "Width table rows / columns: " << fluxTable.size() << " " << fluxTable[0].size() << RESTendl; + if (fluxTable.size() != 1000 || fluxTable[0].size() != 200) { fluxTable.clear(); RESTError << "LoadWidthTable. The table does not contain the right number of rows or columns" @@ -296,9 +288,7 @@ void TRestAxionSolarHiddenPhotonFlux::LoadWidthTable() { for (unsigned int n = 0; n < fluxTable.size(); n++) { TH1D* h = new TH1D(Form("%s_ResonanceWidthAtRadius%d", GetName(), n), "", 200, 0, 20); - for (unsigned int m = 0; m < fluxTable[n].size(); m++) { - h->SetBinContent(m + 1, fluxTable[n][m]); - } + for (unsigned int m = 0; m < fluxTable[n].size(); m++) { h->SetBinContent(m + 1, fluxTable[n][m]); } fWidthTable.push_back(h); } } @@ -328,7 +318,7 @@ void TRestAxionSolarHiddenPhotonFlux::LoadPlasmaFreqTable() { } TRestTools::ReadBinaryTable(fullPathName, fluxTable); - + if (fluxTable.size() != 1000 || fluxTable[0].size() != 1) { fluxTable.clear(); RESTError << "LoadPlasmaFreqTable. The table does not contain the right number of rows or columns" @@ -338,9 +328,7 @@ void TRestAxionSolarHiddenPhotonFlux::LoadPlasmaFreqTable() { for (unsigned int n = 0; n < fluxTable.size(); n++) { TH1D* h = new TH1D(Form("%s_PlasmaFreqAtRadius%d", GetName(), n), "", 1, 0, 20); - for (unsigned int m = 0; m < fluxTable[n].size(); m++) { - h->SetBinContent(m + 1, fluxTable[n][m]); - } + for (unsigned int m = 0; m < fluxTable[n].size(); m++) { h->SetBinContent(m + 1, fluxTable[n][m]); } fPlasmaFreqTable.push_back(h); } } @@ -353,21 +341,20 @@ void TRestAxionSolarHiddenPhotonFlux::CalculateSolarFlux() { if (GetMass() == 0) { RESTError << "CalculateSolarFlux. The hidden photon mass is set to zero!" << RESTendl; return; + } + if (fContinuumTable.size() == 0 ) { + RESTError << "TRestAxionSolarHiddenPhotonFlux::CalculateSolarFlux - empty flux table!" << RESTendl; + return; } - if (fContinuumTable.size() == 0) { - RESTError << "TRestAxionSolarHiddenPhotonFlux::CalculateSolarFlux - empty flux table!" << RESTendl; - return; + if (fPlasmaFreqTable.size() == 0 ) { + RESTError << "TRestAxionSolarHiddenPhotonFlux::CalculateSolarFlux - empty plasma freq table!" << RESTendl; + return; } - if (fPlasmaFreqTable.size() == 0) { - RESTError << "TRestAxionSolarHiddenPhotonFlux::CalculateSolarFlux - empty plasma freq table!" - << RESTendl; - return; - } - if (fWidthTable.size() == 0) { - RESTError << "TRestAxionSolarHiddenPhotonFlux::CalculateSolarFlux - empty width table!" << RESTendl; - return; + if (fWidthTable.size() == 0 ) { + RESTError << "TRestAxionSolarHiddenPhotonFlux::CalculateSolarFlux - empty width table!" << RESTendl; + return; } - + Double_t mass = GetMass(); cout << mass << endl; for (unsigned int n = 0; n < fContinuumTable.size(); n++) { @@ -376,21 +363,19 @@ void TRestAxionSolarHiddenPhotonFlux::CalculateSolarFlux() { Double_t wp = fPlasmaFreqTable[n]->GetBinContent(1); TH1D* hMass = new TH1D(Form("%s_hMass%d", GetName(), n), "hMass", 200, 0, 20); TH1D* hWg2 = (TH1D*)fWidthTable[n]->Clone(); - hWg2->Multiply(hWg2); // (w G)^2 + hWg2->Multiply(hWg2); // (w G)^2 - for (unsigned int c = 0; c < 200; c++) { - Double_t wG = fWidthTable[n]->GetBinContent(c + 1); - hMass->SetBinContent( - c + 1, pow(mass, -4) * (pow(pow(mass, 2) - pow(wp, 2), 2))); // + pow(wG,2) ) ); // m2 - } + for ( unsigned int c = 0; c < 200; c++ ) { + //Double_t wG = fWidthTable[n]->GetBinContent(c+1); + hMass->SetBinContent( c+1, pow(mass,-4) * ( pow( pow(mass,2) - pow(wp,2) , 2 )));// + pow(wG,2) ) ); // m2 + } + + hMass->Add(hWg2); // (m2 - wp2)^2 + (w G)^2 - hMass->Add(hWg2); // (m2 - wp2)^2 + (w G)^2 - - TH1D* h = (TH1D*)fWidthTable[n]->Clone(); // wG - h->Multiply(fContinuumTable[n]); // wG * flux - h->Divide(hMass); // wG * flux / ( (m2 - wp2)^2 + (w G)^2 ) - // h->Scale(pow(mass, 4)); // m4 * wG * flux / ( (m2 - wp2)^2 + (w G)^2 - // ) + TH1D* h = (TH1D*)fWidthTable[n]->Clone(); // wG + h->Multiply(fContinuumTable[n]); // wG * flux + h->Divide(hMass); // wG * flux / ( (m2 - wp2)^2 + (w G)^2 ) + //h->Scale(pow(mass, 4)); // m4 * wG * flux / ( (m2 - wp2)^2 + (w G)^2 ) fFluxTable.push_back(h); } @@ -492,11 +477,9 @@ Double_t TRestAxionSolarHiddenPhotonFlux::IntegrateFluxInRange(TVector2 eRange) /// flux distributions defined inside the solar tables loaded in the class /// std::pair TRestAxionSolarHiddenPhotonFlux::GetRandomEnergyAndRadius(TVector2 eRange) { + std::pair result = {0, 0}; - if (!AreTablesLoaded()) { - RESTWarning << "Tables not loaded!!" << RESTendl; - return result; - } + if (!AreTablesLoaded()) { RESTWarning << "Tables not loaded!!" << RESTendl; return result; } Double_t rnd = fRandom->Rndm(); for (unsigned int r = 0; r < fFluxTableIntegrals.size(); r++) { if (rnd < fFluxTableIntegrals[r]) { @@ -546,9 +529,9 @@ void TRestAxionSolarHiddenPhotonFlux::PrintIntegratedRingFlux() { void TRestAxionSolarHiddenPhotonFlux::PrintMetadata() { TRestAxionSolarFlux::PrintMetadata(); - RESTMetadata << " - Solar hidden photon datafile (flux) : " << fFluxDataFile << RESTendl; - RESTMetadata << " - Solar hidden photon datafile (width) : " << fWidthDataFile << RESTendl; - RESTMetadata << " - Solar hidden photon datafile (plasma freq) : " << fPlasmaFreqDataFile << RESTendl; + RESTMetadata << " - Solar hidden photon datafile (flux) : " << fFluxDataFile << RESTendl; + RESTMetadata << " - Solar hidden photon datafile (width) : " << fWidthDataFile << RESTendl; + RESTMetadata << " - Solar hidden photon datafile (plasma freq) : " << fPlasmaFreqDataFile << RESTendl; RESTMetadata << "-------" << RESTendl; RESTMetadata << " - Total continuum flux : " << fTotalContinuumFlux << " cm-2 s-1" << RESTendl; RESTMetadata << "++++++++++++++++++" << RESTendl; @@ -627,3 +610,4 @@ TCanvas* TRestAxionSolarHiddenPhotonFlux::DrawSolarFlux() { return fCanvas; } + From fae682bc6680c4fc0b01282e61c123c9fe03c7ae Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 15 Sep 2023 13:18:37 +0000 Subject: [PATCH 35/48] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- src/TRestAxionSolarHiddenPhotonFlux.cxx | 114 ++++++++++++++---------- 1 file changed, 65 insertions(+), 49 deletions(-) diff --git a/src/TRestAxionSolarHiddenPhotonFlux.cxx b/src/TRestAxionSolarHiddenPhotonFlux.cxx index a59cbc95..64deb8f3 100644 --- a/src/TRestAxionSolarHiddenPhotonFlux.cxx +++ b/src/TRestAxionSolarHiddenPhotonFlux.cxx @@ -184,23 +184,28 @@ TRestAxionSolarHiddenPhotonFlux::~TRestAxionSolarHiddenPhotonFlux() {} /// inside the metadata members, and calculate the solar flux for a given m. /// Bool_t TRestAxionSolarHiddenPhotonFlux::LoadTables() { - - if (GetMass() <= 0 ) { - RESTWarning << "TRestAxionSolarHiddenPhotonFlux::LoadTables - hidden photon mass not yet defined" << RESTendl; - RESTWarning << "TRestAxionSolarHiddenPhotonFlux::LoadTables - mass given as " << GetMass() << " eV" << RESTendl; - return false; + if (GetMass() <= 0) { + RESTWarning << "TRestAxionSolarHiddenPhotonFlux::LoadTables - hidden photon mass not yet defined" + << RESTendl; + RESTWarning << "TRestAxionSolarHiddenPhotonFlux::LoadTables - mass given as " << GetMass() << " eV" + << RESTendl; + return false; + } + if (fFluxDataFile == "") { + RESTWarning << "TRestAxionSolarHiddenPhotonFlux::LoadTables - flux table not found!!\n " + << fFluxDataFile << RESTendl; + return false; } - if ( fFluxDataFile == "" ){ - RESTWarning << "TRestAxionSolarHiddenPhotonFlux::LoadTables - flux table not found!!\n " << fFluxDataFile << RESTendl; - return false; + if (fWidthDataFile == "") { + RESTWarning << "TRestAxionSolarHiddenPhotonFlux::LoadTables - width table not found!!\n " + << fWidthDataFile << RESTendl; + return false; } - if ( fWidthDataFile == "") { - RESTWarning << "TRestAxionSolarHiddenPhotonFlux::LoadTables - width table not found!!\n " << fWidthDataFile << RESTendl; - return false; - } - if ( fPlasmaFreqDataFile == "" ) { - RESTWarning << "TRestAxionSolarHiddenPhotonFlux::LoadTables - plasma frequency table not found!!\n " << fPlasmaFreqDataFile << RESTendl; - return false; + if (fPlasmaFreqDataFile == "") { + RESTWarning + << "TRestAxionSolarHiddenPhotonFlux::LoadTables - plasma frequency table not found!!\n " + << fPlasmaFreqDataFile << RESTendl; + return false; } LoadContinuumFluxTable(); @@ -248,7 +253,9 @@ void TRestAxionSolarHiddenPhotonFlux::LoadContinuumFluxTable() { for (unsigned int n = 0; n < fluxTable.size(); n++) { TH1D* h = new TH1D(Form("%s_ContinuumFluxAtRadius%d", GetName(), n), "", 200, 0, 20); - for (unsigned int m = 0; m < fluxTable[n].size(); m++) { h->SetBinContent(m + 1, fluxTable[n][m]); } + for (unsigned int m = 0; m < fluxTable[n].size(); m++) { + h->SetBinContent(m + 1, fluxTable[n][m]); + } fContinuumTable.push_back(h); } } @@ -277,8 +284,9 @@ void TRestAxionSolarHiddenPhotonFlux::LoadWidthTable() { } TRestTools::ReadBinaryTable(fullPathName, fluxTable); - //RESTMetadata << "Width table rows / columns: " << fluxTable.size() << " " << fluxTable[0].size() << RESTendl; - + // RESTMetadata << "Width table rows / columns: " << fluxTable.size() << " " << fluxTable[0].size() << + // RESTendl; + if (fluxTable.size() != 1000 || fluxTable[0].size() != 200) { fluxTable.clear(); RESTError << "LoadWidthTable. The table does not contain the right number of rows or columns" @@ -288,7 +296,9 @@ void TRestAxionSolarHiddenPhotonFlux::LoadWidthTable() { for (unsigned int n = 0; n < fluxTable.size(); n++) { TH1D* h = new TH1D(Form("%s_ResonanceWidthAtRadius%d", GetName(), n), "", 200, 0, 20); - for (unsigned int m = 0; m < fluxTable[n].size(); m++) { h->SetBinContent(m + 1, fluxTable[n][m]); } + for (unsigned int m = 0; m < fluxTable[n].size(); m++) { + h->SetBinContent(m + 1, fluxTable[n][m]); + } fWidthTable.push_back(h); } } @@ -318,7 +328,7 @@ void TRestAxionSolarHiddenPhotonFlux::LoadPlasmaFreqTable() { } TRestTools::ReadBinaryTable(fullPathName, fluxTable); - + if (fluxTable.size() != 1000 || fluxTable[0].size() != 1) { fluxTable.clear(); RESTError << "LoadPlasmaFreqTable. The table does not contain the right number of rows or columns" @@ -328,7 +338,9 @@ void TRestAxionSolarHiddenPhotonFlux::LoadPlasmaFreqTable() { for (unsigned int n = 0; n < fluxTable.size(); n++) { TH1D* h = new TH1D(Form("%s_PlasmaFreqAtRadius%d", GetName(), n), "", 1, 0, 20); - for (unsigned int m = 0; m < fluxTable[n].size(); m++) { h->SetBinContent(m + 1, fluxTable[n][m]); } + for (unsigned int m = 0; m < fluxTable[n].size(); m++) { + h->SetBinContent(m + 1, fluxTable[n][m]); + } fPlasmaFreqTable.push_back(h); } } @@ -341,20 +353,21 @@ void TRestAxionSolarHiddenPhotonFlux::CalculateSolarFlux() { if (GetMass() == 0) { RESTError << "CalculateSolarFlux. The hidden photon mass is set to zero!" << RESTendl; return; - } - if (fContinuumTable.size() == 0 ) { - RESTError << "TRestAxionSolarHiddenPhotonFlux::CalculateSolarFlux - empty flux table!" << RESTendl; - return; } - if (fPlasmaFreqTable.size() == 0 ) { - RESTError << "TRestAxionSolarHiddenPhotonFlux::CalculateSolarFlux - empty plasma freq table!" << RESTendl; - return; + if (fContinuumTable.size() == 0) { + RESTError << "TRestAxionSolarHiddenPhotonFlux::CalculateSolarFlux - empty flux table!" << RESTendl; + return; } - if (fWidthTable.size() == 0 ) { - RESTError << "TRestAxionSolarHiddenPhotonFlux::CalculateSolarFlux - empty width table!" << RESTendl; - return; + if (fPlasmaFreqTable.size() == 0) { + RESTError << "TRestAxionSolarHiddenPhotonFlux::CalculateSolarFlux - empty plasma freq table!" + << RESTendl; + return; + } + if (fWidthTable.size() == 0) { + RESTError << "TRestAxionSolarHiddenPhotonFlux::CalculateSolarFlux - empty width table!" << RESTendl; + return; } - + Double_t mass = GetMass(); cout << mass << endl; for (unsigned int n = 0; n < fContinuumTable.size(); n++) { @@ -363,19 +376,21 @@ void TRestAxionSolarHiddenPhotonFlux::CalculateSolarFlux() { Double_t wp = fPlasmaFreqTable[n]->GetBinContent(1); TH1D* hMass = new TH1D(Form("%s_hMass%d", GetName(), n), "hMass", 200, 0, 20); TH1D* hWg2 = (TH1D*)fWidthTable[n]->Clone(); - hWg2->Multiply(hWg2); // (w G)^2 + hWg2->Multiply(hWg2); // (w G)^2 - for ( unsigned int c = 0; c < 200; c++ ) { - //Double_t wG = fWidthTable[n]->GetBinContent(c+1); - hMass->SetBinContent( c+1, pow(mass,-4) * ( pow( pow(mass,2) - pow(wp,2) , 2 )));// + pow(wG,2) ) ); // m2 - } - - hMass->Add(hWg2); // (m2 - wp2)^2 + (w G)^2 + for (unsigned int c = 0; c < 200; c++) { + // Double_t wG = fWidthTable[n]->GetBinContent(c+1); + hMass->SetBinContent( + c + 1, pow(mass, -4) * (pow(pow(mass, 2) - pow(wp, 2), 2))); // + pow(wG,2) ) ); // m2 + } - TH1D* h = (TH1D*)fWidthTable[n]->Clone(); // wG - h->Multiply(fContinuumTable[n]); // wG * flux - h->Divide(hMass); // wG * flux / ( (m2 - wp2)^2 + (w G)^2 ) - //h->Scale(pow(mass, 4)); // m4 * wG * flux / ( (m2 - wp2)^2 + (w G)^2 ) + hMass->Add(hWg2); // (m2 - wp2)^2 + (w G)^2 + + TH1D* h = (TH1D*)fWidthTable[n]->Clone(); // wG + h->Multiply(fContinuumTable[n]); // wG * flux + h->Divide(hMass); // wG * flux / ( (m2 - wp2)^2 + (w G)^2 ) + // h->Scale(pow(mass, 4)); // m4 * wG * flux / ( (m2 - wp2)^2 + (w G)^2 + // ) fFluxTable.push_back(h); } @@ -477,9 +492,11 @@ Double_t TRestAxionSolarHiddenPhotonFlux::IntegrateFluxInRange(TVector2 eRange) /// flux distributions defined inside the solar tables loaded in the class /// std::pair TRestAxionSolarHiddenPhotonFlux::GetRandomEnergyAndRadius(TVector2 eRange) { - std::pair result = {0, 0}; - if (!AreTablesLoaded()) { RESTWarning << "Tables not loaded!!" << RESTendl; return result; } + if (!AreTablesLoaded()) { + RESTWarning << "Tables not loaded!!" << RESTendl; + return result; + } Double_t rnd = fRandom->Rndm(); for (unsigned int r = 0; r < fFluxTableIntegrals.size(); r++) { if (rnd < fFluxTableIntegrals[r]) { @@ -529,9 +546,9 @@ void TRestAxionSolarHiddenPhotonFlux::PrintIntegratedRingFlux() { void TRestAxionSolarHiddenPhotonFlux::PrintMetadata() { TRestAxionSolarFlux::PrintMetadata(); - RESTMetadata << " - Solar hidden photon datafile (flux) : " << fFluxDataFile << RESTendl; - RESTMetadata << " - Solar hidden photon datafile (width) : " << fWidthDataFile << RESTendl; - RESTMetadata << " - Solar hidden photon datafile (plasma freq) : " << fPlasmaFreqDataFile << RESTendl; + RESTMetadata << " - Solar hidden photon datafile (flux) : " << fFluxDataFile << RESTendl; + RESTMetadata << " - Solar hidden photon datafile (width) : " << fWidthDataFile << RESTendl; + RESTMetadata << " - Solar hidden photon datafile (plasma freq) : " << fPlasmaFreqDataFile << RESTendl; RESTMetadata << "-------" << RESTendl; RESTMetadata << " - Total continuum flux : " << fTotalContinuumFlux << " cm-2 s-1" << RESTendl; RESTMetadata << "++++++++++++++++++" << RESTendl; @@ -610,4 +627,3 @@ TCanvas* TRestAxionSolarHiddenPhotonFlux::DrawSolarFlux() { return fCanvas; } - From 5cab20e09a1c890fe2443a2d2f5972d8080a31ed Mon Sep 17 00:00:00 2001 From: tomasoshea Date: Tue, 26 Sep 2023 09:29:40 +0200 Subject: [PATCH 36/48] created some plots --- flux.png | Bin 19725 -> 32743 bytes flux0.001.png | Bin 0 -> 36954 bytes flux0.01.png | Bin 0 -> 37352 bytes flux0.1.png | Bin 0 -> 37172 bytes flux1.png | Bin 0 -> 30693 bytes flux10.png | Bin 0 -> 32331 bytes flux100.png | Bin 0 -> 36014 bytes flux1000.png | Bin 0 -> 36178 bytes flux20.png | Bin 0 -> 35192 bytes flux30.png | Bin 0 -> 35393 bytes flux50.png | Bin 0 -> 35928 bytes 11 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 flux0.001.png create mode 100644 flux0.01.png create mode 100644 flux0.1.png create mode 100644 flux1.png create mode 100644 flux10.png create mode 100644 flux100.png create mode 100644 flux1000.png create mode 100644 flux20.png create mode 100644 flux30.png create mode 100644 flux50.png diff --git a/flux.png b/flux.png index 26f7d1e50d09175a549d87940cce0bf89e8034df..e2df6fc81dba562dbe32ffc5fa4ebd5830d9192f 100644 GIT binary patch literal 32743 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 GGywp@_)F{n diff --git a/flux0.001.png b/flux0.001.png new file mode 100644 index 0000000000000000000000000000000000000000..87ca31e2312fa035013d39feb8809bf58cc22a94 GIT binary patch literal 36954 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 literal 0 HcmV?d00001 diff --git a/flux0.01.png b/flux0.01.png new file mode 100644 index 0000000000000000000000000000000000000000..d90face08d7935486e30198bb94a65b081a1ccd1 GIT binary patch literal 37352 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 ?j!+!z+OE20H6D5dXEdd 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�~OlnCnlzQ4Msc#B!vHAv%*4X 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 b-S*D(yB!E-r32786A`hova@__e*NCxWbJ5l literal 0 HcmV?d00001 diff --git a/flux1.png b/flux1.png new file mode 100644 index 0000000000000000000000000000000000000000..60cb71b321b6b54c3065c1d7987bfee49400dd80 GIT binary patch literal 30693 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 be;jk*8}NRKw!^@UfIw<0VCBlE7NP$i`}A8u literal 0 HcmV?d00001 diff --git a/flux10.png b/flux10.png new file mode 100644 index 0000000000000000000000000000000000000000..dbf8a3c34706850e7b20fc942755e53d3a0532bb GIT binary patch literal 32331 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 VfVT!XjtT@)me-IgfBoj;{|A8b?lu4b literal 0 HcmV?d00001 diff --git a/flux100.png b/flux100.png new file mode 100644 index 0000000000000000000000000000000000000000..02b84648da477d72fb74ec9bfb0f27fc7600808d GIT binary patch literal 36014 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 Q2Z1qoy85}Sb4q9e06n^k^Z)<= literal 0 HcmV?d00001 diff --git a/flux1000.png b/flux1000.png new file mode 100644 index 0000000000000000000000000000000000000000..639aa3eb7c75f27ff2a51c8d4b1283cd50906319 GIT binary patch literal 36178 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 Oz~JfX=d#Wzp$PyC|CWyc literal 0 HcmV?d00001 diff --git a/flux20.png b/flux20.png new file mode 100644 index 0000000000000000000000000000000000000000..8f8641a11a76e23b7dcdc0a825ade87448ba7ffb GIT binary patch literal 35192 zcmd3Nbx@RV6z(D@iU=YS3J5L|F4El~D@fPU-3>}gBS=e0Nl3cDF5S{7(j7|*sB}v# zNZ%KKbLakdXYS0Mxff=Ljc?!gyyraUoaa1WxQdd@9fF4h5D4Us>`S;B1cFNqfn3YF zc?~?0@o;kq{JLQ(F9Qd^!Pl`=gFgg92a$zKBHpBL&Uz>`@r>#10 z_c~8%T)_7j0e1zhnP@XJiEl4Og8GGGS2J9;xj1ixcfK$P_M}|wlpA*&_{OL6Lx2hw#wS@)wV6UoQb) zYbh5tMJxhc!*0v zvy`#!0Qphlg0>RI;VvX4DwYzt-(9k<4coCcHg{6-Up3-?cy=kMm;Y%Q)6!kN!*6;j;*KYisiNGqUB->pC zb|_!`d`&X*8rNaW<=>bfvFmg#lm{HYznt+yq8Ew`8r<#e6-F0WG>bThJu|FEmMQdK zy>&eB^*1&BcH~>R8$#vC(Xi$~a{MP$+~;I1KTXPaT|HB7d5)&D?qEc|e^#Eo>7Z&< zX>{i55}l3P^&74W3?!Ye9b3-bNjUS1#e)SmQ+e$+wKzSP7#aI666F|<9l__0Z*uVQ zS=MO5$SQqJO`+INRm9D<81$mxy!(v9;YIDd-)V(K@6}a0U$fOM-Xjq_`r*<~Le6ez zztd>meQ&lI{HPpmKBMsV?l(A1o?PvF8^_fusSHnIH*(Bq@HuvNkxP_ofB)DLLK3%8 z+A_E4y%X{D^!bVHTPt|u0vb=mzSPdv__$3yJMPi!yJY_-DA$vgwoLe9J_q<#qZqf zl)`J;CjXQBv`smwUXA?}*h8NIN!{WH`92%4Yd-hW-;wO(aY*^(Ik3<2O3dBw)GO0= zrPaiR9&SH$Y8_|m-8K%~_nPj-wMSBv>QqX1<}LLmr){xll@PYQ0?$IZ#KatHHtx9m z;ULs1(YLAD5RB|9uAO`6%}Q!!;IrGlY`v21qC^=&d-=EX#p0N{a<#t<|BqK~cldu~ zWoI=1a`Hc&ng0{Q|IsK`u)& zIknhqG8WBuCIv?9ogE#0hYa#b?@Zo|D)NVS9j|24hWw&EAEs@;LCbCI_Y;@4OnI=` zE{4NP&%b_uKv=of<7lR}6?o#iX!fY*+QP0w4MNTDV`9>V9={JEI}I68HdqH1+N|j9 z+rn;4bSf!SDt6D5tLrwt+5O!f*=GH|taio&Th-PfnMgwzY*K)u^8R=i8?anlX7q9a zR@pMAUFVGSl^`{4ADGIMOpNxBqldZZ1;J>RH(wXeW}($kAGenIRE+Cr4mKrVgi_pU z?b1y9?FyCFmJJ;mCX^Ze7srQ(`-9>}xJAM{jojpj6yH>Q4a;}o=dO4fQcnmA5N_Il%H<7CNHL%*=>I4`R>tU1pBX)0~>?zzNDs zmYD>Ft^Pc1#U4 zQp|~;8b9p(Zx@Vc| znp)*~wD9)LwpYh{OEWbNqpRrSm@<>L5VwtS8*8`ye*S!NN{5*mMfNj?A76&=>)FrN zS0BeQzzRl0c@r%rSAKlwozPzph)x=3Gi=nRM$&pDB%xHd#qYc-cf7`7W^?d#a`NN3gNrUJkr*>95bZPkBV^?J8|O^0FhwM@_m^QO z8`_IMq5gaEnfmTi7AW@D-3-b0bB)LGnP;EFJ_fpy=#-nbOU0F!mydCnZcSI)O_cbq zW`}}{lS?P!EBaCQvpP(cJtk}eTXC4J=hZ1}cHf#7-u@y*{Ke;ZFN%skqU-P9FEmjmj}kqMMP zS!SvF~-$i^=SgNml3)4uY zX`pK8D5WyvO*27E7MQ+>7V`Pn(~t1N>>SQG)$&i15$hr!h5Tx#FlxN=wwPJ|uXBp( z8?r+==RWf`&Y~Jk8gP^DLDvd+83k1&-St(q}FMf-*VX0hWI?L12|X z$4=gwY{}I=lgSp6mdwC!ntYlPg<_|Xu3qo{Dr1L^&o8T2#4Uhr@88_vp6e@@o4eDa2t~ExXc;&);!#*v5z<(JxbJj;KwANrd0i zF@FC3{zbqz)@!JN&$Q+xkI|Q5I+t0uiL0aO-r}Ei1rR%Xf2JT&4<&Xo9OHM8OY7k0 z#Z1Wbx$dIucqmlt;AaqVs!_Tjl8fTBnrzN2MwG8$6gR*gYdYjYZ3U9Wr$n=BQA27b zf6r#;&p#c`@#^(y=Tezn$AfT;fimD3GlEu5S!5SZY4L4KKbNoB4v|9yk%H|@#_*7N zz3l~69;lww{|`!~2y(;}s|P5jPV!VF6F2HX!2yAA3i`9fU((=F_T~ z4dvrPrdYBCz5UCIG4KEN|xcJNYVh5=c zn+_Ln7jHaznDmn@3g?efYo01go*5TLqc5RqD1@t-^3tEC8zH*;T|XyUGA33Z3(xI| zIPuugK8OpjU)pbwbFxDR(hW(-!F}dS5ipD`#vX^m)@OdF%>xFZ49mdRK&o|{pY|t@ zsmfpALIS>Rs4FH)Yn^+tlF1W(@W#I}u-_<$E(D97UN&5I3E&V+X0bR@?}-8(fVOVGaD#gGqHRH z&IbINV#p{muag|P-shhhHauJ?2d_Z_pbsPti-?~JcfKaqFAuWwmk9ZCHc{?lm=6ij z6%*GC(#d1I892O&CL|PIIS%J_sDCev2sGlBc$W-&=>+{KGtz?014|KPQo10KU2i+}Dm;Z}%25A1Br z=J0@rj^jGzKkyCi`^>W^%4Mt|-A#t_wyJge=R%*m(YcHv+@58&)3&Pg0+WO$U#42` z3Y2V|G?&VjI@hJAa~D+JRy6I)u=(;cg64L~B#Csz$uPL68WuLhjiXYhKTiF@am>P2 zjRH?WP_UCTnFM=T{smT}s@1+LGWa^(Gt<+xBdP8io&+7eIa)}1o4QM1j9cS;Rh`T` zoP0iP(nX!vB8S;UD@WvkBv~wLAUb-<LQ}s z5Xex{9GiOX3)Mq8|A$Hz)qgUd&cPDp%EN4TFjlK~R<{3EI#bSEYcuUAsi8oSA0KTF z;zIWFS0pu1h>;3dIF~G_l-rVTwyCgRg2Fu6)<(wd*B&hdvKpDeUO=s_%dVOX=PMj0 zlX5_1)!J3-+J3M3)02O*7`TZt)-2^=F$4dw^2Y1Lrb;C$9xC3B3JUviRtFl;*U_m}69-nDrbCJ)HYQrU~y0vrTFC=WTYeegU76kJ0lK|vEk=R_C+iX30W*@{q)-ffpcmc=Wj(r zm~k}&NQk^s5G)GW2SM{&58rxE*RQ>yn@%r~{r%bV9^20nZ?Py91NKXsqkS=RG&2I9 zYhr0hoVyZUVRtF~?8_OxIa_9Co?mACtU;59DX+%27ZO=^{Xyt9rTLM?x`&805wcNY zB>u`rbvzA;<-KE@b@gno9Ybg$TfsAE5sJ|KMQE9?_#3MRWs$v4;$>Q5v5nCoO;Re? z|GVxO0(-y!A-q1}CIb@&!Gks15;yoWIX4$tj(G;IFfdyIym7HG0EY{Mh)RmT7GN?l zlO-3FuMNl0?u+dg)E(A>13U4*1~KhI;4s%@SfMGUaUiYCtLpoM7o$9hVIO%g-&iuC z7T1l-R?lwT*ER`)LAuCDl}NO3UL+o6$xT#SJ3mmRGGaKI@;!Qb=nvidO`)8pNdti# zyc8$E2yY*vNQ2QB+q-y6&UL!QjKmsj$@0h#Q=P8G9Kq|5SpH-Ca@;KWrhbG?*68ji zZ;rFU#D1e1DnXxJq1L*h$B~s;Q;`fpNS%BZpgJ^@g;wPli_lK$-ETCf9X9`MJ2rkF zm*akyJV1?=6o7Thr_J0Nnw=g7wV>v1(}a|n1%IB0anffFIQ4OZ-@eb0qx1Jf zN-J*%%GMJ`ryQ)*m!#nS-F5Qz@IO}bw$d#GU_H0yDSv%%ziR32uTwu3hjBBCy@#Uh zbNz-bg5;{6_SzM}+N?=XFt3hLj>>-uV zldjK$JvgcQPy`T~u+1D__0)GvCLUk^RXfq?w&c{rR0=KxQk4S`ohOMa`4107t|l$@ zkZx4k*cA{ikRZ(dRj*?G3;;mSQpH-p(CCCB*PZb#JAZ{6fYZ=f>)aH-g9aJ0O@(4@ z0~-lAjRT!hTXZU1iIp7TW^*)~Kj~q{pqW~lV@=cAx>PwwE`jfL524r)?My3uH!6on zY17QY0w5E9`&r1Mz(632y8@N!lpst^Q^F-x#d9+)x$5*g_ne2*XAj4@AJ?s zgJXr=!(3$GA!=kshgAjaA(lmy_&^~PEcP?M!u-ITtRMS(45EEPx(kMBofAil<$ zn#KgLU^ET7Pi^pH^+cUeL(GqCck6UlN|v_Vzcxff4ICP%7bw*U4dGig?#yYrkK#Pe z9Ce3)c%hlzB(pgPS@A43I(4D$#8WFqd`XL&{+CFq+O;EuU|D1jY7mswS?J=k(U(o! z5}kX3?+@1ZGW{O#qUbwcSIKH@oZsj1<0ARE;_3BHT7Lo~9|dvlDk>&|yucJ@q4n7S zF+wASy)>b`A*oWV={rAowp8_)9J?do=$WC#mRwC#p@t$nafQ%%H|eVA6cI2D?#m%R z%<*aMR@@1w`rR{EakS3;aLe99%YQeL$u8Tg0wpwydHXqYP@rOAWu2d;`3%C0_A5Hq zD#Uo5wDY)UtFV4C?X(-5t65ol0ezk=6iW(6KnRLJMtWw4sh|8g^Z8-he&bk{!{BIS z-kp4f)E*wqveQ65FM4AzVmRU@(3+73Ib_u#lDix zaZdpWa9Uc@TTxb+G^AhM+?L&v)fMwb{zz77GMc8RB-i#yl0TIG`lRc%{kHjwc=yaV z+ukj)Z7GB2aQW+WF30w$p|)QC^4snu8#Sl<8|ohz)DK@jq|vlPKgu{=ayc~E8`0{V z_A&tO8JBxQ$(la94xIT?%u?g{d%M#EU3$s_TP(JeBnwl{@ zS%(aQ`u4sNKxWpQk>yP948td+r*NM@F-iLf7DgGl$#d`j0g=Y9nhu{)N)0MSr)h&#Ql8SXg6nG$sR1rKv;7IuW zaHE*b4}kW1U)9MApl0ewvZ|>o*${|c5I7WT*b%b;sIe)sLw$bvp4H{@??EWs98^Mi z`m>9LsY5)8pNgQb!3IA#8x(BUI~HpeY8Fb~P3T>+txna~pL(4Ra>Wl&p#e-$t|LP8 zfCQq&t&y?PzNg`(bx9jpYuc^`R_ObyoQ!*Y7PDc4wn;83Pr*w>RpdNn4wy43e`vhA zc(iBq3<2O>vykEFX`QEi%itnE5s@EEHhvAf7$U>khHQ0ZM5 zfkb9qi5^?>R)cO7-7w_3vFqZ=o)JqQ!*i0?)Sdex=RK4g1&*7|4Tg@@z@NF{C0`bu zwlDUO_jt8yFEdXL0Lb*YNi>)ml-_cdyc>MvD&RkqAIo0Oqfx9m`s-yc+21_;_X*j= zXb@EoYG8>GJEuaeQ^D&ae%Hw$u1`}?T(`%ns@3kaYqXYi?JTuS@;8pbz2cqTf(BAl znSCT`nrKYKHXjB5teV=hnVI@E0*Oj>HF+tP@B?3ha}qZ}Qzbv#6=CP!TF~vL0+!`FKLI^ZLz&}iGsdD3uq9`~y1}`^ z!J&)HlT7V3X4xm{n+>SC0_j_@)0$bAuYO}nrtObxU3s!vsq>>)jHEjE8=dQl42(f3 zrW(JI3Y&0i<4~x{uIRm8#U(1}my(M1+N$HxUm%v4zt1&Lb{o@QpwX3iU%~|(ErP|2 zbb*3HJJT`7%+|t754-j}T!_Oygsx!y!+1s-6}zvSg4H!fDrTOw&&J#q zYk8$!`!_aFGixmYfyaMqo1}?T-mu&Zj8ptIX|cvwRliYEHp_8aB4epOk3hoY&klR-!DhJp_x!3Yrws(!V!E2 z4WScX%_Mps`0a*9d8tQt;adj{^(jww)*PrL@OgXi3Z4ktjrvC*06VP#ia}!EezQa) zifo>5K6YvFeBSGrWjxeG3V}@i3${n!EiYATiSDb-1;MTwnTZZQ)E!*2>uVTW4G(#T zixgOmw&I7R0)E|ukOZ;-o2zb%ZsMv*uGTHqEe1HxmaN!%Umb<$b9V{4YM!z(otyCL z7X%n%M=qIWZse8xE}`05&a4^8!^_jue6U!k^5&#m=rYZJZkzOS+gEGJGkp!W^Yudu zw5~mY&~GQY*o2eP%hn}+b>wb*x5&T5p?-8LP{OI~5bTgL;g=&Ss~l0MPZZdC5G1M&g{cv3aRNB_I zhPKl_iQV#3FA(K{Fys5Hc*~;~7o{`4zn6*ilU82m5vNumRJJV9(r4#*?~({;UR_mi zi@ai|zC2G0wWDF@tg7*z%MCTps*v>3NF{cHpQ z4lVBSzY)`3%zq=Ox)Rj7bdjcLU9)q=V4&~QAw(Y2umY%mo{;es*j8k5fhsP!UmS-p z82I4`&y4vfUSg9=r1BHRV3I2D%RtG@Zz`#L5g<}x$+KF^a`XNTwt#a|cfO{!0`R@+ zZ`lCoE+yV66iV6#R%zh$%9F%8vPR}LHIp0WDTLA;y!ac(RULZnUm-^$kqM}nddItX zfd4QwAb=3$c7e>a*H*Of0Pn5NUusCi=Q7E}y5|&yLba!iJT|Gu(|Kvlx4PvH&9j9R z$vGR&XKbT9a7>65_00e|||5Pwgh@?1_Z3WM7j=-ZNDHmv(d` zhJBPL-1@QCNjMqSbxY>PBRlRX-7fX%QPN+N_NI{t;vpLfTk$+(x(|t9nn;1UAn9%f zI@jp~x~RBl)6=k6vyv8h%oNLVa{cMeK;2?Z6yk=j5G1xqA7A64>Kf1H6>}utuXSDW z=c!+0Cr{)EPn@n8@-jw4JudZ{E=7pRUA(B~hh%!oG?=<~1dA$ups&pA`@7+3m}@hc z`u%s$wOIe$2ddq!stICp>Tbr9OHFyUx+NP)a>zIu6b?i}X^~$YLr^>jI9p+*Hg=zG z!>mJIFGg; ziSUXTI5WJ6G#Hj=Rh?+=lf1i{3wVxA%ZQ$SgQnpEn|z)DdEV*yA43$jBXT@$!Vn1a zhqD_RJqeko%}#kHX*L0GkqDRujEvkC_&#pjMz4SUA9Rg8NAfWoUdzL-6oWyqCL9#L zh1H3Ut4S8UQ@34y>PC+NuK7M1*sEm2){H9U;d7*BUZ*p{k``6~@QwCc4^pdVs^BJ;hc~Wb|;WG+OW(8;-OJ zD4Z-tlt2vi$JUuzd|dWFEPtT4JT1K8cw+s`$l`-qR1GfuZ%lFw<-t=zBwH>sMCxto zzoG4YK6SD}lrHe5=~ZZXphv_E6_AKNB9GTKcNiQ)DI3ySO)H;bCkf|WH zei5MwqmVxHM1Gf1#W2Jl+tkC*eUozXK#KH88?~CmgxWt*}_20x_^e^Q1rQX9*~_ zLc`6m>n8&=R>g?No$jrGGB^06vMM!E zCfk3y+Yr|nG4b0C7#Rnm^5%F;9m6oXu72uI1iCwj#8;3dxD?7gBTxBl*HTgwY{&Gg zwkq*Lz85uBPMMEv0*!JuNqH{?S!&WcNUMH@2Ht(d-e%%}mZ7vm5Qh?Sh1boxcz`xr4q4=6l zYejnrDz)a=iqy9k*X`_ionkf)gd-I|=u*8SWk~rPfhk6w_i1|0)lnU&156=fDOry( ze^lUEJ4k4B69OU3)i(ko3J4|ne-amFdligkwigTLw~j%6E*bdXU>-bPjZfJsS8Sj< z06~W}y4z&(0@WG*(1qY^^6gJk+x~~6L3A8Vs*o(u6F?5aH|m$1J%_A@ncl^;-h^!~ zwP@35Flym$l@OrprVmJ)C}UZ!TE=N#X{G@V`9|UsIOISBAUNn^`~VO~OA}Y$b0SmV z^3iXq|K*y}u)W@GoG2v8MA*hi>d}|$B_*Tk(kABY9H2OR^L;8PcObE}#WG5k%1y&h z9^%IGk0GibV?mk(l2wSb6D9PrQ5l5;`mNqEaLE14I1mWM2b6>>xMJ_kWaZeEXqQcW7; zXC+)fM_VytuMR5dPrVh6`5S|;U+mgtl|t87C>4}`)0 zsjA+BuGz717o@TQk^R1w%hQ(HT4JYtWiSYQA0k{JwBN_=)UZ_}^T>12V8?3$U+fQ# za0x;FNEB*VV}nW^yY*32$bLS0Dz`2AFRBI`oGlajqSF+!p~y!xUKaCGROlJK8h_{J ztO>r|mmu_x?~Zqj$X?g!{N;t7Qxo>;k`A@Ae5>5ohGIABQw52@L~-RBWQyu{mfXJD zj{oH;b{lA6{xt3QI%QemWj((0`5Q-(W?{z4oxk>wEc_6Gf@>V`K)P23T5$b|VvKE& z7!9P$(Bu^1=5HYyN`>!tE!X7&SNyF{MoXCe<#up!i~jo?8o4M{BqFmHoqCxHT)k~h z@bLR&h9V!I|C-4q{M7}kBUtc$-bYEYt+BUac1u!LA2f19NN!P*NckKOBGjJ}paVo) z43YupxAT3MOswDSpu%>5jkp8h&YP>*>2h0bN_B$g+u{|^DL;=154suk{*Ik$(2k2Bpu_o3i5YRl`CK@#@*Y|@q zP@1sB?HH7m^&AHLYRQ|FUllH5kK5vG@MQTAsxf=U@FXUsdw#2G$5t=Y;edbs+{yMc z2b2@a5Yruo*d%#M!8DA#I{P@8N4MIBE=1RM=;9Yfh1e}oNa5?G+4c-Hmwk_vk;wg_58IQqYr`HX(6EAsr@^mRMO3QDzP_bWa`*a0z}n zht1MHao22G{XwZ$^`!7fvW3WU#zC#+!Awih4?mL#hK?D72aMRO%c63?={Cz9;hVrK zfZM)?uWRjUiic^OGCokm8%lWNhTbN&GuI}6$S5b!AYK8~VUCPe!VWlQ_&cv`i!F{o zAc#9@T4bC2?%a7%ZKG#3v*^@(IzRT(1h`Gb4i_|~;rgRE0y4xDFOE+CwU?|+eT!X( zyOlz^MKEZ5OWCCG&^c$kc!lrur}MV>v+tIBdK-gxle*^}_R7lnvuCA{&EB(@dC~+| z8#jd$$XLRizkOqsLkhMUehv{B6J(Q6Ent#?h}56dLAdT^zlxv338 zn6g)It-kv-ETIg5^1)}s_hw{@9&_<&)`+=w94a(>+54(D zeH!GvErCxNcVga}!e#uC*XBz;v20bsJB2MxD{)(=1m@ymWzKG&S;aheW~JsTg)R1U zk?t`q;`|MdXM##KxEz#mH=?r$R`qSK2l-8Jy%2Q$IW%+FY64`8-jXqsS-DsKy4;)b zB(!YNIKc-ywlZy|nGwnXxdGM)QrxPhJu6XsF5mo3Go6je-|NdYvK|w*ye@r{*K$A= zDRNxZJG>E?+dUfDRNwq=c?P>Kv6qfRcw7224z%D}y&5c0_p*v9G-J#uDGFfeY4e=* zZaDZzeYQ{&fvrOCtBHzR?O1yaWRaGBB;bya#tp*qWimo{F8w0&hNd*e@_5gkNtZ2= zMx9-;0H))A3yiL#qy0zF7<+dJCx0ac~dq%Qyg^a_HmW|jn)7+ila<9O#o#4Ybvv|{QH?C(d zXD=Ro8#=j2JptU25HGe2;v7k0^V9m`7NGbN_ZpM&QVtn0;2fEeimi|q{OV%F-zus)k;s8&k!st9)VNqbxzmU*t5&zhOno01n zV4gmkmB90V>KsiOT#omYak`yL;#ach{~Ch-|7Fu4X#Tf)?iYW)qAm`UFRP04jo$nU z_G)vRWo&4|7CSlkrQc@zA^~S>Ios=HZ)q$hy&G3KASCZpq+eGtyE3heufkC~=e2RA zDg#p9NcQG8)1UHb^4?#m0L!jK%pzkxce!yHW1-*wkjAM$+q$rHTZ!>mq-V-_W18zb zAbRw}CI%%8GAUzc-Jfr_#dpJ%dAzoPs%z{dr4$GOmwFNpM{(}=y`V670+ml@Yg)~T zOky*bK8v60;jnmS)T|FDmpP~r8#CuP@XZ{)p%{yTg@Gk*bibqwfsQyfuV;8~A5RVX zji0CBNe(Rv#E4(KS$7v*sR0T~phzsH5vP&3nDvUCxJD_R z#_u%#BQZ?>)z|CYas5C(82o^s57{)TEPmcbdr>AjJqgs_%|OAJB1GA7gL5XB!myy5 z`)BM|#-7+)B!U}7l?R6!S_a7L(q0}uS6@FiYrvv72zeoUzT$*ZG%?>e&bnm8a`;P{ z4s}WD4yWzfIL5xenWQUyB>Y98>C7slkbWAdKCw$|jeov@_ZdeRw2b!p%O^eKtaYki z%X_tsX#z^^Oz-VFFT7KXnYbBJt(-r@YaO+GD7cb7x~q35D|55g|IqzBKns=#G~30x zNLqJpg*C0OS3><^i)IeOiBcnW=#^^x1iP`d6(Yu>K=r*3r+-PD=7sm=4dbpq{Hl1} z+Q;a^61imdsNc7s=ACDXt8 zhBhmB)?V?VaYElE%25P6rhW?@@YuPRwf5uY*a%YIE%(@!g(gxh6s4___`{Ls7MhTT zBfMbfX7VM$x9A+;X+`3vmExmY87nC)u6fsF;p4@66b&Za$(MW%(_?3D{S16AZId+) zX<exZ}pPuREJ2d03m(j(VTZ1N8?hGp1Cbbf^>N=({Ol0Ay-lXpF9r- z8lHs?Xg;hiO_^!lQC3i}F0;U=zS5cI=Ep=u0ZpuIW=`@oy*NTN9NsHFQDOkpsvXVk z8Z~34w;@u$#`T=4r3$Vz`=5(a^?*>fBZ|uHuAL#7?aY_gW);h7_~pRHlR=XUG2+{& z7w1Rw^S|Rbg>Iq=diyT8GkxMwK*Y>JrQTw1Lv8@Cahji7Wa#MZR2-`S+T_XH<%U@% z@nc!<0$U!OA&&0KQlBLj#=AW9X7TC|X=!UKUxNsaVkm(S#(^cM!Z!~QmIpve&0!Yp zms{B~aV2Oj-R^b``UqAQ0fH>e>M3{F?CVaNNDB7x?}@rV?f?BdUhsO@;{sR_jj(&z zmH7su0j&=_73i8XRzxrUE`ZwzhSO{6BrMZ`j{!;dh#-4C1K$v3p=R-Py<6cUrsD#} zf`j2Jh4;abRQ(9iYB)@_O-=kTp<=rc=Frkd-0>&y0N?Q;B%!Oip_Wobj??W#ORP%mNUx|wC z#*69}qJ=kQcqJ`va0(aPBcXYjW`52YaiZN4{Ivi9a~G_e+CFW5s--+K<$oB(*y*&l z3c|>3E;DZWj9Z%NynTSllMw(EFrh(1KA!OxumD!D3i)*@MX^nx(^7Bn8QtqD%py#m z?VzClodAli|GT&B7%zVLZxRl~%P;TZDSciry9e$B3K+hJ_crXE31vw3&M8z4)ZiFf z$`CNqa+@6>^44~@`ba?^b}|o zGA2O_BFql(D>S;g=x$y+_nO|NoQ6t2q0{S^`D}FQWtbZZ##Avrckwb-Gzv8;+xJE0 zkAyE;osWrISDg)N5wOHw3sy9QL#Q$ASPA)7m*41Z`g1>j=XBEx{Z{v8D@3Qh_uwRe-6NujD-=7tHA_OnUF}~bHA|%-vau`F3gZNmww6>T4 zE_7i3j&MHzxc&7sHWGx%>Qwm{kVrr)ym*tfAdvH<(Nvg&o2_Ff0g3BgB@iG|psy4T zYF0uO+x0ACmp6Q&;4Bk6vj7ABDJIvoZj^%%tRO_OeiEE*ecFmAP*~o)w#6x)Re1wY zq^vPl)E_wKAJzFn4JB0Gh@z?_vFX}k{fE|Q#oxbyTY7XikoEFW}E$(=<^(9{7_0{cg5E8*Z zk^DSfUElRm<3?`#m-`ASjb7a$7m&?krZsaL7J1eXhDTDV!PMlYuEKz)!3RPa#GFd_kS|Y{mG@zwP5H@`3)d|UVZw(zxfSEg<8Ct zVuecalLFJJB1TX4_eGCa3y1(Z_?x34Su3W&8DmTb)7xfBjt45X-?~@1(h^T}%`2tx z!NB8y`ihggq8D-Fg|)w?60#R5(SmWPzuRz9$C#`KC8oKyFg$*=-m!JIW#o58xo z1j8kdsu8PdfPF)7fO7hZeS2~LI;5=x`#E7b%I`Sw1lz3L!3^Hg{%6uaSr&RbF?A|p z)_?;WjykQ{lTz)Qi#l&vH%>`?l!F9ECUFB$_SYbU4PzDgMjd=gCvo&{HxWJnx*;&qb~Bi8 z6CLFKs;LK5wUB@~QoOg}1${|$H^E4vvl|VZNxCu+2NDweX*zs1N=x{~=@`?JXr0bI zc}Bb7_~pVUJ-@A$HimG_;{Upb3r3?}dF@6hIz~ zpR16`06%E8KEa4L<_=3m{VoQwoVXy0wV!Ucslb{~7?YmbWYEbL-%Ztx;z2UXZluHE zhY?|Cot|b;u9ef4VF%s&NJeGhAAaH8>KmQI`F)dITJQ`#?fEyaOf$p!eh79_>*NiP zrvDK1?vaP%PiUoJsGA=Pii!XEl^SG*HT3S?|*DzRQ;D_&eIC(F;G^CU{!5F@?wRtK_tW z(NSZ1Rus6%n(zp#U%E%FXGb_M_X?T}TtpbZF7%}(ST|>EJ1MYDm-6!zS04pI zp`qep7PP*UD+k1<-*K42ss-)E!^BxF>v$=R(aR6b~^5Kg_^w_4m=IE247>!QT_&5tZHtBrJY_*k* zly~vukJiNUW)m#474qafq8+M6wZvN*FYdW`JYs`#`|m}Z>!$h(eaWBW_U$;6t&H(( zPl+UY3FUP=Gdg>oM=l=T1;mt$&?`mMj&1NbnAdGiR2vzjG9uMj`b?GI)38?iIJoAW zVwu%3ND)i4{se1s?;)6+p@%_R_3Cl1* z^X??Ccs@iR-8b%$0N7rw)NXj%K*^kx8o~N2KRi?0Y`5)lPX@}hV>kS+nIfNBX7pvb zNbJb5FR;4Ij?(t0r%d}z0=DH@vxWJIPtM4 zne+>FlDN*fC(u)JMZv#k@#`8Y4Tb`S@WYl@jbUBF>-lJ;F88QhgTm1>Ul;dJZ$h-| zIDHYl#nIszIWehB(@sBsbF23hzt>FCp$--q&syXxu!ZvVmLp&``|3@0Mg)q>Gk2O9 z!7VI(cXU*ck$WG9VB_+0M0H{5kgWX8Zzv-rhi8w{g7Ul{t#dny-cNfha8%Xy!h8pR zqprZyC~YrdT44QWI5$Jj(Mz6`?bfsTur7O)^3m;>c^0U!Upahdz`#`k&Up1NzsL#6 ztN^{O6a%!ybH>GMq1eSA1~oErZ49G!8LPyG#@s9K$+uMAF4O4 z$qF`W*Sma1mwNp;iTg=v$(w>TE&HcZB;kHf$JIiZ7Rx8=|ECt9^U-tVJN?vaHkB%e zM1ALvo>n1NiN!Q&s5)xd+${ZADvvfIFZ`DJP0#mf^|Z8Y_WQ;jeJs!WR9b`%74Rxn zG<(LXo4k52&G3RdN)+onM@1o$>oL!NIuBoT5f`2jd#kSW<~dxmW!dP(;#%3GW)aak z75Ihcd>Y(*a1<+t6&E{yOj76XB+7ht5qS9++Uw_&=4lZAo8!(vRdx{EVyER~`{|+1 znsT-Q6`^l^4OwD=3J~{)KQ9?$yze!Er;KW$*C@+^WwMfm(5WNyno2r@TS&&tg}@2= z^7+hX>T8?d2%74!oIX=LN~})IRpd$hP2ZxcTf4_Q=HM zdbe?p7mEiemwIrqnkv64ns}Kh{0Si#>z{gmrKZom6TLDo5qB)-p#7>ep36i{g|pOE z1^$|@Jc>q``D68b9?eg)SzG9ejk(z3E1jp0un{S!3Rr7~%AO8HyE)n#fZ=8iGo&l2 zsquXnwVlJ5ega(QuGM<#*U|xDHTa*z^T$ivBXBg;){$Kh*pEARtWt)fRd!R`854m@8ZrR zi<>=NnPGoDJ}jQZENNjK4bv2J`_11%r7w!#aPdvD>4Okp~r zrF+jj>8_YXw|Hb1w|9~(LWe>1o6YPG+K8@(jLXt`RVqcBX-xQUc;}#@s&D_L0ScwYO z$WN#B#Zn@ECf1i2ZIoO?!|c%N#DtWyNmsCZ_36h=NZe}2-!Lt`jY>T z?%wh*%I}LB9zYaCkq#+Ax}_VX85(9N=`I231_h*~8M<>Ax}`%pq+3F|yYspD{_f}9 z{TJMC;rhT8=j^@q+H0@#&rU0eE>_g~MBFmpeB+Km3oia5!!pV^e}g4$+(%yjtNfv zRoPNnWqC}aVhRiHCC4thlS>ym!*Qwdw2bl%y@yH^aTD^WnHI$APQU(Lp27tKD(R2v z)qnf{mOvO=4tKw(s<$a`IXK7yVJO)bxmVc+uE1gxKB*fb1B~CU%R1Am^BOOG8OgNx zda_M*?joK4CFV&3NKJLx!bVkj>3{xgm`Obacmbx915}ld!067&RNlFZLWZt=Supd% zHt=b0;T~3-+w~ZdYZ>~8x|A_V(3`Shr=m?=GhYP>llIatMtNyw&A+52XbBarc@-TY zv|%|kM%vmY@eC7rXVtFtS)w_GN@GItBBP`VVGY&6J6jgR8Lg`(*t4f+RLzaXeYPQH zWQ%;8@(Xa>H~QXdt5h7j&BJqL*72x1_8XXvq_LS}Z@KU5h9*2MPZ=FGmav9YBrOYW zl6oFqok^Wur}Lkk5=&#=;N{cXWFYJjpE5B0sMrZH0R0%5?VtqZml^|?3vXX~ZD9Nn z{2?K2x~u4gH^CNv&sTXA1VM@3(2`WpmFDb+SVg?C`G{2rBYt>Ybpq5T)xplJxC zVc-@62lT!ZAR@$%r@G7@yTHXZk6#xP7e^%Grue(8JmR+ROXLGbK1d5QsWj4x-~Lpx z6u{@dJ7z#tIu*T53?7^ll;gGH=w>C4fxql`8Xmig6|qtUH*jTbzz3DA=$z$Q!H3D; zS%f1*RB(0sR%ZskI#CEe674tpY%u_!5!O8}51aeo9=A9G#c+mwOe3dPd8;%n&t<1; z(_viP$$0JGv&NYM830bzrXXRldGNyOVmpiG!KQ+mk6V-J&UG~ zkAZjGcuGIMY2Kx{eT|*uxJF)KRdIN|$QV*e^yh9Wj^NdWHq+R$7?fFpeYcvv8B^1@ zT4kArO08^#JCt&7c`rdtZuR_e-C!=q()c@*eg26n<$H)e2rhMRhSBi9oa+~l_9%~?<&YRvpf;a*nZ zbXZ6CVSw(bbgaLdh9GS%V#O)BysM{@p!Ah@Qit2xo@$K7XTfX#6ac%(MLpmBR0)XC zVOfMQJ*^w23ah^J(v2d;s|DZ5a1TqRQz(vZ#h8&*m03BF3Rv=8eLVmG>o(jj-9~BX@R2Z+OzVs(kP#OZ9l2>PxhYN@Xbdr5EuW=8>O>jIMvpgIe#P-7c% zib@&ozvMSF#&*87HpX{ ze0r!wtKO`#SFOfLUnmN(DpZcG#s1>_dV~}jXOA%Vh!A|#FoJ33jrk9YY?#P$S&YQR z!0J-i)br*zhgor>Gss#sipQ$!4)1!|-Xt_FuXDm+!%4C=S?I zffE*(O#sED(49y}{+>!DONlwju#zFUjc@<(QM-5|nAt~9!dCR)6ZZ9~zuowkgg%!L z51-K9QrBP!hIkZJ(K%awt?UQn@ci7_dYY>ApM5#h8AP5GdzF-y+VWGW1o%U>5jJFo zUm;k4_36#k=X!Ytr?bLs8*0z_mQ&hheMuSAoL##75E zBt{^)j@{ErIxk6Zmvew?n&WyAS90ym;xWqt{B`WX%&9H5yW2s6^Xlar&t?gXx!~S^ zo@SxFMPV0Vz3FTbyWJix=F?dkyhfJP-V=(-#2XOj49&OO3E`(wU)Bv&=~@6OhEXii z`I(ba?6a}&1xcdrlEo3~u^5{`s3zQnsg|X?Z6(f)f+Z9MjDbQ<;1G&^Jt6CxLsI5` zqY6Nz(dv~oPXN~Tv78_1OY2;yh4_#KJ(}L*`woB;L*)4l#|x~2?^>6xH36c#>vQ_1 zGp=G`(=^0#2JgpHKSHGGd5qblD)zDW(jqV&l*s}#-VOleursOdy0BWFB?1_Uc{j2L z2=d0A;-09VF4kb=kBe)$IUdZ?d3y|&g}W7r5^`>Ldf5CYxoI96DXx$0qoM>wIhUU| zA0QG3q6eo`mG;)&>2rJg(sFTX(eM@NQ{DXPUiSfFDh}g^TnS5(_v!XlO)(X-<9f2R z*N(H&)-=*E0de;8-U@=93u16}oWjrh-&XHSsTGK=OeY_fmdZ$+(=skuOG0{INBT(c zrdOI&1q+=@csFEhz^gwbCdt9WX0~?3s|b`VgD0EXJ(cSv?obu2e+QI=Ged# zSn_uc(ekWMux4|tXB#+%IVfWtz>OVR@xGX^T?#>hQN5E?88+^kVF7VL_6DM)HoBMOi4BTita{WW~$ClYg zTA(Ux(F@44tK4{WGRu?TXY>wfCX}ptXGx4bUx9!yL@hMTlrW&JZ)zm3psb>U3aXtTUr7#fqhuM)4lktE z#!(D&8|+Tfmgn~6Xb_Z^m`Xn;!*&;tXLv3Ekf$Evu~eLdWFw6|4_#~$CYK+iWwKxH z%;+*SPbjGFw*eWmv#Hf`oQ|q8)912q<5tdEZjL+Yp0F`(?g1RDT5+bt{1q;`x_fsc znD49+TR;X7pS1u+K5RMKrE+NJERtM{!%ZIvr{nkR1iyUfMidHs&<;I*g6X3-ejCpF zc_7z;I9EP(3)szbOx*~C^a(j61dy&=pejx~8~=}?|28l%w>{fGoP4y!00>2p`_i=Y#vn2+caz-+%Cv zh`%RaH{R)zNUUx51vVTn1l`L^9Ne5AZt3d!e4UN7i>0r!*!tO_iJuV4(rcj#yBPp0 z`0`xmodx?8mtIFK9pH-Ilb5+>^!zLOZ+arD$;-E2-KT{xyPy|xjtdau=bI(gV?qqh zO0jn%c#<|SUWNBvThttB{d82m4tuT=Yp27_pC!`oO90=*-P-$liSVWxtDX@LvJeO3 z4~1l7YALPrqJh;JaU32h&*PFWL({Bcou3;wPaC)9z(=f#Y$sau=~!o(|6@9Nt*o8Z zRxau@(pXe@R89k_PEr6KP-OuotI2pjnW&$dpD+Ji?NMg0QBu_rdBO$^?`Qr^!El1GA{`CV=c00A6zG5 zHLEV=ujy7Fn(YXpd0E}0B;ti!n{6j7Em}3t1gSXc9cyhToPq(|_F=?Vy?cLL(`zFu zF63G(dt;mIp=m)hkF#O|a@yy2p_Rw;1{ZtQ(;~-`mwS`0EVy?#LR6)A);Bqa1MsuR znFGoUVCH=Ta{;bbPt8myWNCFs5C)TwANsA3;zPplzozrrizoLbK$nly zMlVw`9g-&{AKI(OZTHFP8Sw6RQk~3}{+-fFnjHN3?VPhABcC=g$4MRs4{R9p{={pQ za(G?v2$8rL{G3a|O=h%_F!azz?)WzLu<-Jw=*@fz&FF7g7Cxub5m^^yH5lXktnW}H z=YEl9)g~s31-+X2<94yIxM%*rZTe_qa?TjP9~G6Oq(qDRoma>Slyfu4Rww?l`&+c|1wn2}1iejuIl0YR>F(UTHNB$r*D)D>^4j)65g+ ztLi99co%OXD8hPqGakP*-|h@Z2ltYl*kaf3|9n*9U98vyLKfgvA+grhv4y2R{d^o< zU1>}nPtz@L(uK0*z4c?#1~xE;{J*KCX29qGfJnOy>6`VX^Rty5&!9xk8*=Eei%6M7 z55VBJLStlFJ`Q#`{H(Tqv=rbuxgI5$G?TtQG%BO(6A4?ZpDtS_oV9roL`doO$%d}okEjJ)BeIM)Eh&h9$TAF z-#Fw5o!)7X+eChG=@vC=`-}P9=nvLUNT}d3E zv&@YJ>b0!=h*AUVqEzOTX6*wR)&vvu!k2u6MxSxM{xWHo1>qXWqo(#DU37|?t>`CJ zjNBie-3}IMuqeol$25FiQmWS(FFDY#tIM6ru@fD>+%^qW3iB%a*pX<*KP&f*>AtF= zM_;GO8Atslj&I>G?q=w9iz-dT&Wd{AhovNWJ!Td9n!%C2C60TmWNPrf0$^yC zFwkYBa?0u9xRbhAcL83Hf>o?JDaUKGi@xt)lj+Oekh|}D@xbdxm%qdq_UO7M2P);e z)6zVdJW|UM$Oo$_VrRc&3|5>uxF`M99P`U2{bMtu`~_?r{qx8) zu{>6IW=Q|{P_J=RLfj2_Qug^+{IOz`$F9d?MGMDY!w@ZPkx*+uF(8sLt!Bb@aWa8Q ztAe`oVh4=|or@~e0)@|Vk*>dUrKCj(79WZJ0>N~CIPK$Aavv3|U@D5bGtfhdPxqA( z(i0#nn*61KkorTv7QXcd_h!(ma0QfJy;d~>3e78F5Xs_|qvy=}?^t$QXeghqY*xl< zJh?@}I+yqxgOTA$H#OOi<_F5kXW z8=KyNm6pVG(?1w);f(8^0zj-*nPV$hC&T4H5a}J#N#Do#0z-FYVej+2@=6yG&IXb;^EV4f%gxOO7$5)^-(TU0iil@I?H-7}R4UsTbUPUa- z8#*9rQ%@11BSfI$U)FfEu$OIvz4f5@y`q#zDHQf_nAREj#IhQ}lL*{I6D?)n)!}%w5IAP9_WWy8Y zj+acme4$^V8E0&JcTZO!PFOWt>>XB4ES$_s8Gt3W0tR0B=IKTD;;%zKc(e`~*fGJ@6 zT-ut>U9v@0hXPb@l7?D1~ z?(_>G)ULohu9pa#t1x$J%uu2Z%%g!$89RoyW9D`7(jF5ofIiaQh+n5E5$x-uF1Hx! zXU6z&VPx)5Y#g{Y z?^wm{poL}=JmaxlHnEgjVD35+g;rc~eA-MAsqJF&&A>`CXNsW^UVJ#)aUF3I zQn|eqr5{XbF9Fu`U?}{SWBh(UeDnt&Gh7Pa?dL`Gh2N@q{EJcw&ojXx7vfgHnmK6y z*I(*`Pxx<dU$zkUmW##KFAYDrrlh%C?RWlcAZu_Y)q(vIH#35Vx$&} z4}+-?KXfx9f2<)sc95`EXUb89dMocRFQbW8TKw_yb2hJm{?cEi8D`@tm03| zPILWKLR@Eyj6;@G*@bnFh?hNyU*K-!jNqd8dEM^w2K$TQMzpX*bQoea{ zRtF-U70lqQrP?l0q;li4=UVk>=AcwvPShM`=*-@C0QDN5u7rgg3U_X$A9l?g=HXQByW`IbR@fo2)I*NhYu$C6X@YM#4&QxW3SKQ+0gur9t+k|um zg1|>tfXUrCmoPlPQ8quhc*3!$?@PzG=~6#gTeZ`(3eh`kKYuno)S)uuh{aaDORM;| z_=$XzY~f%Lbwcmk3Kv&WU`-u(ldE~&Mr!yz-Sk<^#PcU~L_vDpq~CgTXH=SSk*#Qu zI5Zti-V9=OJ0oOA4$)M~YA^7#K36BIWBe-i{c8n+1=X+X^ZkAS1xetf=F!Oe-814e zf{q8=p?)6c{D0rjm7>dAWjSIMAmjFNTuGB%T>0SlJaq$tqduWlEGmbug1b3&%z^v}q2t$)0j9+I2h6T_& zzkR}|3~(Z|+5{HOwtS4ii8SN3h9a!w!>g0qP=GTD87{0EcZHy0x7yI9fEfpJsg=jm zsbBAQ`(BD`-91Ft{f>*guaj$GWU?FHdr|(7km0|sMpHZoO*mLJaE%*>ATX_Nj3g7U z2Y6hj@ODz}+nY2`z?Qz4#Itj*SU}sc$^X|QKK~vN1#zXPnOsrISxtb+D z8|D|{J3rTp-w36qV-Ke?sy||L@V*hzG!7yKUU$jAeNizqS(XS@qdHkNZkbNX&&guV zQh6}bakifwXb|>UNJ6UXt2Rlyo64RgvqjWcE$1=U>+Tru&5p6|y%TYTj1$2X;Y!)Z z=YBV->F%LaER~t0)9@)JyqRUTBZgFm`j2c({47+++t2M79!Nh<5=r#cBO=m}$_@Hm z5pR90@Y>=d_x#SYy^O7J{ajg3OS)Kz1)dvh_P+Y5m$%9+q{-{37DKH3P>2k@beI#6 zvQ{xhhW&4Oqh+c}%Ba14J&YE@UjmC+jfd5*+(H!eP(FS>lf6-V4%LKuu0(NF`@)zH zh#HaFObJ`imSehnvX*#hd6BMmc7l++?&_8L!TLtT+$A7sMP$u~tpRr77f1%ABQYO2 z#iNUnW1~7IcKP{eHEWl1ziWjxh+nY$f=y*N~HHRKt;wVC-@B zjM<#Qo&P|m{7u{V?}VFSXEVIEh@5UA?-SA|Kn?nFL3DaXGW<<8dyG&6j3F5(pi>sb zzuA5*NE-u{m-(WMAB$`jqmw8hiAI^rqDlh!5K0yB>YZb4o`1A2Bp@-q)bX+mrTirQ zzEZV+02$R*fZ*UivtV<<7PaCHx0PIudS=}rF=SAMY zx;_dQ+>iISn#zl+VG=YnKfO$ODJE>H_(_ljm;f~%>6`M8bxto-vXHx2R3Z&>Mfk(D zDStVgB7qJ)ho_NJZ#purbHdYp^jV^?hv$Lffm~(a5qJm}X);&MaQ${{o-ikmjX6Az zKeGC!Vz4ljWU!D5NcFvK(F5xoN%FL@3<(1&;Yr$0XmLfn6$j^g%CGwY1&gEa0+0T& zAOa#4t4U5#|53SW^HemAjKsTY=8dICVbBYZCd+2Jh&zMdVTQY)-;&M)g~@ty-Xnfn zjNJ{taBG7jnO}4dQqc&TF>vMqXS^}9t(=HrcFZz$Y>kwQ(3;(BbzIpov4SEr&A`~H ztN}X}R+*DA0L}QhE)>`+qwV7A1}wfE7@eWzHwVP@{uQGi#?n2m*0nx?2>Np5^_W=0w7`R7@krn`53 zhs?M7pogKp$Qh;{jjLug0)_Nv_8U^5U(2J-7o0bS;{l?M=p0<#0!>D^@;2sLVj#x_ zBiz(i_x%1Sn@w7V%Hx}rjx)~B(jLDSTmO}eP;p5W4n=PR6D6dc?IbgRfWpdj-CW8Q z#qG#-dM?L%vAF71JQPkmX34vzwT`;`%)7fwWD$)w8bnE-b?vdBZl7r@Cb;DFbQdNF&HZWolsm^S+!h zFKx2$WRF?F0`usi2>*>bI@hOt!Pd(fx)fpRVYdL2buWGT1X$dDc2fzc?jqkzRL z0+kIagakODkCMc{5Y9~wFnR1q|yWl|FMWbg|#TiwC1HmEG1xM>eESwFjZ4-)xN z!rmNj$avS<@U@W{y!eJE)lXLY1^bCxntX=wI2HvT5!Ry)aL}(Q= zv`p(qqj3pCFg;ZF!^?M^+j43Jys3WcKi|n(W~(%-p3<-~U}CXYo%c_h=DAVr5nX1e z42sf(fE~xA$wj|;NTYM{*L^GK?PK3%yCJtG96rrGC{r!Odl?Adhmu&4)T>NB*@zkHh_Ba^vW#G-?&S*){e+^NcH<~iW8){P0WlK*4(JdBnk7o# z*~*aV80&|=6PwY|En$MIOVN|W6U^Ghq zkD0;i7()4SAr_DV(Y1tJmTOwjs$KQy()!wrWny;KTrz`}`)yw&vKyVx>=hoB5zWIut`+M^fmIhLojr@hDTvd)tA8LQ<7aY)TYZ;sh= z_S`kpH{j8DN>9*fhkQgGH}u$FU_-t-$2~lY{OW}!l`}TM^=YA%mERYqt+{pn)qCZk zi1OM4nVN#A<}Es(>#`qHZc`eMffjESHmHgDp)PR1l^5{83{X4qtV7rN&3%{<_X%$zGZ@CpA zO39Nfi@f?=isVNo?LBQbS|Q>)^a%2+da!VLBRC6cOWLJFO1+F?LspR2L&*FsVwc(ZS4dc$`ePx$`K51id&;aZQl<>;80GWpW_+Ne&I>lo zbg8rGte@kW|A`d?UMYnX($gTr90P$Jd;!L8?OS#Ow`|kDTknVl3#Ox#RE$)7;O7(lR}FP+JHcn?H1!Rz@+#3@^k!ugfX% z*-v=BscY?6K2c771Bz<^lWazeT5jWj`_Usgp+bLJE}C67OGvbUy!!0aPDyzjqE*lV zgZW%hsM$oiPg~98Yd4>^Zuzde=7AO`?;nunQ3nSo4D&|T;32iZ?|J(e8)};O0`E6u zs9>isTs0h_$=ts#yG9?9M-8{iH^v@&{nmR?>kZ#K8Hv2sbuN_lZyMBM&*OUqI9*Ag zxof=Hy7%Uf^l<}P0b~WTt-U53faD1Wk>RhcZg8o(ok7!xd{ z3QSl%D6(U&)Y~s;rNLH926ru88uyc{KIhsS=h#Hpa_)Hz$ZaSXt#n~V)6}bQ%U^t) zAyPD|SZ^mXm-9U}(gP5D`EAM)$>>ZkFr?;2zpQPM;)9>DA7^T`%ja@T#&^~ zGR16r)VXj5v1RCBynECYmDE&>a5(BJGLSFeQb1U}+C?g!J8!z9M5L3pq$BZr!HB;6 zW2s;FIjI;st2vTia8$SyiTtX8z`K`B99U2F5gycj7to1RPtaG^0_>E)zWa1M%3N1! zTDU{7V?Hva3HvCivR1X)+~>I7PR66TL#OXWgq+%Ix`ozp7DAP7CTEB?^9s|%pR(0& zn@w~ye6D9jqeRpH+GjMc0+ba9;Hnt?I<9mpRXY<|C}xqEYUChEv31viEgxL?{r(9% z|4|)h8{ARSCU!Mhg|aWIgu;~(XTiw4cN6r?Uu=xl-hw8hIYG7$y^2~4EY}3A=V{H0 z^?L~*#$mme%WZ*7rg@NyeWF&Rw(JVdN>w3v^^27w#{wh>FKfU$E|23&f!8X%Af2<3 z)A9iE&pF9MT}io51?1RkWX?RXd|BBB7%Ra`)MFZ{K`J^iw1!pEKbZjh zG(#sAMKvSi(@FQvx-ytqkoW-4MboJ7A_8DUr*Jn(E}L$!Zc zXn9{x%^0Ew^`73XRE?|3ilzjqP2WmulK~WN{2mF=1!DZE{A{^Q^g@zI+HIY}?v4Zm zAo*Gia<9V$c4YjYM;B-Pa!B$9;jN=v=$bydllVCxj#wzb$lrg7zv9=61;w|nwc3|7 z61-et7F`aeiM^Y%G>jQzMLz<-cT}Rm^!uXy^3cyQ@KO@%Ar4AvTX?viu^YdVY7wL> zmrlr%u%Rku2C$Slxo-N))@xSf;)kl{4S>CKVH-PKUs5L8_G22?sPk+UOT)A;)42`P zUyD)fJ^WjJqMQD*8!GtsgJGat{n9Kj5EkS~V<)Eip`r7!m zh{6y0tnO?Fs3PWmy;L7>9$tEQ=hy1>PYH>6t`)2f&ReW3M0n?NzUO4`as?rb%?(1a zYJ%-9XTy-Z%$#`rG^|>@&Xt`}{04qR^k)xx4Mo?X{Bpbg<5>%Cu+W-$O$o}l%yu2Yz#{b_xVRIzr#hoQr z+#IBW?fzrVobs4inuzF#jui~VQ-YUwB_ui>6eN7qBw)KcCPeZwU3CFv-0ip4zIg1o zj_e4KVCTiPgN1qQb+p6Ro2Mpuxy>(1 zA@gYSIAXRbJN<3X94$YgIBuZa>&E^OV!>Z~p|r*$UkF8@ZPPF+QXe$NR?8&{dNl1y z%M5PEIJ%wqhz3%Iv|@xrN#ucL>rA?Up}^dY3Dmce&le#M0Zav=KPMgqn}g^?ooiST z3h-dnpcbz{X2pf)iGsE(pE85T-rw6B3}R4wlC=T+(>G@gMK`0H5)kQ~Ykf{WaGCIh*yiG0=wqyQWLh3laeql`!Iu*M-j~qey_3UksRsf~on+70`!wex zecJRGyrb>r9uq)5&BMcigul^d$=lL{>_F`IS?|kLSNG%G_U+y$Z6^o1>_scEd%zHW zh`aVU86t{{tp{f%k4B1gM{#`omkG=44XC0m4!T>9V z4T7)^^a(<)PrF$;66rE2RSy`n?ma;M3JioC6*$zQNvC(h#N*BS`=Apzi#A zm{ABnmk4v%iB1Iky@j~ZtYp|r)NS_nMlm~jD}C2gT)i%^%qN-k0}+Rnsl@z*@doN? zZ@;_5@bu6ZtY_QF`IEISj%>eOqt_I>->qb@AAndvzWxB--P1~?@_SmbQ9Sml#iaV@ zA1$fvNk$=%^5`>$LiH5bFIte?3Zl9ERomH1kY;6B>E*KIr>aH zrJZ^d6N*{<@SX<+8p(VU`;zW^td1#RaUpe1%$uK9d0XPOVK7?8kTKj~H5~fJL0WBv z*X@wU!Vh&n%}9*e5nOl@zA>^uu{Lqfj~kB;|CE4tz#r)2pzNS{)@B+oRiJ`4k)e$d zwCy+P8}JH?tC)(%iv)`UjU7%!?E!I^uN{KXqsj6{{GzI6|K$Lo&j@K)fDXlAx+;Fj zgbUV=C)kN-|6%#3E|np5m384w*abRon1V>_o@0VXZ4#hc;jGZ{%*`7=tX$Yy<5 z2*8Tb(Z)+IeDz*dg^EwBe=5J5g)GJS^K&))otgVx1IATIAizw4%IDzvCqFCKZ-yRt zvgtx@xKq5jxo@2qL-=dlvPJv;LINwf8GFv|0EX?lr)Jk(mw1Ln1%2WIx$c#`(ffZP zJfFF0KHOLOUF;Jp;vd)vSnvQW5!x!^*{^Hhx8OYFOl5kv^cU}9`%J2|K@FN`T11#$Ta;w0A;78J&S9s(7GS z)|+vvQ-8&m0k8PJS&EBUH-2jiBE@H9NALSE!<7wbE5^L$*JPXb7i9SNI?ZH?-#_z% zXY*05*^5a5>rj5^!tam|8?t}>8ACDvU-V7D46M(6f}e2KMm_eAwwL)Sov}PoYNHR2 zjlMVdS&)sD*BHQ)*G)G=b5Jb<9}FUBl-KI-_*ZUg&+JdyzYR# z_?jk{x19eSWk7D^uScJ;G0{&P7pK=vy7vX!W^WCST@CMu?Eze%Ec_1m1i#e?Sq!PO z-DxQU3m+WGjTH1Fvs5S1!--7*3QUYCJTH5Q<2|r@(6;@4y?_n{|J6X05#9azg+FPMtL(`wh56TXr+e$Be!6wP3svBkZ*!;yIE4qQL*C z#;tg67YQJUQC=GtnjMk2Vl7*Pd*4O<$w=cb1?`&(}rF2o(-Y zV1Ei@|FwvyG1*ztfc;Ca9PMJLEZKl@cmu>ZVl1Ftha*TD7A@3Faw7AE=}HP)`SJ9*Jy_qL`3yQN5ZOGY{Pypc?9{8 z1D>jz?&+J7c}!}BRJz|PAds!3HSacw@ob#RYww_D?<=Jf$W+0+h$VK{w#M>?JLgu2+Sx5i+gI;i4SxB%rJk zfSO^USM`NIBL{_zZs?f78v`{tF|-iQSBTywEM2Sl+E;dW&M8vpQH8reu4Ee1+8RLK zSd8j3ajPnew3(k8zvTb#(@V>&Nf;Gk@k0Bh%dRV{Ccye#uKzNZ#-+s%;*Xv?EMb9o+?5_1NuMS;fBrIdl05xDj-gXb9j`PA}QL#pcE( z#}Mp4@je&8DOPCrvJ#&l(*^hV1M^-e!KaE_PjZsnVT&UyL&x<_;JmMoz_`QyV)LzI z#_eC=gzX#Q9860l_BZd!-HV}Sk3|G z<*Kz7jC1i=eYKN(w2fX{EB@N@uI`JY=Mm5pa*WaWmWCy^AzQEWXWan=#N#~G5UZKa zx@%^-^9MyWnO*dHq&GO$%H z4&EFX4OjB83*Onyk)yusJrSd)pfHnk;n5{Xq-u|sA+KVwZT%`u&_V5h09B3d+LuU#og1m>VmQQ$QqWti_R>_-UW2IFW}g108kBDEH{86t z#($VGg-7X+Q5GOte`miP4`KKXoChdVop&9%UHs})oPV(V4+ht8S?IO3F147^m4nl2 z>>^3_&CM20pK!&u&Z80%O3U6tFw#yu($l0nBkZUiZ1@9KoGg}w)t9ykl>9?xIVBRX z`A2{;1n@~%m(0Phfy87(Ecfl=CRLTRF|n*nweTGnvNAKlx!qJ>Ov`wC70pUflGorX7G@N`JY%Yp^-EC4QqP<-tG`*d6aDbyKJvP zU-=1ZXAls~slNr5!21$ax}Z2^63(+Ra1C)NKS{JiDex~b`C}47&VII;nXDi!1kG~E zzqhwFyx1S3OFQc94mf)T{Zo^_%9ac7wzU2j0tdXoub9jd4cCqH2^;xa3x5A(2qd{t zP80-F4*ON*35|Mn@4aJ1f86m*H>cD6<16o3rNhd*iTYu!e2fY50Gx+Hxha36nEHM> z$}wyWc<)rLd(v{etXa9A&xFE?!rBl?Vp|>6N2^@%k%5B~>5d;+6226@b@^i`2xq|X z-K%jy^xbenHHnufmvAVDL30cZ2i^aIh^G`S(tHoTG>psPN(<>nur^P6euU^#=u*|w z)keFuIOkA7UzpMT8Z789oaGC*8?WtO(tb5VwD%*)H__e2Sf0j98Q)Cv))fj-s|ies zvI}AVT}zVbw0a~+#N&lWB-6ka81g=yO*&z5NBG_US&8#9LQ4%Q*jnZrS6I+WxoTO? z1tRvfaxx*i*8I>5K^+(4!KmN0a;^Duc^a`%W=`8Bizr49hO!4CWTdJriM#z6v5Z%AS#V^6 z)W+SBTv@5!;Go;!oG*YQQh`MiF>8~!YefO1dl?g%I$~~S2E3QYKXrkX7odxQPMIqQ zIMW(cz*Qi$v7;iE#{qyYBU+^pViQC(e7YCm!~Xh8yDsi4PgE<(WsGDahQjheLrYgI z&u1Iq&j7IDIgx|@yK8-}%e*0kmB!-9jw^N(ro#z@ zDdfSGTha;a7%7R93Q;5YV>oKje$MHg8Ux z0ve@ocYSI%0Gt9Oe)P-5ghGlY4c3@~q(%YfJfIohXCgskby;}L&Kb0F$Ae&_UxygEdkUp@!M`y*gn zy?Nj8Mqb*E`QJQ>ZL<|!%RmDD&i=X7aG+IpR@v$n#Lm(n(U0x&5MgF z{Xb}$g=71AbN<;ia327+@+Pjw{V|)b<@pmFOwCb-PtQKSHJ1aP{3EMGZDG33)QT4_ zyBcS!K00M|=8n@Uoj$phi)1;){xYpW*uv+?DI4{Yr|bWx;Q^M}v!e@&rz%nA8L$|i z@NNj`2^IoN7`yF>HwIE6^8Z=m|M#W+KPKQw5%mA?AMty9!^f>qFE8>8IMW9Nl9g1H KC>1mK{{I0ZxWu0T literal 0 HcmV?d00001 diff --git a/flux30.png b/flux30.png new file mode 100644 index 0000000000000000000000000000000000000000..b8e12eadafe45eba16f17e645d3ac057ba3eea4d GIT binary patch literal 35393 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 literal 0 HcmV?d00001 diff --git a/flux50.png b/flux50.png new file mode 100644 index 0000000000000000000000000000000000000000..76c4c5b7e81d8a41840e5252c370680e0b6b874b GIT binary patch literal 35928 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 Date: Tue, 26 Sep 2023 07:29:54 +0000 Subject: [PATCH 37/48] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- src/TRestAxionSolarHiddenPhotonFlux.cxx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/TRestAxionSolarHiddenPhotonFlux.cxx b/src/TRestAxionSolarHiddenPhotonFlux.cxx index 64deb8f3..87b3360b 100644 --- a/src/TRestAxionSolarHiddenPhotonFlux.cxx +++ b/src/TRestAxionSolarHiddenPhotonFlux.cxx @@ -389,7 +389,8 @@ void TRestAxionSolarHiddenPhotonFlux::CalculateSolarFlux() { TH1D* h = (TH1D*)fWidthTable[n]->Clone(); // wG h->Multiply(fContinuumTable[n]); // wG * flux h->Divide(hMass); // wG * flux / ( (m2 - wp2)^2 + (w G)^2 ) - // h->Scale(pow(mass, 4)); // m4 * wG * flux / ( (m2 - wp2)^2 + (w G)^2 + // h->Scale(pow(mass, 4)); // m4 * wG * flux / ( (m2 - wp2)^2 + (w + // G)^2 // ) fFluxTable.push_back(h); From 914fa2090024cab4dfbc91a338320325daa02b2b Mon Sep 17 00:00:00 2001 From: tomasoshea Date: Tue, 26 Sep 2023 13:37:33 +0200 Subject: [PATCH 38/48] created HP field code --- inc/TRestAxionHiddenPhotonField.h | 64 ++++ ...TRestAxionField.h => TRestAxionQCDField.h} | 12 +- src/TRestAxionHiddenPhotonField.cxx | 323 ++++++++++++++++++ ...tAxionField.cxx => TRestAxionQCDField.cxx} | 55 +-- 4 files changed, 423 insertions(+), 31 deletions(-) create mode 100644 inc/TRestAxionHiddenPhotonField.h rename inc/{TRestAxionField.h => TRestAxionQCDField.h} (93%) create mode 100644 src/TRestAxionHiddenPhotonField.cxx rename src/{TRestAxionField.cxx => TRestAxionQCDField.cxx} (90%) diff --git a/inc/TRestAxionHiddenPhotonField.h b/inc/TRestAxionHiddenPhotonField.h new file mode 100644 index 00000000..9ea444ed --- /dev/null +++ b/inc/TRestAxionHiddenPhotonField.h @@ -0,0 +1,64 @@ +/************************************************************************* + * This file is part of the REST software framework. * + * * + * Copyright (C) 2016 GIFNA/TREX (University of Zaragoza) * + * For more information see http://gifna.unizar.es/trex * + * * + * REST 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. * + * * + * REST 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 a copy of the GNU General Public License along with * + * REST in $REST_PATH/LICENSE. * + * If not, see http://www.gnu.org/licenses/. * + * For the list of contributors see $REST_PATH/CREDITS. * + *************************************************************************/ + +#ifndef _TRestAxionHiddenPhotonField +#define _TRestAxionHiddenPhotonField + +#include "TRestAxionBufferGas.h" + +//! A basic class to define analytical axion-photon conversion calculations for axion helioscopes +class TRestAxionHiddenPhotonField : public TObject { + private: + Bool_t fDebug = false; //! + + void Initialize(); + + /// A pointer to the buffer gas definition + TRestAxionBufferGas* fBufferGas = NULL; //! + + public: + /// momentum difference q, useful in all calculations + Double_t TRestAxionHiddenPhotonField::momentumTransfer( Double_t Ea, Double_t ma, Double_t mg ) { + return sqrt(Ea*Ea - mg*mg) - sqrt(Ea*Ea - ma*ma); + } + + /// It enables/disables debug mode + void SetDebug(Bool_t v) { fDebug = v; } + + /// It assigns a gas buffer medium to the calculation + void AssignBufferGas(TRestAxionBufferGas* buffGas) { fBufferGas = buffGas; } + + /// It assigns a gas buffer medium to the calculation + void SetBufferGas(TRestAxionBufferGas* buffGas) { fBufferGas = buffGas; } + + Double_t GammaTransmissionProbability(Double_t Lcoh, Double_t Ea, Double_t ma, + Double_t mg = 0, Double_t absLength = 0); + + //Double_t PhotonAbsorptionProbability(Double_t Lcoh, Double_t Ea, Double_t ma, + // Double_t mg = 0, Double_t absLength = 0); + + TRestAxionHiddenPhotonField(); + ~TRestAxionHiddenPhotonField(); + + ClassDef(TRestAxionHiddenPhotonField, 2); +}; +#endif diff --git a/inc/TRestAxionField.h b/inc/TRestAxionQCDField.h similarity index 93% rename from inc/TRestAxionField.h rename to inc/TRestAxionQCDField.h index 22662d63..ecfb183d 100644 --- a/inc/TRestAxionField.h +++ b/inc/TRestAxionQCDField.h @@ -20,13 +20,13 @@ * For the list of contributors see $REST_PATH/CREDITS. * *************************************************************************/ -#ifndef _TRestAxionField -#define _TRestAxionField +#ifndef _TRestAxionQCDField +#define _TRestAxionQCDField #include "TRestAxionBufferGas.h" //! A basic class to define analytical axion-photon conversion calculations for axion helioscopes -class TRestAxionField : public TObject { +class TRestAxionQCDField : public TObject { private: Bool_t fDebug = false; //! @@ -57,9 +57,9 @@ class TRestAxionField : public TObject { Double_t AxionAbsorptionProbability(Double_t Bmag, Double_t Lcoh, Double_t Ea, Double_t ma, Double_t mg = 0, Double_t absLength = 0); - TRestAxionField(); - ~TRestAxionField(); + TRestAxionQCDField(); + ~TRestAxionQCDField(); - ClassDef(TRestAxionField, 2); + ClassDef(TRestAxionQCDField, 2); }; #endif diff --git a/src/TRestAxionHiddenPhotonField.cxx b/src/TRestAxionHiddenPhotonField.cxx new file mode 100644 index 00000000..8236136b --- /dev/null +++ b/src/TRestAxionHiddenPhotonField.cxx @@ -0,0 +1,323 @@ +/************************************************************************* + * This file is part of the REST software framework. * + * * + * Copyright (C) 2016 GIFNA/TREX (University of Zaragoza) * + * For more information see http://gifna.unizar.es/trex * + * * + * REST 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. * + * * + * REST 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 a copy of the GNU General Public License along with * + * REST in $REST_PATH/LICENSE. * + * If not, see http://www.gnu.org/licenses/. * + * For the list of contributors see $REST_PATH/CREDITS. * + *************************************************************************/ + +////////////////////////////////////////////////////////////////////////// +/// TRestAxionHiddenPhotonField is a class used to calculate the axion-photon mixing +/// and determine the probability of the particle being in an axion or photon +/// state. +/// +/// A peculiarity from this class is that it encapsulates internally the high +/// precision calculations using the real precisions types using TRestComplex. +/// It is known that double precision is not good enough in some scenarios. +/// +///-------------------------------------------------------------------------- +/// +/// RESTsoft - Software for Rare Event Searches with TPCs +/// +/// History of developments: +/// +/// 2019-March: First concept and implementation of TRestAxionHiddenPhotonField class. +/// Javier Galan +/// 2023-September: Separation of QCD and HiddenPhoton classes. +/// Tom O'Shea +/// +/// \class TRestAxionHiddenPhotonField +/// \author Javier Galan +/// +///


+/// +#include "TRestAxionHiddenPhotonField.h" + +#include + +#include "TH1F.h" + +#ifdef USE_MPFR +#include "TRestComplex.h" +#endif + +#include + +using namespace std; + +ClassImp(TRestAxionHiddenPhotonField); + +/////////////////////////////////////////////// +/// \brief Default constructor +/// +TRestAxionHiddenPhotonField::TRestAxionHiddenPhotonField() { Initialize(); } + +/////////////////////////////////////////////// +/// \brief Default destructor +/// +TRestAxionHiddenPhotonField::~TRestAxionHiddenPhotonField() {} + +/////////////////////////////////////////////// +/// \brief Initialization of TRestAxionHiddenPhotonField class +/// +/// It sets the default real precision to be used with mpfr types. Now it is 30 digits. +/// So that we can still calculate numbers such as : 1.0 - 1.e-30 +/// +void TRestAxionHiddenPhotonField::Initialize() { +#ifdef USE_MPFR + TRestComplex::SetPrecision(30); +#endif + + fBufferGas = NULL; + + /// MOVED TO TRestAxionHiddenPhotonFieldPropagationProcess class + /// faxion = SetComplexReal(1, 0); + /// fAem = SetComplexReal(0, 0); +} + + +/////////////////////////////////////////////// +/// vacuum conversion probability +/// ie. when photonMass = 0 +Double_t TRestAxionHiddenPhotonField::VacuumConversion(Double_t Lcoh, Double_t Ea, Double_t ma) { + Double_t q = momentumTransfer(Ea, ma, 0.); + return pow(2*sin(q*Lcoh/2), 2); +} + + + +/////////////////////////////////////////////// +/// \brief Performs the calculation of hidden photon - photon conversion probability. +/// +/// If m_gamma (mg) is not given as an argument, i.e. it is equal to zero, then m_gamma +/// will be obtainned from the buffer gas definition. If no buffer gas has been assigned +/// then the medium will be assumed to be vacuum. +/// +/// Ea in keV, ma in eV, Lcoh in mm, mg in eV, absLength in cm-1 +/// +/// The returned value is given for chi = 1 +/// +Double_t TRestAxionHiddenPhotonField::GammaTransmissionProbability(Double_t Lcoh, Double_t Ea, Double_t ma, + Double_t mg, Double_t absLength) { +#ifndef USE_MPFR + RESTWarning + << "MPFR libraries not linked to REST libraries. Try adding -DREST_MPFR=ON to your REST compilation" + << RESTendl; + RESTWarning << "TRestAxionHiddenPhotonField::GammaTransmissionProbability will return 0" << RESTendl; + return 0; +#else + mpfr::mpreal hiddenPhotonMass = ma; + mpfr::mpreal cohLength = Lcoh / 1000.; // Default REST units are mm; + + mpfr::mpreal photonMass = mg; + + if (mg == 0 && fBufferGas) photonMass = fBufferGas->GetPhotonMass(Ea); + + RESTDebug << "+--------------------------------------------------------------------------+" << RESTendl; + RESTDebug << " TRestAxionHiddenPhotonField::GammaTransmissionProbability. Parameter summary" << RESTendl; + RESTDebug << " Photon mass : " << photonMass << " eV" << RESTendl; + RESTDebug << " Hidden photon mass : " << ma << " eV" << RESTendl; + RESTDebug << " Hidden photon energy : " << Ea << " keV" << RESTendl; + RESTDebug << " Lcoh : " << Lcoh << " mm" << RESTendl; + RESTDebug << " Bmag : " << Bmag << " T" << RESTendl; + RESTDebug << "+--------------------------------------------------------------------------+" << RESTendl; + + if (photonMass == 0.0) return VacuumConversion(Lcoh, Ea, ma); + + mpfr::mpreal q = momentumTransfer(Ea, ma, mg) // eV + mpfr::mpreal l = cohLength * REST_Physics::PhMeterIneV; // eV-1 + + mpfr::mpreal Gamma = absLength; // cm-1 + if (absLength == 0 && fBufferGas) Gamma = fBufferGas->GetPhotonAbsorptionLength(Ea); // cm-1 + mpfr::mpreal GammaL = Gamma * cohLength * 100; + Gamma *= 100 / REST_Physics::PhMeterIneV; // eV + + if (fDebug) { + RESTDebug << "+------------------------+" << RESTendl; + RESTDebug << " Intermediate calculations" << RESTendl; + RESTDebug << " q : " << q << " eV" << RESTendl; + RESTDebug << " l : " << l << " eV-1" << RESTendl; + RESTDebug << " ql : " << q*l << RESTendl; + RESTDebug << "Gamma : " << Gamma << RESTendl; + RESTDebug << "GammaL : " << GammaL << RESTendl; + RESTDebug << "+------------------------+" << RESTendl; + } + + mpfr::mpreal MFactor = pow(ma,4)/(pow(ma*ma - mg*mg, 2) + pow(Ea*Gamma, 2)); // all should be in eV + + + if (fDebug) { + RESTDebug << "Mfactor : " << MFactor << RESTendl; + RESTDebug << "cos(ql) : " << cos(q*l) << RESTendl; + RESTDebug << "Exp(-GammaL) : " << exp(-GammaL) << RESTendl; + } + + double sol = + (double)(MFactor * (1 + exp(-GammaL) - 2 * exp(-GammaL / 2) * cos(q*l))); + + RESTDebug << "Axion-photon transmission probability : " << sol << RESTendl; + + return sol; +#endif +} + + + +/////////////////////////////////////////////// +/// \brief Performs the calculation of the photon absorbtion probability in the buffer gas. +/// +/// If not provided as argument, m_g it will be attempted to obtain the value from the buffer gas +/// definition. If no buffer gas has been assigned the medium will be assumed to be vacuum. +/// +/// Ea in keV, ma in eV, Lcoh in mm, mg in eV, absLength in cm-1 +/// +/// The returned value is given for chi = 1 +/// +Double_t TRestAxionHiddenPhotonField::AxionAbsorptionProbability(Double_t Bmag, Double_t Lcoh, Double_t Ea, Double_t ma, + Double_t mg, Double_t absLength) { +#ifndef USE_MPFR + RESTWarning + << "MPFR libraries not linked to REST libraries. Try adding -DREST_MPFr=ON to your REST compilation" + << RESTendl; + RESTWarning << "TRestAxionHiddenPhotonField::GammaTransmissionProbability will return 0" << RESTendl; + return 0; +#else + mpfr::mpreal axionMass = ma; + mpfr::mpreal cohLength = Lcoh / 1000.; // Default REST units are mm; + + mpfr::mpreal photonMass = mg; + if (mg == 0 && fBufferGas) photonMass = fBufferGas->GetPhotonMass(Ea); + + if (fDebug) { + RESTDebug << "+--------------------------------------------------------------------------+" + << RESTendl; + RESTDebug << " TRestAxionHiddenPhotonField::GammaTransmissionProbability. Parameter summary" << RESTendl; + RESTDebug << " Photon mass : " << photonMass << " eV" << RESTendl; + RESTDebug << " Axion mass : " << ma << " eV" << RESTendl; + RESTDebug << " Axion energy : " << Ea << " keV" << RESTendl; + RESTDebug << " Lcoh : " << Lcoh << " mm" << RESTendl; + RESTDebug << " Bmag : " << Bmag << " T" << RESTendl; + RESTDebug << "+--------------------------------------------------------------------------+" + << RESTendl; + } + + if (ma == 0.0 && photonMass == 0.0) return BLHalfSquared(Bmag, Lcoh); + + mpfr::mpreal q = (ma * ma - photonMass * photonMass) / 2. / Ea / 1000.0; + mpfr::mpreal l = cohLength * REST_Physics::PhMeterIneV; + mpfr::mpreal phi = q * l; + + mpfr::mpreal Gamma = absLength; + if (absLength == 0 && fBufferGas) Gamma = fBufferGas->GetPhotonAbsorptionLength(Ea); // cm-1 + mpfr::mpreal GammaL = Gamma * cohLength * 100; + + if (fDebug) { + RESTDebug << "+------------------------+" << RESTendl; + RESTDebug << " Intermediate calculations" << RESTendl; + RESTDebug << " q : " << q << " eV" << RESTendl; + RESTDebug << " l : " << l << " eV-1" << RESTendl; + RESTDebug << " phi : " << phi << RESTendl; + RESTDebug << "Gamma : " << Gamma << RESTendl; + RESTDebug << "GammaL : " << GammaL << RESTendl; + RESTDebug << "+------------------------+" << RESTendl; + } + + mpfr::mpreal MFactor = phi * phi + GammaL * GammaL / 4.0; + MFactor = 1.0 / MFactor; + + if (fDebug) { + RESTDebug << "Mfactor : " << MFactor << RESTendl; + RESTDebug << "(BL/2)^2 : " << BLHalfSquared(Bmag, Lcoh) << RESTendl; + RESTDebug << "cos(phi) : " << cos(phi) << RESTendl; + RESTDebug << "Exp(-GammaL) : " << exp(-GammaL) << RESTendl; + } + + double sol = (double)(MFactor * BLHalfSquared(Bmag, Lcoh) * GammaL); + + if (fDebug) RESTDebug << "Axion-photon absorption probability : " << sol << RESTendl; + + return sol; +#endif +} + +/// Commented because it uses ComplexReal structure that is moved to TRestAxionHiddenPhotonFieldPropagationProcess class +/* +void TRestAxionHiddenPhotonField::PropagateAxion(Double_t Bmag, Double_t Lcoh, Double_t Ea, Double_t ma, + Double_t mg, Double_t absLength) { + mpfr::mpreal axionMass = ma; + mpfr::mpreal cohLength = Lcoh / 1000.; // Default REST units are mm; + + mpfr::mpreal photonMass = mg; + if (mg == 0 && fBufferGas) photonMass = fBufferGas->GetPhotonMass(Ea); + + if (fDebug) { + RESTDebug << "+--------------------------------------------------------------------------+" << +RESTendl; RESTDebug << " TRestAxionHiddenPhotonField::GammaTransmissionProbability. Parameter summary" << +RESTendl; RESTDebug << " Photon mass : " << photonMass << " eV" << RESTendl; RESTDebug << " Axion mass : " << +ma << " eV" << RESTendl; RESTDebug << " Axion energy : " << Ea << " keV" << RESTendl; RESTDebug << " Lcoh : " +<< Lcoh << " mm" << RESTendl; RESTDebug << " Bmag : " << Bmag << " T" << RESTendl; RESTDebug << +"+--------------------------------------------------------------------------+" << RESTendl; + } + + mpfr::mpreal q = (ma * ma - photonMass * photonMass) / 2. / Ea / 1000.0; + mpfr::mpreal l = cohLength * PhMeterIneV; + mpfr::mpreal phi = q * l; + + mpfr::mpreal Gamma = absLength; + if (absLength == 0 && fBufferGas) Gamma = fBufferGas->GetPhotonAbsorptionLength(Ea); // cm-1 + mpfr::mpreal GammaL = Gamma * cohLength * 100; + + if (fDebug) { + RESTDebug << "+------------------------+" << RESTendl; + RESTDebug << " Intermediate calculations" << RESTendl; + RESTDebug << " q : " << q << " eV" << RESTendl; + RESTDebug << " l : " << l << " eV-1" << RESTendl; + RESTDebug << " phi : " << phi << RESTendl; + RESTDebug << "Gamma : " << Gamma << RESTendl; + RESTDebug << "GammaL : " << GammaL << RESTendl; + RESTDebug << "+------------------------+" << RESTendl; + } + + mpfr::mpreal bl = BL(Bmag, Lcoh); + + /// We have now calculated the main quantities BL, QL, and GammaL + + ComplexReal I = SetComplexReal(0, 1); + ComplexReal ExpPhi = SetComplexReal(cos(-phi), sin(-phi)); + + ComplexReal Bcomplex = SetComplexReal(BL(Bmag, Lcoh), 0); + ComplexReal Qcomplex = SetComplexReal(phi, -GammaL / 2); + + ComplexReal Bterm = ComplexCocient(Bcomplex, Qcomplex); + Bterm = ComplexProduct(I, Bterm); + + mpfr::mpreal ExpGamma = exp(-GammaL / 2.); + Double_t ExpGammaDouble = TMath::Exp((Double_t)-GammaL / 2.); + + cout.precision(30); + + if (fDebug) { + cout << "ExpGamma : " << ExpGamma << RESTendl; + cout << "ExpGammaDouble : " << ExpGammaDouble << RESTendl; + RESTDebug << "(BL/2)^2 : " << BLHalfSquared(Bmag, Lcoh) << RESTendl; + RESTDebug << "cos(phi) : " << cos(phi) << RESTendl; + RESTDebug << "Exp(-GammaL) : " << exp(-GammaL) << RESTendl; + } + + // if (fDebug) RESTDebug << "Axion-photon absorption probability : " << sol << RESTendl; +} +*/ diff --git a/src/TRestAxionField.cxx b/src/TRestAxionQCDField.cxx similarity index 90% rename from src/TRestAxionField.cxx rename to src/TRestAxionQCDField.cxx index a5cb8b94..744c5e4d 100644 --- a/src/TRestAxionField.cxx +++ b/src/TRestAxionQCDField.cxx @@ -21,7 +21,7 @@ *************************************************************************/ ////////////////////////////////////////////////////////////////////////// -/// TRestAxionField is a class used to calculate the axion-photon mixing +/// TRestAxionQCDField is a class used to calculate the axion-photon mixing /// and determine the probability of the particle being in an axion or photon /// state. /// @@ -35,15 +35,17 @@ /// /// History of developments: /// -/// 2019-March: First concept and implementation of TRestAxionField class. +/// 2019-March: First concept and implementation of TRestAxionQCDField class. /// Javier Galan +/// 2023-September: Separation of QCD and HiddenPhoton classes. +/// Tom O'Shea /// -/// \class TRestAxionField +/// \class TRestAxionQCDField /// \author Javier Galan /// ///
/// -#include "TRestAxionField.h" +#include "TRestAxionQCDField.h" #include @@ -57,32 +59,32 @@ using namespace std; -ClassImp(TRestAxionField); +ClassImp(TRestAxionQCDField); /////////////////////////////////////////////// /// \brief Default constructor /// -TRestAxionField::TRestAxionField() { Initialize(); } +TRestAxionQCDField::TRestAxionQCDField() { Initialize(); } /////////////////////////////////////////////// /// \brief Default destructor /// -TRestAxionField::~TRestAxionField() {} +TRestAxionQCDField::~TRestAxionQCDField() {} /////////////////////////////////////////////// -/// \brief Initialization of TRestAxionField class +/// \brief Initialization of TRestAxionQCDField class /// /// It sets the default real precision to be used with mpfr types. Now it is 30 digits. /// So that we can still calculate numbers such as : 1.0 - 1.e-30 /// -void TRestAxionField::Initialize() { +void TRestAxionQCDField::Initialize() { #ifdef USE_MPFR TRestComplex::SetPrecision(30); #endif fBufferGas = NULL; - /// MOVED TO TRestAxionFieldPropagationProcess class + /// MOVED TO TRestAxionQCDFieldPropagationProcess class /// faxion = SetComplexReal(1, 0); /// fAem = SetComplexReal(0, 0); } @@ -93,7 +95,7 @@ void TRestAxionField::Initialize() { /// `Lcoh` should be expressed in `mm`, and `Bmag` in `T`. /// The result will be given for an axion-photon coupling of 10^{-10} GeV^{-1} /// -double TRestAxionField::BL(Double_t Bmag, Double_t Lcoh) { +double TRestAxionQCDField::BL(Double_t Bmag, Double_t Lcoh) { Double_t lengthInMeters = Lcoh / 1000.; Double_t tm = REST_Physics::lightSpeed / REST_Physics::naturalElectron * 1.0e-9; // GeV @@ -109,7 +111,7 @@ double TRestAxionField::BL(Double_t Bmag, Double_t Lcoh) { /// `Lcoh` should be expressed in `mm`, and `Bmag` in `T`. /// The result will be given for an axion-photon coupling of 10^{-10} GeV^{-1} /// -double TRestAxionField::BLHalfSquared(Double_t Bmag, Double_t Lcoh) // (BL/2)**2 +double TRestAxionQCDField::BLHalfSquared(Double_t Bmag, Double_t Lcoh) // (BL/2)**2 { Double_t lengthInMeters = Lcoh / 1000.; @@ -134,13 +136,13 @@ double TRestAxionField::BLHalfSquared(Double_t Bmag, Double_t Lcoh) // (BL/2)** /// /// The returned value is given for g_ag = 10^-10 GeV-1 /// -Double_t TRestAxionField::GammaTransmissionProbability(Double_t Bmag, Double_t Lcoh, Double_t Ea, Double_t ma, +Double_t TRestAxionQCDField::GammaTransmissionProbability(Double_t Bmag, Double_t Lcoh, Double_t Ea, Double_t ma, Double_t mg, Double_t absLength) { #ifndef USE_MPFR RESTWarning << "MPFR libraries not linked to REST libraries. Try adding -DREST_MPFR=ON to your REST compilation" << RESTendl; - RESTWarning << "TRestAxionField::GammaTransmissionProbability will return 0" << RESTendl; + RESTWarning << "TRestAxionQCDField::GammaTransmissionProbability will return 0" << RESTendl; return 0; #else mpfr::mpreal axionMass = ma; @@ -151,7 +153,7 @@ Double_t TRestAxionField::GammaTransmissionProbability(Double_t Bmag, Double_t L if (mg == 0 && fBufferGas) photonMass = fBufferGas->GetPhotonMass(Ea); RESTDebug << "+--------------------------------------------------------------------------+" << RESTendl; - RESTDebug << " TRestAxionField::GammaTransmissionProbability. Parameter summary" << RESTendl; + RESTDebug << " TRestAxionQCDField::GammaTransmissionProbability. Parameter summary" << RESTendl; RESTDebug << " Photon mass : " << photonMass << " eV" << RESTendl; RESTDebug << " Axion mass : " << ma << " eV" << RESTendl; RESTDebug << " Axion energy : " << Ea << " keV" << RESTendl; @@ -218,14 +220,14 @@ Double_t TRestAxionField::GammaTransmissionProbability(Double_t Bmag, Double_t L /// to solve the problem with a density profile. TOBE implemented in a new method if needed, where /// Gamma is not constant and \integral{q(z)} is integrated at each step. /// -Double_t TRestAxionField::GammaTransmissionProbability(std::vector Bmag, Double_t deltaL, +Double_t TRestAxionQCDField::GammaTransmissionProbability(std::vector Bmag, Double_t deltaL, Double_t Ea, Double_t ma, Double_t mg, Double_t absLength) { #ifndef USE_MPFR RESTWarning << "MPFR libraries not linked to REST libraries. Try adding -DREST_MPFR=ON to your REST compilation" << RESTendl; - RESTWarning << "TRestAxionField::GammaTransmissionProbability will return 0" << RESTendl; + RESTWarning << "TRestAxionQCDField::GammaTransmissionProbability will return 0" << RESTendl; return 0; #else mpfr::mpreal axionMass = ma; @@ -242,7 +244,7 @@ Double_t TRestAxionField::GammaTransmissionProbability(std::vector Bma if (Bmag.size() > 0) fieldAverage = std::accumulate(Bmag.begin(), Bmag.end(), 0.0) / Bmag.size(); RESTDebug << "+--------------------------------------------------------------------------+" << RESTendl; - RESTDebug << " TRestAxionField::GammaTransmissionProbability. Parameter summary" << RESTendl; + RESTDebug << " TRestAxionQCDField::GammaTransmissionProbability. Parameter summary" << RESTendl; RESTDebug << " Photon mass : " << photonMass << " eV" << RESTendl; RESTDebug << " Axion mass : " << ma << " eV" << RESTendl; RESTDebug << " Axion energy : " << Ea << " keV" << RESTendl; @@ -317,6 +319,7 @@ Double_t TRestAxionField::GammaTransmissionProbability(std::vector Bma #endif } +/* /////////////////////////////////////////////// /// \brief Performs the calculation of axion-photon absorption probability using directly /// equation (18) from van Bibber, Phys Rev D Part Fields. 1989. @@ -330,13 +333,13 @@ Double_t TRestAxionField::GammaTransmissionProbability(std::vector Bma /// /// The returned value is given for g_ag = 10^-10 GeV-1 /// -Double_t TRestAxionField::AxionAbsorptionProbability(Double_t Bmag, Double_t Lcoh, Double_t Ea, Double_t ma, +Double_t TRestAxionQCDField::AxionAbsorptionProbability(Double_t Bmag, Double_t Lcoh, Double_t Ea, Double_t ma, Double_t mg, Double_t absLength) { #ifndef USE_MPFR RESTWarning - << "MPFR libraries not linked to REST libraries. Try adding -DREST_MPFr=ON to your REST compilation" + << "MPFR libraries not linked to REST libraries. Try adding -DREST_MPFR=ON to your REST compilation" << RESTendl; - RESTWarning << "TRestAxionField::GammaTransmissionProbability will return 0" << RESTendl; + RESTWarning << "TRestAxionQCDField::AxionAbsorptionProbability will return 0" << RESTendl; return 0; #else mpfr::mpreal axionMass = ma; @@ -348,7 +351,7 @@ Double_t TRestAxionField::AxionAbsorptionProbability(Double_t Bmag, Double_t Lco if (fDebug) { RESTDebug << "+--------------------------------------------------------------------------+" << RESTendl; - RESTDebug << " TRestAxionField::GammaTransmissionProbability. Parameter summary" << RESTendl; + RESTDebug << " TRestAxionQCDField::GammaTransmissionProbability. Parameter summary" << RESTendl; RESTDebug << " Photon mass : " << photonMass << " eV" << RESTendl; RESTDebug << " Axion mass : " << ma << " eV" << RESTendl; RESTDebug << " Axion energy : " << Ea << " keV" << RESTendl; @@ -397,9 +400,11 @@ Double_t TRestAxionField::AxionAbsorptionProbability(Double_t Bmag, Double_t Lco #endif } -/// Commented because it uses ComplexReal structure that is moved to TRestAxionFieldPropagationProcess class +*/ + +/// Commented because it uses ComplexReal structure that is moved to TRestAxionQCDFieldPropagationProcess class /* -void TRestAxionField::PropagateAxion(Double_t Bmag, Double_t Lcoh, Double_t Ea, Double_t ma, +void TRestAxionQCDField::PropagateAxion(Double_t Bmag, Double_t Lcoh, Double_t Ea, Double_t ma, Double_t mg, Double_t absLength) { mpfr::mpreal axionMass = ma; mpfr::mpreal cohLength = Lcoh / 1000.; // Default REST units are mm; @@ -409,7 +414,7 @@ void TRestAxionField::PropagateAxion(Double_t Bmag, Double_t Lcoh, Double_t Ea, if (fDebug) { RESTDebug << "+--------------------------------------------------------------------------+" << -RESTendl; RESTDebug << " TRestAxionField::GammaTransmissionProbability. Parameter summary" << +RESTendl; RESTDebug << " TRestAxionQCDField::GammaTransmissionProbability. Parameter summary" << RESTendl; RESTDebug << " Photon mass : " << photonMass << " eV" << RESTendl; RESTDebug << " Axion mass : " << ma << " eV" << RESTendl; RESTDebug << " Axion energy : " << Ea << " keV" << RESTendl; RESTDebug << " Lcoh : " << Lcoh << " mm" << RESTendl; RESTDebug << " Bmag : " << Bmag << " T" << RESTendl; RESTDebug << From 3e3b9358ea7a73ee2b4ee2cb91caf1b83045b851 Mon Sep 17 00:00:00 2001 From: tomasoshea Date: Wed, 27 Sep 2023 10:51:33 +0200 Subject: [PATCH 39/48] continued work on HP field --- inc/TRestAxionFieldPropagationProcess.h | 4 ++-- inc/TRestAxionHiddenPhotonField.h | 9 ++++---- inc/TRestAxionLikelihood.h | 4 ++-- src/TRestAxionFieldPropagationProcess.cxx | 2 +- src/TRestAxionHiddenPhotonField.cxx | 27 ++++++++++++++++------- src/TRestAxionLikelihood.cxx | 2 +- src/TRestAxionQCDField.cxx | 4 ++-- 7 files changed, 32 insertions(+), 20 deletions(-) diff --git a/inc/TRestAxionFieldPropagationProcess.h b/inc/TRestAxionFieldPropagationProcess.h index c12e3ac8..89461739 100644 --- a/inc/TRestAxionFieldPropagationProcess.h +++ b/inc/TRestAxionFieldPropagationProcess.h @@ -25,7 +25,7 @@ #include "TRestAxionEvent.h" #include "TRestAxionEventProcess.h" -#include "TRestAxionField.h" +#include "TRestAxionQCDField.h" #include "TRestAxionMagneticField.h" #include "TRestPhysics.h" #include "TVector3.h" @@ -44,7 +44,7 @@ class TRestAxionFieldPropagationProcess : public TRestAxionEventProcess { TRestAxionMagneticField* fMagneticField = nullptr; //! /// A pointer to TRestAxionField that implements probability calculations - TRestAxionField* fAxionField = nullptr; //! + TRestAxionQCDField* fAxionField = nullptr; //! /// A pointer to TRestBufferGas given to TRestAxionField to perform calculations in a particular gas TRestAxionBufferGas* fBufferGas = nullptr; //! diff --git a/inc/TRestAxionHiddenPhotonField.h b/inc/TRestAxionHiddenPhotonField.h index 9ea444ed..e910c7bd 100644 --- a/inc/TRestAxionHiddenPhotonField.h +++ b/inc/TRestAxionHiddenPhotonField.h @@ -36,10 +36,11 @@ class TRestAxionHiddenPhotonField : public TObject { TRestAxionBufferGas* fBufferGas = NULL; //! public: - /// momentum difference q, useful in all calculations - Double_t TRestAxionHiddenPhotonField::momentumTransfer( Double_t Ea, Double_t ma, Double_t mg ) { - return sqrt(Ea*Ea - mg*mg) - sqrt(Ea*Ea - ma*ma); - } + /// momentum difference q + Double_t momentumTransfer( Double_t Ea, Double_t ma, Double_t mg ); + + /// vacuum conversion probability + Double_t VacuumConversion(Double_t Lcoh, Double_t Ea, Double_t ma); /// It enables/disables debug mode void SetDebug(Bool_t v) { fDebug = v; } diff --git a/inc/TRestAxionLikelihood.h b/inc/TRestAxionLikelihood.h index 055bb819..5ed94db8 100644 --- a/inc/TRestAxionLikelihood.h +++ b/inc/TRestAxionLikelihood.h @@ -27,7 +27,7 @@ #include "TRandom3.h" #include "TRestAxionBufferGas.h" -#include "TRestAxionField.h" +#include "TRestAxionQCDField.h" #include "TRestAxionSolarModel.h" #include "TRestAxionSpectrum.h" @@ -62,7 +62,7 @@ class TRestAxionLikelihood : public TRestMetadata { Double_t fLastStepDensity = 0.; //-> - TRestAxionField* fAxionField; //! + TRestAxionQCDField* fAxionField; //! TRestAxionBufferGas* fBufferGas; //! TRestAxionSpectrum* fAxionSpectrum; //! diff --git a/src/TRestAxionFieldPropagationProcess.cxx b/src/TRestAxionFieldPropagationProcess.cxx index e7de98b3..03021654 100644 --- a/src/TRestAxionFieldPropagationProcess.cxx +++ b/src/TRestAxionFieldPropagationProcess.cxx @@ -171,7 +171,7 @@ void TRestAxionFieldPropagationProcess::InitProcess() { } if (!fAxionField) { - fAxionField = new TRestAxionField(); + fAxionField = new TRestAxionQCDField(); fBufferGas = (TRestAxionBufferGas*)this->GetMetadata("TRestAxionBufferGas"); if (fBufferGas) diff --git a/src/TRestAxionHiddenPhotonField.cxx b/src/TRestAxionHiddenPhotonField.cxx index 8236136b..17261911 100644 --- a/src/TRestAxionHiddenPhotonField.cxx +++ b/src/TRestAxionHiddenPhotonField.cxx @@ -87,14 +87,25 @@ void TRestAxionHiddenPhotonField::Initialize() { /// MOVED TO TRestAxionHiddenPhotonFieldPropagationProcess class /// faxion = SetComplexReal(1, 0); /// fAem = SetComplexReal(0, 0); + } + + +/////////////////////////////////////////////// +/// momentum difference q in eV, useful in all calculations +/// Ea in keV, ma in eV, mg in eV +Double_t TRestAxionHiddenPhotonField::momentumTransfer( Double_t Ea, Double_t ma, Double_t mg ) { + Ea *= 1000; // [eV] Ea is given in keV + return sqrt(Ea*Ea - mg*mg) - sqrt(Ea*Ea - ma*ma); //[eV] } /////////////////////////////////////////////// /// vacuum conversion probability /// ie. when photonMass = 0 +/// Ea in keV, ma in eV, Lcoh in mm Double_t TRestAxionHiddenPhotonField::VacuumConversion(Double_t Lcoh, Double_t Ea, Double_t ma) { - Double_t q = momentumTransfer(Ea, ma, 0.); + Lcoh *= REST_Physics::PhMeterIneV / 1000; // [eV-1] + Double_t q = momentumTransfer(Ea, ma, 0.); // [eV] return pow(2*sin(q*Lcoh/2), 2); } @@ -120,10 +131,10 @@ Double_t TRestAxionHiddenPhotonField::GammaTransmissionProbability(Double_t Lcoh RESTWarning << "TRestAxionHiddenPhotonField::GammaTransmissionProbability will return 0" << RESTendl; return 0; #else - mpfr::mpreal hiddenPhotonMass = ma; - mpfr::mpreal cohLength = Lcoh / 1000.; // Default REST units are mm; + mpfr::mpreal hiddenPhotonMass = ma; // [eV] + mpfr::mpreal cohLength = Lcoh / 1000.; // [m] Default REST units are mm - mpfr::mpreal photonMass = mg; + mpfr::mpreal photonMass = mg; // [eV] if (mg == 0 && fBufferGas) photonMass = fBufferGas->GetPhotonMass(Ea); @@ -133,12 +144,11 @@ Double_t TRestAxionHiddenPhotonField::GammaTransmissionProbability(Double_t Lcoh RESTDebug << " Hidden photon mass : " << ma << " eV" << RESTendl; RESTDebug << " Hidden photon energy : " << Ea << " keV" << RESTendl; RESTDebug << " Lcoh : " << Lcoh << " mm" << RESTendl; - RESTDebug << " Bmag : " << Bmag << " T" << RESTendl; RESTDebug << "+--------------------------------------------------------------------------+" << RESTendl; if (photonMass == 0.0) return VacuumConversion(Lcoh, Ea, ma); - mpfr::mpreal q = momentumTransfer(Ea, ma, mg) // eV + mpfr::mpreal q = momentumTransfer(Ea, ma, mg); // eV mpfr::mpreal l = cohLength * REST_Physics::PhMeterIneV; // eV-1 mpfr::mpreal Gamma = absLength; // cm-1 @@ -152,7 +162,7 @@ Double_t TRestAxionHiddenPhotonField::GammaTransmissionProbability(Double_t Lcoh RESTDebug << " q : " << q << " eV" << RESTendl; RESTDebug << " l : " << l << " eV-1" << RESTendl; RESTDebug << " ql : " << q*l << RESTendl; - RESTDebug << "Gamma : " << Gamma << RESTendl; + RESTDebug << "Gamma : " << Gamma << " eV" << RESTendl; RESTDebug << "GammaL : " << GammaL << RESTendl; RESTDebug << "+------------------------+" << RESTendl; } @@ -176,7 +186,7 @@ Double_t TRestAxionHiddenPhotonField::GammaTransmissionProbability(Double_t Lcoh } - +/* /////////////////////////////////////////////// /// \brief Performs the calculation of the photon absorbtion probability in the buffer gas. /// @@ -253,6 +263,7 @@ Double_t TRestAxionHiddenPhotonField::AxionAbsorptionProbability(Double_t Bmag, return sol; #endif } +*/ /// Commented because it uses ComplexReal structure that is moved to TRestAxionHiddenPhotonFieldPropagationProcess class /* diff --git a/src/TRestAxionLikelihood.cxx b/src/TRestAxionLikelihood.cxx index f5d26c17..4f9b9e74 100644 --- a/src/TRestAxionLikelihood.cxx +++ b/src/TRestAxionLikelihood.cxx @@ -84,7 +84,7 @@ void TRestAxionLikelihood::Initialize() { fBufferGas = new TRestAxionBufferGas(); // Conversion probabilities as defined by van Bibber paper - fAxionField = new TRestAxionField(); + fAxionField = new TRestAxionQCDField(); fAxionField->AssignBufferGas(fBufferGas); diff --git a/src/TRestAxionQCDField.cxx b/src/TRestAxionQCDField.cxx index 744c5e4d..30d06e2f 100644 --- a/src/TRestAxionQCDField.cxx +++ b/src/TRestAxionQCDField.cxx @@ -319,7 +319,7 @@ Double_t TRestAxionQCDField::GammaTransmissionProbability(std::vector #endif } -/* + /////////////////////////////////////////////// /// \brief Performs the calculation of axion-photon absorption probability using directly /// equation (18) from van Bibber, Phys Rev D Part Fields. 1989. @@ -400,7 +400,7 @@ Double_t TRestAxionQCDField::AxionAbsorptionProbability(Double_t Bmag, Double_t #endif } -*/ + /// Commented because it uses ComplexReal structure that is moved to TRestAxionQCDFieldPropagationProcess class /* From d9b1946b0c42f0cc89f354b6538d496ffc328e65 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 27 Sep 2023 08:58:18 +0000 Subject: [PATCH 40/48] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- inc/TRestAxionFieldPropagationProcess.h | 2 +- inc/TRestAxionHiddenPhotonField.h | 16 +++--- inc/TRestAxionLikelihood.h | 2 +- src/TRestAxionHiddenPhotonField.cxx | 65 +++++++++++-------------- src/TRestAxionQCDField.cxx | 18 +++---- src/TRestAxionSolarHiddenPhotonFlux.cxx | 4 +- 6 files changed, 48 insertions(+), 59 deletions(-) diff --git a/inc/TRestAxionFieldPropagationProcess.h b/inc/TRestAxionFieldPropagationProcess.h index 89461739..8313bf50 100644 --- a/inc/TRestAxionFieldPropagationProcess.h +++ b/inc/TRestAxionFieldPropagationProcess.h @@ -25,8 +25,8 @@ #include "TRestAxionEvent.h" #include "TRestAxionEventProcess.h" -#include "TRestAxionQCDField.h" #include "TRestAxionMagneticField.h" +#include "TRestAxionQCDField.h" #include "TRestPhysics.h" #include "TVector3.h" #include "TVectorD.h" diff --git a/inc/TRestAxionHiddenPhotonField.h b/inc/TRestAxionHiddenPhotonField.h index e910c7bd..0db3630e 100644 --- a/inc/TRestAxionHiddenPhotonField.h +++ b/inc/TRestAxionHiddenPhotonField.h @@ -36,11 +36,11 @@ class TRestAxionHiddenPhotonField : public TObject { TRestAxionBufferGas* fBufferGas = NULL; //! public: - /// momentum difference q - Double_t momentumTransfer( Double_t Ea, Double_t ma, Double_t mg ); + /// momentum difference q + Double_t momentumTransfer(Double_t Ea, Double_t ma, Double_t mg); - /// vacuum conversion probability - Double_t VacuumConversion(Double_t Lcoh, Double_t Ea, Double_t ma); + /// vacuum conversion probability + Double_t VacuumConversion(Double_t Lcoh, Double_t Ea, Double_t ma); /// It enables/disables debug mode void SetDebug(Bool_t v) { fDebug = v; } @@ -51,11 +51,11 @@ class TRestAxionHiddenPhotonField : public TObject { /// It assigns a gas buffer medium to the calculation void SetBufferGas(TRestAxionBufferGas* buffGas) { fBufferGas = buffGas; } - Double_t GammaTransmissionProbability(Double_t Lcoh, Double_t Ea, Double_t ma, - Double_t mg = 0, Double_t absLength = 0); + Double_t GammaTransmissionProbability(Double_t Lcoh, Double_t Ea, Double_t ma, Double_t mg = 0, + Double_t absLength = 0); - //Double_t PhotonAbsorptionProbability(Double_t Lcoh, Double_t Ea, Double_t ma, - // Double_t mg = 0, Double_t absLength = 0); + // Double_t PhotonAbsorptionProbability(Double_t Lcoh, Double_t Ea, Double_t ma, + // Double_t mg = 0, Double_t absLength = 0); TRestAxionHiddenPhotonField(); ~TRestAxionHiddenPhotonField(); diff --git a/inc/TRestAxionLikelihood.h b/inc/TRestAxionLikelihood.h index 5ed94db8..a542d1c9 100644 --- a/inc/TRestAxionLikelihood.h +++ b/inc/TRestAxionLikelihood.h @@ -62,7 +62,7 @@ class TRestAxionLikelihood : public TRestMetadata { Double_t fLastStepDensity = 0.; //-> - TRestAxionQCDField* fAxionField; //! + TRestAxionQCDField* fAxionField; //! TRestAxionBufferGas* fBufferGas; //! TRestAxionSpectrum* fAxionSpectrum; //! diff --git a/src/TRestAxionHiddenPhotonField.cxx b/src/TRestAxionHiddenPhotonField.cxx index 17261911..7c0d9560 100644 --- a/src/TRestAxionHiddenPhotonField.cxx +++ b/src/TRestAxionHiddenPhotonField.cxx @@ -87,30 +87,26 @@ void TRestAxionHiddenPhotonField::Initialize() { /// MOVED TO TRestAxionHiddenPhotonFieldPropagationProcess class /// faxion = SetComplexReal(1, 0); /// fAem = SetComplexReal(0, 0); - } - +} /////////////////////////////////////////////// /// momentum difference q in eV, useful in all calculations /// Ea in keV, ma in eV, mg in eV -Double_t TRestAxionHiddenPhotonField::momentumTransfer( Double_t Ea, Double_t ma, Double_t mg ) { - Ea *= 1000; // [eV] Ea is given in keV - return sqrt(Ea*Ea - mg*mg) - sqrt(Ea*Ea - ma*ma); //[eV] +Double_t TRestAxionHiddenPhotonField::momentumTransfer(Double_t Ea, Double_t ma, Double_t mg) { + Ea *= 1000; // [eV] Ea is given in keV + return sqrt(Ea * Ea - mg * mg) - sqrt(Ea * Ea - ma * ma); //[eV] } - /////////////////////////////////////////////// /// vacuum conversion probability /// ie. when photonMass = 0 /// Ea in keV, ma in eV, Lcoh in mm Double_t TRestAxionHiddenPhotonField::VacuumConversion(Double_t Lcoh, Double_t Ea, Double_t ma) { - Lcoh *= REST_Physics::PhMeterIneV / 1000; // [eV-1] - Double_t q = momentumTransfer(Ea, ma, 0.); // [eV] - return pow(2*sin(q*Lcoh/2), 2); + Lcoh *= REST_Physics::PhMeterIneV / 1000; // [eV-1] + Double_t q = momentumTransfer(Ea, ma, 0.); // [eV] + return pow(2 * sin(q * Lcoh / 2), 2); } - - /////////////////////////////////////////////// /// \brief Performs the calculation of hidden photon - photon conversion probability. /// @@ -123,7 +119,7 @@ Double_t TRestAxionHiddenPhotonField::VacuumConversion(Double_t Lcoh, Double_t E /// The returned value is given for chi = 1 /// Double_t TRestAxionHiddenPhotonField::GammaTransmissionProbability(Double_t Lcoh, Double_t Ea, Double_t ma, - Double_t mg, Double_t absLength) { + Double_t mg, Double_t absLength) { #ifndef USE_MPFR RESTWarning << "MPFR libraries not linked to REST libraries. Try adding -DREST_MPFR=ON to your REST compilation" @@ -131,10 +127,10 @@ Double_t TRestAxionHiddenPhotonField::GammaTransmissionProbability(Double_t Lcoh RESTWarning << "TRestAxionHiddenPhotonField::GammaTransmissionProbability will return 0" << RESTendl; return 0; #else - mpfr::mpreal hiddenPhotonMass = ma; // [eV] + mpfr::mpreal hiddenPhotonMass = ma; // [eV] mpfr::mpreal cohLength = Lcoh / 1000.; // [m] Default REST units are mm - mpfr::mpreal photonMass = mg; // [eV] + mpfr::mpreal photonMass = mg; // [eV] if (mg == 0 && fBufferGas) photonMass = fBufferGas->GetPhotonMass(Ea); @@ -148,36 +144,35 @@ Double_t TRestAxionHiddenPhotonField::GammaTransmissionProbability(Double_t Lcoh if (photonMass == 0.0) return VacuumConversion(Lcoh, Ea, ma); - mpfr::mpreal q = momentumTransfer(Ea, ma, mg); // eV - mpfr::mpreal l = cohLength * REST_Physics::PhMeterIneV; // eV-1 + mpfr::mpreal q = momentumTransfer(Ea, ma, mg); // eV + mpfr::mpreal l = cohLength * REST_Physics::PhMeterIneV; // eV-1 - mpfr::mpreal Gamma = absLength; // cm-1 + mpfr::mpreal Gamma = absLength; // cm-1 if (absLength == 0 && fBufferGas) Gamma = fBufferGas->GetPhotonAbsorptionLength(Ea); // cm-1 mpfr::mpreal GammaL = Gamma * cohLength * 100; - Gamma *= 100 / REST_Physics::PhMeterIneV; // eV + Gamma *= 100 / REST_Physics::PhMeterIneV; // eV if (fDebug) { RESTDebug << "+------------------------+" << RESTendl; RESTDebug << " Intermediate calculations" << RESTendl; RESTDebug << " q : " << q << " eV" << RESTendl; RESTDebug << " l : " << l << " eV-1" << RESTendl; - RESTDebug << " ql : " << q*l << RESTendl; + RESTDebug << " ql : " << q * l << RESTendl; RESTDebug << "Gamma : " << Gamma << " eV" << RESTendl; RESTDebug << "GammaL : " << GammaL << RESTendl; RESTDebug << "+------------------------+" << RESTendl; } - mpfr::mpreal MFactor = pow(ma,4)/(pow(ma*ma - mg*mg, 2) + pow(Ea*Gamma, 2)); // all should be in eV - + mpfr::mpreal MFactor = + pow(ma, 4) / (pow(ma * ma - mg * mg, 2) + pow(Ea * Gamma, 2)); // all should be in eV if (fDebug) { RESTDebug << "Mfactor : " << MFactor << RESTendl; - RESTDebug << "cos(ql) : " << cos(q*l) << RESTendl; + RESTDebug << "cos(ql) : " << cos(q * l) << RESTendl; RESTDebug << "Exp(-GammaL) : " << exp(-GammaL) << RESTendl; } - double sol = - (double)(MFactor * (1 + exp(-GammaL) - 2 * exp(-GammaL / 2) * cos(q*l))); + double sol = (double)(MFactor * (1 + exp(-GammaL) - 2 * exp(-GammaL / 2) * cos(q * l))); RESTDebug << "Axion-photon transmission probability : " << sol << RESTendl; @@ -185,7 +180,6 @@ Double_t TRestAxionHiddenPhotonField::GammaTransmissionProbability(Double_t Lcoh #endif } - /* /////////////////////////////////////////////// /// \brief Performs the calculation of the photon absorbtion probability in the buffer gas. @@ -197,10 +191,8 @@ Double_t TRestAxionHiddenPhotonField::GammaTransmissionProbability(Double_t Lcoh /// /// The returned value is given for chi = 1 /// -Double_t TRestAxionHiddenPhotonField::AxionAbsorptionProbability(Double_t Bmag, Double_t Lcoh, Double_t Ea, Double_t ma, - Double_t mg, Double_t absLength) { -#ifndef USE_MPFR - RESTWarning +Double_t TRestAxionHiddenPhotonField::AxionAbsorptionProbability(Double_t Bmag, Double_t Lcoh, Double_t Ea, +Double_t ma, Double_t mg, Double_t absLength) { #ifndef USE_MPFR RESTWarning << "MPFR libraries not linked to REST libraries. Try adding -DREST_MPFr=ON to your REST compilation" << RESTendl; RESTWarning << "TRestAxionHiddenPhotonField::GammaTransmissionProbability will return 0" << RESTendl; @@ -215,13 +207,11 @@ Double_t TRestAxionHiddenPhotonField::AxionAbsorptionProbability(Double_t Bmag, if (fDebug) { RESTDebug << "+--------------------------------------------------------------------------+" << RESTendl; - RESTDebug << " TRestAxionHiddenPhotonField::GammaTransmissionProbability. Parameter summary" << RESTendl; - RESTDebug << " Photon mass : " << photonMass << " eV" << RESTendl; - RESTDebug << " Axion mass : " << ma << " eV" << RESTendl; - RESTDebug << " Axion energy : " << Ea << " keV" << RESTendl; - RESTDebug << " Lcoh : " << Lcoh << " mm" << RESTendl; - RESTDebug << " Bmag : " << Bmag << " T" << RESTendl; - RESTDebug << "+--------------------------------------------------------------------------+" + RESTDebug << " TRestAxionHiddenPhotonField::GammaTransmissionProbability. Parameter summary" << +RESTendl; RESTDebug << " Photon mass : " << photonMass << " eV" << RESTendl; RESTDebug << " Axion mass : " << +ma << " eV" << RESTendl; RESTDebug << " Axion energy : " << Ea << " keV" << RESTendl; RESTDebug << " Lcoh : " +<< Lcoh << " mm" << RESTendl; RESTDebug << " Bmag : " << Bmag << " T" << RESTendl; RESTDebug << +"+--------------------------------------------------------------------------+" << RESTendl; } @@ -265,7 +255,8 @@ Double_t TRestAxionHiddenPhotonField::AxionAbsorptionProbability(Double_t Bmag, } */ -/// Commented because it uses ComplexReal structure that is moved to TRestAxionHiddenPhotonFieldPropagationProcess class +/// Commented because it uses ComplexReal structure that is moved to +/// TRestAxionHiddenPhotonFieldPropagationProcess class /* void TRestAxionHiddenPhotonField::PropagateAxion(Double_t Bmag, Double_t Lcoh, Double_t Ea, Double_t ma, Double_t mg, Double_t absLength) { diff --git a/src/TRestAxionQCDField.cxx b/src/TRestAxionQCDField.cxx index 30d06e2f..b77f2886 100644 --- a/src/TRestAxionQCDField.cxx +++ b/src/TRestAxionQCDField.cxx @@ -136,8 +136,8 @@ double TRestAxionQCDField::BLHalfSquared(Double_t Bmag, Double_t Lcoh) // (BL/2 /// /// The returned value is given for g_ag = 10^-10 GeV-1 /// -Double_t TRestAxionQCDField::GammaTransmissionProbability(Double_t Bmag, Double_t Lcoh, Double_t Ea, Double_t ma, - Double_t mg, Double_t absLength) { +Double_t TRestAxionQCDField::GammaTransmissionProbability(Double_t Bmag, Double_t Lcoh, Double_t Ea, + Double_t ma, Double_t mg, Double_t absLength) { #ifndef USE_MPFR RESTWarning << "MPFR libraries not linked to REST libraries. Try adding -DREST_MPFR=ON to your REST compilation" @@ -221,8 +221,8 @@ Double_t TRestAxionQCDField::GammaTransmissionProbability(Double_t Bmag, Double_ /// Gamma is not constant and \integral{q(z)} is integrated at each step. /// Double_t TRestAxionQCDField::GammaTransmissionProbability(std::vector Bmag, Double_t deltaL, - Double_t Ea, Double_t ma, Double_t mg, - Double_t absLength) { + Double_t Ea, Double_t ma, Double_t mg, + Double_t absLength) { #ifndef USE_MPFR RESTWarning << "MPFR libraries not linked to REST libraries. Try adding -DREST_MPFR=ON to your REST compilation" @@ -319,7 +319,6 @@ Double_t TRestAxionQCDField::GammaTransmissionProbability(std::vector #endif } - /////////////////////////////////////////////// /// \brief Performs the calculation of axion-photon absorption probability using directly /// equation (18) from van Bibber, Phys Rev D Part Fields. 1989. @@ -333,8 +332,8 @@ Double_t TRestAxionQCDField::GammaTransmissionProbability(std::vector /// /// The returned value is given for g_ag = 10^-10 GeV-1 /// -Double_t TRestAxionQCDField::AxionAbsorptionProbability(Double_t Bmag, Double_t Lcoh, Double_t Ea, Double_t ma, - Double_t mg, Double_t absLength) { +Double_t TRestAxionQCDField::AxionAbsorptionProbability(Double_t Bmag, Double_t Lcoh, Double_t Ea, + Double_t ma, Double_t mg, Double_t absLength) { #ifndef USE_MPFR RESTWarning << "MPFR libraries not linked to REST libraries. Try adding -DREST_MPFR=ON to your REST compilation" @@ -400,9 +399,8 @@ Double_t TRestAxionQCDField::AxionAbsorptionProbability(Double_t Bmag, Double_t #endif } - - -/// Commented because it uses ComplexReal structure that is moved to TRestAxionQCDFieldPropagationProcess class +/// Commented because it uses ComplexReal structure that is moved to TRestAxionQCDFieldPropagationProcess +/// class /* void TRestAxionQCDField::PropagateAxion(Double_t Bmag, Double_t Lcoh, Double_t Ea, Double_t ma, Double_t mg, Double_t absLength) { diff --git a/src/TRestAxionSolarHiddenPhotonFlux.cxx b/src/TRestAxionSolarHiddenPhotonFlux.cxx index 87b3360b..b0a234bf 100644 --- a/src/TRestAxionSolarHiddenPhotonFlux.cxx +++ b/src/TRestAxionSolarHiddenPhotonFlux.cxx @@ -389,8 +389,8 @@ void TRestAxionSolarHiddenPhotonFlux::CalculateSolarFlux() { TH1D* h = (TH1D*)fWidthTable[n]->Clone(); // wG h->Multiply(fContinuumTable[n]); // wG * flux h->Divide(hMass); // wG * flux / ( (m2 - wp2)^2 + (w G)^2 ) - // h->Scale(pow(mass, 4)); // m4 * wG * flux / ( (m2 - wp2)^2 + (w - // G)^2 + // h->Scale(pow(mass, 4)); // m4 * wG * flux / ( (m2 - wp2)^2 + + // (w G)^2 // ) fFluxTable.push_back(h); From 60274a150e904cf69f375e3662be648facb42711 Mon Sep 17 00:00:00 2001 From: tomasoshea Date: Wed, 27 Sep 2023 11:07:37 +0200 Subject: [PATCH 41/48] moved images --- flux.png | Bin 32743 -> 0 bytes .../SolarHiddenPhotonFlux/flux0.001.png | Bin .../SolarHiddenPhotonFlux/flux0.01.png | Bin .../SolarHiddenPhotonFlux/flux0.1.png | Bin .../SolarHiddenPhotonFlux/flux1.png | Bin .../SolarHiddenPhotonFlux/flux10.png | Bin .../SolarHiddenPhotonFlux/flux100.png | Bin .../SolarHiddenPhotonFlux/flux1000.png | Bin .../SolarHiddenPhotonFlux/flux20.png | Bin .../SolarHiddenPhotonFlux/flux30.png | Bin .../SolarHiddenPhotonFlux/flux50.png | Bin 11 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 flux.png rename flux0.001.png => images/SolarHiddenPhotonFlux/flux0.001.png (100%) rename flux0.01.png => images/SolarHiddenPhotonFlux/flux0.01.png (100%) rename flux0.1.png => images/SolarHiddenPhotonFlux/flux0.1.png (100%) rename flux1.png => images/SolarHiddenPhotonFlux/flux1.png (100%) rename flux10.png => images/SolarHiddenPhotonFlux/flux10.png (100%) rename flux100.png => images/SolarHiddenPhotonFlux/flux100.png (100%) rename flux1000.png => images/SolarHiddenPhotonFlux/flux1000.png (100%) rename flux20.png => images/SolarHiddenPhotonFlux/flux20.png (100%) rename flux30.png => images/SolarHiddenPhotonFlux/flux30.png (100%) rename flux50.png => images/SolarHiddenPhotonFlux/flux50.png (100%) diff --git a/flux.png b/flux.png deleted file mode 100644 index e2df6fc81dba562dbe32ffc5fa4ebd5830d9192f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 32743 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 W0|B}6nSi$uNI^ygQX*yY`TqmsV$ Date: Wed, 27 Sep 2023 09:08:25 +0000 Subject: [PATCH 42/48] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- src/TRestAxionSolarHiddenPhotonFlux.cxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/TRestAxionSolarHiddenPhotonFlux.cxx b/src/TRestAxionSolarHiddenPhotonFlux.cxx index b0a234bf..178f4cb5 100644 --- a/src/TRestAxionSolarHiddenPhotonFlux.cxx +++ b/src/TRestAxionSolarHiddenPhotonFlux.cxx @@ -389,8 +389,8 @@ void TRestAxionSolarHiddenPhotonFlux::CalculateSolarFlux() { TH1D* h = (TH1D*)fWidthTable[n]->Clone(); // wG h->Multiply(fContinuumTable[n]); // wG * flux h->Divide(hMass); // wG * flux / ( (m2 - wp2)^2 + (w G)^2 ) - // h->Scale(pow(mass, 4)); // m4 * wG * flux / ( (m2 - wp2)^2 + - // (w G)^2 + // h->Scale(pow(mass, 4)); // m4 * wG * flux / ( (m2 - wp2)^2 + // + (w G)^2 // ) fFluxTable.push_back(h); From 4ee82fc3e3ae009f445db5833c2a325957c68947 Mon Sep 17 00:00:00 2001 From: Javier Galan Date: Tue, 3 Oct 2023 08:36:05 +0200 Subject: [PATCH 43/48] Update src/TRestAxionSolarHiddenPhotonFlux.cxx MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Juan Antonio GarcĂ­a <80903717+juanangp@users.noreply.github.com> --- src/TRestAxionSolarHiddenPhotonFlux.cxx | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/TRestAxionSolarHiddenPhotonFlux.cxx b/src/TRestAxionSolarHiddenPhotonFlux.cxx index 178f4cb5..7884b94d 100644 --- a/src/TRestAxionSolarHiddenPhotonFlux.cxx +++ b/src/TRestAxionSolarHiddenPhotonFlux.cxx @@ -389,10 +389,9 @@ void TRestAxionSolarHiddenPhotonFlux::CalculateSolarFlux() { TH1D* h = (TH1D*)fWidthTable[n]->Clone(); // wG h->Multiply(fContinuumTable[n]); // wG * flux h->Divide(hMass); // wG * flux / ( (m2 - wp2)^2 + (w G)^2 ) - // h->Scale(pow(mass, 4)); // m4 * wG * flux / ( (m2 - wp2)^2 - // + (w G)^2 - // ) - + + // m4 * wG * flux / ( (m2 - wp2)^2 + (w G)^2) + // h->Scale(pow(mass, 4)); fFluxTable.push_back(h); } } From 1e9d52f5fafb448cd4cdef1e63db2696929fd6a6 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 3 Oct 2023 06:36:14 +0000 Subject: [PATCH 44/48] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- src/TRestAxionSolarHiddenPhotonFlux.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/TRestAxionSolarHiddenPhotonFlux.cxx b/src/TRestAxionSolarHiddenPhotonFlux.cxx index 7884b94d..66ffa0ec 100644 --- a/src/TRestAxionSolarHiddenPhotonFlux.cxx +++ b/src/TRestAxionSolarHiddenPhotonFlux.cxx @@ -389,7 +389,7 @@ void TRestAxionSolarHiddenPhotonFlux::CalculateSolarFlux() { TH1D* h = (TH1D*)fWidthTable[n]->Clone(); // wG h->Multiply(fContinuumTable[n]); // wG * flux h->Divide(hMass); // wG * flux / ( (m2 - wp2)^2 + (w G)^2 ) - + // m4 * wG * flux / ( (m2 - wp2)^2 + (w G)^2) // h->Scale(pow(mass, 4)); fFluxTable.push_back(h); From 3bb32600a25e74957a6b613969f1245a0b0091f5 Mon Sep 17 00:00:00 2001 From: Javier Galan Date: Sun, 21 Jan 2024 13:52:51 +0100 Subject: [PATCH 45/48] TRestAxionQCDField fixing conflicts --- src/TRestAxionQCDField.cxx | 31 +++---------------------------- 1 file changed, 3 insertions(+), 28 deletions(-) diff --git a/src/TRestAxionQCDField.cxx b/src/TRestAxionQCDField.cxx index c2ce782f..af766fe3 100644 --- a/src/TRestAxionQCDField.cxx +++ b/src/TRestAxionQCDField.cxx @@ -344,12 +344,7 @@ Double_t TRestAxionQCDField::GammaTransmissionProbability(std::vector /// /// The returned value is given for g_ag = 10^-10 GeV-1 /// -<<<<<<< HEAD:src/TRestAxionQCDField.cxx -Double_t TRestAxionQCDField::AxionAbsorptionProbability(Double_t Bmag, Double_t Lcoh, Double_t Ea, - Double_t ma, Double_t mg, Double_t absLength) { -======= -Double_t TRestAxionField::AxionAbsorptionProbability(Double_t ma, Double_t mg, Double_t absLength) { ->>>>>>> master:src/TRestAxionField.cxx +Double_t TRestAxionQCDField::AxionAbsorptionProbability(Double_t ma, Double_t mg, Double_t absLength) { #ifndef USE_MPFR RESTWarning << "MPFR libraries not linked to REST libraries. Try adding -DREST_MPFR=ON to your REST compilation" @@ -415,38 +410,19 @@ Double_t TRestAxionField::AxionAbsorptionProbability(Double_t ma, Double_t mg, D #endif } -<<<<<<< HEAD:src/TRestAxionQCDField.cxx -/// Commented because it uses ComplexReal structure that is moved to TRestAxionQCDFieldPropagationProcess -/// class -/* -void TRestAxionQCDField::PropagateAxion(Double_t Bmag, Double_t Lcoh, Double_t Ea, Double_t ma, - Double_t mg, Double_t absLength) { - mpfr::mpreal axionMass = ma; - mpfr::mpreal cohLength = Lcoh / 1000.; // Default REST units are mm; -======= /////////////////////////////////////////////// /// \brief On top of calculating the axion absorption probability it will assign new values /// for the magnetic field (Bmag/T), coherence length (Lcoh/mm) and axion energy (Ea/keV). /// -Double_t TRestAxionField::AxionAbsorptionProbability(Double_t Bmag, Double_t Lcoh, Double_t Ea, Double_t ma, +Double_t TRestAxionQCDField::AxionAbsorptionProbability(Double_t Bmag, Double_t Lcoh, Double_t Ea, Double_t ma, Double_t mg, Double_t absLength) { fBmag = Bmag; fLcoh = Lcoh; fEa = Ea; ->>>>>>> master:src/TRestAxionField.cxx return AxionAbsorptionProbability(ma, mg, absLength); } -<<<<<<< HEAD:src/TRestAxionQCDField.cxx - if (fDebug) { - RESTDebug << "+--------------------------------------------------------------------------+" << -RESTendl; RESTDebug << " TRestAxionQCDField::GammaTransmissionProbability. Parameter summary" << -RESTendl; RESTDebug << " Photon mass : " << photonMass << " eV" << RESTendl; RESTDebug << " Axion mass : " << -ma << " eV" << RESTendl; RESTDebug << " Axion energy : " << Ea << " keV" << RESTendl; RESTDebug << " Lcoh : " -<< Lcoh << " mm" << RESTendl; RESTDebug << " Bmag : " << Bmag << " T" << RESTendl; RESTDebug << -"+--------------------------------------------------------------------------+" << RESTendl; -======= /////////////////////////////////////////////// /// \brief Performs the calculation of the FWHM for the axion-photon conversion probability /// computed in `TRestAxionField::GammaTransmissionProbability`. @@ -459,7 +435,7 @@ ma << " eV" << RESTendl; RESTDebug << " Axion energy : " << Ea << " keV" << REST /// IMPORTANT: In the case that the buffer gas is not defined, this method will return the mass at which the /// probability reaches half of the maximum **vacuum** probability. /// -Double_t TRestAxionField::GammaTransmissionFWHM(Double_t step) { +Double_t TRestAxionQCDField::GammaTransmissionFWHM(Double_t step) { Double_t maxMass = 10; // 10eV is the maximum mass (exit condition) Double_t resonanceMass = 0; @@ -476,7 +452,6 @@ Double_t TRestAxionField::GammaTransmissionFWHM(Double_t step) { << RESTendl; return maxMass; } ->>>>>>> master:src/TRestAxionField.cxx } Double_t fwhm = scanMass - resonanceMass; From ca1961aff218d70cfd69f8bbc35c56c5f56ecf28 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sun, 21 Jan 2024 12:53:02 +0000 Subject: [PATCH 46/48] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- src/TRestAxionQCDField.cxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/TRestAxionQCDField.cxx b/src/TRestAxionQCDField.cxx index af766fe3..e83006cb 100644 --- a/src/TRestAxionQCDField.cxx +++ b/src/TRestAxionQCDField.cxx @@ -414,8 +414,8 @@ Double_t TRestAxionQCDField::AxionAbsorptionProbability(Double_t ma, Double_t mg /// \brief On top of calculating the axion absorption probability it will assign new values /// for the magnetic field (Bmag/T), coherence length (Lcoh/mm) and axion energy (Ea/keV). /// -Double_t TRestAxionQCDField::AxionAbsorptionProbability(Double_t Bmag, Double_t Lcoh, Double_t Ea, Double_t ma, - Double_t mg, Double_t absLength) { +Double_t TRestAxionQCDField::AxionAbsorptionProbability(Double_t Bmag, Double_t Lcoh, Double_t Ea, + Double_t ma, Double_t mg, Double_t absLength) { fBmag = Bmag; fLcoh = Lcoh; fEa = Ea; From 7205cecd4d32e901531bb3ce017ec0f0eb3ef596 Mon Sep 17 00:00:00 2001 From: Javier Galan Date: Sun, 21 Jan 2024 13:57:12 +0100 Subject: [PATCH 47/48] TRestAxionQCDField. Fixing compilation issues --- src/TRestAxionQCDField.cxx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/TRestAxionQCDField.cxx b/src/TRestAxionQCDField.cxx index e83006cb..72605e90 100644 --- a/src/TRestAxionQCDField.cxx +++ b/src/TRestAxionQCDField.cxx @@ -204,7 +204,7 @@ Double_t TRestAxionQCDField::GammaTransmissionProbability(Double_t ma, Double_t /// \brief On top of calculating the gamma transmission probability it will assign new values /// for the magnetic field (Bmag/T), coherence length (Lcoh/mm) and axion energy (Ea/keV). /// -Double_t TRestAxionField::GammaTransmissionProbability(Double_t Bmag, Double_t Lcoh, Double_t Ea, Double_t ma, +Double_t TRestAxionQCDField::GammaTransmissionProbability(Double_t Bmag, Double_t Lcoh, Double_t Ea, Double_t ma, Double_t mg, Double_t absLength) { fBmag = Bmag; fLcoh = Lcoh; @@ -483,7 +483,7 @@ Double_t TRestAxionQCDField::GammaTransmissionFWHM(Double_t step) { /// /// For additional info see PR: https://github.com/rest-for-physics/axionlib/pull/78 /// -std::vector> TRestAxionField::GetMassDensityScanning(std::string gasName, +std::vector> TRestAxionQCDField::GetMassDensityScanning(std::string gasName, double maMax, double rampDown) { std::vector> massDensityPairs; From b05d3f3e2b8b8bd013d2f449b9e886abd1763786 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sun, 21 Jan 2024 12:57:32 +0000 Subject: [PATCH 48/48] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- src/TRestAxionQCDField.cxx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/TRestAxionQCDField.cxx b/src/TRestAxionQCDField.cxx index 72605e90..6a5c5f3a 100644 --- a/src/TRestAxionQCDField.cxx +++ b/src/TRestAxionQCDField.cxx @@ -204,8 +204,8 @@ Double_t TRestAxionQCDField::GammaTransmissionProbability(Double_t ma, Double_t /// \brief On top of calculating the gamma transmission probability it will assign new values /// for the magnetic field (Bmag/T), coherence length (Lcoh/mm) and axion energy (Ea/keV). /// -Double_t TRestAxionQCDField::GammaTransmissionProbability(Double_t Bmag, Double_t Lcoh, Double_t Ea, Double_t ma, - Double_t mg, Double_t absLength) { +Double_t TRestAxionQCDField::GammaTransmissionProbability(Double_t Bmag, Double_t Lcoh, Double_t Ea, + Double_t ma, Double_t mg, Double_t absLength) { fBmag = Bmag; fLcoh = Lcoh; fEa = Ea; @@ -484,8 +484,8 @@ Double_t TRestAxionQCDField::GammaTransmissionFWHM(Double_t step) { /// For additional info see PR: https://github.com/rest-for-physics/axionlib/pull/78 /// std::vector> TRestAxionQCDField::GetMassDensityScanning(std::string gasName, - double maMax, - double rampDown) { + double maMax, + double rampDown) { std::vector> massDensityPairs; // Storing the gas pointer, if there was one