]> git.uio.no Git - u/mrichter/AliRoot.git/blame - PWGLF/FORWARD/analysis2/sim/FastSim.C
Minor updates and add participant information to output for fast simulations
[u/mrichter/AliRoot.git] / PWGLF / FORWARD / analysis2 / sim / FastSim.C
CommitLineData
15cb4a2b 1#ifndef FASTSIM_H
2#define FASTSIM_H
3#include <TSelector.h>
4#include <TQObject.h>
5#ifndef __CINT__
6# include "AliGenerator.h"
7# include "AliRunLoader.h"
8# include "AliStack.h"
9# include "AliHeader.h"
10# include "AliGenEventHeader.h"
11# include "AliRun.h"
12# include "AliCollisionGeometry.h"
13# include "AliGenPythiaEventHeader.h"
14# include "AliGenDPMjetEventHeader.h"
15# include "AliGenGeVSimEventHeader.h"
16# include "AliGenHerwigEventHeader.h"
17# include <TROOT.h>
18# include <TString.h>
19# include <TMath.h>
20# include <TParticle.h>
21# include <TH1.h>
22# include <TTree.h>
23# include <TClonesArray.h>
24# include <TList.h>
25# include <TProof.h>
26# include <TParticlePDG.h>
27# include <TStopwatch.h>
28# include <TFile.h>
29# include <TProofOutputFile.h>
30# include <TCanvas.h>
f3c8e1f4 31# include <TTimer.h>
15cb4a2b 32# include <fstream>
33#else
34class AliGenerator;
35class AliRunLoader;
36class AliStack;
37class AliHeader;
38class AliGenEventHeader;
39class TH1;
40class TTree;
41class TClonesArray;
42class TBrowser;
43class TList;
44class TFile;
45class TProofOutputFile;
46class TCanvas;
47class TVirtualPad;
f3c8e1f4 48class TTimer;
15cb4a2b 49#endif
50
51//====================================================================
52/**
53 * Monitor output objects
54 */
55struct FastMonitor : public TObject, public TQObject
56{
57 /**
58 * Constructor
59 *
60 *
61 * @return
62 */
f3c8e1f4 63 FastMonitor(TSelector* s=0)
64 : fName("FastMonitor"),
65 fCanvas(0),
66 fSelector(s)
15cb4a2b 67 {
15cb4a2b 68 if (gROOT->IsBatch()) {
69 Warning("FastMonitor", "Batch processing, no monitoring");
70 return;
71 }
72
f3c8e1f4 73 if (gProof) {
74 fName = gProof->GetSessionTag();
75 gDirectory->Add(this);
701a83f4 76 Bool_t ret = gProof->Connect("Feedback(TList *objs)",
77 "FastMonitor", this,
f3c8e1f4 78 "Feedback(TList *objs)");
79 if (!ret) {
80 Warning("FastMonitor", "Failed to connect to Proof");
81 return;
82 }
83 }
84 else if (!s) return;
85
15cb4a2b 86 fCanvas = new TCanvas(fName, Form("Monitor %s", fName.Data()), 1000, 800);
87 fCanvas->SetFillColor(0);
88 fCanvas->SetFillStyle(0);
89 fCanvas->SetTopMargin(0.01);
90 fCanvas->SetRightMargin(0.01);
91
92 fCanvas->Divide(2,2);
93 RegisterDraw(1, "type", "", 0);
94 RegisterDraw(2, "b", "", 0);
95 RegisterDraw(3, "cent", "", 0);
96 RegisterDraw(4, "dNdeta", "", 0x8);
15cb4a2b 97 }
98 /**
99 * Register a draw of a an object
100 *
101 * @param i Pad number
102 * @param name Name of object
103 * @param option Drawing option
104 * @param flags Flags
105 *
106 * - 0x1 Log(x)
107 * - 0x2 Log(y)
108 * - 0x4 Log(z)
109 * - 0x8 Scale to events and bin width
110 */
111 void RegisterDraw(Int_t i,
112 const char* name,
113 const char* option,
114 UShort_t flags=0)
115 {
116 TVirtualPad* p = fCanvas->GetPad(i);
117 if (!p) {
118 Warning("RegisterDraw", "Not enough sub-pads (%d)", i);
119 return;
120 }
121 p->SetFillColor(0);
122 p->SetFillStyle(0);
123 p->SetTopMargin(0.01);
124 p->SetRightMargin(0.01);
125 p->SetName(Form("p_%s", name));
126 p->SetTitle(option);
127 if (flags & 0x1) p->SetLogx();
128 if (flags & 0x2) p->SetLogy();
129 if (flags & 0x4) p->SetLogz();
130 if (flags & 0x8) p->SetBit(BIT(15));
15cb4a2b 131 }
132 /**
133 * Desctructor
134 */
135 virtual ~FastMonitor()
136 {
137 if (!gProof) return;
138 gProof->Disconnect("Feedback(TList *objs)",this,
139 "Feedback(TList* objs)");
140 }
141 /**
142 * Set name of this object
143 *
144 * @param name Name
145 */
146 void SetName(const char* name) { fName = name; }
147 /**
148 * Get the name of this object
149 *
150 * @return Name
151 */
152 const char* GetName() const { return fName.Data(); }
153 /**
154 * Find pad corresponding to an object
155 *
156 * @param name Name of object
157 *
158 * @return Pointer to pad or null
159 */
160 TVirtualPad* FindPad(const TString& name)
161 {
162 TVirtualPad* p = 0;
163 Int_t i = 1;
164 TString t = Form("p_%s", name.Data());
165 while ((p = fCanvas->GetPad(i))) {
166 if (t.EqualTo(p->GetName())) return p;
167 i++;
168 }
169 return 0;
170 }
171 /**
172 * Called when we get notified of
173 *
174 * @param objs List of monitored objects
175 */
176 void Feedback(TList* objs)
177 {
178 // Info("FeedBack", "List is %p", objs);
179 // if (objs) objs->ls();
180 if (!fCanvas) return;
181
182 TList* l = static_cast<TList*>(objs->FindObject("histograms"));
183 if (!l) {
184 Warning("Feedback", "No histograms");
185 return;
186 }
187 Int_t nEvents = 1;
f3c8e1f4 188 TObject* oIpz = l->FindObject("ipZ");
189 if (oIpz && oIpz->IsA()->InheritsFrom(TH1::Class()))
190 nEvents = static_cast<TH1*>(oIpz)->GetEntries();
191 else
192 Warning("Feedback", "Histogram ipZ not found");
193
15cb4a2b 194 TIter next(l);
195 TObject* o = 0;
196 while ((o = next())) {
197 TVirtualPad* p = FindPad(o->GetName());
198 if (!p)
199 // Info("FeedBack", "no pad for %s", o->GetName());
200 continue;
201
202 p->cd();
203 if (o->IsA()->InheritsFrom(TH1::Class())) {
f3c8e1f4 204 TH1* h = static_cast<TH1*>(o);
15cb4a2b 205 TH1* c = h->DrawCopy(p->GetTitle());
206 c->SetDirectory(0);
f3c8e1f4 207 c->SetBit(TObject::kCanDelete);
15cb4a2b 208 if (p->TestBit(BIT(15))) {
701a83f4 209 // Info("Feedback", "Scaling %s by 1./%d and width",
210 // c->GetName(), nEvents);
15cb4a2b 211 c->Scale(1./nEvents, "width");
212 }
213 }
f3c8e1f4 214 else {
215 TObject* c = o->DrawClone(p->GetTitle());
216 c->SetBit(TObject::kCanDelete);
217 }
15cb4a2b 218 p->Modified();
219 }
220 fCanvas->Modified();
221 fCanvas->Update();
222 fCanvas->cd();
223 }
f3c8e1f4 224 /**
225 * Function to handle connect signals
226 *
227 */
228 void Handle()
229 {
230 HandleTimer(0);
231 }
232 /**
233 * Function to handle timer events
234 */
235 Bool_t HandleTimer(TTimer*)
236 {
237 Info("HandleTimer", "Selector=%p", fSelector);
238 if (!fSelector) return false;
239 Feedback(fSelector->GetOutputList());
240 return true;
241 }
15cb4a2b 242 /** Our name */
243 TString fName;
244 /** Our canvas */
f3c8e1f4 245 TCanvas* fCanvas;
246 /** Possibly link to selector */
247 TSelector* fSelector;
15cb4a2b 248 ClassDef(FastMonitor,1);
249};
250
251
252//====================================================================
253/**
254 * Run a event generator simulation
255 */
256struct FastSim : public TSelector
257{
258 /**
259 * Constructor
260 *
261 * @param eg Event generator
262 * @param runNo Run number to simulate
263 * @param bMin Lease impact parameter
264 * @param bMax Largest impact parameter
265 */
266 FastSim(const char* eg="",
267 ULong_t runNo=0,
268 Double_t bMin=0,
f3c8e1f4 269 Double_t bMax=20,
270 Long64_t nEvents=0)
15cb4a2b 271 : TSelector(),
272 fEGName(eg),
273 fRunNo(runNo),
274 fBMin(bMin),
275 fBMax(bMax),
276 fGRP(0),
f3c8e1f4 277 fNEvents(nEvents),
701a83f4 278 fIsTgtA(false),
279 fIsProjA(false),
15cb4a2b 280 fGenerator(0),
281 fRunLoader(0),
282 fStack(0),
283 fHeader(0),
284 fTree(0),
285 fParticles(0),
286 fList(0),
287 fHEta(0),
288 fHIpz(0),
289 fHType(0),
290 fHCent(0),
291 fHB(0),
292 fHPhiR(0),
293 fHTime(0),
294 fProofFile(0),
295 fFile(0),
296 fFileName("")
297 {}
298 const char* FileName() const
299 {
300 static TString fn;
301 if (fn.IsNull()) {
302 if (!fFileName.IsNull()) fn = fFileName;
303 else {
f3c8e1f4 304 const char* egName = (fGenerator ?
305 fGenerator->GetName() :
306 fEGName.Data());
307 fn = Form("%s_%09d", egName, fRunNo);
701a83f4 308 if (fGenerator) {
309 TString tgt, proj;
310 Int_t tgtA, tgtZ, projA, projZ;
311 fGenerator->GetTarget(tgt, tgtA, tgtZ);
312 fGenerator->GetProjectile(proj, projA, projZ);
313 fn.Append(Form("_%s%s", tgt.Data(), proj.Data()));
314 fn.Append(Form("_%05d", Int_t(fGenerator->GetEnergyCMS())));
315 }
316
f3c8e1f4 317 if (fNEvents > 0) {
318 if (fNEvents >= 1000000)
319 fn.Append(Form("_%lldM", fNEvents/1000000));
320 else if (fNEvents >= 1000)
321 fn.Append(Form("_%lldk", fNEvents/1000));
322 else
323 fn.Append(Form("_%lld", fNEvents));
324 }
325 fn.Append(".root");
15cb4a2b 326 fFileName = fn;
327 }
328 }
329 return fn.Data();
330 /*
331 if (fFileName.IsNull())
332 fFileName = Form("%s_%09d.root", fEGName.Data(), fRunNo);
333 return fFileName.Data();*/
334 }
f3c8e1f4 335 const char* GetName() const { return "FastSim"; }
336 const char* GetTitle() const { return "ALICE Event Generator simulation"; }
15cb4a2b 337 /**
338 * Create our outputs
339 *
340 *
341 * @return true on success
342 */
343 Bool_t SetupOutput()
344 {
345 Info("SetupOutput", "First the file");
346 Bool_t isProof = false;
347 if (fInput && fInput->FindObject("PROOF_Ordinal"))
348 isProof = true;
349 if (isProof) {
350 Info("SetupOutput", "Making Proof File");
351 fProofFile = new TProofOutputFile(FileName(), "M");
352 // TProofOutputFile::kMerge,
353 // TProofOutputFile::kRemote);
354 fFile = fProofFile->OpenFile("RECREATE");
355 }
356 else
357 fFile = TFile::Open(FileName(), "RECREATE");
358
359 Info("SetupOutput", "Making our tree");
360 fTree = new TTree("T", "T");
361 fParticles = new TClonesArray("TParticle");
362 fTree->Branch("header", &fShortHead,
701a83f4 363 "run/i:event:ntgt:nproj:nbin:type:ipx/D:ipy:ipz:b:c:phir");
15cb4a2b 364 fTree->Branch("particles", &fParticles);
365 fTree->AutoSave();
366 fTree->SetDirectory(fFile);
367 fTree->SetAlias("primary", "(particles.fBits&(1<<14))");
368 fTree->SetAlias("weak", "(particles.fBits&(1<<15))");
369 fTree->SetAlias("charged", "(particles.fBits&(1<<16))");
370 fTree->SetAlias("pt", "(sqrt(pow(particles.fPx,2)+"
371 /* */"pow(particles.fPy,2)))");
372 fTree->SetAlias("eta", "(pt<1e-10?1024:"
373 "-log(tan(atan2(particles.Pt(),particles.fPz)/2)))");
374 fTree->SetAlias("good", "(primary&&charged&&abs(eta)<1000)");
375 fTree->SetAlias("sd", "(header.fType & 0x1)");
376 fTree->SetAlias("dd", "(header.fType & 0x2)");
377 fTree->SetAlias("pion", "(abs(particles.fPdgCode)==211)");
378 fTree->SetAlias("kaon", "(abs(particles.fPdgCode)==321)");
379 fTree->SetAlias("proton", "(abs(particles.fPdgCode)==2212)");
f3c8e1f4 380 fTree->SetAlias("electron","(abs(particles.fPdgCode)==11)");
381 fTree->SetAlias("other", "(!pion&&!kaon&&!proton&&!electron)");
382 fTree->SetAlias("beta", "(particles.P()/particle.Energy())");
383 fTree->SetAlias("gamma", "(1./sqrt(1-beta*beta))");
701a83f4 384 fTree->SetAlias("npart", "(header.ntgt+header.nproj)");
15cb4a2b 385
386 Info("SetupOutput", "Making histograms");
387 Double_t maxEta = 10;
388 Double_t dEta = 10./200;
389 fHEta = new TH1D("dNdeta", "Charged particle pseudo-rapidity density",
390 Int_t(2*maxEta/dEta+.5), -maxEta, +maxEta);
391 fHEta->Sumw2();
392 fHEta->SetXTitle("#it{#eta}");
393 fHEta->SetYTitle("1/N d#it{N}_{ch}/d#it{#eta}");
394 fHEta->SetMarkerColor(kRed+2);
395 fHEta->SetMarkerStyle(20);
396 fHEta->SetDirectory(0);
397
398 fHIpz = new TH1D("ipZ", "Z-coordinate of interaction point",
399 10, -10, 10);
400 fHIpz->SetMarkerColor(kGreen+2);
401 fHIpz->SetFillColor(kGreen+2);
402 fHIpz->SetFillStyle(3001);
403 fHIpz->SetXTitle("IP_{#it{z}} [cm]");
404 fHIpz->SetDirectory(0);
405
406 fHType = new TH1D("type", "Diffractive", 3, .5, 3.5);
407 fHType->SetMarkerColor(kOrange+2);
408 fHType->SetFillColor(kOrange+2);
409 fHType->SetFillStyle(3001);
410 fHType->SetDirectory(0);
411 fHType->GetXaxis()->SetBinLabel(1, "Non");
412 fHType->GetXaxis()->SetBinLabel(2, "Single");
413 fHType->GetXaxis()->SetBinLabel(3, "Double");
414
415 fHCent = new TH1D("cent", "Centrality", 20, 0, 100);
416 fHCent->SetMarkerColor(kPink+2);
417 fHCent->SetFillColor(kPink+2);
418 fHCent->SetFillStyle(3001);
419 fHCent->SetDirectory(0);
420 fHCent->SetXTitle("Centrality [%]");
421
422 fHB = new TH1D("b", "Impact parameter", 20, 0, 20);
423 fHB->SetMarkerColor(kYellow+2);
424 fHB->SetFillColor(kYellow+2);
425 fHB->SetFillStyle(3001);
426 fHB->SetXTitle("#it{b} [fm]");
427 fHB->SetDirectory(0);
428
429 fHPhiR = new TH1D("phiR", "Event plane angle", 360, 0, 360);
430 fHPhiR->SetMarkerColor(kMagenta+2);
431 fHPhiR->SetFillColor(kMagenta+2);
432 fHPhiR->SetFillStyle(3001);
433 fHPhiR->SetXTitle("#it{#Phi}_{R} [degrees]");
434 fHPhiR->SetDirectory(0);
435
436 fHTime = new TH1D("timing", "Timing of processing", 5,0.5,5.5);
437 fHTime->SetMarkerColor(kBlue+2);
438 fHTime->SetFillColor(kBlue+2);
439 fHTime->SetFillStyle(3001);
440 fHTime->GetXaxis()->SetBinLabel(1,"Reset");
441 fHTime->GetXaxis()->SetBinLabel(2,"Generate");
442 fHTime->GetXaxis()->SetBinLabel(3,"Header");
443 fHTime->GetXaxis()->SetBinLabel(4,"Particles");
444 fHTime->GetXaxis()->SetBinLabel(5,"Filling");
445 fHTime->SetDirectory(0);
446
447 fList = new TList;
448 fList->SetName("histograms");
449 fList->SetOwner(true);
450 fList->Add(fHEta);
451 fList->Add(fHIpz);
452 fList->Add(fHType);
453 fList->Add(fHCent);
454 fList->Add(fHB);
455 fList->Add(fHPhiR);
456 fList->Add(fHTime);
457
458 Info("SetupOutput", "Adding list ot outputs");
459 fOutput->Add(fList);
460
461 return true;
462 }
463 Bool_t SetupGen()
464 {
465 Printf(" === Setup ==============================");
466 Printf(" Run #: %6d", fRunNo);
467 Printf(" EG: %30s", fEGName.Data());
468 Printf(" B range: %5.1ffm - %5.1ffm", fBMin, fBMax);
469 Printf(" ========================================");
470 Printf("Macro path: %s", gROOT->GetMacroPath());
471
472 // --- Check if we shoud get the GRP line ------------------------
473 if (!fGRP && fInput) {
474 fGRP = fInput->FindObject("GRP");
475 std::ofstream* pout = new std::ofstream("grp.dat");
476 if (pout) {
477 Info("SetupGen", "Writing GRP line '%s' to \"grp.dat\"",
478 fGRP->GetTitle());
479 std::ostream& out = *pout;
480 out << fGRP->GetTitle() << std::endl;
481 pout->close();
482 }
483 }
484
485 // --- Load our settings -----------------------------------------
486 Info("SetupGen", "Loading scripts");
487 gROOT->Macro(Form("GRP.C(%d)", fRunNo));
488 gROOT->Macro("BaseConfig.C");
489 gROOT->Macro("EGConfig.C");
490
491 gROOT->ProcessLine(Form("VirtualEGCfg::LoadGen(\"%s\")",fEGName.Data()));
492
493 // --- Make our generator ----------------------------------------
494 Info("SetupGen", "Creating generator");
495 TString egMk = Form("egCfg->MakeGenerator(\"%s\",%f,%f)",
496 fEGName.Data(), fBMin, fBMax);
497 Long64_t egPtr = gROOT->ProcessLine(egMk);
498 if (egPtr == 0) {
499 Error("Setup", "Failed to make generator");
500 return false;
501 }
502 fGenerator = reinterpret_cast<AliGenerator*>(egPtr);
701a83f4 503 TString tgt, proj;
504 Int_t tgtA=0, tgtZ=0, projA=0, projZ=0;
505 fGenerator->GetTarget(tgt, tgtA, tgtZ);
506 fGenerator->GetProjectile(proj, projA, projZ);
507 fIsTgtA = (tgtA == tgtZ && tgtA == 1);
508 fIsProjA = (projA == projZ && projZ == 1);
15cb4a2b 509
f3c8e1f4 510 if (fFileName.IsNull()) FileName();
15cb4a2b 511 Info("SetupRun", "File name is '%s'", fFileName.Data());
512
513 return true;
514 }
515 /**
516 * Setup the generator etc. of the job
517 *
518 * @param nev Maximum number of events per file
519 *
520 * @return true on success
521 */
f3c8e1f4 522 Bool_t SetupRun()
15cb4a2b 523 {
524 // --- gAlice (bare ROOT) ----------------------------------------
525 if (!gAlice)
526 new AliRun("gAlice", "The ALICE Off-line framework");
527
f3c8e1f4 528 Long64_t nev = (fNEvents <= 0 ? 0xFFFFFFFF : fNEvents);
15cb4a2b 529 // --- Run-loader, stack, etc -----------------------------------
530 Info("SetupRun", "Set-up run Loader");
531 fRunLoader = AliRunLoader::Open("galice.root", "FASTRUN", "RECREATE");
532 fRunLoader->SetCompressionLevel(2);
533 fRunLoader->SetNumberOfEventsPerFile(nev);
534 fRunLoader->LoadKinematics("RECREATE");
535 fRunLoader->MakeTree("E");
536 gAlice->SetRunLoader(fRunLoader);
537 fRunLoader->MakeStack();
538 fStack = fRunLoader->Stack();
539 fHeader = fRunLoader->GetHeader();
540
541 // --- Initialize generator --------------------------------------
542 Info("SetupRun", "Initializing generator");
543 fGenerator->Init();
544 fGenerator->SetStack(fStack);
545
546 return true;
547 }
548 /**
549 * Read the previously created grp.dat file
550 *
551 */
552 Bool_t ReadGRPLine()
553 {
554 std::ifstream* pin = new std::ifstream("grp.dat");
555 if (!pin) {
556 Warning("ReadGRPLine", "Failed to open \"grp.dat\"");
557 return false;
558 }
559 std::istream& in = *pin;
560 TString line;
561 TString env;
562 do {
563 line.ReadLine(in);
564 if (line.IsNull()) continue;
565 if (line.BeginsWith("#")) continue;
566 env = line;
567 break;
568 } while (!in.eof());
569 pin->close();
570
571 if (env.IsNull()) {
572 Warning("ReadGRPLine", "Got no line from \"grp.dat\"");
573 return false;
574 }
575
576 fGRP = new TNamed("GRP",env.Data());
577 return true;
578 }
579
580 /**
581 * Set up job
582 *
583 */
584 void Init(TTree*)
585 {
586 }
587 /**
588 * Set up job
589 *
590 */
591 void Begin(TTree*)
592 {
593 // Make a monitor
594 Info("Begin", "gProof=%p Nomonitor=%p",
595 gProof, (gProof ? gProof->GetParameter("NOMONITOR") : 0));
596
597 if (gProof && !gProof->GetParameter("NOMONITOR")) {
598 new FastMonitor;
599 gProof->AddFeedback("histograms");
600 Info("Begin", "Adding monitoring");
601 }
602 gROOT->Macro(Form("GRP.C(%d)", fRunNo));
603 if (ReadGRPLine()) {
604 if(gProof) {
605 gProof->AddInput(fGRP);
606 }
607 }
608 }
609 /**
610 * Set-up this sub-job
611 *
612 */
613 void SlaveBegin(TTree*)
614 {
615 SetupGen();
616 SetupOutput();
617 SetupRun();
618 }
619 /* Reset internal caches etc.
620 *
621 * @param iEv Event number
622 *
623 * @return true on success
624 */
625 Bool_t PreEvent(Long64_t iEv)
626 {
627 // --- Reset header ----------------------------------------------
628 fShortHead.fRunNo = fRunNo;
629 fShortHead.fEventId = iEv;
630 fShortHead.fIpX = 1024;
631 fShortHead.fIpY = 1024;
632 fShortHead.fIpZ = 1024;
701a83f4 633 fShortHead.fNtgt = -1;
634 fShortHead.fNproj = -1;
15cb4a2b 635 fShortHead.fNbin = -1;
636 fShortHead.fPhiR = -1;
f3c8e1f4 637 fShortHead.fB = -1;
701a83f4 638 fShortHead.fC = -1;
15cb4a2b 639 fParticles->Clear();
640 // --- Reset header, etc. ---------------------------------------
641 fHeader->Reset(fRunNo, iEv);
642 fRunLoader->SetEventNumber(iEv);
643 fStack->Reset();
644 fRunLoader->MakeTree("K");
645
646 return true;
647 }
648 /**
649 * Process the event header
650 *
651 * @return true if the event should be diagnosed
652 */
653 Bool_t ProcessHeader()
654 {
655 // --- Copy to short header --------------------------------------
656 fShortHead.fRunNo = fHeader->GetRun();
657 fShortHead.fEventId = fHeader->GetEvent();
658 TArrayF ip;
659 fHeader->GenEventHeader()->PrimaryVertex(ip);
660 fShortHead.fIpX = ip[0];
661 fShortHead.fIpY = ip[1];
662 fShortHead.fIpZ = ip[2];
663
664 // --- Check header type -----------------------------------------
665 AliGenEventHeader* genHeader = fHeader->GenEventHeader();
666 AliCollisionGeometry* geometry =
667 dynamic_cast<AliCollisionGeometry*>(genHeader);
668 AliGenPythiaEventHeader* pythia =
669 dynamic_cast<AliGenPythiaEventHeader*>(genHeader);
670 AliGenDPMjetEventHeader* dpm =
671 dynamic_cast<AliGenDPMjetEventHeader*>(genHeader);
672 AliGenGeVSimEventHeader* gev =
673 dynamic_cast<AliGenGeVSimEventHeader*>(genHeader);
674 AliGenHerwigEventHeader* herwig =
675 dynamic_cast<AliGenHerwigEventHeader*>(genHeader);
676 if (geometry) {
677 fShortHead.fB = geometry->ImpactParameter();
701a83f4 678 fShortHead.fNtgt = geometry->TargetParticipants();
679 fShortHead.fNproj = geometry->ProjectileParticipants();
15cb4a2b 680 fShortHead.fNbin = geometry->NN();
681 fShortHead.fPhiR = geometry->ReactionPlaneAngle();
682 }
683 // --- Determine diffraction flags -------------------------------
684 Bool_t sd = false;
685 Bool_t dd = false;
686 if (pythia) {
687 Int_t type = pythia->ProcessType();
688 if (type < 100) { // pythia6
689 switch (type) {
690 case 92: case 93: sd = true; break;
691 case 94: dd = true; break;
692 }
693 }
694 else {
695 switch (type) { // Pythia8
696 case 103: case 104: sd = true; break;
697 case 105: dd = true; break;
698 }
699 }
700 fShortHead.fB = pythia->GetImpactParameter();
701a83f4 701 fShortHead.fNtgt = 1;
702 fShortHead.fNproj = 1;
15cb4a2b 703 fShortHead.fNbin = 1;
704 }
705 if (dpm) {
706 Int_t type = dpm->ProcessType();
701a83f4 707#ifndef NO_DPMJET_TYPE
15cb4a2b 708 switch (type) {
709 case 5: case 6: sd = true;
15cb4a2b 710 case 7: dd = true;
701a83f4 711 }
712#else
713 // The below - or rather a different implementation with some
714 // errors - was proposed by Cvetan - I don't think it's right
715 // though. See also
716 //
717 // https://cern.ch/twiki/pub/ALICE/PAPaperCentrality/normalization.pdf
718 // https://cern.ch/twiki/bin/view/ALICE/PAMCProductionStudies
719 //
720 Int_t nsd1=0, nsd2=0, ndd=0;
721 Int_t npP = dpm->ProjectileParticipants();
722 Int_t npT = dpm->TargetParticipants();
723 // Get the numbeer of single and double diffractive participants
724 dpm->GetNDiffractive(nsd1,nsd2,ndd);
725 // Check if all partipants are single/double diffractive
726 if ((ndd == 0) && ((npP == nsd1) || (npT == nsd2))) sd = true;
727 else if (ndd == (npP + npT)) dd = true;
728 Printf("Projectile: %3d (%3d) Target: %3d (%3d) DD: %3d Process: %d",
729 npP, nsd1, npT, nsd2, ndd, type);
730#endif
15cb4a2b 731 }
732 if (gev) fShortHead.fPhiR = gev->GetEventPlane();
733 if (herwig) {
734 Int_t type = herwig->ProcessType();
735 switch (type) {
736 case 5: case 6: sd = true; break;
737 }
701a83f4 738 fShortHead.fNtgt = 1;
739 fShortHead.fNproj = 1;
15cb4a2b 740 fShortHead.fNbin = 1;
741 }
742 fShortHead.fType = (sd ? 0x1 : 0) | (dd ? 0x2 : 0);
743
744 // --- Check centrality -----------------------------------------
701a83f4 745 Float_t np = -1;
746 Float_t nc = -1;
f3c8e1f4 747 Double_t c = -1;
15cb4a2b 748 Double_t b = fShortHead.fB;
701a83f4 749 if (b >= 0 && fIsProjA && fIsTgtA &&
750 TMath::Abs(fGenerator->GetEnergyCMS()-2760) < 10) {
751 // PbPb @ 2.76TeV only
752 // Updated 4th of November 2014 from
753 // cern.ch/twiki/bin/view/ALICE/CentStudies
754 // #Tables_with_centrality_bins_AN1
f3c8e1f4 755 if (0.00 >= b && b < 1.57) { c=0.5; np=403.8; nc=1861; }
756 else if (1.57 >= b && b < 2.22) { c=1.5; np=393.6; nc=1766; }
757 else if (2.22 >= b && b < 2.71) { c=2.5; np=382.9; nc=1678; }
758 else if (2.71 >= b && b < 3.13) { c=3.5; np=372; nc=1597; }
759 else if (3.13 >= b && b < 3.50) { c=4.5; np=361.1; nc=1520; }
760 else if (3.50 >= b && b < 4.94) { c=7.5; np=329.4; nc=1316; }
761 else if (4.94 >= b && b < 6.05) { c=12.5; np=281.2; nc=1032; }
762 else if (6.05 >= b && b < 6.98) { c=17.5; np=239; nc=809.8; }
763 else if (6.98 >= b && b < 7.81) { c=22.5; np=202.1; nc=629.6; }
764 else if (7.81 >= b && b < 8.55) { c=27.5; np=169.5; nc=483.7; }
765 else if (8.55 >= b && b < 9.23) { c=32.5; np=141; nc=366.7; }
766 else if (9.23 >= b && b < 9.88) { c=37.5; np=116; nc=273.4; }
767 else if (9.88 >= b && b < 10.47) { c=42.5; np=94.11; nc=199.4; }
768 else if (10.47 >= b && b < 11.04) { c=47.5; np=75.3; nc=143.1; }
769 else if (11.04 >= b && b < 11.58) { c=52.5; np=59.24; nc=100.1; }
770 else if (11.58 >= b && b < 12.09) { c=57.5; np=45.58; nc=68.46; }
771 else if (12.09 >= b && b < 12.58) { c=62.5; np=34.33; nc=45.79; }
772 else if (12.58 >= b && b < 13.05) { c=67.5; np=25.21; nc=29.92; }
773 else if (13.05 >= b && b < 13.52) { c=72.5; np=17.96; nc=19.08; }
774 else if (13.52 >= b && b < 13.97) { c=77.5; np=12.58; nc=12.07; }
775 else if (13.97 >= b && b < 14.43) { c=82.5; np=8.812; nc=7.682; }
776 else if (14.43 >= b && b < 14.96) { c=87.5; np=6.158; nc=4.904; }
777 else if (14.96 >= b && b < 15.67) { c=92.5; np=4.376; nc=3.181; }
778 else if (15.67 >= b && b < 20.00) { c=97.5; np=3.064; nc=1.994; }
f3c8e1f4 779 }
701a83f4 780 else if (b >= 0 && (fIsTgtA || fIsProjA) &&
781 TMath::Abs(fGenerator->GetEnergyCMS()-5023) < 10) {
782 // pPb/Pbp @ 5.02TeV
783 // From Glauber
784 // cern.ch/twiki/bin/viewauth/ALICE/PACentStudies
785 // #Ncoll_in_centrality_bins_from_CL
786 Double_t ac[] = { 2.5, 7.5, 15., 30., 50., 70., 90. };
787 Double_t ab[] = { 100., 14.4, 13.8, 12.7, 10.2, 6.30, 3.10, 1.44, 0 };
788 for (Int_t i = 0; i < 7; i++) {
789 Double_t bC = ab[i+1];
790 Double_t bH = bC + (ab[i] - bC) / 2;
791 Double_t bL = bC - (bC - ab[i+2]) / 2;
792 if (b >= bL && b < bH) {
793 c = ac[i];
794 break;
795 }
796 }
797 }
798 if (c >= 0) fShortHead.fC = c;
799 Double_t nb = nc/2;
800 // Be careful to round off
801 if ((fShortHead.fNtgt+fShortHead.fNproj) <= 0 && np >= 0) {
802 fShortHead.fNtgt = Int_t(np-nb+.5);
803 fShortHead.fNproj = Int_t(nb+.5);
804 }
805 if (fShortHead.fNbin <= 0 && nb >= 0)
806 fShortHead.fNbin = Int_t(nb+.5);
15cb4a2b 807
808 // --- Check if within vertex cut -------------------------------
809 Bool_t selected = (fShortHead.fIpZ <= fHIpz->GetXaxis()->GetXmax() &&
810 fShortHead.fIpZ >= fHIpz->GetXaxis()->GetXmin());
811
812 // --- Only update histograms if within IPz cut ------------------
813 if (selected) {
814 fHPhiR->Fill(fShortHead.fPhiR*TMath::RadToDeg());
815 fHB->Fill(fShortHead.fB);
816 fHIpz->Fill(fShortHead.fIpZ);
701a83f4 817 if (dd) fHType->Fill(3);
818 if (sd) fHType->Fill(2);
819 if (!dd && !sd) fHType->Fill(1);
15cb4a2b 820 fHCent->Fill(c);
821 }
822 return selected;
823 }
824 /**
825 * Process all particles
826 *
827 * @param selected True if particle information should be diagnosed
828 *
829 * @return true on success
830 */
831 Bool_t ProcessParticles(Bool_t selected)
832 {
833 Int_t nPart = fStack->GetNprimary();
834 for (Int_t iPart = 0; iPart < nPart; iPart++) {
835 TParticle* particle = fStack->Particle(iPart);
836 TParticlePDG* pdg = particle->GetPDG();
837 Bool_t primary = fStack->IsPhysicalPrimary(iPart);
838 Bool_t weakDecay = fStack->IsSecondaryFromWeakDecay(iPart);
839 Bool_t charged = (pdg && TMath::Abs(pdg->Charge()) > 0);
840 if (primary) particle->SetBit(BIT(14));
841 if (weakDecay) particle->SetBit(BIT(15));
842 if (charged) particle->SetBit(BIT(16));
843
844 new ((*fParticles)[iPart]) TParticle(*particle);
845
846 if (!selected || !charged || !primary) continue;
847 Double_t pT = particle->Pt();
848 if (pT < 1e-10) continue; /// Along beam axis
849 Double_t pZ = particle->Pz();
850 Double_t theta = TMath::ATan2(pT, pZ);
851 Double_t eta = -TMath::Log(TMath::Tan(theta/2));
852 fHEta->Fill(eta);
853 }
854 return true;
855 }
856 /**
857 * Do final event processing (fill output)
858 *
859 */
860 void PostEvent()
861 {
862 fHeader->SetNprimary(fStack->GetNprimary());
863 fHeader->SetNtrack(fStack->GetNtrack());
864
865 fTree->Fill();
866
867 fStack->FinishEvent();
868 fHeader->SetStack(fStack);
869
870 fRunLoader->TreeE()->Fill();
871 fRunLoader->WriteKinematics("OVERWRITE");
872 }
873 /**
874 * Process one event
875 *
876 * @param iEv Event number
877 *
878 * @return true on success, false otherwize
879 */
880 Bool_t Process(Long64_t iEv)
881 {
882 // --- The stopwatch ---------------------------------------------
883 TStopwatch timer;
884 timer.Start();
885 PreEvent(iEv);
886 fHTime->Fill(1, timer.RealTime());
887
888 // --- Generate event --------------------------------------------
889 timer.Start();
890 fGenerator->Generate();
891 fHTime->Fill(2, timer.RealTime());
892
893 // --- Process the header ----------------------------------------
894 timer.Start();
895 Bool_t selected = ProcessHeader();
896 fHTime->Fill(3, timer.RealTime());
897
898 // --- Loop over particles ---------------------------------------
899 timer.Start();
900 ProcessParticles(selected);
901 fHTime->Fill(4, timer.RealTime());
902
903 // --- Do final stuff --------------------------------------------
904 timer.Start();
905 PostEvent();
906 fHTime->Fill(5, timer.RealTime());
907
908 return true;
909 }
910 /**
911 * Finalize this sub-job
912 *
913 */
914 void SlaveTerminate()
915 {
916 fGenerator->FinishRun();
917 fRunLoader->WriteHeader("OVERWRITE");
918 fGenerator->Write();
919 fRunLoader->Write();
920
15cb4a2b 921 if (fFile) {
922 if (fProofFile) {
923 fOutput->Add(fProofFile);
924 fOutput->Add(new TH1F("filename", fFileName.Data(),1,0,1));
925 }
926 // Flush out tree
927 fFile->cd();
928 fTree->Write(0, TObject::kOverwrite);
929 fFile->Close();
930 fFile->Delete();
931 fFile = 0;
932 }
933 }
934 /**
935 * Final processing of the data
936 *
937 */
938 void Terminate()
939 {
f3c8e1f4 940 if (gProof) gProof->ClearFeedback();
941
15cb4a2b 942 if (!fList)
943 fList = static_cast<TList*>(fOutput->FindObject("histograms"));
944 if (!fList) {
945 Error("Terminate", "No output list");
946 return;
947 }
948
949 if (!fProofFile) {
950 TObject* fn = fOutput->FindObject("filename");
951 if (fn) fFileName = fn->GetTitle();
952 fProofFile =
953 static_cast<TProofOutputFile*>(fOutput->FindObject(FileName()));
954 }
f3c8e1f4 955 if (fProofFile)
15cb4a2b 956 fFile = fProofFile->OpenFile("UPDATE");
15cb4a2b 957 if (!fFile)
958 fFile = TFile::Open(FileName(),"UPDATE");
959
960
961 fHEta = static_cast<TH1*>(fList->FindObject("dNdeta"));
962 fHIpz = static_cast<TH1*>(fList->FindObject("ipZ"));
963 fHType = static_cast<TH1*>(fList->FindObject("type"));
964 fHCent = static_cast<TH1*>(fList->FindObject("cent"));
965 fHB = static_cast<TH1*>(fList->FindObject("b"));
966 fHPhiR = static_cast<TH1*>(fList->FindObject("phiR"));
967 fHTime = static_cast<TH1*>(fList->FindObject("timing"));
968
969 if (!(fHEta && fHIpz && fHType && fHB && fHPhiR && fHTime)) {
970 Warning("Terminate", "Missing histograms (%p,%p,%p,%p,%p,%p)",
971 fHEta, fHIpz, fHType, fHB, fHPhiR, fHTime);
972 return;
973 }
974
975 Int_t nTotal = fHIpz->GetEntries();
976 fHEta ->Scale(1./nTotal, "width");
977 fHB ->Scale(1./nTotal, "width");
978 fHPhiR->Scale(1./nTotal, "width");
979 fHTime->Scale(1./nTotal, "width");
980
981 if (!fFile){
982 Warning("Terminate", "No file to write to");
983 return;
984 }
985
986 fHEta ->Write();
987 fHIpz ->Write();
988 fHType->Write();
989 fHCent->Write();
990 fHB ->Write();
991 fHPhiR->Write();
992 fHTime->Write();
993
994 fTree = static_cast<TTree*>(fFile->Get("T"));
995 if (!fTree) Warning("Terminate", "No tree");
996
997 fFile->Close();
998 }
999 /**
1000 * Interface version used
1001 *
1002 * @return 1
1003 */
1004 Int_t Version() const { return 1; }
1005
1006 /**
1007 * @{
1008 * @name Parameters
1009 */
1010 TString fEGName; // Name of event generator
1011 Int_t fRunNo; // Run to simulate
1012 Double_t fBMin; // Least impact parameter
1013 Double_t fBMax; // Largest impact parameter
f3c8e1f4 1014 TObject* fGRP; //! GRP in one line
1015 Long64_t fNEvents; // Number of requested events
701a83f4 1016 Bool_t fIsTgtA; //! True if target beam is nuclei
1017 Bool_t fIsProjA; //! True if projectile beam is nuclei
15cb4a2b 1018 /* @} */
1019 /**
1020 * @{
1021 * @name ALICE EG interface
1022 */
1023 AliGenerator* fGenerator; //! Event generator
1024 AliRunLoader* fRunLoader; //! Loader of trees
1025 AliStack* fStack; //! Stack of particles
1026 AliHeader* fHeader; //! Header handler
1027 /* @} */
1028 /**
1029 * @{
1030 * @name Custom output
1031 */
1032 TTree* fTree; //! Custom tree
1033 TClonesArray* fParticles; //! List of particles
1034 /**
1035 * @{
1036 * @name Diagnostics
1037 */
1038 TList* fList; //! List of outputs
1039 TH1* fHEta; //! dN/deta
1040 TH1* fHIpz; //! IPz histogram
1041 TH1* fHType; //! Event type histogram
1042 TH1* fHCent; //! Event type histogram
1043 TH1* fHB; //! B histogram
1044 TH1* fHPhiR; //! Reaction plane
1045 TH1* fHTime; //! Timing
1046 /* @} */
1047 /**
1048 * @{
1049 * @name Output files
1050 */
1051 TProofOutputFile* fProofFile; //! Proof output file
1052 TFile* fFile; //! Output file
1053 mutable TString fFileName; //! Output file name
1054 /* @} */
1055
1056 // Hide from CINT
1057#ifndef __CINT__
1058 struct ShortHeader {
1059 UInt_t fRunNo;
1060 UInt_t fEventId;
701a83f4 1061 UInt_t fNtgt;
1062 UInt_t fNproj;
15cb4a2b 1063 UInt_t fNbin;
1064 UInt_t fType;
1065 Double_t fIpX;
1066 Double_t fIpY;
1067 Double_t fIpZ;
1068 Double_t fB;
1069 Double_t fC;
1070 Double_t fPhiR;
1071 } fShortHead;
1072#endif
1073 /**
f3c8e1f4 1074 * Run this selector as a normal process
15cb4a2b 1075 *
f3c8e1f4 1076 * @param nev Number of events
1077 * @param run Run number to anchor in
1078 * @param gen Generator
1079 * @param bMin Least impact parameter [fm]
1080 * @param bMax Largest impact parameter [fm]
1081 * @param monitor Monitor frequency [s]
15cb4a2b 1082 *
f3c8e1f4 1083 * @return true on succes
15cb4a2b 1084 */
1085 static Bool_t Run(Long64_t nev,
1086 UInt_t run,
1087 const char* gen,
1088 Double_t bMin,
1089 Double_t bMax,
1090 Int_t monitor)
1091 {
f3c8e1f4 1092 TStopwatch stopwatch;
1093 stopwatch.Start();
15cb4a2b 1094
f3c8e1f4 1095 FastSim* sim = new FastSim(gen,run,bMin,bMax,nev);
15cb4a2b 1096 sim->Begin(0);
1097 sim->SlaveBegin(0);
1098
f3c8e1f4 1099 TTimer* timer = 0;
1100 if (monitor > 0) {
1101 // timer = new TTimer(new FastMonitor(sim), monitor*1000,true);
1102 timer = new TTimer(1000);
1103 timer->Connect("Timeout()","FastMonitor",
1104 new FastMonitor(sim), "Handle()");
1105 ::Info("Run", "Turning on monitoring");
1106 timer->Start(-1,false);
1107 }
1108
15cb4a2b 1109 for (Long64_t i=0; i <nev; i++) {
1110 Printf("=== Event # %6lld/%6lld ==========================",
1111 i+1, nev);
1112 sim->Process(i);
f3c8e1f4 1113 if (timer && (i > 0) && (i % 500 == 0)) {
1114 if (timer->CheckTimer(gSystem->Now()))
1115 Printf("Fired timer");
1116 }
15cb4a2b 1117 }
f3c8e1f4 1118 if (timer) timer->TurnOff();
15cb4a2b 1119 sim->SlaveTerminate();
1120 sim->Terminate();
1121
f3c8e1f4 1122 stopwatch.Print();
15cb4a2b 1123 return true;
1124 }
1125 static void ProofLoadLibs()
1126 {
1127 if (!gProof) return;
1128
1129 // Remember to copy changes to RunFast.C
1130 TList clsLib;
1131 clsLib.Add(new TNamed("TVirtualMC", "libVMC"));
1132 clsLib.Add(new TNamed("TLorentzVector", "libPhysics"));
1133 clsLib.Add(new TNamed("TLinearFitter", "libMinuit"));
1134 clsLib.Add(new TNamed("TTree", "libTree"));
1135 clsLib.Add(new TNamed("TProof", "libProof"));
1136 clsLib.Add(new TNamed("TGFrame", "libGui"));
1137 clsLib.Add(new TNamed("TSAXParser", "libXMLParser"));
1138 clsLib.Add(new TNamed("AliVEvent", "libSTEERBase"));
1139 clsLib.Add(new TNamed("AliESDEvent", "libESD"));
1140 clsLib.Add(new TNamed("AliAODEvent", "libAOD"));
1141 clsLib.Add(new TNamed("AliAnalysisManager", "libANALYSIS"));
1142 clsLib.Add(new TNamed("AliCDBManager", "libCDB"));
1143 clsLib.Add(new TNamed("AliRawVEvent", "libRAWDatabase"));
1144 clsLib.Add(new TNamed("AliHit", "libSTEER"));
1145 clsLib.Add(new TNamed("AliGenMC", "libEVGEN"));
1146 clsLib.Add(new TNamed("AliFastEvent", "libFASTSIM"));
1147
1148 TIter next(&clsLib);
1149 TObject* obj = 0;
1150 while ((obj = next())) {
1151 gProof->Exec(Form("gROOT->LoadClass(\"%s\",\"%s\");",
1152 obj->GetName(), obj->GetTitle()));
1153 }
1154 }
f3c8e1f4 1155 /**
1156 * Run this selector in PROOF(Lite)
1157 *
1158 * @param url Proof URL
1159 * @param nev Number of events
1160 * @param run Run number to anchor in
1161 * @param gen Generator
1162 * @param bMin Least impact parameter [fm]
1163 * @param bMax Largest impact parameter [fm]
1164 * @param monitor Monitor frequency [s]
1165 * @param opt Compilation options
1166 *
1167 * @return true on succes
1168 */
1169 static Bool_t Proof(const char* url,
1170 Long64_t nev,
15cb4a2b 1171 UInt_t run,
1172 const char* gen,
1173 Double_t bMin,
1174 Double_t bMax,
1175 Int_t monitor=-1,
1176 const char* opt="")
1177 {
1178 Printf("# events: %lld", nev);
1179 Printf("Run #: %u", run);
1180 Printf("Generator: %s", gen);
1181 Printf("b range: %5.1f-%5.1f", bMin, bMax);
1182 Printf("monitor: %ds", monitor);
1183
1184 TStopwatch timer;
1185 timer.Start();
1186
f3c8e1f4 1187 TProof::Reset(url);
1188 TProof::Open(url);
15cb4a2b 1189 gProof->ClearCache();
1190
1191 TString ali = gSystem->ExpandPathName("$(ALICE_ROOT)");
1192 // TString fwd = gSystem->ExpandPathName("$ANA_SRC");
1193 TString fwd = ali + "/PWGLF/FORWARD/analysis2";
1194
1195 gProof->AddIncludePath(Form("%s/include", ali.Data()));
1196 ProofLoadLibs();
1197 gProof->Load(Form("%s/sim/GRP.C",fwd.Data()), true);
1198 gProof->Load(Form("%s/sim/BaseConfig.C",fwd.Data()), true);
1199 gProof->Load(Form("%s/sim/EGConfig.C",fwd.Data()), true);
1200
1201 // gROOT->ProcessLine("gProof->SetLogLevel(5);");
1202 gProof->Load(Form("%s/sim/FastSim.C+%s", fwd.Data(), opt),true);
1203
1204 if (monitor <= 0) gProof->SetParameter("NOMONITOR", true/*ignored*/);
1205 else gProof->SetParameter("PROOF_FeedbackPeriod",
1206 monitor*1000/*ms*/);
1207
f3c8e1f4 1208 FastSim* sim = new FastSim(gen,run,bMin,bMax,nev);
15cb4a2b 1209 gProof->Process(sim, nev, "");
1210
1211 timer.Print();
1212 return true; // status >= 0;
1213 }
1214 ClassDef(FastSim,1);
1215};
1216
1217#endif
1218//
1219// EOF
1220//