27-oct-2005 NvE Memberfunction GetX to access individual vector components also intro...
[u/mrichter/AliRoot.git] / RALICE / icepack / iceconvert / IceF2k.cxx
CommitLineData
f67e2651 1/*******************************************************************************
2 * Copyright(c) 2003, IceCube Experiment at the South Pole. All rights reserved.
3 *
4 * Author: The IceCube RALICE-based Offline Project.
5 * Contributors are mentioned in the code where appropriate.
6 *
7 * Permission to use, copy, modify and distribute this software and its
8 * documentation strictly for non-commercial purposes is hereby granted
9 * without fee, provided that the above copyright notice appears in all
10 * copies and that both the copyright notice and this permission notice
11 * appear in the supporting documentation.
12 * The authors make no claims about the suitability of this software for
13 * any purpose. It is provided "as is" without express or implied warranty.
14 *******************************************************************************/
15
16// $Id$
17
18///////////////////////////////////////////////////////////////////////////
19// Class IceF2k
20// Conversion of Amanda F2K data into IceEvent physics event structures.
5481c137 21// This class is derived from AliJob providing a task-based processing
22// structure on an event-by-event basis.
23// The main object in the job environment is an IceEvent* pointer.
24// In case the user has provided sub-tasks, these will be executed
25// on an event-by-event basis after the IceEvent structure has been filled
26// with the F2K data and before the final structures are written out.
1c9018c6 27// Note that the data structures are only written out if an outputfile has
28// been specified via the SetOutputFile memberfunction.
29// In case no outputfile has been specified, this class provides a facility
30// to investigate/analyse F2K data using the Ralice/IcePack analysis tools.
f67e2651 31//
32// Usage example :
33// ---------------
34//
35// gSystem->Load("ralice");
36// gSystem->Load("icepack");
37// gSystem->Load("iceconvert");
38//
5481c137 39// IceF2k q("IceF2k","F2K to IcePack data structure conversion");
f67e2651 40//
41// // Limit the number of entries for testing
5481c137 42// q.SetMaxEvents(10);
f67e2651 43//
44// // Print frequency to produce a short summary print every printfreq events
5481c137 45// q.SetPrintFreq(1);
f67e2651 46//
47// // Split level for the output structures
5481c137 48// q.SetSplitLevel(2);
f67e2651 49//
50// // Buffer size for the output structures
5481c137 51// q.SetBufferSize(32000);
52//
53// // The F2K input filename
54// q.SetInputFile("run7825.f2k");
f67e2651 55//
5481c137 56// // Output file for the event structures
57// TFile* ofile=new TFile("events.root","RECREATE","F2K data in IceEvent structure");
58// q.SetOutputFile(ofile);
59//
60// ///////////////////////////////////////////////////////////////////
61// // Here the user can specify his/her sub-tasks to be executed
62// // on an event-by-event basis after the IceEvent structure
63// // has been filled and before the data is written out.
64// // Sub-tasks (i.e. a user classes derived from TTask) are entered
65// // as follows :
66// //
67// // MyXtalk task1("task1","Cross talk correction");
68// // MyClean task2("task2","Hit cleaning");
69// // q.Add(&task1);
70// // q.Add(&task2);
71// //
72// // The sub-tasks will be executed in the order as they are entered.
73// ///////////////////////////////////////////////////////////////////
74//
75// // Perform the conversion and execute subtasks (if any)
76// // on an event-by-event basis
77// q.ExecuteJob();
f67e2651 78//
79// // Select various objects to be added to the output file
80//
1c9018c6 81// ofile->cd(); // Switch to the output file directory
82//
f67e2651 83// AliObjMatrix* omdb=q.GetOMdbase();
84// if (omdb) omdb->Write();
85//
86// AliDevice* fitdefs=q.GetFitdefs();
87// if (fitdefs) fitdefs->Write();
88//
89// TDatabasePDG* pdg=q.GetPDG();
90// if (pdg) pdg->Write();
91//
9f575717 92// // Flush the output file.
93// // The output file is not explicitly closed here
94// // to allow ineractive investigation of the data tree
95// // when this macro is run in an interactive ROOT/CINT session.
f67e2651 96// ofile->Write();
f67e2651 97//
98//--- Author: Nick van Eijndhoven 11-mar-2005 Utrecht University
99//- Modified: NvE $Date$ Utrecht University
100///////////////////////////////////////////////////////////////////////////
101
102#include "IceF2k.h"
103#include "Riostream.h"
104
105ClassImp(IceF2k) // Class implementation to enable ROOT I/O
106
5481c137 107IceF2k::IceF2k(const char* name,const char* title) : AliJob(name,title)
f67e2651 108{
109// Default constructor.
5481c137 110// By default maxevent=-1, split=99, bsize=32000, printfreq=1.
f67e2651 111
5481c137 112 fSplit=99;
113 fBsize=32000;
114 fMaxevt=-1;
115 fPrintfreq=1;
116 fInfile="";
117 fOutfile=0;
f67e2651 118
119 fPdg=0;
120 fOmdb=0;
121 fFitdefs=0;
f67e2651 122}
123///////////////////////////////////////////////////////////////////////////
124IceF2k::~IceF2k()
125{
126// Default destructor.
5481c137 127
f67e2651 128 if (fPdg)
129 {
130 delete fPdg;
131 fPdg=0;
132 }
133
134 if (fOmdb)
135 {
136 delete fOmdb;
137 fOmdb=0;
138 }
139
140 if (fFitdefs)
141 {
142 delete fFitdefs;
143 fFitdefs=0;
144 }
145}
146///////////////////////////////////////////////////////////////////////////
5481c137 147void IceF2k::SetMaxEvents(Int_t n)
148{
149// Set the maximum number of events to be processed.
150// n=-1 implies processing of the complete input file, which is the default
151// initialisation in the constructor.
152 fMaxevt=n;
153}
154///////////////////////////////////////////////////////////////////////////
155void IceF2k::SetPrintFreq(Int_t f)
156{
157// Set the printfrequency to produce info every f events.
158// f=1 is the default initialisation in the constructor.
64c21700 159 if (f>=0) fPrintfreq=f;
5481c137 160}
161///////////////////////////////////////////////////////////////////////////
162void IceF2k::SetSplitLevel(Int_t split)
163{
164// Set the split level for the ROOT data file.
165// split=99 is the default initialisation in the constructor.
166 if (split>=0) fSplit=split;
167}
168///////////////////////////////////////////////////////////////////////////
169void IceF2k::SetBufferSize(Int_t bsize)
170{
171// Set the buffer size for the ROOT data file.
172// bsize=32000 is the default initialisation in the constructor.
173 if (bsize>=0) fBsize=bsize;
174}
175///////////////////////////////////////////////////////////////////////////
176void IceF2k::SetInputFile(TString name)
177{
178// Set the name of the F2K input file.
179 fInfile=name;
180}
181///////////////////////////////////////////////////////////////////////////
182void IceF2k::SetOutputFile(TFile* ofile)
183{
184// Set the output file for the ROOT data.
185 fOutfile=ofile;
186}
187///////////////////////////////////////////////////////////////////////////
f67e2651 188TDatabasePDG* IceF2k::GetPDG()
189{
190// Provide pointer to the PDG database
191 return fPdg;
192}
193///////////////////////////////////////////////////////////////////////////
194AliObjMatrix* IceF2k::GetOMdbase()
195{
196// Provide pointer to the OM geometry, calib. etc... database
197 return fOmdb;
198}
199///////////////////////////////////////////////////////////////////////////
200AliDevice* IceF2k::GetFitdefs()
201{
202// Provide pointer to the fit definitions
203 return fFitdefs;
204}
205///////////////////////////////////////////////////////////////////////////
5481c137 206void IceF2k::Exec(Option_t* opt)
f67e2651 207{
5481c137 208// Job to loop over the specified number of events and convert the
f67e2651 209// F2K data into the IceEvent structure.
5481c137 210// If maxevents<0 (default) all the entries of the input file
f67e2651 211// will be processed.
212// Every "printfreq" events a short event summary will be printed.
213// The default value is printfreq=1.
5481c137 214// The output will be written on a standard output tree named "T".
215//
216// Notes :
217// -------
218// 1) This class is derived from AliJob, allowing a task based processing.
219// After the conversion of an F2K event into an IceEvent structure,
220// the processing of all available sub-tasks (if any) is invoked.
221// This provides an event-by-event (sub)task processing before the
222// final data structures are written out.
223// 2) The main object in this job environment is an IceEvent* pointer.
224
225 if (fInfile=="")
226 {
227 cout << " *IceF2k Exec* No data input file specified." << endl;
228 return;
229 }
f67e2651 230
5481c137 231 // Open the input file in the default ascii format (autodetection) for reading
232 fInput=rdmc_mcopen(fInfile.Data(),"r",RDMC_DEFAULT_ASCII_F);
f67e2651 233
5481c137 234 if (!fInput)
235 {
236 cout << " *IceF2k Exec* No input file found with name : " << fInfile.Data() << endl;
237 return;
238 }
f67e2651 239
5481c137 240 // Initialise the event structure
241 rdmc_init_mevt(&fEvent);
242
243 // Read the file header information
244 rdmc_rarr(fInput,&fHeader);
245
1c9018c6 246 TTree* otree=0;
247 if (fOutfile)
5481c137 248 {
1c9018c6 249 otree=new TTree("T","F2K Data converted to IceEvent structures");
250 otree->SetDirectory(fOutfile);
5481c137 251 }
f67e2651 252
5481c137 253 IceEvent* evt=new IceEvent();
f67e2651 254 evt->SetTrackCopy(1);
255 evt->SetDevCopy(1);
256
257 // Branch in the tree for the event structure
1c9018c6 258 if (otree) otree->Branch("IceEvent","IceEvent",&evt,fBsize,fSplit);
f67e2651 259
260 // Create the particle database and extend it with some F2000 specific definitions
261 if (!fPdg) fPdg=new TDatabasePDG();
262 Double_t me=fPdg->GetParticle(11)->Mass();
263 fPdg->AddParticle("brems" ,"brems" ,0,1,0,0,"none",10001001,0,0);
264 fPdg->AddParticle("deltae" ,"deltae" ,me,1,0,-3,"Lepton",10001002,0,0);
265 fPdg->AddParticle("pairprod","pairprod",0,1,0,0,"none",10001003,0,0);
266 fPdg->AddParticle("nucl_int","nucl_Int",0,1,0,0,"none",10001004,0,0);
267 fPdg->AddParticle("mu_pair" ,"mu_pair" ,0,1,0,0,"none",10001005,0,0);
268 fPdg->AddParticle("hadrons" ,"hadrons" ,0,1,0,0,"none",10001006,0,0);
269 fPdg->AddParticle("fiberlaser","fiberlaser",0,1,0,0,"none",10002100,0,0);
270 fPdg->AddParticle("n2laser" ,"n2laser" ,0,1,0,0,"none",10002101,0,0);
271 fPdg->AddParticle("yaglaser" ,"yaglaser" ,0,1,0,0,"none",10002201,0,0);
272 fPdg->AddParticle("z_primary","z_primary",0,1,0,0,"none",10003000,0,0);
273 fPdg->AddParticle("a_primary","a_primary",0,1,0,0,"none",10003500,0,0);
274
275 // Fill the database with geometry, calib. etc... parameters
276 // for all the devices
277 FillOMdbase();
278
279 // Set the fit definitions according to the F2000 header info
280 SetFitdefs();
281
5481c137 282 // Initialise the job working environment
283 SetMainObject(evt);
1c9018c6 284 if (fOutfile)
285 {
286 AddObject(fOutfile);
287 AddObject(otree);
288 }
5481c137 289
290 cout << " ***" << endl;
291 cout << " *** Start processing of job " << GetName() << " ***" << endl;
292 cout << " ***" << endl;
293 cout << " F2K input file : " << fInfile.Data() << endl;
294 cout << " Maximum number of events to be processed : " << fMaxevt << endl;
295 cout << " Print frequency : " << fPrintfreq << endl;
1c9018c6 296 if (fOutfile)
297 {
298 cout << " ROOT output file : " << fOutfile->GetName() << endl;
299 cout << " Output characteristics : splitlevel = " << fSplit << " buffersize = " << fBsize << endl;
300 }
5481c137 301
302 ListEnvironment();
303
304 Int_t nevt=0;
305 while (!rdmc_revt(fInput,&fHeader,&fEvent))
f67e2651 306 {
5481c137 307 if (fMaxevt>-1 && nevt>=fMaxevt) break;
f67e2651 308
309 // Reset the complete Event structure
310 evt->Reset();
311
312 evt->SetRunNumber(fEvent.nrun);
313 evt->SetEventNumber(fEvent.enr);
314 evt->SetMJD(fEvent.mjd,fEvent.secs,fEvent.nsecs);
315
5481c137 316 PutMcTracks();
f67e2651 317
5481c137 318 PutRecoTracks();
f67e2651 319
5481c137 320 PutHits();
f67e2651 321
5481c137 322 // Invoke all available sub-tasks (if any)
225085ba 323 CleanTasks();
5481c137 324 ExecuteTasks(opt);
325
64c21700 326 if (fPrintfreq)
327 {
328 if (!(nevt%fPrintfreq)) evt->HeaderData();
329 }
f67e2651 330
331 // Write the complete structure to the output Tree
1c9018c6 332 if (otree) otree->Fill();
f67e2651 333
5481c137 334 // Update event counter
335 nevt++;
336 }
1c9018c6 337
338 // Remove the IceEvent object from the environment
339 // and delete it as well
340 if (evt)
341 {
342 RemoveObject(evt);
343 delete evt;
344 }
f67e2651 345}
346///////////////////////////////////////////////////////////////////////////
347void IceF2k::FillOMdbase()
348{
349// Fill the database with geometry, calib. etc... parameters
350// for all the devices.
351
352 if (fHeader.nch<=0) return;
353
64c21700 354 Int_t adccal=fHeader.is_calib.adc;
355 Int_t tdccal=fHeader.is_calib.tdc;
356 Int_t totcal=fHeader.is_calib.tot;
64c21700 357
358 TF1 fadccal("fadccal","(x-[1])*[0]");
359 TF1 fadcdecal("fadcdecal","(x/[0])+[1]");
216d1d91 360 fadccal.SetParName(0,"BETA-ADC");
361 fadccal.SetParName(1,"PED-ADC");
362 fadcdecal.SetParName(0,"BETA-ADC");
363 fadcdecal.SetParName(1,"PED-ADC");
364
64c21700 365 TF1 ftdccal("ftdccal","(x*[0])-[1]-([0]-1.)*32767.-[2]/sqrt([3])");
366 TF1 ftdcdecal("ftdcdecal","(x+([0]-1.)*32767.+[1]+[2]/sqrt([3]))/[0]");
216d1d91 367 ftdccal.SetParName(0,"BETA-TDC");
368 ftdccal.SetParName(1,"T0");
369 ftdccal.SetParName(2,"ALPHA-TDC");
370 ftdccal.SetParName(3,"ADC-SLEW");
371 ftdcdecal.SetParName(0,"BETA-TDC");
372 ftdcdecal.SetParName(1,"T0");
373 ftdcdecal.SetParName(2,"ALPHA-TDC");
374 ftdcdecal.SetParName(3,"ADC-SLEW");
375
64c21700 376 TF1 ftotcal("ftotcal","x*[0]");
377 TF1 ftotdecal("ftotdecal","x/[0]");
216d1d91 378 ftotcal.SetParName(0,"BETA-TOT");
379 ftotdecal.SetParName(0,"BETA-TOT");
64c21700 380
f67e2651 381 if (fOmdb)
382 {
383 fOmdb->Reset();
384 }
385 else
386 {
387 fOmdb=new AliObjMatrix();
388 fOmdb->SetNameTitle("OMDBASE","The OM geometry, calib. etc... database");
389 fOmdb->SetOwner();
390 }
391
392 IceAOM* dev=0;
393 Double_t pos[3]={0,0,0};
394 for (Int_t i=0; i<fHeader.nch; i++)
395 {
396 dev=new IceAOM();
397 dev->SetUniqueID(i+1);
64c21700 398
399 dev->SetSlotName("ADC",1);
400 dev->SetSlotName("LE",2);
401 dev->SetSlotName("TOT",3);
402
403 dev->SetSlotName("TYPE",4);
404 dev->SetSlotName("ORIENT",5);
405 dev->SetSlotName("THRESH",6);
406 dev->SetSlotName("SENSIT",7);
407 dev->SetSlotName("BETA-TDC",8);
408 dev->SetSlotName("T0",9);
409 dev->SetSlotName("ALPHA-TDC",10);
410 dev->SetSlotName("PED-ADC",11);
411 dev->SetSlotName("BETA-ADC",12);
412 dev->SetSlotName("KAPPA-ADC",13);
413 dev->SetSlotName("PED-TOT",14);
414 dev->SetSlotName("BETA-TOT",15);
415 dev->SetSlotName("KAPPA-TOT",16);
f67e2651 416
417 pos[0]=fHeader.x[i];
418 pos[1]=fHeader.y[i];
419 pos[2]=fHeader.z[i];
420 dev->SetPosition(pos,"car");
64c21700 421
422 fadccal.SetParameter(0,fHeader.cal[i].beta_a);
423 fadccal.SetParameter(1,fHeader.cal[i].ped);
424 fadcdecal.SetParameter(0,fHeader.cal[i].beta_a);
425 if (!fHeader.cal[i].beta_a) fadcdecal.SetParameter(0,1);
426 fadcdecal.SetParameter(1,fHeader.cal[i].ped);
427
428 ftdccal.SetParameter(0,fHeader.cal[i].beta_t);
429 ftdccal.SetParameter(1,fHeader.cal[i].t_0);
430 ftdccal.SetParameter(2,fHeader.cal[i].alpha_t);
431 ftdccal.SetParameter(3,1.e20);
432 ftdcdecal.SetParameter(0,fHeader.cal[i].beta_t);
433 if (!fHeader.cal[i].beta_t) ftdcdecal.SetParameter(0,1);
434 ftdcdecal.SetParameter(1,fHeader.cal[i].t_0);
435 ftdcdecal.SetParameter(2,fHeader.cal[i].alpha_t);
436 ftdcdecal.SetParameter(3,1.e20);
437
438 ftotcal.SetParameter(0,fHeader.cal[i].beta_tot);
439 ftotdecal.SetParameter(0,fHeader.cal[i].beta_tot);
440 if (!fHeader.cal[i].beta_tot) ftotdecal.SetParameter(0,1);
441
442 if (adccal)
443 {
444 dev->SetDecalFunction(&fadcdecal,1);
445 }
446 else
447 {
448 dev->SetCalFunction(&fadccal,1);
449 }
450
451 if (tdccal)
452 {
453 dev->SetDecalFunction(&ftdcdecal,2);
454 }
455 else
456 {
457 dev->SetCalFunction(&ftdccal,2);
458 }
459
460 if (totcal)
461 {
462 dev->SetDecalFunction(&ftotdecal,3);
463 }
464 else
465 {
466 dev->SetCalFunction(&ftotcal,3);
467 }
468
469 dev->SetSignal(fHeader.type[i],4);
470 dev->SetSignal((Float_t)fHeader.costh[i],5);
471 dev->SetSignal(fHeader.thresh[i],6);
472 dev->SetSignal(fHeader.sensit[i],7);
473 dev->SetSignal(fHeader.cal[i].beta_t,8);
474 dev->SetSignal(fHeader.cal[i].t_0,9);
475 dev->SetSignal(fHeader.cal[i].alpha_t,10);
476 dev->SetSignal(fHeader.cal[i].ped,11);
477 dev->SetSignal(fHeader.cal[i].beta_a,12);
478 dev->SetSignal(fHeader.cal[i].kappa,13);
479 dev->SetSignal(fHeader.cal[i].ped_tot,14);
480 dev->SetSignal(fHeader.cal[i].beta_tot,15);
481 dev->SetSignal(fHeader.cal[i].kappa_tot,16);
482
f67e2651 483 fOmdb->EnterObject(i+1,1,dev);
484 }
485}
486///////////////////////////////////////////////////////////////////////////
487void IceF2k::SetFitdefs()
488{
489// Obtain the names of the variables for each fit procedure from the
490// f2000 header. Each different fit procedure is then stored as a separate
491// hit of an AliDevice object and the various fit variables are stored
492// as separate signal slots of the corresponding hit.
493// Via the GetFitdefs() memberfunction this AliDevice object can be
494// retrieved and stored in the ROOT output file if wanted.
495// The name of the object is FitDefinitions and the stored data can be
496// inspected via the AliDevice::Data() memberfunction and looks as follows :
497//
498// *AliDevice::Data* Id :0 Name : FitDefinitions
499// Position Vector in car coordinates : 0 0 0
500// Err. in car coordinates : 0 0 0
501// The following 8 hits are registered :
502// *AliSignal::Data* Id :0
503// Position Vector in car coordinates : 0 0 0
504// Err. in car coordinates : 0 0 0
505// Owned by device : AliDevice Name : FitDefinitions
506// Slot : 1 Signal value : 1 name : id
507// Slot : 2 Signal value : 2 name : rchi2
508// Slot : 3 Signal value : 3 name : prob
509// Slot : 4 Signal value : 4 name : sigth
510// Slot : 5 Signal value : 5 name : covmin
511// Slot : 6 Signal value : 6 name : covmax
512// Slot : 7 Signal value : 7 name : cutflag
513// Slot : 8 Signal value : 8 name : chi2
514// *AliSignal::Data* Id :1
515// Position Vector in car coordinates : 0 0 0
516// Err. in car coordinates : 0 0 0
517// Owned by device : AliDevice Name : FitDefinitions
518// Slot : 1 Signal value : 1 name : id
519// Slot : 2 Signal value : 2 name : rchi2
520// Slot : 3 Signal value : 3 name : prob
521// etc....
522//
523// This memberfunction is based on the original idea/code by Adam Bouchta.
524
525 if (fHeader.n_fit<=0) return;
526
527 if (fFitdefs)
528 {
529 fFitdefs->Reset(1);
530 }
531 else
532 {
533 fFitdefs=new AliDevice();
534 }
535
536 fFitdefs->SetName("FitDefinitions");
537 fFitdefs->SetHitCopy (1);
538
539 AliSignal s;
540 s.Reset();
541
542 for (Int_t i=0; i<fHeader.n_fit; i++)
543 {
544 s.SetUniqueID(fHeader.def_fit[i].id);
545
546 for (Int_t j=0; j<fHeader.def_fit[i].nwords; j++)
547 {
548 s.SetSlotName(TString(fHeader.def_fit[i].words[j]),j+1);
549 s.SetSignal(j+1,j+1);
550 }
551
552 fFitdefs->AddHit(s);
553 s.Reset(1);
554 }
555}
556///////////////////////////////////////////////////////////////////////////
5481c137 557void IceF2k::PutMcTracks()
f67e2651 558{
559// Get the MC tracks from the F2000 file into the IcePack structure.
560// Note : MC tracks are given negative track id's in the event structure.
561// This memberfunction is based on the original code by Adam Bouchta.
562
5481c137 563 IceEvent* evt=(IceEvent*)GetMainObject();
f67e2651 564 if (!evt || fEvent.ntrack<=0) return;
565
566 // Loop over all the tracks and add them to the current event
567 AliTrack t;
568 Double_t vec[3];
569 AliPosition r;
570 Ali3Vector p;
571 Int_t tid=0;
572 Int_t idpdg=0;
573 Int_t idf2k=0;
574 for (Int_t i=0; i<fEvent.ntrack; i++)
575 {
576 t.Reset ();
577
578 // Beginpoint of the track
579 vec[0]=fEvent.gen[i].x;
580 vec[1]=fEvent.gen[i].y;
581 vec[2]=fEvent.gen[i].z;
582 r.SetPosition(vec,"car");
583 t.SetBeginPoint(r);
584
585 // Endpoint of the track
586 vec[0]+=fEvent.gen[i].length*fEvent.gen[i].px;
587 vec[1]+=fEvent.gen[i].length*fEvent.gen[i].py;
588 vec[2]+=fEvent.gen[i].length*fEvent.gen[i].pz;
589 r.SetPosition(vec,"car");
590 t.SetEndPoint(r);
591
592 // Momentum in GeV/c
593 vec[0]=fEvent.gen[i].e*fEvent.gen[i].px*1e-3;
594 vec[1]=fEvent.gen[i].e*fEvent.gen[i].py*1e-3;
595 vec[2]=fEvent.gen[i].e*fEvent.gen[i].pz*1e-3;
596 p.SetVector (vec,"car");
597 t.Set3Momentum(p);
598
599 // MC tracks are indicated by negative track id's
600 tid=fEvent.gen[i].tag;
601 t.SetId(-abs(tid));
602
603 idf2k=fEvent.gen[i].id;
604 idpdg=0;
605 if (idf2k>1000)
606 {
607 idpdg=idf2k+10000000;
608 }
609 else if (idf2k <= 48)
610 {
611 idpdg=fPdg->ConvertGeant3ToPdg(idf2k);
612 }
613 else
614 {
615 if (idf2k==201) idpdg=12;
616 if (idf2k==202) idpdg=14;
617 if (idf2k==203) idpdg=16;
618 if (idf2k==204) idpdg=-12;
619 if (idf2k==205) idpdg=-14;
620 if (idf2k==206) idpdg=-16;
621 }
622
623 t.SetParticleCode(idpdg);
624 t.SetName(fPdg->GetParticle(idpdg)->GetName());
625 t.SetTitle("MC track");
626 t.SetMass(fPdg->GetParticle(idpdg)->Mass());
627 t.SetCharge(fPdg->GetParticle(idpdg)->Charge()/3.);
628
629 evt->AddTrack(t);
630 }
631
632 // Create the pointers to each particle's parent particle.
633 Int_t txid=0;
634 Int_t parid=0;
635 for (Int_t itk=1; itk<=evt->GetNtracks (); itk++)
636 {
637 AliTrack* tx=evt->GetTrack(itk);
638
639 if (!tx) continue;
640
641 txid=tx->GetId();
642
643 parid=-1;
644 for (Int_t j=0; j<fEvent.ntrack; j++)
645 {
646 tid=fEvent.gen[j].tag;
647 if (-abs(tid) == txid) parid=fEvent.gen[j].parent;
648 }
649
650 if (parid<0) continue;
651
652 AliTrack* tpar=evt->GetIdTrack(-abs(parid));
653
654 if (!tpar) continue;
655
656 tx->SetParentTrack(tpar);
657 }
658}
659///////////////////////////////////////////////////////////////////////////
5481c137 660void IceF2k::PutRecoTracks()
f67e2651 661{
662// Get the reconstructed tracks from the F2000 file into the IcePack structure.
663// Note : Reco tracks are given positive track id's in the event structure.
664// This memberfunction is based on the original code by Adam Bouchta.
665
5481c137 666 IceEvent* evt=(IceEvent*)GetMainObject();
f67e2651 667 if (!evt || fEvent.nfit<=0) return;
668
669 // Loop over all the tracks and add them to the current event
670 AliTrack t;
671 Double_t vec[3];
672 AliPosition r;
673 Ali3Vector p;
674 Int_t tid=0;
675 Int_t idpdg=0;
676 Int_t idf2k=0;
677 for (Int_t i=0; i<fEvent.nfit; i++)
678 {
679 t.Reset ();
680
681 // Beginpoint of the track
682 vec[0]=fEvent.rec[i].x;
683 vec[1]=fEvent.rec[i].y;
684 vec[2]=fEvent.rec[i].z;
685 r.SetPosition(vec,"car");
686 t.SetBeginPoint(r);
687
688 // Endpoint of the track
689 vec[0]+=fEvent.rec[i].length*fEvent.rec[i].px;
690 vec[1]+=fEvent.rec[i].length*fEvent.rec[i].py;
691 vec[2]+=fEvent.rec[i].length*fEvent.rec[i].pz;
692 r.SetPosition(vec,"car");
693 t.SetEndPoint(r);
694
695 // Momentum in GeV/c
696 if (fEvent.rec[i].e > 0)
697 {
698 vec[0]=fEvent.rec[i].e*fEvent.rec[i].px*1e-3;
699 vec[1]=fEvent.rec[i].e*fEvent.rec[i].py*1e-3;
700 vec[2]=fEvent.rec[i].e*fEvent.rec[i].pz*1e-3;
701 }
702 else // Give the track a nominal momentum of 1 GeV/c
703 {
704 vec[0]=fEvent.rec[i].px;
705 vec[1]=fEvent.rec[i].py;
706 vec[2]=fEvent.rec[i].pz;
707 }
708 p.SetVector (vec,"car");
709 t.Set3Momentum(p);
710
711 // Use the fit number as track id
712 tid=fEvent.rec[i].tag;
713 t.SetId(abs(tid));
714
715 idf2k=fEvent.rec[i].id;
716 idpdg=0;
717 if (idf2k>1000)
718 {
719 idpdg=idf2k+10000000;
720 }
721 else if (idf2k <= 48)
722 {
723 idpdg=fPdg->ConvertGeant3ToPdg(idf2k);
724 }
725 else
726 {
727 if (idf2k==201) idpdg=12;
728 if (idf2k==202) idpdg=14;
729 if (idf2k==203) idpdg=16;
730 if (idf2k==204) idpdg=-12;
731 if (idf2k==205) idpdg=-14;
732 if (idf2k==206) idpdg=-16;
733 }
734
735 t.SetParticleCode(idpdg);
736 t.SetName(fPdg->GetParticle(idpdg)->GetName());
737 t.SetTitle("RECO track");
738 t.SetMass(fPdg->GetParticle(idpdg)->Mass());
739 t.SetCharge(fPdg->GetParticle(idpdg)->Charge()/3.);
740
741 // Retrieve the various fit parameters for this track
742 AliSignal* fitdata=fFitdefs->GetIdHit(i);
743 for (Int_t jval=0; jval<fEvent.fresult[i].nval; jval++)
744 {
745 fitdata->SetSignal(fEvent.fresult[i].val[jval],jval+1);
746 }
747
748 // Store the various fit parameters for this track
749 t.SetFitDetails(fitdata);
750
751 // Store the various reco tracks as track hypotheses.
752 // A copy of the first reco track is entered as a new track instance
753 // into the event and all reco tracks (incl. the first one) are
754 // stored as hypotheses linked to this new reco track.
755 if (i==0)
756 {
757 evt->AddTrack(t);
758 AliTrack* tx=evt->GetTrack(evt->GetNtracks());
759 Int_t nrec=evt->GetNtracks(1);
760 tx->SetId(nrec+1);
761 }
762 AliTrack* tx=evt->GetTrack(evt->GetNtracks());
763 if (tx) tx->AddTrackHypothesis(t);
764 }
765}
766///////////////////////////////////////////////////////////////////////////
5481c137 767void IceF2k::PutHits()
f67e2651 768{
769// Get the hit and waveform info from the F2000 file into the IcePack structure.
770// This memberfunction is based on the original code by Adam Bouchta.
771
5481c137 772 IceEvent* evt=(IceEvent*)GetMainObject();
f67e2651 773 if (!evt) return;
774
775 // Loop over all the hits and add them to the current event
776 IceAOM om;
777 AliSignal s;
778 s.SetSlotName("ADC",1);
779 s.SetSlotName("LE",2);
780 s.SetSlotName("TOT",3);
781 Int_t chan=0;
782 Int_t maxchan=800;
783 if (fOmdb) maxchan=fHeader.nch;
784 IceAOM* omx=0;
785 AliSignal* sx=0;
786 Int_t tid=0;
787 AliTrack* tx=0;
64c21700 788 Float_t adc=0;
f67e2651 789 for (Int_t i=0; i<fEvent.nhits; i++)
790 {
791 chan=fEvent.h[i].ch+1;
792 if (chan>maxchan) continue; // Channels 9001, 9002 etc are trigger channels
793
794 // Get corresponding device from the current event structure
795 omx=(IceAOM*)evt->GetIdDevice(chan);
796 if (!omx)
797 {
798 if (fOmdb)
799 {
800 omx=(IceAOM*)fOmdb->GetObject(chan,1);
801 evt->AddDevice(omx);
802 }
803 else
804 {
805 om.Reset(1);
806 om.SetUniqueID(chan);
807 evt->AddDevice(om);
808 }
809 omx=(IceAOM*)evt->GetIdDevice(chan);
810 }
811
812 if (!omx) continue;
813
814 s.Reset();
815 s.SetUniqueID(fEvent.h[i].id);
816 s.SetSignal(fEvent.h[i].amp,1);
817 s.SetSignal(fEvent.h[i].t,2);
818 s.SetSignal(fEvent.h[i].tot,3);
819
820 omx->AddHit(s);
821
822 sx=omx->GetHit(omx->GetNhits());
823 if (!sx) continue;
824
64c21700 825 // ADC dependent TDC (de)calibration function for this hit
826 TF1* fcal=omx->GetCalFunction("LE");
827 TF1* fdecal=omx->GetDecalFunction("LE");
828 if (fcal) sx->SetCalFunction(fcal,2);
829 if (fdecal) sx->SetDecalFunction(fdecal,2);
830 fcal=sx->GetCalFunction(2);
831 fdecal=sx->GetDecalFunction(2);
832 adc=sx->GetSignal(1,-4);
833 if (adc>0)
834 {
835 if (fcal) fcal->SetParameter(3,adc);
836 if (fdecal) fdecal->SetParameter(3,adc);
837 }
838 else
839 {
a4b77ddf 840 if (fcal) fcal->SetParameter(3,1.e20);
841 if (fdecal) fdecal->SetParameter(3,1.e20);
64c21700 842 }
843
f67e2651 844 // Bi-directional link between this hit and the track that caused the ADC value.
845 // This F2K info is probably only present for MC tracks.
846 tid=fEvent.h[i].ma;
847 if (tid > 0)
848 {
849 tx=evt->GetIdTrack(tid); // Reco tracks
850 if (!tx) tx=evt->GetIdTrack(-tid); // MC tracks
851 if (tx) sx->AddLink(tx);
852 }
853 else
854 {
855 if (tid == -2) s.SetNameTitle("N","Noise");
856 if (tid == -3) s.SetNameTitle("A","Afterpulse");
857 }
858 }
859
860 // Loop over all the waveforms and add the histo(s) to the corresponding OM's
861 TH1F histo;
862 Int_t nbins=0;
863 Float_t xlow=0;
864 Float_t xup=0;
865 TString hname;
866 for (Int_t iwf=0; iwf<fEvent.nwf; iwf++)
867 {
868 chan=fEvent.wf[iwf].om;
869 if (chan<=0 || chan>maxchan) continue; // Skip trigger channels
870
871 // Get corresponding device from the current event structure
872 omx=(IceAOM*)evt->GetIdDevice(chan);
873 if (!omx)
874 {
875 if (fOmdb)
876 {
877 omx=(IceAOM*)fOmdb->GetObject(chan,1);
878 evt->AddDevice(omx);
879 }
880 else
881 {
882 om.Reset(1);
883 om.SetUniqueID(chan);
884 evt->AddDevice(om);
885 }
886 omx=(IceAOM*)evt->GetIdDevice(chan);
887 }
888
889 if (!omx) continue;
890
891 omx->SetSlotName("BASELINE",omx->GetNnames()+1);
892 omx->SetSignal(fEvent.wf[iwf].baseline,"BASELINE");
893
894 // Fill the waveform histogram
895 hname="OM";
896 hname+=chan;
897 hname+="-WF";
898 hname+=omx->GetNwaveforms()+1;
899
900 histo.Reset();
901 histo.SetName(hname.Data());
902 nbins=fEvent.wf[iwf].ndigi;
903 xlow=fEvent.wf[iwf].t_start;
904 xup=xlow+float(nbins)*fEvent.wf[iwf].t_bin;
905 histo.SetBins(nbins,xlow,xup);
906
907 for (Int_t jbin=1; jbin<=fEvent.wf[iwf].ndigi; jbin++)
908 {
0e50ad4d 909 histo.SetBinContent(jbin,fEvent.wf[iwf].digi[jbin-1]);
f67e2651 910 }
911
912 omx->SetWaveform(&histo,omx->GetNwaveforms()+1);
913 }
914
915 // Set bi-directional links between hits and reco track hypotheses.
916 // Note : Reco tracks are recognised by their positive id.
917 Int_t hid=0;
918 TObjArray* rectracks=evt->GetTracks(1);
919 for (Int_t jtk=0; jtk<rectracks->GetEntries(); jtk++)
920 {
921 tx=(AliTrack*)rectracks->At(jtk);
922 if (!tx) continue;
923
924 for (Int_t jhyp=1; jhyp<=tx->GetNhypotheses(); jhyp++)
925 {
926 AliTrack* hypx=tx->GetTrackHypothesis(jhyp);
927 if (!hypx) continue;
928
929 // Loop over all combinations of F2K fits and used OM hits
930 for (Int_t k=0; k<fEvent.nfit_uses; k++)
931 {
932 if (fEvent.fit_uses[k].useid != hypx->GetId()) continue;
933 hid=fEvent.fit_uses[k].hitid;
934 sx=evt->GetIdHit(hid,"IceAOM");
935 if (sx) sx->AddLink(hypx);
936 }
937 }
938 }
939}
940///////////////////////////////////////////////////////////////////////////