Skip to content

Commit

Permalink
Merge pull request #78 from rest-for-physics/fran_SCAN
Browse files Browse the repository at this point in the history
New methods added to AxionLib in order to obtain a SCAN of the axion masses
  • Loading branch information
francandon authored Dec 15, 2023
2 parents ffed4a0 + 9f0f8b8 commit e421bf2
Show file tree
Hide file tree
Showing 5 changed files with 360 additions and 83 deletions.
4 changes: 3 additions & 1 deletion inc/TRestAxionBufferGas.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ class TRestAxionBufferGas : public TRestMetadata {
void SetGasDensity(TString gasName, Double_t density);
Double_t GetGasDensity(TString gasName);

void SetGasMixture(TString gasMixture, TString gasDensities);
void SetGasMixture(TString gasMixture, TString gasDensities = "0");

/// It returns the number of gases in the mixture
Int_t GetNumberOfGases() { return (Int_t)fBufferGasName.size(); }
Expand All @@ -75,6 +75,8 @@ class TRestAxionBufferGas : public TRestMetadata {

Double_t GetPhotonMass(double en);

Double_t GetDensityForMass(double m_gamma, double en = 4.2);

void PrintAbsorptionGasData(TString gasName);
void PrintFormFactorGasData(TString gasName);

Expand Down
31 changes: 29 additions & 2 deletions inc/TRestAxionField.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,29 @@ class TRestAxionField : public TObject {
private:
Bool_t fDebug = false; //!

/// The magnetic field in Teslas
Double_t fBmag = 2.5;

/// The coherence lenght (in mm) where the magnetic field is defined
Double_t fLcoh = 10000;

/// The energy of the axion in keV
Double_t fEa = 4.2;

void Initialize();

/// A pointer to the buffer gas definition
TRestAxionBufferGas* fBufferGas = NULL; //!

public:
void SetMagneticField(Double_t b) { fBmag = b; }
void SetCoherenceLength(Double_t l) { fLcoh = l; }
void SetAxionEnergy(Double_t e) { fEa = e; }

Double_t GetMagneticField() const { return fBmag; }
Double_t GetCoherenceLength() const { return fLcoh; }
Double_t GetAxionEnergy() const { return fEa; }

Double_t BL(Double_t Bmag, Double_t Lcoh);
Double_t BLHalfSquared(Double_t Bmag, Double_t Lcoh);

Expand All @@ -48,15 +65,25 @@ class TRestAxionField : public TObject {
/// It assigns a gas buffer medium to the calculation
void SetBufferGas(TRestAxionBufferGas* buffGas) { fBufferGas = buffGas; }

Double_t GammaTransmissionProbability(Double_t ma, Double_t mg = 0, Double_t absLength = 0);

Double_t GammaTransmissionProbability(Double_t Bmag, Double_t Lcoh, Double_t Ea, Double_t ma,
Double_t mg = 0, Double_t absLength = 0);

Double_t GammaTransmissionProbability(std::vector<Double_t> Bmag, Double_t deltaL, Double_t Ea,
Double_t ma, Double_t mg = 0, Double_t absLength = 0);
Double_t AxionAbsorptionProbability(Double_t ma, Double_t mg = 0, Double_t absLength = 0);

Double_t AxionAbsorptionProbability(Double_t Bmag, Double_t Lcoh, Double_t Ea, Double_t ma,
Double_t mg = 0, Double_t absLength = 0);

Double_t GammaTransmissionProbability(std::vector<Double_t> Bmag, Double_t deltaL, Double_t Ea,
Double_t ma, Double_t mg = 0, Double_t absLength = 0);

Double_t GammaTransmissionFWHM(Double_t step = 0.00001);

std::vector<std::pair<Double_t, Double_t>> GetMassDensityScanning(std::string gasName = "He",
Double_t maMax = 0.15,
Double_t rampDown = 5.0);

TRestAxionField();
~TRestAxionField();

Expand Down
136 changes: 136 additions & 0 deletions macros/REST_Axion_PlotResonances.C
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
#include "TCanvas.h"
#include "TGraph.h"
#include "TLatex.h"
#include "TLegend.h"
#include "TLine.h"
#include "TRestAxionBufferGas.h"
#include "TRestAxionField.h"
//*******************************************************************************************************
//*** Description: This script plots the transmission probability as a function of the axion mass for a given
// gas and an
//*** axion energy until a maximum axion mass.
//***
//*** Arguments by default are (in order):
//*** - *ma_max* = 0.1: Maximum axion mass (in eV) to be plotted.
//*** - *ma_min* = 0: Minimum axion mass (in eV) to be plotted.
//*** - *Ea* = 4.2: Axion energy (in keV).
//*** - *Bmag* = 2.5: Magnetic field (in T).
//*** - *Lcoh* = 10000: Coherence length (in mm).
//*** - *gasName* = "He": Gas name.
//*** - *vacuum* = true: If true, the vacuum probability is added to the sum of all the probabilities.
//*** - *n_ma* = 10000: Number of points to be plotted.
//***
//*** The generated plots are the results from `TRestAxionField::GetMassDensityScanning`,
//*** `TRestAxionField::GammaTransmissionFWHM` and `TRestAxionBufferGas::GetMassDensity`.
//***
//*** --------------
//*** Usage: restManager PlotResonances [ma_max=0.1] [ma_min=0] [Ea=4.2] [Bmag=2.5] [Lcoh=10000] [gasName=He]
//*** [vacuum=true] [n_ma=10000]
//***
//*** Being all of them optional arguments.
//*** --------------
//*** Author: Fran Candón
//*******************************************************************************************************

int REST_Axion_PlotResonances(double ma_max = 0.1, double ma_min = 0, double Ea = 4.2, double Bmag = 2.5,
double Lcoh = 10000, std::string gasName = "He", Bool_t vacuum = true,
int n_ma = 10000) {
TRestAxionField* ax = new TRestAxionField();
ax->SetMagneticField(Bmag);
ax->SetCoherenceLength(Lcoh);
ax->SetAxionEnergy(Ea);

vector<std::pair<Double_t, Double_t>> pair = ax->GetMassDensityScanning(gasName, ma_max, 20);
std::vector<double> m_a;
std::vector<double> sum_prob;

// Creates the vector of axion masses
double ma_step = (ma_max - ma_min) / n_ma;
for (int i = 0; i < n_ma; i++) {
m_a.push_back(ma_min + i * ma_step);
sum_prob.push_back(0);
}

TCanvas* c1 = new TCanvas("c1", "c1", 800, 600);
std::vector<TGraph*> grp;

TRestAxionBufferGas* gas = new TRestAxionBufferGas();

for (const auto& p : pair) {
// Creates the gas and the axion field
gas->SetGasDensity(gasName, p.second);
ax->AssignBufferGas(gas);

// Obtain the probability for each axion mass
std::vector<double> prob;
for (int j = 0; j < n_ma; j++) {
prob.push_back(ax->GammaTransmissionProbability(m_a[j]));
sum_prob[j] += prob[j];
}

TGraph* gr = new TGraph(n_ma, &m_a[0], &prob[0]);
grp.push_back(gr);
}

// Computes the Vacuum probability
TRestAxionField* ax_vac = new TRestAxionField();
std ::vector<double> prob_vac;
for (int j = 0; j < n_ma; j++) {
prob_vac.push_back(ax_vac->GammaTransmissionProbability(m_a[j]));
}

// Computes the sum of all the probabilities
if (vacuum == true) {
for (int i = 0; i < n_ma; i++) {
sum_prob[i] += prob_vac[i];
}
}

///// PLOTS /////

// Plot the density scan
grp[0]->SetLineColor(kBlue - 3);
grp[0]->SetTitle("Transmission probability as a function of the axion mass");
grp[0]->GetXaxis()->SetTitle("m_{a} [eV]");
grp[0]->GetYaxis()->SetTitle("P_{ag}");
grp[0]->GetXaxis()->SetLimits(ma_min, ma_max);
double ylim = 3.5e-18;
grp[0]->GetYaxis()->SetRangeUser(0, ylim);
grp[0]->Draw("AL");

for (const auto g : grp) {
g->SetLineColor(kBlue - 3);
g->Draw("SAME");
}

// PLot of the sum of all the probabilities
TGraph* sum = new TGraph(n_ma, &m_a[0], &sum_prob[0]);
sum->SetLineColor(kBlue + 3);
sum->SetLineWidth(3);
sum->Draw("SAME");

// Plot of the vacuum probability
TGraph* vac = new TGraph(n_ma, &m_a[0], &prob_vac[0]);
vac->SetLineColor(kCyan + 1);
vac->SetLineWidth(2);
vac->Draw("SAME");

// Plot of the vertical line
TLine* verticalLine = new TLine(pair[0].first, c1->GetUymin(), pair[0].first, ylim);
verticalLine->SetLineColor(kGreen - 3);
verticalLine->SetLineWidth(2);
verticalLine->Draw("same");

// Plot of the legend
TLegend* legend = new TLegend(0.9, 0.7, 0.48, 0.9);
legend->AddEntry(grp[0], "P_{ag} for each mass", "l");
legend->AddEntry(vac, "P_{ag} for vacuum", "l");
legend->AddEntry(sum, "Sum of all the probs.", "l");
legend->AddEntry(verticalLine, "m_{a} where P_{ag}^{vac} = max(P_{ag}^{vac}/2) ", "l");
legend->Draw("same");
c1->Draw();

c1->Print("/tmp/resonances.png");

return 0;
}
65 changes: 60 additions & 5 deletions src/TRestAxionBufferGas.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
/// \code
/// TRestAxionBufferGas *gas = new TRestAxionBufferGas();
///
/// //Density units must be expressed here in g/cm3
/// //Density units must be expressed here in the default REST units, `kg/mm3`.
/// gas->SetGasDensity( "He", 2.6e-9 );
/// gas->SetGasDensity( "Xe", 5.6e-9 );
/// \endcode
Expand All @@ -48,7 +48,7 @@
/// \code
/// TRestAxionBufferGas *gas = new TRestAxionBufferGas();
///
/// gas->SetGasMixture( "He+Xe", "2.6e-6g/dm3+5.6mg/m3" );
/// gas->SetGasMixture( "He+Xe", "2.6e-6g/dm^3+5.6mg/m^3" );
/// \endcode
///
/// The corresponding RML section for initialization through a configuration
Expand All @@ -57,7 +57,7 @@
/// \code
/// <TRestAxionBufferGas name="heliumAndXenon" verboseLevel="warning" >
/// <gas name="He" density="2.6e-9"/>
/// <gas name="Xe" density="5.6mg/cm3"/>
/// <gas name="Xe" density="5.6mg/cm^3"/>
/// </TRestAxionBufferGas>
/// \endcode
///
Expand Down Expand Up @@ -174,17 +174,28 @@ void TRestAxionBufferGas::SetGasDensity(TString gasName, Double_t density) {
///
/// Example : SetGasMixture("Ne+Xe", "2e-3g/cm3+3mg/cm3" );
///
/// If the second argument with densities is not given, the buffer gas will
/// add the gas components with zero density.
///
void TRestAxionBufferGas::SetGasMixture(TString gasMixture, TString gasDensities) {
Initialize();

std::vector<string> names = Split((string)gasMixture, "+");
std::vector<string> densities = Split((string)gasDensities, "+");
std::vector<string> densities;
if (gasDensities == "0")
densities.clear();
else
densities = Split((string)gasDensities, "+");

if (names.size() == densities.size()) {
if (!densities.empty() && names.size() == densities.size()) {
for (unsigned int n = 0; n < names.size(); n++) {
Double_t density = GetValueInRESTUnits(densities[n]);
SetGasDensity(names[n], density);
}
} else if (densities.empty()) {
for (unsigned int n = 0; n < names.size(); n++) {
SetGasDensity(names[n], 0);
}
} else {
this->SetError("SetGasMixture. Number of gases does not match the densities!");
}
Expand Down Expand Up @@ -376,6 +387,10 @@ Double_t TRestAxionBufferGas::cmToeV(double l_Inv) // E in keV, P in bar ---> G
///
Double_t TRestAxionBufferGas::GetPhotonMass(double en) {
Double_t photonMass = 0;

if (fBufferGasName.empty())
RESTError << "TRestAxionBufferGas::GetDensityForMass gas has not been defined!" << RESTendl;

for (unsigned int n = 0; n < fBufferGasName.size(); n++) {
Double_t W_value = 0;
if (fBufferGasName[n] == "H") W_value = 1.00794; // g/mol
Expand All @@ -398,6 +413,46 @@ Double_t TRestAxionBufferGas::GetPhotonMass(double en) {
return 28.77 * TMath::Sqrt(photonMass);
}

////////////////////////////////////////////
/// \brief It returns the equivalent gas density for a given photon mass expressed in eV and a given axion
/// energy Ea (4.2 by default).
///
/// This method is only valid for pure gases with only one gas component. Before calling the method
/// one needs to define a gas with a single component,
/// e.g. using TRestAxionBufferGas::SetGasDensity( "He", 0 )
///
/// The resulting density will be expressed in kg/mm^3, which are the standard REST Units.
///
Double_t TRestAxionBufferGas::GetDensityForMass(double m_gamma, double en) {
Double_t massDensity = 0;

if (fBufferGasName.empty())
RESTError << "TRestAxionBufferGas::GetDensityForMass gas has not been defined!" << RESTendl;

if (fBufferGasName.size() > 1)
RESTError << "TRestAxionBufferGas::GetDensityForMass gas this method is only for sinale gas mixtures!"
<< RESTendl;

Double_t W_value = 0;
if (fBufferGasName[0] == "H") W_value = 1.00794; // g/mol
if (fBufferGasName[0] == "He") W_value = 4.002; // g/mol
if (fBufferGasName[0] == "Ne") W_value = 20.179; // g/mol
if (fBufferGasName[0] == "Ar") W_value = 39.948; // g/mol
if (fBufferGasName[0] == "Xe") W_value = 131.293; // g/mol

if (W_value == 0) {
RESTError << "Gas name : " << fBufferGasName[0] << " is not implemented in TRestAxionBufferGas!!"
<< RESTendl;
RESTError << "W value must be defined in TRestAxionBufferGas::GetDensityForMass" << RESTendl;
RESTError << "This gas will not contribute to the calculation of the photon mass!" << RESTendl;

} else {
massDensity += pow(m_gamma, 2) * W_value / (GetFormFactor(fBufferGasName[0], en) * pow(28.77, 2));
}

return massDensity / units("g/cm^3");
}

///////////////////////////////////////////////
/// \brief It returns the absorption coefficient, in cm2/g, for the given gas component and
/// energy in keV.
Expand Down
Loading

0 comments on commit e421bf2

Please sign in to comment.