Skip to content

Commit e3fbd3a

Browse files
committed
Implementation of time adaptability
1 parent 9757ce2 commit e3fbd3a

1 file changed

Lines changed: 92 additions & 6 deletions

File tree

MC/config/common/external/generator/TPCLoopers.C

Lines changed: 92 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,54 @@ class GenTPCLoopers : public Generator
243243
return true;
244244
}
245245

246+
Bool_t generateEvent(TH1D* t_hist)
247+
{
248+
// Clear the vector of pairs
249+
mGenPairs.clear();
250+
// Clear the vector of compton electrons
251+
mGenElectrons.clear();
252+
// Set number of loopers if poissonian params are available
253+
if (mPoissonSet)
254+
{
255+
mNLoopersPairs = static_cast<short int>(std::round(mMultiplier[0] * PoissonPairs()));
256+
}
257+
if (mGaussSet)
258+
{
259+
mNLoopersCompton = static_cast<short int>(std::round(mMultiplier[1] * GaussianElectrons()));
260+
}
261+
// Find the time histogram edge
262+
double time_constraint = t_hist->GetXaxis()->GetXmax();
263+
LOG(info) << "Time constraint for loopers: " << time_constraint << " ns";
264+
// Generate pairs
265+
for (int i = 0; i < mNLoopersPairs; ++i)
266+
{
267+
std::vector<double> pair = mONNX_pair->generate_sample();
268+
// Apply the inverse transformation using the scaler
269+
std::vector<double> transformed_pair = mScaler_pair->inverse_transform(pair);
270+
// Check if the time constraint is satisfied
271+
while ((transformed_pair[9] / 1e9) > time_constraint)
272+
{
273+
transformed_pair[9] = t_hist->GetRandom() * 1e9; // Regenerate time if it exceeds the constraint, multiplied by 1e9 to account for ratio in importParticles
274+
}
275+
LOG(info) << "Transformed pair time: " << transformed_pair[9] / 1e9 << " ns";
276+
mGenPairs.push_back(transformed_pair);
277+
}
278+
// Generate compton electrons
279+
for (int i = 0; i < mNLoopersCompton; ++i)
280+
{
281+
std::vector<double> electron = mONNX_compton->generate_sample();
282+
// Apply the inverse transformation using the scaler
283+
std::vector<double> transformed_electron = mScaler_compton->inverse_transform(electron);
284+
while ((transformed_electron[6] / 1e9) > time_constraint)
285+
{
286+
transformed_electron[6] = t_hist->GetRandom() * 1e9; // Regenerate time if it exceeds the constraint, multiplied by 1e9 to account for ratio in importParticles
287+
}
288+
LOG(info) << "Transformed electron time: " << transformed_electron[6] / 1e9 << " ns";
289+
mGenElectrons.push_back(transformed_electron);
290+
}
291+
return true;
292+
}
293+
246294
Bool_t importParticles() override
247295
{
248296
// Get looper pairs from the event
@@ -390,12 +438,18 @@ class GenLoopersInjector : public Generator
390438
Generator::setEnergyUnit(1.0);
391439
}
392440

393-
void setAdaptiveLoopers(Bool_t adaptive)
441+
void setAdaptiveLoopers(Bool_t &adaptive)
394442
{
395443
mAdaptiveLoopers = adaptive;
396444
LOG(info) << "Adaptive loopers: " << (mAdaptiveLoopers ? "ON" : "OFF");
397445
}
398446

447+
void setTimeConstraint(Bool_t &constraint)
448+
{
449+
mTimeConstraint = constraint;
450+
LOG(info) << "Time constraint: " << (mTimeConstraint ? "ON" : "OFF");
451+
}
452+
399453
void setLoopsFractions(float &fraction, float &fractionPairs)
400454
{
401455
if (fraction < 0 || fraction >= 1)
@@ -458,6 +512,19 @@ class GenLoopersInjector : public Generator
458512
// apply unit transformation of sub-generator
459513
unit_transformer(p, pos_unit, time_unit, energy_unit, mom_unit);
460514
}
515+
// Print Maximum values of time
516+
double maxTime = 0.0;
517+
double minTime = 0.0;
518+
for (const auto &p : parts) {
519+
if (p.T() > maxTime) {
520+
maxTime = p.T();
521+
}
522+
if (p.T() < minTime) {
523+
minTime = p.T();
524+
}
525+
}
526+
LOG(info) << "Maximum time in the event: " << maxTime;
527+
LOG(info) << "Minimum time in the event: " << minTime;
461528
return parts;
462529
}
463530

@@ -475,9 +542,20 @@ class GenLoopersInjector : public Generator
475542
LOG(info) << "Size of kineparts: " << kineparts.size();
476543
mParticles.insert(mParticles.end(), kineparts.begin(), kineparts.end());
477544
LOG(info) << "Size mParticles at kine stage " << mParticles.size();
545+
double maxTime = 0.0;
546+
// Find the maximum time in the imported particles
547+
for (const auto &p : mParticles) {
548+
if (p.T() > maxTime) {
549+
maxTime = p.T();
550+
}
551+
}
552+
// Create a histogram containing original generator time values
553+
auto time_hist = std::make_unique<TH1D>("time_hist", "Time Histogram", 1000, 0., maxTime);
554+
for (const auto &p : mParticles) {
555+
time_hist->Fill(p.T());
556+
}
478557
// Check size of mParticles stack and set loopers accordingly if mAdaptiveLoopers is true
479-
if (mAdaptiveLoopers)
480-
{
558+
if (mAdaptiveLoopers) {
481559
int nParticles = mParticles.size();
482560
if (nParticles > 0)
483561
{
@@ -494,7 +572,11 @@ class GenLoopersInjector : public Generator
494572
}
495573
// Generate loopers using GenTPCLoopers
496574
// this is valid also when number of loopers is fixed
497-
mGenTPCLoopers->generateEvent();
575+
if (mTimeConstraint) {
576+
mGenTPCLoopers->generateEvent(time_hist.get());
577+
} else {
578+
mGenTPCLoopers->generateEvent();
579+
}
498580
auto stat2 = mGenTPCLoopers->importParticles();
499581
if (!stat2) {
500582
LOG(error) << "Failed to import particles from GenTPCLoopers";
@@ -506,7 +588,7 @@ class GenLoopersInjector : public Generator
506588
mParticles.insert(mParticles.end(), loopers.begin(), loopers.end());
507589
LOG(info) << "Size mParticles at loopers stage " << mParticles.size();
508590
} else {
509-
LOG(error) << "Failed to import particles from O2 Kinematics or TPCLoopers";
591+
LOG(error) << "Failed to import particles from O2 Kinematics";
510592
return false;
511593
}
512594
return true;
@@ -518,6 +600,8 @@ class GenLoopersInjector : public Generator
518600
Bool_t mAdaptiveLoopers = true; // Flag to indicate if adaptive loopers are used
519601
float mLoopsFraction = 0.05; // Fraction of loopers to be injected adaptively
520602
float mLoopsFractionPairs = 0.08; // Fraction of loopers from Pairs
603+
Bool_t mTimeConstraint = true; // Flag to indicate if time constraint is applied
604+
double mTimeConstraintValue = 0.0; // Time constraint value, adaptively set based on the maximum time of the main generator events
521605
};
522606

523607
} // namespace eventgen
@@ -600,7 +684,7 @@ FairGenerator *
600684
// Loopers are considered adaptive by default, meaning that the number of loopers is determined by the number of particles in the kinematics file per event
601685
FairGenerator *
602686
GeneratorLoopersInjector(std::string kineFileName = "genevents_Kine.root", std::string model_pairs = "tpcloopmodel.onnx", std::string model_compton = "tpcloopmodelcompton.onnx",
603-
std::string scaler_pair = "scaler_pair.json", std::string scaler_compton = "scaler_compton.json", float loopers_fraction = 0.05, float fraction_pairs = 0.08)
687+
std::string scaler_pair = "scaler_pair.json", std::string scaler_compton = "scaler_compton.json", bool time_constraint = true, float loopers_fraction = 0.05, float fraction_pairs = 0.08)
604688
{
605689
// Expand all environment paths
606690
model_pairs = gSystem->ExpandPathName(model_pairs.c_str());
@@ -694,5 +778,7 @@ GeneratorLoopersInjector(std::string kineFileName = "genevents_Kine.root", std::
694778
} else {
695779
generator->setLoopsFractions(loopers_fraction, fraction_pairs);
696780
}
781+
// Set adaptive time constraint flag
782+
generator->setTimeConstraint(time_constraint);
697783
return generator;
698784
}

0 commit comments

Comments
 (0)