Giter VIP home page Giter VIP logo

ecomug's Introduction

EcoMug: Efficient COsmic MUon Generator

EcoMug is a header-only C++11 library for the generation of cosmic ray (CR) muons, based on a parametrization of experimental data. Unlike other tools, EcoMug gives the possibility of generating from different surfaces (plane, cylinder and half-sphere), while keeping the correct angular and momentum distribution of generated tracks. EcoMug also allows the generation of CR muons according to user-defined parametrizations of their differential flux.

If you use, or want to refer to, EcoMug please cite the following paper:

Pagano, D., Bonomi, G., Donzella, A., Zenoni, A., Zumerle, G., & Zurlo, N. (2021). EcoMug: An Efficient COsmic MUon Generator for cosmic-ray muon applications. Nuclear Instruments and Methods in Physics Research Section A: Accelerators, Spectrometers, Detectors and Associated Equipment, 1014, 165732.

Latest release: EcoMug v2.1

Basic Usage

The use of the library requires the initialization of the EcoMug class, the choice of the generation method, and the definition of the size and position of the generation surface. Once the setup of the instance of the EcoMug class is done, the generation of a cosmic-ray muon can be invoked with the method Generate(), which will compute its position, direction, momentum, and charge. All these quantities can be accessed with the methods GetGenerationPosition(), GetGenerationTheta(), GetGenerationPhi(), GetGenerationMomentum(), and GetCharge(), as shown in the examples below. The charge for generated muons takes into account the excess of positive muons over negative ones, assuming a constant charge ratio (see the above mentioned paper for more details). Angles are in radians, momentum is in GeV/c, whereas the unit of measure of the position is arbitrary and depends on the choice done in the simulation code where EcoMug is used.

Plane-based generation

EcoMug gen; // initialization of the class
gen.SetUseSky(); // plane surface generation
gen.SetSkySize({{10., 10.}}); // x and y size of the plane
// (x,y,z) position of the center of the plane
gen.SetSkyCenterPosition({{0., 0., 20.}});

// The array storing muon generation position
std::array<double, 3> muon_position;

for (auto event = 0; event < number_of_events; ++event) {
  gen.Generate();
  muon_position = gen.GetGenerationPosition();
  double muon_p = gen.GetGenerationMomentum();
  double muon_theta = gen.GetGenerationTheta();
  double muon_phi = gen.GetGenerationPhi();
  double muon_charge = gen.GetCharge();
  ...
}

Cylinder-based generation

EcoMug gen; // initialization of the class
gen.SetUseCylinder(); // cylindrical surface generation
gen.SetCylinderRadius(10.); // cylinder radius
gen.SetCylinderHeight(30.); // cylinder height
// (x,y,z) position of the center of the cylinder
gen.SetCylinderCenterPosition({{0., 0., 15.}});

// The array storing muon generation position
std::array<double, 3> muon_position;

for (auto event = 0; event < number_of_events; ++event) {
  gen.Generate();
  muon_position = gen.GetGenerationPosition();
  double muon_p = gen.GetGenerationMomentum();
  double muon_theta = gen.GetGenerationTheta();
  double muon_phi = gen.GetGenerationPhi();
  double muon_charge = gen.GetCharge();
  ...
}

Hsphere-based generation

EcoMug gen; // initialization of the class
gen.SetUseHSphere(); // half-spherical surface generation
gen.SetHSphereRadius(30.); // half-sphere radius
// (x,y,z) position of the center of the half-sphere
gen.SetHSphereCenterPosition({{0., 0., 0.}});

// The array storing muon generation position
std::array<double, 3> muon_position;

for (auto event = 0; event < number_of_events; ++event) {
  gen.Generate();
  muon_position = gen.GetGenerationPosition();
  double muon_p = gen.GetGenerationMomentum();
  double muon_theta = gen.GetGenerationTheta();
  double muon_phi = gen.GetGenerationPhi();
  double muon_charge = gen.GetCharge();
  ...
}

More Advanced Usage

It is possible to set the seed in EcoMug, for reproducible generations. This can be done with the method SetSeed, as shown in the example below. If the seed is set to 0 (or the method is not invoked at all), a random seed is used.

EcoMug gen;
gen.SetUseSky();
gen.SetSkySize({{10., 10.}});
gen.SetSkyCenterPosition({{0., 0., 20.}});

// set the seed (only positive integers are accepted)
gen.SetSeed(1234);

In several scenarios, one could be interested in generating tracks from a subset of these parameters, saving space and computation time. EcoMug allows this by exposing to the user the following methods:

  • SetMinimumMomentum - Set the minimum momentum for generated cosmic-ray muons;
  • SetMaximumMomentum - Set the maximum momentum for generated cosmic-ray muons;
  • SetMinimumTheta - Set the minimum zenith angle 𝜃 for generated cosmic-ray muons;
  • SetMaximumTheta - Set the maximum zenith angle 𝜃 for generated cosmic-ray muons;
  • SetMinimumPhi - Set the minimum azimuthal angle 𝜙 for generated cosmic-ray muons;
  • SetMaximumPhi - Set the maximum azimuthal angle 𝜙 for generated cosmic-ray muons.
#include <math.h> // necessary for the M_PI constant

EcoMug gen;
gen.SetUseSky();
gen.SetSkySize({{10., 10.}});
gen.SetSkyCenterPosition({{0., 0., 20.}});

gen.SetMinimumMomentum(80.);
gen.SetMaximumMomentum(800.);
gen.SetMinimumTheta(0.);
gen.SetMaximumTheta(M_PI/4);
gen.SetMinimumPhi(0.);
gen.SetMaximumPhi(M_PI);

In those cases where the proposed parametrization of the differential flux J of CR muons does not fit the user needs, EcoMug gives the possibility to use a custom function for J, as shown in the example below.

double J(double p, double theta) {
  double A = 0.14*pow(p, -2.7);
  double B = 1. / (1. + 1.1*p*cos(theta)/115.);
  double C = 0.054 / (1. + 1.1*p*cos(theta)/850.);
  return A*(B+C);
}

EcoMug gen;
gen.SetUseSky();
gen.SetSkySize({{x, y}});
gen.SetSkyCenterPosition({0., 0., z});
gen.SetMinimumMomentum(150);
gen.SetDifferentialFlux(&J);

for (auto event = 0; event < nevents; ++event) {
  gen.GenerateFromCustomJ(); // generate from user-defined J
  ... // retrieve and use muon data
  gen.Generate(); // generate from J as in equation 2
  ... // retrieve and use muon data
}

Rate and time estimation

EcoMug allows to estimate the rate and time to collect a given number of muons, also in those cases where the user has constrained the generation (for example by cutting on the momentum or angles). The user can specify the average expected rate (via SetHorizontalRate) to take into account, for example, the effect of altitude. Default value is 129 $Hz/m^2$.

While the rate and time estimation also works with custom definitions of the flux, it is up to the user to define a properly normalized J: SetHorizontalRate does not work in this case.

EcoMug genPlane;
genPlane.SetUseSky();
genPlane.SetSkySize({{200.*EMUnits::cm, 200.*EMUnits::cm}});
genPlane.SetSkyCenterPosition({0., 0., 1.*EMUnits::mm});

cout << "Estimated time [s] = " << genPlane.GetEstimatedTime(10000) << endl;

Deal with background

The class EMMultiGen allows to handle the generation of the background as well as the signal. It requires a EcoMug instance for the signal and one or more instances for the background. Additionally the user has to specify the differential flux (even unnormalized), the PID (Monte Carlo particle numbering scheme) and the relative weight (w.r.t. signal) for all backgrounds.

EcoMug muonGen;
muonGen.SetUseSky();
muonGen.SetSkySize({{200.*EMUnits::cm, 200.*EMUnits::cm}});
muonGen.SetSkyCenterPosition({0., 0., 1.*EMUnits::mm});

EcoMug electronGen(muonGen);
electronGen.SetDifferentialFlux(&J);

EcoMug positronsGen(muonGen);
electronGen.SetDifferentialFlux(&J);

EMMultiGen genSuite(muonGen, {electronGen, positronsGen});
genSuite.SetBckWeights({0.2, 0.1});
genSuite.SetBckPID({11, -11});

map<int, int> counts;
for (auto i = 0; i < number_of_events; ++i) {
  genSuite.Generate();
  counts[genSuite.GetPID()]++;
}

In case you want to compile the previous code, please take a look at the following example, which should be compiled with the -std=c++11 flag.

#include <iostream>
#include <map>
#include <iomanip>
#include "EcoMug.h"

double J(double p, double theta) {
  double A = 1400*pow(p, -2.7);
  double B = 1. / (1. + 1.1*p*cos(theta)/115.);
  double C = 0.054 / (1. + 1.1*p*cos(theta)/850.);
  return A*(B+C);
};

EMLog::TLogLevel EMLog::ReportingLevel = WARNING;

int main() {

    EcoMug muonGen;
    muonGen.SetUseSky();
    muonGen.SetSkySize({{200.*EMUnits::cm, 200.*EMUnits::cm}});
    muonGen.SetSkyCenterPosition({0., 0., 1.*EMUnits::mm});

    EcoMug electronGen(muonGen);
    electronGen.SetDifferentialFlux(&J);

    EcoMug positronsGen(muonGen);
    electronGen.SetDifferentialFlux(&J);

    EMMultiGen genSuite(muonGen, {electronGen, positronsGen});
    genSuite.SetBckWeights({0.2, 0.1});
    genSuite.SetBckPID({11, -11});

    std::map<int, int> counts;
    for (auto i = 0; i < 10000; ++i) {
        genSuite.Generate();
        counts[genSuite.GetPID()]++;
    }
    std::cout << std::right << std::setw(5) << "PID" << std::right << std::setw(8) << " counts" 
        << "     ratio" << std::endl; 

    for (auto const& x : counts) {
        std::cout << std::right << std::setw(5) << x.first << std::right << std::setw(8) << x.second 
            << "   (" << std::setprecision(3) << (double) x.second/(counts[13]+counts[-13]) << ")" << std::endl;
    }
}

ecomug's People

Contributors

dr4kan avatar zhao-shihan avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

ecomug's Issues

‘std::function’ issue on geant4 virtual machine version 11.0

I am trying to use EcoMug.h in the geant4 virtual machine v11.0 from "Geant4 Virtual Machine – G4VM with RockyLinux 8.5 Geant4 "
and I am getting this error using c++ 11

home/local1/Desktop/t4_rpc/include/EcoMug.h:100:8: error: ‘function’ in namespace ‘std’ does not name a template type std::function<double(double, double)> mFunc;

/home/local1/Desktop/t4_rpc/include/EcoMug.h:100:3: note: ‘std::function’ is defined in header ‘<functional>’; did you forget to ‘#include <functional>’? /home/local1/Desktop/t4_rpc/include/EcoMug.h:29:1: +#include <functional>

Problem with implementation of EcoMug2.0 with Geant4.11

Hi everyone,
I've implemented EcoMug2.0 as particle generator in my Geant4 simulation.
I received this error messages after compilation:

usr/bin/ld: CMakeFiles/nuscale1.dir/src/CilSteppingAction.cc.o:(.data+0x0): multiple definition of `EMLog::ReportingLevel'; CMakeFiles/nuscale1.dir/src/CilPrimaryGeneratorAction.cc.o:(.data+0x0): first defined here
collect2: error: ld returned 1 exit status
make[2]: *** [CMakeFiles/nuscale1.dir/build.make:220: nuscale1] Error 1
make[1]: *** [CMakeFiles/Makefile2:104: CMakeFiles/nuscale1.dir/all] Error 2
make: *** [Makefile:130: all] Error 2

What is the problem?
Thank you very much

Very slow when using custom differential flux function

Hello, When I use GenerateFromCustomJ() with a user-defined differential flux function, same with the example code in the paper:

double PrimaryGeneratorAction::J_Gaisser(double p, double theta)
{
  double A = 0.14*pow(p, -2.7);
  double B = 1. / (1. + 1.1*p*cos(theta)/115.);
  double C = 0.054 / (1. + 1.1*p*cos(theta)/850.);
  return A*(B+C);
}

The generation gets very slow (several tenth slower compared to the pre-defined J. What can I do to improve the performance? Thanks.

Question on theta / zenith angle implementation

Hi there!
I have had some problems understanding how the theta angle is "understood" in EcoMug.

For example, I was expecting to give it the theta angle as a zenith angle, range from 9° to 11° and get back zenith from 9 - 11° or 191° to 189° or 179° to 181°.
But I get 99° to 101°. Somewhere the theta angle is understood as an altitude angle and sometimes as an azimuth angle, at least as I understand it?

At least for my use case, I just want to have azimuth angles (and a 180° flip at the end to point it down, for the simulation). I also tried to convert the angles, but that somehow failed too. So I thought I would give it a try here!

If you could explain it to me, I would be very grateful!
(I'm still on v1.3.1, but at least from what I've seen, everything regarding theta calculations hasn't been touched in the newer versions?)

Thanks in advance!
Martin

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.