Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2024-06-26 07:06:28

0001 
0002 // ROOT
0003 //#include "TH1D.h"
0004 //#include <TCanvas.h>
0005 #include "TTree.h"
0006 #include "TFile.h"
0007 #include <TRandom.h>
0008 
0009 // NPdet
0010 #include "dd4pod/Geant4ParticleCollection.h"
0011 #include "dd4pod/TrackerHitCollection.h"
0012 
0013 // IRT
0014 #include "CherenkovEvent.h"
0015 #include "CherenkovDetectorCollection.h"
0016 
0017 // Optionally: mimic low wave length cutoff and average QE x Geometric sensor efficiency;
0018 #define _WAVE_LENGTH_CUTOFF_ (350.0)
0019 #define _AVERAGE_PDE_        ( 0.30)
0020 
0021 int main(int argc, char** argv) 
0022 {
0023 #if _BACK_
0024   // Command line "parser";
0025   if (argc != 3 && argc != 4) {
0026     printf("usage: %s <root-data-file> <root-config-file> [DNAME]\n", argv[0]);
0027     exit(0);
0028   } //if
0029 
0030   // .root file with event tree;
0031   auto fdata = new TFile(argv[1]);
0032   TTree *t = dynamic_cast<TTree*>(fdata->Get("events"));
0033 
0034   // .root file with the IRT configuration;
0035   auto fcfg  = new TFile(argv[2]);
0036   CherenkovDetector *detector = 0;
0037   auto geometry = dynamic_cast<CherenkovDetectorCollection*>(fcfg->Get("CherenkovDetectorCollection"));
0038 
0039   if (argc == 4) 
0040     detector = geometry->GetDetector(argv[3]);
0041   else {
0042     // Assume a single detector (PFRICH or DRICH);
0043     auto &detectors = geometry->GetDetectors();
0044     if (detectors.size() != 1) {
0045       printf("More than one detector in the provided IRT geometry config .root file!\n");
0046       exit(0);
0047     } //if
0048 
0049     //dname = new std::string((*detectors.begin()).first.Data());
0050     detector = (*detectors.begin()).second;
0051   } //if
0052 
0053   // Either this or that way, the detector should be available;
0054   if (!detector) {
0055     printf("Was not able to find a valid Cherenkov detector in the provided IRT geometry config .root file!\n");
0056     exit(0);
0057   } //if
0058 
0059   //auto np = new TH1D("np", "Photon count",            50,     0,    50);
0060 
0061   auto gas      = detector->GetRadiator("GasVolume");
0062   auto aerogel  = detector->GetRadiator("Aerogel");
0063   //auto acrylic  = detector->GetRadiator("Filter");
0064   // Assume the reference value was close enough in PFRICH_geo.cpp; since QE was not accounted, 
0065   // this may not be true; 
0066   gas    ->m_AverageRefractiveIndex = gas    ->n();
0067   aerogel->m_AverageRefractiveIndex = aerogel->n();
0068   //acrylic->m_AverageRefractiveIndex = acrylic->n();
0069 
0070   //aerogel->SetGaussianSmearing(0.002);
0071   aerogel->SetUniformSmearing(0.003);
0072   // Be aware, that AddLocations() part should take this into account;
0073   aerogel->SetTrajectoryBinCount(1);
0074   // This may be bogus for a blob-like operation mode;
0075   //gas    ->SetUniformSmearing(0.003);
0076 
0077   // TTree interface variable;
0078   auto event = new CherenkovEvent();
0079 
0080   // Use MC truth particles, and deal with just pfRICH hits here; however the interface 
0081   // should work for combinations like pfRICH+DIRC, eventually; 
0082   std::vector<dd4pod::Geant4ParticleData>     *tracks = new std::vector<dd4pod::Geant4ParticleData>();
0083   std::vector<dd4pod::TrackerHitData> *hits   = new std::vector<dd4pod::TrackerHitData>();
0084   t->SetBranchAddress("mcparticles", &tracks);
0085   {
0086     TString hname; hname.Form("%sHits", detector->GetName());
0087     t->SetBranchAddress(hname,   &hits);
0088   }
0089 
0090   // Loop through all events;
0091   unsigned false_assignment_stat = 0;
0092   for(int ev=0; ev<t->GetEntries(); ev++) {
0093     t->GetEntry(ev);
0094   
0095     // Loop through all tracks and populate the internal arrays in a way 
0096     // IRT code expects; FIXME: this is not dramatically efficient; streamline once debugging is over;
0097     for(auto track: *tracks) {
0098       // FIXME: consider only primaries here?;
0099       if (track.g4Parent) continue;
0100 
0101       // Create a combined (for all radiators) hit array; eventually will move this
0102       // structure out of the track loop;
0103       std::vector<OpticalPhoton*> photons;  
0104       for(auto hit: *hits) {
0105     // FIXME: yes, use MC truth here; not really needed I guess; 
0106     if (hit.g4ID != track.ID) continue;
0107     
0108 #ifdef _WAVE_LENGTH_CUTOFF_ 
0109     {
0110       auto &p = hit.momentum;
0111       double pmag = sqrt(p.x*p.x + p.y*p.y + p.z*p.z);
0112       
0113       if (1239.84/(1E9*pmag) < _WAVE_LENGTH_CUTOFF_) continue;
0114     }
0115 #endif
0116 #ifdef _AVERAGE_PDE_  
0117     if (gRandom->Uniform(0.0, 1.0) > _AVERAGE_PDE_) continue;
0118 #endif
0119     
0120     auto photon = new OpticalPhoton();
0121     
0122     {
0123       auto &x = hit.position;
0124       photon->SetDetectionPosition(TVector3(x.x, x.y, x.z));
0125     }
0126 
0127     // A single photodetector type is used;
0128     photon->SetPhotonDetector(detector->m_PhotonDetectors[0]);
0129     photon->SetDetected(true);
0130     // Get cell index; mask out everything apart from {module,sector};
0131     photon->SetVolumeCopy(hit.cellID & detector->GetReadoutCellMask());
0132     
0133     photons.push_back(photon);
0134       } //for hit
0135 
0136       auto particle = new ChargedParticle(track.pdgID);
0137       event->AddChargedParticle(particle);
0138 
0139       aerogel->ResetLocations();
0140 #if 1//_TODAY_
0141       // Create a fake (empty) history; then track locations at the aerogel boundaries;
0142       particle->StartRadiatorHistory(std::make_pair(aerogel, new RadiatorHistory()));
0143       {
0144     // FIXME: need it not at vertex, but in the radiator; as coded here, this can 
0145     // hardly work once the magnetic field is turned on;
0146     auto &vtx = track.vs, &p = track.ps;
0147     auto x0 = TVector3(vtx.x, vtx.y, vtx.z), p0 = TVector3(p.x, p.y, p.z), n0 = p0.Unit();
0148 
0149     // So, give the algorithm aerogel surface boundaries as encoded in PFRICH_geo.cpp;
0150     TVector3 from, to;
0151     aerogel->GetFrontSide(0)->GetCrossing(x0, n0, &from);
0152     aerogel->GetRearSide (0)->GetCrossing(x0, n0, &to);
0153       
0154     // Move the points a bit inwards;
0155     TVector3 nn = (to - from).Unit(); from += (0.010)*nn; to -= (0.010)*nn;
0156     // FIXME: will this work for pfRICH?;
0157     for(unsigned isec=0; isec<6; isec++) {
0158       aerogel->AddLocation(isec, from, p0);
0159       aerogel->AddLocation(isec,   to, p0);
0160     } //for isec
0161       }
0162 
0163       // Now that all internal track-level structures are populated, run IRT code;
0164       {
0165     CherenkovPID pid;
0166 
0167     // Consider just pi/K case for now;
0168     pid.AddMassHypothesis(0.140);
0169     pid.AddMassHypothesis(0.494);
0170 
0171     particle->PIDReconstruction(pid, &photons);
0172     {
0173       auto pion = pid.GetHypothesis(0), kaon = pid.GetHypothesis(1);
0174       double wt0 = pion->GetWeight(aerogel), wt1 = kaon->GetWeight(aerogel);
0175 
0176       printf("%10.3f (%10.3f) vs %10.3f (%10.3f) ...  %3d %d\n", 
0177          wt0, pion->GetNpe(aerogel), wt1, kaon->GetNpe(aerogel), particle->GetPDG(), wt0 > wt1);
0178 
0179       if (wt0 <= wt1) false_assignment_stat++;
0180     }
0181       }
0182 #endif
0183     } //for track
0184 
0185     event->Reset();
0186   } //for ev
0187 
0188   printf("%d false out of %lld\n", false_assignment_stat, t->GetEntries());
0189 
0190   //auto cv = new TCanvas("cv", "", 800, 600);
0191   //cv->cd(1); np->Draw();
0192 #endif
0193 
0194   return 0;
0195 } // main()