LCOV - code coverage report
Current view: top level - src/magneticLens - ParticleMapsContainer.cpp (source / functions) Hit Total Coverage
Test: coverage.info.cleaned Lines: 74 105 70.5 %
Date: 2024-04-29 14:43:01 Functions: 9 13 69.2 %

          Line data    Source code
       1             : #include "HepPID/ParticleIDMethods.hh"
       2             : #include "crpropa/Random.h"
       3             : #include "crpropa/magneticLens/ParticleMapsContainer.h"
       4             : #include "crpropa/Units.h"
       5             : 
       6             : #include <iostream>
       7             : #include <fstream>
       8             : 
       9             : namespace crpropa  {
      10             : 
      11           2 : ParticleMapsContainer::~ParticleMapsContainer() {
      12           2 :         for(std::map<int, std::map<int, double*> >::iterator pid_iter = _data.begin(); 
      13           4 :                         pid_iter != _data.end(); ++pid_iter) {
      14           2 :                 for(std::map<int, double*>::iterator energy_iter = pid_iter->second.begin();
      15           4 :                         energy_iter != pid_iter->second.end(); ++energy_iter) {
      16           2 :                         delete[] (energy_iter->second);
      17             :                 }
      18             :         }
      19           2 : }
      20             : 
      21         422 : int ParticleMapsContainer::energy2Idx(double energy) const {
      22         422 :         double lE = log10(energy / eV);
      23         422 :         return int((lE - _bin0lowerEdge) / _deltaLogE);
      24             : }
      25             : 
      26         421 : double ParticleMapsContainer::idx2Energy(int idx) const {
      27         421 :         return pow(10, idx * _deltaLogE + _bin0lowerEdge + _deltaLogE / 2) * eV;
      28             : }
      29             : 
      30             :                 
      31           0 : double* ParticleMapsContainer::getMap(const int particleId, double energy) {
      32           0 :         _weightsUpToDate = false;
      33           0 :         if (_data.find(particleId) == _data.end()) {
      34           0 :                 std::cerr << "No map for ParticleID " << particleId << std::endl;
      35           0 :                 return NULL;
      36             :         }
      37           0 :         int energyIdx   = energy2Idx(energy);
      38           0 :         if (_data[particleId].find(energyIdx) == _data[particleId].end()) {
      39           0 :                 std::cerr << "No map for ParticleID and energy" << energy / eV << " eV" << std::endl;
      40           0 :                 return NULL;
      41             :         }
      42           0 :         return _data[particleId][energy2Idx(energy)];
      43             : }
      44             :                         
      45             :                         
      46           2 : void ParticleMapsContainer::addParticle(const int particleId, double energy, double galacticLongitude, double galacticLatitude, double weight) {
      47           2 :         _weightsUpToDate = false;
      48           2 :         if (_data.find(particleId) == _data.end()) {
      49             :                 map<int, double*> M;
      50           2 :                 _data[particleId] = M;
      51             :         }
      52             : 
      53           2 :         int energyIdx   = energy2Idx(energy);
      54           4 :         if (_data[particleId].find(energyIdx) == _data[particleId].end()) {
      55           2 :                 _data[particleId][energyIdx] = new double[_pixelization.getNumberOfPixels()];
      56           2 :                 std::fill(_data[particleId][energyIdx], _data[particleId][energyIdx] + _pixelization.getNumberOfPixels(), 0);
      57             :         }
      58             : 
      59           2 :         uint32_t pixel = _pixelization.direction2Pix(galacticLongitude, galacticLatitude);
      60           2 :         _data[particleId][energyIdx][pixel] += weight;
      61           2 : }
      62             : 
      63             : 
      64           0 : void ParticleMapsContainer::addParticle(const int particleId, double energy, const Vector3d &p, double weight) {
      65           0 :         double galacticLongitude = atan2(-p.y, -p.x);
      66           0 :         double galacticLatitude =       M_PI / 2 - acos(-p.z / p.getR());
      67           0 :         addParticle(particleId, energy, galacticLongitude, galacticLatitude, weight);
      68           0 : }
      69             : 
      70             : 
      71           1 : std::vector<int> ParticleMapsContainer::getParticleIds() {
      72             :         std::vector<int> ids;
      73           1 :         for(std::map<int, std::map<int, double*> >::iterator pid_iter = _data.begin(); 
      74           2 :                         pid_iter != _data.end(); ++pid_iter) {
      75           1 :                 ids.push_back(pid_iter->first);
      76             :         }
      77           1 :         return ids;
      78             : }
      79             : 
      80             : 
      81           1 : std::vector<double> ParticleMapsContainer::getEnergies(int pid) {
      82             :         std::vector<double> energies;
      83           1 :         if (_data.find(pid) != _data.end()) {
      84           1 :                 for(std::map<int, double*>::iterator iter = _data[pid].begin(); 
      85           2 :                         iter != _data[pid].end(); ++iter) {
      86           1 :                         energies.push_back( idx2Energy(iter->first) / eV );
      87             :                 }
      88             :         }
      89           1 :         return energies;
      90             : }
      91             : 
      92             : 
      93           0 : void ParticleMapsContainer::applyLens(MagneticLens &lens) {
      94             :         // if lens is normalized, this should not be necessary.
      95           0 :         _weightsUpToDate = false;
      96             : 
      97           0 :         for(std::map<int, std::map<int, double*> >::iterator pid_iter = _data.begin(); 
      98           0 :                         pid_iter != _data.end(); ++pid_iter) {
      99           0 :                 for(std::map<int, double*>::iterator energy_iter = pid_iter->second.begin();
     100           0 :                         energy_iter != pid_iter->second.end(); ++energy_iter) {
     101             :                         // transform only nuclei
     102           0 :                         double energy = idx2Energy(energy_iter->first);
     103           0 :                         int chargeNumber = HepPID::Z(pid_iter->first);
     104           0 :                         if (chargeNumber != 0 && lens.rigidityCovered(energy / chargeNumber)) {
     105           0 :                                 lens.transformModelVector(energy_iter->second, energy / chargeNumber);
     106             :                         } else { // still normalize the vectors 
     107           0 :                                 for(size_t j=0; j< _pixelization.getNumberOfPixels() ; j++) {
     108           0 :                                         energy_iter->second[j] /= lens.getNorm();
     109             :                                 }
     110             :                         }
     111             :                 }
     112             :         }
     113           0 : }
     114             : 
     115             : 
     116         421 : void ParticleMapsContainer::_updateWeights() {
     117         421 :         if (_weightsUpToDate)
     118             :                 return;
     119             : 
     120           1 :         for(std::map<int, std::map<int, double*> >::iterator pid_iter = _data.begin(); 
     121           2 :                         pid_iter != _data.end(); ++pid_iter) {
     122           1 :                 _weightsPID[pid_iter->first] = 0;
     123             : 
     124           1 :                 for(std::map<int, double*>::iterator energy_iter = pid_iter->second.begin();
     125           2 :                         energy_iter != pid_iter->second.end(); ++energy_iter)  {
     126             : 
     127           1 :                         _weights_pidEnergy[pid_iter->first][energy_iter->first] = 0;
     128       49153 :                         for(size_t j = 0; j< _pixelization.getNumberOfPixels() ; j++) {
     129       49152 :                                 _weights_pidEnergy[pid_iter->first][energy_iter->first] +=energy_iter->second[j];
     130       49152 :                                 _weightsPID[pid_iter->first]+=energy_iter->second[j];
     131             :                         }
     132           1 :                         _sumOfWeights+=_weights_pidEnergy[pid_iter->first][energy_iter->first];
     133             :                 }
     134             :         }
     135           1 :         _weightsUpToDate = true;
     136             : }
     137             : 
     138             : 
     139           1 : void ParticleMapsContainer::getRandomParticles(size_t N, vector<int> &particleId, 
     140             :         vector<double> &energy, vector<double> &galacticLongitudes,
     141             :         vector<double> &galacticLatitudes) {
     142           1 :         _updateWeights();
     143             : 
     144           1 :         particleId.resize(N);
     145           1 :         energy.resize(N);
     146           1 :         galacticLongitudes.resize(N);
     147           1 :         galacticLatitudes.resize(N);
     148             : 
     149         421 :         for(size_t i=0; i< N; i++) {
     150             :                 //get particle
     151         420 :                 double r = Random::instance().rand() * _sumOfWeights;
     152             :                 std::map<int, double>::iterator iter = _weightsPID.begin();
     153         420 :                 while ((r-= iter->second) > 0) {
     154             :                         ++iter; 
     155             :                 }
     156         420 :                 particleId[i] = iter->first;
     157             :         
     158             :                 //get energy
     159         420 :                 r = Random::instance().rand() * iter->second;
     160         420 :                 iter = _weights_pidEnergy[particleId[i]].begin();
     161         420 :                 while ((r-= iter->second) > 0) {
     162             :                  ++iter; 
     163             :                 }
     164         420 :                 energy[i] = idx2Energy(iter->first) / eV;
     165             : 
     166         420 :                 placeOnMap(particleId[i], energy[i] * eV, galacticLongitudes[i], galacticLatitudes[i]);
     167             :         }
     168           1 : }
     169             : 
     170             : 
     171         420 : bool ParticleMapsContainer::placeOnMap(int pid, double energy, double &galacticLongitude, double &galacticLatitude) {
     172         420 :         _updateWeights();
     173             : 
     174         420 :         if (_data.find(pid) == _data.end()) {
     175             :                 return false;
     176             :         }
     177         420 :         int energyIdx   = energy2Idx(energy);
     178         840 :         if (_data[pid].find(energyIdx) == _data[pid].end()) {
     179             :                 return false;
     180             :         }
     181             : 
     182         420 :         double r = Random::instance().rand() * _weights_pidEnergy[pid][energyIdx];
     183             : 
     184    10268580 :         for(size_t j = 0; j< _pixelization.getNumberOfPixels(); j++) {
     185    10268580 :                 r -= _data[pid][energyIdx][j];
     186    10268580 :                 if (r <= 0) {
     187         420 :                         _pixelization.getRandomDirectionInPixel(j, galacticLongitude, galacticLatitude);
     188         420 :                         return true;
     189             :                 }
     190             :         }
     191             :         return false;
     192             : }
     193             : 
     194             : 
     195           0 : void ParticleMapsContainer::forceWeightUpdate() {
     196           0 :         _weightsUpToDate = false;
     197           0 : }
     198             : 
     199             : } // namespace crpropa

Generated by: LCOV version 1.14