GENIEGenerator
Loading...
Searching...
No Matches
GSimpleNtpFlux.cxx
Go to the documentation of this file.
1//____________________________________________________________________________
2/*
3 Copyright (c) 2003-2025, The GENIE Collaboration
4 For the full text of the license visit http://copyright.genie-mc.org
5
6 Robert Hatcher <rhatcher@fnal.gov>
7 Fermi National Accelerator Laboratory
8*/
9//____________________________________________________________________________
10
11#include <cstdlib>
12#include <fstream>
13#include <sstream>
14#include <cassert>
15#include <limits.h>
16#include <algorithm>
17
18#include <TFile.h>
19#include <TChain.h>
20#include <TChainElement.h>
21#include <TSystem.h>
22#include <TStopwatch.h>
23
26#include "Framework/Conventions/GBuild.h"
27
29
38
39using std::endl;
40
41#include <vector>
42#include <algorithm>
43#include <iomanip>
44#include "TRegexp.h"
45#include "TString.h"
46
49
50//#define __GENIE_LOW_LEVEL_MESG_ENABLED__
51// next line won't work for NOvA: ROOT's Error() != DefaultErrorHandler
52//#define USE_INDEX_FOR_META
53
54using namespace genie;
55using namespace genie::flux;
56
62
63// static storage
65
66//____________________________________________________________________________
69{
70 this->Initialize();
71}
72//___________________________________________________________________________
77//___________________________________________________________________________
79{
80 // complete the GFluxExposureI interface
81 return UsedPOTs();
82}
83//___________________________________________________________________________
85{
86 ///< number of flux neutrinos looped so far
87 return fNNeutrinos;
88}
89//___________________________________________________________________________
91{
92// Get next (unweighted) flux ntuple entry on the specified detector location
93//
95 while ( true ) {
96 // Check for end of flux ntuple
97 bool end = this->End();
98 if ( end ) {
99 LOG("Flux", pNOTICE) << "GenerateNext signaled End() ";
100 return false;
101 }
102
103 // Get next weighted flux ntuple entry
104 bool nextok = this->GenerateNext_weighted();
105 if ( fGenWeighted ) return nextok;
106 if ( ! nextok ) continue;
107 if ( fAlreadyUnwgt ) return true;
108
109 /* RWH - debug purposes
110 if ( fNCycles == 0 ) {
111 LOG("Flux", pNOTICE)
112 << "Got flux entry: " << fIEntry
113 << " - Cycle: "<< fICycle << "/ infinite";
114 } else {
115 LOG("Flux", pNOTICE)
116 << "Got flux entry: "<< fIEntry
117 << " - Cycle: "<< fICycle << "/"<< fNCycles;
118 }
119 */
120
121 // Get fractional weight & decide whether to accept curr flux neutrino
122 double f = this->Weight() / fMaxWeight;
123 //LOG("Flux", pNOTICE)
124 // << "Curr flux neutrino fractional weight = " << f;
125 if (f > 1.) {
126 fMaxWeight = this->Weight() * 1.01; // bump the weight
127 LOG("Flux", pERROR)
128 << "** Fractional weight = " << f
129 << " > 1 !! Bump fMaxWeight estimate to " << fMaxWeight
130 << GetCurrentEntry();
131 std::cout << std::flush;
132 }
133 double r = (f < 1.) ? rnd->RndFlux().Rndm() : 0;
134 bool accept = ( r < f );
135 if ( accept ) {
136
137#ifdef __GENIE_LOW_LEVEL_MESG_ENABLED__
138 LOG("Flux", pNOTICE)
139 << "Generated beam neutrino: "
140 << "\n pdg-code: " << fCurEntry->pdg
141 << "\n p4: " << utils::print::P4AsShortString(&(fP4))
142 << "\n x4: " << utils::print::X4AsString(&(fX4));
143#endif
144
145 fWeight = 1.;
146 return true;
147 }
148
149 //LOG("Flux", pNOTICE)
150 // << "** Rejecting current flux neutrino based on the flux weight only";
151 }
152 return false;
153}
154//___________________________________________________________________________
156{
157// Get next (weighted) flux ntuple entry
158//
159
160 // Check whether a flux ntuple has been loaded
161 if ( ! fNuFluxTree ) {
162 LOG("Flux", pFATAL)
163 << "The flux driver has not been properly configured";
164 // return false; // don't do this - creates an infinite loop!
165 exit(1);
166 }
167
168 // Reuse an entry?
169 //std::cout << " ***** iuse " << fIUse << " nuse " << fNUse
170 // << " ientry " << fIEntry << " nentry " << fNEntries
171 // << " icycle " << fICycle << " ncycle " << fNCycles << std::endl;
173 // Reuse this entry
174 fIUse++;
175 } else {
176 // Reset previously generated neutrino code / 4-p / 4-x
177 this->ResetCurrent();
178 // Move on, read next flux ntuple entry
179 ++fIEntry;
180 ++fNEntriesUsed; // count total # used
181 if ( fIEntry >= fNEntries ) {
182 // Ran out of entries @ the current cycle of this flux file
183 // Check whether more (or infinite) number of cycles is requested
184 if (fICycle < fNCycles || fNCycles == 0 ) {
185 fICycle++;
186 fIEntry=0;
187 } else {
188 LOG("Flux", pWARN)
189 << "No more entries in input flux neutrino ntuple, cycle "
190 << fICycle << " of " << fNCycles;
191 fEnd = true;
192 //assert(0);
193 return false;
194 }
195 }
196
197 int nbytes = fNuFluxTree->GetEntry(fIEntry);
198 UInt_t metakey = fCurEntry->metakey;
199 if ( fAllFilesMeta && ( fCurMeta->metakey != metakey ) ) {
200 UInt_t oldkey = fCurMeta->metakey;
201#ifdef USE_INDEX_FOR_META
202 int nbmeta = fNuMetaTree->GetEntryWithIndex(metakey);
203#else
204 // unordered indices makes ROOT call Error() which might,
205 // if not DefaultErrorHandler, be fatal.
206 // so find the right one by a simple linear search.
207 // not a large burden since it only happens infrequently and
208 // the list is normally quite short.
209 int nmeta = fNuMetaTree->GetEntries();
210 int nbmeta = 0;
211 for (int imeta = 0; imeta < nmeta; ++imeta ) {
212 nbmeta = fNuMetaTree->GetEntry(imeta);
213 if ( fCurMeta->metakey == metakey ) break;
214 }
215 // next condition should never happen
216 if ( fCurMeta->metakey != metakey ) {
217 fCurMeta = 0; // didn't find it!?
218 LOG("Flux",pERROR) << "Failed to find right metakey=" << metakey
219 << " (was " << oldkey << ") out of " << nmeta
220 << " entries";
221 }
222#endif
223 LOG("Flux",pDEBUG) << "Get meta " << metakey
224 << " (was " << oldkey << ") "
225 << fCurMeta->metakey
226 << " nb " << nbytes << " " << nbmeta;
227#ifdef __GENIE_LOW_LEVEL_MESG_ENABLED__
228 LOG("Flux",pDEBUG) << "Get meta " << *fCurMeta;
229#endif
230 }
231#ifdef __GENIE_LOW_LEVEL_MESG_ENABLED__
232 Int_t ifile = fNuFluxTree->GetFileNumber();
233 LOG("Flux",pDEBUG)
234 << "got " << fNNeutrinos << " nu, using fIEntry " << fIEntry
235 << " ifile " << ifile << " nbytes " << nbytes
236 << *fCurEntry << *fCurMeta;
237#endif
238
239 fIUse = 1;
240
241 // here we might want to do flavor oscillations or simple mappings
242 //RWH modify: fPdgC = fCurEntry->pdg;
243
244 // Check neutrino pdg against declared list of neutrino species declared
245 // by the current instance of the NuMI neutrino flux driver.
246 // No undeclared neutrino species will be accepted at this point as GENIE
247 // has already been configured to handle the specified list.
248 // Make sure that the appropriate list of flux neutrino species was set at
249 // initialization via GSimpleNtpFlux::SetFluxParticles(const PDGCodeList &)
250
251 // update the # POTs, sum of weights & number of neutrinos
252 // do this HERE (before rejecting flavors that users might be weeding out)
253 // in order to keep the POT accounting correct. This allows one to get
254 // the right normalization for generating only events from the intrinsic
255 // nu_e entries.
257 fSumWeight += this->Weight();
258 fNNeutrinos++;
259
260 if ( ! fPdgCList->ExistsInPDGCodeList(fCurEntry->pdg) ) {
261 /// user might modify list via SetFluxParticles() in order to reject certain
262 /// flavors, even if they're found in the file. So don't make a big fuss.
263 /// Spit out a single message and then stop reporting that flavor as problematic.
264 int badpdg = fCurEntry->pdg;
265 if ( ! fPdgCListRej->ExistsInPDGCodeList(badpdg) ) {
266 fPdgCListRej->push_back(badpdg);
267 LOG("Flux", pWARN)
268 << "Encountered neutrino specie (" << badpdg
269 << ") that wasn't in SetFluxParticles() list, "
270 << "\nDeclared list of neutrino species: " << *fPdgCList;
271 }
272 return false;
273 }
274
275 }
276
277 // Update the curr neutrino p4/x4 lorentz vector
278 double Ev = fCurEntry->E;
279 fP4.SetPxPyPzE(fCurEntry->px,fCurEntry->py,fCurEntry->pz,Ev);
280 double t0 = ((fIncludeVtxt) ? fCurEntry->vtxt : 0 );
281 fX4.SetXYZT(fCurEntry->vtxx,fCurEntry->vtxy,fCurEntry->vtxz,t0);
282
283 fWeight = fCurEntry->wgt;
284
285 if (Ev > fMaxEv) {
286 LOG("Flux", pWARN)
287 << "Flux neutrino energy exceeds declared maximum neutrino energy"
288 << "\nEv = " << Ev << "(> Ev{max} = " << fMaxEv << ")";
289 }
290
291 // if desired, move to user specified user coord z
292 if ( TMath::Abs(fZ0) < 1.0e30 ) this->MoveToZ0(fZ0);
293
294#ifdef __GENIE_LOW_LEVEL_MESG_ENABLED__
295 LOG("Flux", pINFO)
296 << "Generated neutrino: " << fIEntry
297#ifdef NOT_YET
298 << " run " << fCurNuMI->evtno
299 << " evtno " << fCurNuMI->evtno
300 << " entryno " << fCurNuMI->entryno
301#endif
302 << "\n pdg-code: " << fCurEntry->pdg << " wgt " << fCurEntry->wgt
303 << "\n p4: " << utils::print::P4AsShortString(&fP4)
304 << "\n x4: " << utils::print::X4AsString(&fX4);
305#endif
306 if ( Ev > fMaxEv ) {
307 LOG("Flux", pFATAL)
308 << "Generated neutrino had E_nu = " << Ev << " > " << fMaxEv
309 << " maximum ";
310 assert(0);
311 }
312
313 return true;
314}
315//___________________________________________________________________________
317{
318 // return distance (user units) between dk point and start position
319 // these are in beam units
320 return fCurEntry->dist;
321}
322//___________________________________________________________________________
323void GSimpleNtpFlux::MoveToZ0(double z0usr)
324{
325 // move ray origin to specified user z0
326 // move beam coord entry correspondingly
327
328 double pzusr = fP4.Pz();
329 if ( TMath::Abs(pzusr) < 1.0e-30 ) {
330 // neutrino is moving almost entirely in x-y plane
331 LOG("Flux", pWARN)
332 << "MoveToZ0(" << z0usr << ") not possible due to pz_usr (" << pzusr << ")";
333 return;
334 }
335
336 // Find the 3-position shift needed to move to the requested z coordinate
337 double dz = z0usr - fX4.Z();
338 double scale = dz / pzusr;
339
340 // LOG("Flux",pDEBUG)
341 // << "MoveToZ0: before x4=(" << fX4.X() << "," << fX4.Y() << "," << fX4.Z()
342 // << "," << fX4.T() << ") z0=" << z0usr << " pzusr=" << pzusr
343 // << " p4=(" << fP4.Px() << "," << fP4.Py() << "," << fP4.Pz() << "," << fP4.E() << ")";
344
345 TVector3 dx3( scale*fP4.Vect() );
346
347 // Find the corresponding time shift
348 double v = fP4.Beta() * constants::kLightSpeed
350 double dt = fP4.P() * dz / ( pzusr * v );
351
352 // Apply these shifts to update the neutrino 4-position
353 TLorentzVector dx4( dx3, dt );
354 fX4 += dx4;
355
356 // LOG("Flux",pDEBUG)
357 // << "MoveToZ0: after x4=(" << fX4.X() << "," << fX4.Y() << "," << fX4.Z()
358 // << "," << fX4.T() << ")"
359}
360
361//___________________________________________________________________________
363{
364 // do this if flux window changes or # of files changes
365
366 if (!fNuFluxTree) return; // not yet fully configured
367
368 fEffPOTsPerNu = ( (double)fFilePOTs / (double)fNEntries ) / fMaxWeight ;
369}
370
371//___________________________________________________________________________
372double GSimpleNtpFlux::UsedPOTs(void) const
373{
374// Compute current number of flux POTs
375
376 if (!fNuFluxTree) {
377 LOG("Flux", pWARN)
378 << "The flux driver has not been properly configured";
379 return 0;
380 }
381 return fAccumPOTs;
382}
383
384//___________________________________________________________________________
385void GSimpleNtpFlux::LoadBeamSimData(const std::vector<string>& patterns,
386 const std::string& config )
387{
388// Loads a beam simulation root file into the GSimpleNtpFlux driver.
389
390 fNuFluxFilePatterns = patterns;
391 std::vector<int> nfiles_from_pattern;
392
393 // create a (sorted) set of file names
394 // this also helps ensure that the same file isn't listed multiple times
395 std::set<std::string> fnames;
396
397 LOG("Flux", pINFO) << "LoadBeamSimData was passed " << patterns.size()
398 << " patterns";
399
400 for (size_t ipatt = 0; ipatt < patterns.size(); ++ipatt ) {
401 string pattern = patterns[ipatt];
402 nfiles_from_pattern.push_back(0);
403 LOG("Flux", pINFO)
404 << "Loading flux tree from ROOT file pattern ["
405 << std::setw(3) << ipatt << "] \"" << pattern << "\"";
406
407 // !WILDCARD only works for file name ... NOT directory
408 string dirname = gSystem->UnixPathName(gSystem->WorkingDirectory());
409 size_t slashpos = pattern.find_last_of("/");
410 size_t fbegin;
411 if ( slashpos != std::string::npos ) {
412 dirname = pattern.substr(0,slashpos);
413 LOG("Flux", pDEBUG) << "Look for flux using directory " << dirname;
414 fbegin = slashpos + 1;
415 } else { fbegin = 0; }
416
417 void* dirp = gSystem->OpenDirectory(gSystem->ExpandPathName(dirname.c_str()));
418 if ( dirp ) {
419 std::string basename =
420 pattern.substr(fbegin,pattern.size()-fbegin);
421 TRegexp re(basename.c_str(),kTRUE);
422 const char* onefile;
423 while ( ( onefile = gSystem->GetDirEntry(dirp) ) ) {
424 TString afile = onefile;
425 if ( afile=="." || afile==".." ) continue;
426 if ( basename!=afile && afile.Index(re) == kNPOS ) continue;
427 std::string fullname = dirname + "/" + afile.Data();
428 fnames.insert(fullname);
429 nfiles_from_pattern[ipatt]++;
430 }
431 gSystem->FreeDirectory(dirp);
432 } // legal directory
433 } // loop over patterns
434
435 size_t indx = 0;
436 std::set<string>::const_iterator sitr = fnames.begin();
437 for ( ; sitr != fnames.end(); ++sitr, ++indx) {
438 string filename = *sitr;
439 //std::cout << " [" << std::setw(3) << indx << "] \""
440 // << filename << "\"" << std::endl;
441 bool isok = true;
442 // this next test only works for local files, so we can't do that
443 // if we want to stream via xrootd
444 // ! (gSystem->AccessPathName(filename.c_str()));
445 if ( ! isok ) continue;
446 // open the file to see what it contains
447 LOG("Flux", pINFO) << "Load file " << filename;
448
449 TFile* tf = TFile::Open(filename.c_str(),"READ");
450 TTree* etree = (TTree*)tf->Get("flux");
451 if ( etree ) {
452 TTree* mtree = (TTree*)tf->Get("meta");
453 // add the file to the chain
454 LOG("Flux", pDEBUG) << "AddFile " << filename
455 << " etree " << etree << " meta " << mtree;
456 this->AddFile(etree,mtree,filename);
457
458 } // found a GSimpleNtpEntry "flux" tree
459 tf->Close();
460 delete tf;
461 } // loop over sorted file names
462
463 // this will open all files and read headers!!
464 fNEntries = fNuFluxTree->GetEntries();
465
466 if ( fNEntries == 0 ) {
467 LOG("Flux", pERROR)
468 << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!";
469 LOG("Flux", pERROR)
470 << "Loaded flux tree contains " << fNEntries << " entries";
471 LOG("Flux", pERROR)
472 << "Was passed the file patterns: ";
473 for (size_t ipatt = 0; ipatt < patterns.size(); ++ipatt ) {
474 string pattern = patterns[ipatt];
475 LOG("Flux", pERROR)
476 << " [" << std::setw(3) << ipatt <<"] " << pattern;
477 }
478 LOG("Flux", pERROR)
479 << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!";
480 } else {
481 LOG("Flux", pNOTICE)
482 << "Loaded flux tree contains " << fNEntries << " entries"
483 << " from " << fnames.size() << " unique files";
484 for (size_t ipatt = 0; ipatt < patterns.size(); ++ipatt ) {
485 string pattern = patterns[ipatt];
486 LOG("Flux", pINFO)
487 << " pattern: " << pattern << " yielded "
488 << nfiles_from_pattern[ipatt] << " files";
489 }
490 }
491
492 int sba_status[3] = { -999, -999, -999 };
493 // "entry" branch isn't optional ... contains the neutrino info
494#if ROOT_VERSION_CODE >= ROOT_VERSION(5,26,0)
495 sba_status[0] =
496#endif
497 fNuFluxTree->SetBranchAddress("entry",&fCurEntry);
498#if ROOT_VERSION_CODE >= ROOT_VERSION(5,26,0)
499 if ( sba_status[0] < 0 ) {
500 LOG("Flux", pFATAL)
501 << "flux chain has no \"entry\" branch " << sba_status[0];
502 assert(0);
503 }
504#endif
505 //TBranch* bentry = fNuFluxTree->GetBranch("entry");
506 //bentry->SetAutoDelete(false);
507
508 if ( OptionalAttachBranch("numi") ) {
509#if ROOT_VERSION_CODE >= ROOT_VERSION(5,26,0)
510 sba_status[1] =
511#endif
512 fNuFluxTree->SetBranchAddress("numi",&fCurNuMI);
513 //TBranch* bnumi = fNuFluxTree->GetBranch("numi");
514 //bnumi->SetAutoDelete(false);
515 } else { delete fCurNuMI; fCurNuMI = 0; }
516
517 if ( OptionalAttachBranch("aux") ) {
518#if ROOT_VERSION_CODE >= ROOT_VERSION(5,26,0)
519 sba_status[2] =
520#endif
521 fNuFluxTree->SetBranchAddress("aux",&fCurAux);
522 //TBranch* baux = fNuFluxTree->GetBranch("aux");
523 //baux->SetAutoDelete(false);
524 } else { delete fCurAux; fCurAux = 0; }
525
526 LOG("Flux", pDEBUG)
527 << " SetBranchAddress status: "
528 << " \"entry\"=" << sba_status[0]
529 << " \"numi\"=" << sba_status[1]
530 << " \"aux\"=" << sba_status[2];
531
532 // attach requested branches
533
534 if (fMaxWeight<=0) {
535 LOG("Flux", pDEBUG)
536 << "Run ProcessMeta() as part of LoadBeamSimData";
537 this->ProcessMeta();
538 }
539
540 // current ntuple cycle # (flux ntuples may be recycled)
541 fICycle = 0;
542 // pick a starting entry index [0:fNEntries-1]
543 // pretend we just used up the the previous one
545 fIUse = 9999999;
546 fIEntry = rnd->RndFlux().Integer(fNEntries) - 1;
547 if ( config.find("no-offset-index") != string::npos ) {
548 LOG("Flux",pINFO) << "Config saw \"no-offset-index\"";
549 fIEntry = -1;
550 }
551 LOG("Flux",pINFO) << "Start with entry fIEntry=" << fIEntry;
552
553 // don't count things we used to estimate max weight
554 fNEntriesUsed = 0;
555 fSumWeight = 0;
556 fNNeutrinos = 0;
557 fAccumPOTs = 0;
558
559 LOG("Flux",pDEBUG) << "about to CalcEffPOTsPerNu";
560 this->CalcEffPOTsPerNu();
561
562}
563//___________________________________________________________________________
564void GSimpleNtpFlux::GetBranchInfo(std::vector<std::string>& branchNames,
565 std::vector<std::string>& branchClassNames,
566 std::vector<void**>& branchObjPointers)
567{
568 // allow flux driver to report back current status and/or ntuple entry
569 // info for possible recording in the output file by supplying
570 // the class name, and a pointer to the object that will be filled
571 // as well as a suggested name for the branch.
572
573 if ( fCurEntry ) {
574 branchNames.push_back("simple");
575 branchClassNames.push_back("genie::flux::GSimpleNtpEntry");
576 branchObjPointers.push_back((void**)&fCurEntry);
577 }
578
579 if ( fCurNuMI ) {
580 branchNames.push_back("numi");
581 branchClassNames.push_back("genie::flux::GSimpleNtpNuMI");
582 branchObjPointers.push_back((void**)&fCurNuMI);
583 }
584
585 if ( fCurAux ) {
586 branchNames.push_back("aux");
587 branchClassNames.push_back("genie::flux::GSimpleNtpAux");
588 branchObjPointers.push_back((void**)&fCurAux);
589 }
590}
592
593//___________________________________________________________________________
595{
596
597 fAlreadyUnwgt = false;
598 fFilePOTs = 0;
599 double minwgt = +1.0e10;
600 double maxwgt = -1.0e10;
601 double maxenu = 0.0;
602
603 // PDGLibrary* pdglib = PDGLibrary::Instance(); // get initialized now
604
605 if ( fAllFilesMeta ) {
606 fNuMetaTree->SetBranchAddress("meta",&fCurMeta);
607#ifdef USE_INDEX_FOR_META
608 int nindices = fNuMetaTree->BuildIndex("metakey"); // key used to tie entries to meta data
609 LOG("Flux", pDEBUG) << "ProcessMeta() BuildIndex nindices " << nindices;
610#endif
611 int nmeta = fNuMetaTree->GetEntries();
612 for (int imeta = 0; imeta < nmeta; ++imeta ) {
613 fNuMetaTree->GetEntry(imeta);
614#ifdef __GENIE_LOW_LEVEL_MESG_ENABLED__
615 LOG("Flux", pNOTICE) << "ProcessMeta() ifile " << imeta
616 << " (of " << fNFiles
617 << ") " << *fCurMeta;
618#endif
619 minwgt = TMath::Min(minwgt,fCurMeta->minWgt);
620 maxwgt = TMath::Max(maxwgt,fCurMeta->maxWgt);
621 maxenu = TMath::Max(maxenu,fCurMeta->maxEnergy);
622 fFilePOTs += fCurMeta->protons;
623 for (size_t i = 0; i < fCurMeta->pdglist.size(); ++i)
624 fPdgCList->push_back(fCurMeta->pdglist[i]);
625 }
626 if ( minwgt == 1.0 && maxwgt == 1.0 ) fAlreadyUnwgt = true;
627 fMaxWeight = maxwgt;
628 this->SetMaxEnergy(maxenu);
629
630 } else {
631 //
632 LOG("Flux", pFATAL) << "ProcessMeta() not all files have metadata";
633 // for now PUNT ... eventually could scan all the entries
634 }
635
636#ifdef __GENIE_LOW_LEVEL_MESG_ENABLED__
637 LOG("Flux", pNOTICE) << "ProcessMeta() Maximum flux weight = " << fMaxWeight
638 << ", energy = " << fMaxEv
639 << ", AlreadyUnwgt=" << (fAlreadyUnwgt?"true":"false");
640#endif
641
642 fCurMeta->Reset();
643 fIFileNumber = -999;
644
645}
646//___________________________________________________________________________
648{
649 fMaxEv = TMath::Max(0.,Ev);
650
651 LOG("Flux", pINFO)
652 << "Declared maximum flux neutrino energy: " << fMaxEv;
653}
654//___________________________________________________________________________
656{
657// With nuse > 1 then the same entry in the file is used "nuse" times
658// before moving on to the next entry in the ntuple
659
660 fNUse = TMath::Max(1L, nuse);
661}
662//___________________________________________________________________________
663void GSimpleNtpFlux::GetFluxWindow(TVector3& p0, TVector3& p1, TVector3& p2) const
664{
665 // return flux window points
666
667 p0 = TVector3(fCurMeta->windowBase[0],
668 fCurMeta->windowBase[1],
669 fCurMeta->windowBase[2]);
670 p1 = p0 + TVector3(fCurMeta->windowDir1[0],
671 fCurMeta->windowDir1[1],
672 fCurMeta->windowDir1[2]);
673 p2 = p0 + TVector3(fCurMeta->windowDir2[0],
674 fCurMeta->windowDir2[1],
675 fCurMeta->windowDir2[2]);
676
677}
678
679//___________________________________________________________________________
681{
682 LOG("Flux", pNOTICE) << "CurrentEntry:" << *fCurEntry;
683}
684//___________________________________________________________________________
685void GSimpleNtpFlux::Clear(Option_t * opt)
686{
687// Clear the driver state
688//
689 LOG("Flux", pWARN) << "GSimpleNtpFlux::Clear(" << opt << ") called";
690 // do it in all cases, but EVGDriver/GMCJDriver will pass "CycleHistory"
691
692 fICycle = 0;
693
694 fSumWeight = 0;
695 fNNeutrinos = 0;
696 fAccumPOTs = 0;
697
698}
699//___________________________________________________________________________
700void GSimpleNtpFlux::GenerateWeighted(bool gen_weighted)
701{
702// Set whether to generate weighted rays
703//
704 fGenWeighted = gen_weighted;
705}
706//___________________________________________________________________________
708{
709 LOG("Flux", pINFO) << "Initializing GSimpleNtpFlux driver";
710
711 fMaxEv = 0;
712 fEnd = false;
713
718
719 fCurEntryCopy = 0;
720 fCurNuMICopy = 0;
721 fCurAuxCopy = 0;
722
723 fNuFluxTree = new TChain("flux");
724 fNuMetaTree = new TChain("meta");
725
726 //fNuFluxFilePatterns = "";
727 fNuFluxBranchRequest = "entry,numi,aux"; // all branches
728
729 fNFiles = 0;
730
731 fNEntries = 0;
732 fIEntry = -1;
733 fIFileNumber = 0;
734 fICycle = 0;
735 fNUse = 1;
736 fIUse = 999999;
737
738 fFilePOTs = 0;
739
740 fMaxWeight = -1;
741
742 fSumWeight = 0;
743 fNNeutrinos = 0;
744 fNEntriesUsed = 0;
745 fEffPOTsPerNu = 0;
746 fAccumPOTs = 0;
747
748 fGenWeighted = false;
749 fAllFilesMeta = true;
750 fAlreadyUnwgt = false;
751
752 fIncludeVtxt = true;
753
754 this->SetDefaults();
755 this->ResetCurrent();
756}
757//___________________________________________________________________________
759{
760
761// - Set the default flux neutrino start z position at use flux window
762// - Set number of cycles to 1
763
764 LOG("Flux", pINFO) << "Setting default GSimpleNtpFlux driver options";
765
766 this->SetUpstreamZ (-3.4e38); // way upstream ==> use flux window
767 this->SetNumOfCycles (0);
768 this->SetEntryReuse (1);
769}
770//___________________________________________________________________________
772{
773// reset running values of neutrino pdg-code, 4-position & 4-momentum
774// and the input ntuple leaves
775
776 if (fCurEntry) fCurEntry->Reset();
777 if (fCurNuMI) fCurNuMI->Reset();
778 if (fCurAux) fCurAux->Reset();
779 //allow caching//if (fCurMeta) fCurMeta->Reset();
780}
781//___________________________________________________________________________
783{
784 LOG("Flux", pINFO) << "Cleaning up...";
785
786 if (fPdgCList) delete fPdgCList;
787 if (fPdgCListRej) delete fPdgCListRej;
788 if (fCurEntry) delete fCurEntry;
789 if (fCurNuMI) delete fCurNuMI;
790 if (fCurAux) delete fCurAux;
791 if (fCurMeta) delete fCurMeta;
792
793 if (fNuFluxTree) delete fNuFluxTree;
794 if (fNuMetaTree) delete fNuMetaTree;
795
796 LOG("Flux", pNOTICE)
797 << " flux file cycles: " << fICycle << " of " << fNCycles
798 << ", entry " << fIEntry << " use: " << fIUse << " of " << fNUse;
799}
800
801//___________________________________________________________________________
802void GSimpleNtpFlux::AddFile(TTree* fluxtree, TTree* metatree, string fname)
803{
804 // Add a file to the chain
805 if ( ! fluxtree ) return;
806
807 ULong64_t nentries = fluxtree->GetEntries();
808
809 int stat = fNuFluxTree->AddFile(fname.c_str());
810 if ( metatree ) fNuMetaTree->AddFile(fname.c_str());
811 else fAllFilesMeta = false;
812
813 LOG("Flux",pINFO)
814 << "flux->AddFile() of " << nentries
815 << " " << ((metatree)?"[+meta]":"[no-meta]")
816 << " [status=" << stat << "]"
817 << " entries in file: " << fname;
818
819 if ( stat != 1 ) return;
820
821 fNFiles++;
822
823}
824
825//___________________________________________________________________________
826
828{
829
830 if ( fNuFluxBranchRequest.find(name) == string::npos ) {
831 LOG("Flux", pINFO)
832 << "no request for \"" << name <<"\" branch ";
833 return false;
834 }
835
836 if ( ( fNuFluxTree->GetBranch(name.c_str()) ) ) return true;
837
838 LOG("Flux", pINFO)
839 << "no \"" << name << "\" branch in the \"flux\" tree";
840 return false;
841}
842
843//___________________________________________________________________________
845
847{
848 wgt = 0.;
849 vtxx = 0.;
850 vtxy = 0.;
851 vtxz = 0.;
852 vtxt = 0.;
853 dist = 0.;
854 px = 0.;
855 py = 0.;
856 pz = 0.;
857 E = 0.;
858
859 pdg = 0;
860 metakey = 0;
861}
862
863void GSimpleNtpEntry::Print(const Option_t* /* opt */ ) const
864{
865 std::cout << *this << std::endl;
866}
867
868//___________________________________________________________________________
870
872{
873 tpx = tpy = tpz = 0.;
874 vx = vy = vz = 0.;
875 pdpx = pdpy = pdpz = 0.;
876 pppx = pppy = pppz = 0.;
877
878 ndecay = 0;
879 ptype = 0;
880 ppmedium = 0;
881 tptype = 0;
882 run = -1;
883 evtno = -1;
884 entryno = -1;
885}
886
887void GSimpleNtpNuMI::Print(const Option_t* /* opt */ ) const
888{
889 std::cout << *this << std::endl;
890}
891
892//___________________________________________________________________________
894
896{
897 auxint.clear();
898 auxdbl.clear();
899}
900
901void GSimpleNtpAux::Print(const Option_t* /* opt */ ) const
902{
903 std::cout << *this << std::endl;
904}
905
906//___________________________________________________________________________
907
908
910 : TObject() //, nflavors(0), flavor(0)
911{
912 Reset();
913}
914
919
921{
922
923 pdglist.clear();
924 maxEnergy = 0.;
925 minWgt = 0.;
926 maxWgt = 0.;
927 protons = 0.;
928 windowBase[0] = 0.;
929 windowBase[1] = 0.;
930 windowBase[2] = 0.;
931 windowDir1[0] = 0.;
932 windowDir1[1] = 0.;
933 windowDir1[2] = 0.;
934 windowDir2[0] = 0.;
935 windowDir2[1] = 0.;
936 windowDir2[2] = 0.;
937
938 auxintname.clear();
939 auxdblname.clear();
940 infiles.clear();
941
942 seed = 0;
943 metakey = 0;
944}
945
947{
948 bool found = false;
949 for (size_t i=0; i < pdglist.size(); ++i)
950 if ( pdglist[i] == nupdg) found = true;
951 if ( ! found ) pdglist.push_back(nupdg);
952
953 /* // OLD fashion array
954 bool found = false;
955 for (int i=0; i < nflavors; ++i) if ( flavor[i] == nupdg ) found = true;
956 if ( ! found ) {
957 Int_t* old_list = flavor;
958 flavor = new Int_t[nflavors+1];
959 for (int i=0; i < nflavors; ++i) flavor[i] = old_list[i];
960 flavor[nflavors] = nupdg;
961 nflavors++;
962 delete [] old_list;
963 }
964 */
965}
966
967void GSimpleNtpMeta::Print(const Option_t* /* opt */ ) const
968{
969 std::cout << *this << std::endl;
970}
971
972//___________________________________________________________________________
973
974
975namespace genie {
976namespace flux {
977
978 ostream & operator << (
979 ostream & stream, const genie::flux::GSimpleNtpEntry & entry)
980 {
981 stream << "\nGSimpleNtpEntry "
982 << " PDG " << entry.pdg
983 << " wgt " << entry.wgt
984 << " ( metakey " << entry.metakey << " )"
985 << "\n vtx [" << entry.vtxx << "," << entry.vtxy << ","
986 << entry.vtxz << ", t=" << entry.vtxt << "] dist " << entry.dist
987 << "\n p4 [" << entry.px << "," << entry.py << ","
988 << entry.pz << "," << entry.E << "]";
989 return stream;
990 }
991
992
993ostream & operator << (ostream & stream,
994 const genie::flux::GSimpleNtpNuMI & numi)
995{
996 stream << "\nGSimpleNtpNuMI "
997 << "run " << numi.run
998 << " evtno " << numi.evtno
999 << " entryno " << numi.entryno
1000 << "\n ndecay " << numi.ndecay << " ptype " << numi.ptype
1001 << "\n tptype " << numi.tptype << " ppmedium " << numi.ppmedium
1002 << "\n tp[xyz] [" << numi.tpx << "," << numi.tpy << "," << numi.tpz << "]"
1003 << "\n v[xyz] [" << numi.vx << "," << numi.vy << "," << numi.vz << "]"
1004 << "\n pd[xyz] [" << numi.pdpx << "," << numi.pdpy << "," << numi.pdpz << "]"
1005 << "\n pp[xyz] [" << numi.pppx << "," << numi.pppy << "," << numi.pppz << "]"
1006 ;
1007 return stream;
1008}
1009
1010 ostream & operator << (
1011 ostream & stream, const genie::flux::GSimpleNtpAux & aux)
1012 {
1013 stream << "\nGSimpleNtpAux ";
1014 size_t nInt = aux.auxint.size();
1015 stream << "\n ints: ";
1016 for (size_t ijInt=0; ijInt < nInt; ++ijInt)
1017 stream << " " << aux.auxint[ijInt];
1018 size_t nDbl = aux.auxdbl.size();
1019 stream << "\n doubles: ";
1020 for (size_t ijDbl=0; ijDbl < nDbl; ++ijDbl)
1021 stream << " " << aux.auxdbl[ijDbl];
1022
1023 return stream;
1024 }
1025
1026 ostream & operator << (
1027 ostream & stream, const genie::flux::GSimpleNtpMeta & meta)
1028 {
1029 size_t nf = meta.pdglist.size();
1030 stream << "\nGSimpleNtpMeta " << nf << " flavors: ";
1031 for (size_t i=0; i<nf; ++i) stream << " " << meta.pdglist[i];
1032
1033 //stream << "\nGSimpleNtpMeta " << meta.nflavors
1034 // << " flavors: ";
1035 //for (int i=0; i< meta.nflavors; ++i) stream << " " << meta.flavor[i];
1036
1037 stream << "\n maxEnergy " << meta.maxEnergy
1038 << " min/maxWgt " << meta.minWgt << "/" << meta.maxWgt
1039 << " protons " << meta.protons
1040 << " metakey " << meta.metakey
1041 << "\n windowBase [" << meta.windowBase[0] << ","
1042 << meta.windowBase[1] << "," << meta.windowBase[2] << "]"
1043 << "\n windowDir1 [" << meta.windowDir1[0] << ","
1044 << meta.windowDir1[1] << "," << meta.windowDir1[2] << "]"
1045 << "\n windowDir2 [" << meta.windowDir2[0] << ","
1046 << meta.windowDir2[1] << "," << meta.windowDir2[2] << "]";
1047
1048 size_t nInt = meta.auxintname.size();
1049 if ( nInt > 0 ) stream << "\n aux ints: ";
1050 for (size_t ijInt=0; ijInt < nInt; ++ijInt)
1051 stream << " " << meta.auxintname[ijInt];
1052
1053 size_t nDbl = meta.auxdblname.size();
1054 if ( nDbl > 0 ) stream << "\n aux doubles: ";
1055 for (size_t ijDbl=0; ijDbl < nDbl; ++ijDbl)
1056 stream << " " << meta.auxdblname[ijDbl];
1057
1058 size_t nfiles = meta.infiles.size();
1059 stream << "\n " << nfiles << " input files: ";
1060 UInt_t nprint = TMath::Min(UInt_t(nfiles),
1062 for (UInt_t ifiles=0; ifiles < nprint; ++ifiles)
1063 stream << "\n " << meta.infiles[ifiles];
1064
1065 stream << "\n input seed: " << meta.seed;
1066
1067 return stream;
1068 }
1069
1070
1071}//flux
1072}//genie
1073
1074//___________________________________________________________________________
1075
1077{
1078
1079 std::ostringstream s;
1080 PDGCodeList::const_iterator itr = fPdgCList->begin();
1081 for ( ; itr != fPdgCList->end(); ++itr) s << (*itr) << " ";
1082 s << "[rejected: ";
1083 itr = fPdgCListRej->begin();
1084 for ( ; itr != fPdgCListRej->end(); ++itr) s << (*itr) << " ";
1085 s << " ] ";
1086
1087 std::ostringstream fpattout;
1088 for (size_t i = 0; i < fNuFluxFilePatterns.size(); ++i)
1089 fpattout << "\n [" << std::setw(3) << i << "] " << fNuFluxFilePatterns[i];
1090
1091 std::ostringstream flistout;
1092 std::vector<std::string> flist = GetFileList();
1093 for (size_t i = 0; i < flist.size(); ++i)
1094 flistout << "\n [" << std::setw(3) << i << "] " << flist[i];
1095
1096 LOG("Flux", pNOTICE)
1097 << "GSimpleNtpFlux Config:"
1098 << "\n Enu_max " << fMaxEv
1099 << "\n pdg-codes: " << s.str() << "\n "
1100 << "\"flux\" " << fNEntries << " entries, "
1101 << "\"meta\" " << fNFiles << " entries"
1102 << " (FilePOTs " << fFilePOTs << ") in files:"
1103 << flistout.str()
1104 << "\n from file patterns: "
1105 << fpattout.str()
1106 << "\n wgt max=" << fMaxWeight
1107 << "\n Z0 pushback " << fZ0
1108 << "\n used entry " << fIEntry << " " << fIUse << "/" << fNUse
1109 << " times, in " << fICycle << "/" << fNCycles << " cycles"
1110 << "\n SumWeight " << fSumWeight << " for " << fNNeutrinos << " neutrinos"
1111 << " with " << fNEntriesUsed << " entries read"
1112 << "\n EffPOTsPerNu " << fEffPOTsPerNu << " AccumPOTs " << fAccumPOTs
1113 << "\n GenWeighted \"" << (fGenWeighted?"true":"false") << "\""
1114 << " AlreadyUnwgt \"" << (fAlreadyUnwgt?"true":"false") << "\""
1115 << " AllFilesMeta \"" << (fAllFilesMeta?"true":"false") << "\"";
1116
1117}
1118
1119//___________________________________________________________________________
1120std::vector<std::string> GSimpleNtpFlux::GetFileList()
1121{
1122 std::vector<std::string> flist;
1123 TObjArray *fileElements=fNuFluxTree->GetListOfFiles();
1124 TIter next(fileElements);
1125 TChainElement *chEl=0;
1126 while (( chEl=(TChainElement*)next() )) {
1127 flist.push_back(chEl->GetTitle());
1128 }
1129 return flist;
1130}
1131
1132//___________________________________________________________________________
ClassImp(EventRecord) namespace genie
#define FLUXDRIVERREG4(_nsa, _nsb, _name, _fqname)
#define pNOTICE
Definition Messenger.h:61
#define pINFO
Definition Messenger.h:62
#define pERROR
Definition Messenger.h:59
#define pFATAL
Definition Messenger.h:56
#define pDEBUG
Definition Messenger.h:63
#define LOG(stream, priority)
A macro that returns the requested log4cpp::Category appending a string (using the FILE,...
Definition Messenger.h:96
#define pWARN
Definition Messenger.h:60
Most commonly used PDG codes. A set of utility functions to handle PDG codes is provided in PDGUtils.
A singleton holding random number generator classes. All random number generation in GENIE should tak...
Definition RandomGen.h:29
static RandomGen * Instance()
Access instance.
Definition RandomGen.cxx:74
TRandom3 & RndFlux(void) const
rnd number generator used by flux drivers
Definition RandomGen.h:71
GENIE interface for uniform flux exposure iterface.
PDGCodeList * fPdgCList
list of neutrino pdg-codes to generate
virtual void SetNumOfCycles(long int ncycle)
limit cycling through input files
virtual void SetUpstreamZ(double z0)
PDGCodeList * fPdgCListRej
list of nu pdg-codes seen but rejected
void Print(const Option_t *opt="") const
std::vector< Int_t > auxint
additional ints associated w/ entry
std::vector< Double_t > auxdbl
additional doubles associated w/ entry
Double_t vtxx
x position in lab frame (meters)
Double_t E
energy in lab frame
Double_t dist
distance from hadron decay
Double_t px
x momentum in lab frame (GeV)
Double_t vtxt
time of ray start (seconds)
Double_t vtxz
z position in lab frame
Double_t py
y momentum in lab frame
Double_t vtxy
y position in lab frame
UInt_t metakey
key to meta data
Double_t pz
z momentum in lab frame
void Print(const Option_t *opt="") const
A GENIE flux driver using a simple ntuple format.
bool fIncludeVtxt
does fX4 include CurEntry.vtxt or 0
bool fEnd
end condition reached
const genie::flux::GSimpleNtpEntry * GetCurrentEntry(void)
GSimpleNtpEntry.
void Clear(Option_t *opt)
reset state variables based on opt
void SetEntryReuse(long int nuse=1)
long int fNNeutrinos
number of flux neutrinos thrown so far
double GetDecayDist() const
dist (user units) from dk to current pos
GSimpleNtpNuMI * fCurNuMI
current "numi" branch extra info
void GenerateWeighted(bool gen_weighted)
set whether to generate weighted or unweighted neutrinos
virtual double GetTotalExposure() const
GFluxExposureI interface.
bool fGenWeighted
does GenerateNext() give weights?
double fMaxWeight
max flux neutrino weight in input file
double fEffPOTsPerNu
what a entry is worth ...
void GetFluxWindow(TVector3 &p1, TVector3 &p2, TVector3 &p3) const
3 points define a plane in beam coordinate
GSimpleNtpEntry * fCurEntryCopy
current entry
bool fAlreadyUnwgt
are input files already unweighted
bool OptionalAttachBranch(std::string bname)
virtual void GetBranchInfo(std::vector< std::string > &branchNames, std::vector< std::string > &branchClassNames, std::vector< void ** > &branchObjPointers)
TChain * fNuFluxTree
TTree // REF ONLY.
std::vector< std::string > GetFileList()
list of files currently part of chain
long int fNUse
how often to use same entry in a row
bool End(void)
true if no more flux nu's can be thrown (eg reaching end of beam sim ntuples)
GSimpleNtpAux * fCurAuxCopy
current "aux" branch extra info
void AddFile(TTree *fluxtree, TTree *metatree, string fname)
TLorentzVector fX4
reconstituted position vector
double fMaxEv
maximum energy
virtual void LoadBeamSimData(const std::vector< string > &filenames, const std::string &det_loc)
double Weight(void)
returns the flux neutrino weight (if any)
TLorentzVector fP4
reconstituted p4 vector
long int fNEntriesUsed
number of entries read from files
void ProcessMeta(void)
scan for max flux energy, weight
GSimpleNtpMeta * fCurMeta
current meta data
Int_t fIFileNumber
which file for the current entry
virtual long int NFluxNeutrinos() const
long int fIUse
current # of times an entry has been used
std::vector< string > fNuFluxFilePatterns
(potentially wildcarded) path(s)
Long64_t fIEntry
current flux ntuple entry
GSimpleNtpNuMI * fCurNuMICopy
current "numi" branch extra info
GSimpleNtpAux * fCurAux
current "aux" branch extra info
virtual TTree * GetMetaDataTree()
void PrintConfig()
print the current configuration
bool fAllFilesMeta
do all files in chain have meta data
GSimpleNtpEntry * fCurEntry
current entry
void MoveToZ0(double z0)
move ray origin to user coord Z0
double fAccumPOTs
POTs used so far.
void PrintCurrent(void)
print current entry from leaves
bool GenerateNext(void)
generate the next flux neutrino (return false in err)
double fWeight
current neutrino weight
int fNFiles
number of files in chain
double fSumWeight
sum of weights for nus thrown so far
TChain * fNuMetaTree
TTree // REF ONLY.
string fNuFluxBranchRequest
list of requested branches "entry,numi,au"
void SetMaxEnergy(double Ev)
specify maximum flx neutrino energy
Long64_t fNEntries
number of flux ntuple entries
Double_t windowBase[3]
x,y,z position of window base point
Double_t windowDir1[3]
dx,dy,dz of window direction 1
Double_t windowDir2[3]
dx,dy,dz of window direction 2
Double_t maxWgt
maximum weight
std::vector< std::string > infiles
list of input files
static UInt_t mxfileprint
allow user to limit # of files to print
Double_t minWgt
minimum weight
std::vector< Int_t > pdglist
list of neutrino flavors
UInt_t metakey
index key to tie to individual entries
Int_t seed
random seed used in generation
std::vector< std::string > auxdblname
tagname of aux doubles associated w/ entry
Double_t protons
represented number of protons-on-target
std::vector< std::string > auxintname
tagname of aux ints associated w/ entry
Double_t maxEnergy
maximum energy
void Print(const Option_t *opt="") const
Int_t ppmedium
tracking medium where parent was produced
Int_t ptype
parent type (PDG)
Double_t vx
vertex position of hadron/muon decay
void Print(const Option_t *opt="") const
Double_t pdpx
nu parent momentum at time of decay
Int_t tptype
parent particle type at target exit
Double_t pppx
nu parent momentum at production point
Double_t tpx
parent particle px at target exit
void Initialize(void)
GENIE flux drivers.
ostream & operator<<(ostream &stream, const genie::flux::GJPARCNuFluxPassThroughInfo &info)
static constexpr double meter
Definition Units.h:35
static constexpr double second
Definition Units.h:37
string X4AsString(const TLorentzVector *x)
string P4AsShortString(const TLorentzVector *p)
THE MAIN GENIE PROJECT NAMESPACE
Definition AlgCmp.h:25