1 /*******************************************************************************
2 * Copyright(c) 2003, IceCube Experiment at the South Pole. All rights reserved.
4 * Author: The IceCube RALICE-based Offline Project.
5 * Contributors are mentioned in the code where appropriate.
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 *******************************************************************************/
18 ///////////////////////////////////////////////////////////////////////////
20 // Conversion of Amanda F2K data into IceEvent physics event structures.
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.
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.
35 // Note : This example creates automatically the ROOT output file, which
36 // is the most user friendly way of running the conversion job.
37 // In the subdirectory /macros the example macro icef2k.cc provides
38 // an example of how to create a ROOT output file yourself and passing
39 // this file via a pointer to IceF2k.
41 // gSystem->Load("ralice");
42 // gSystem->Load("icepack");
43 // gSystem->Load("iceconvert");
45 // IceF2k q("IceF2k","F2K to IcePack data structure conversion");
47 // // Limit the number of entries for testing
48 // q.SetMaxEvents(10);
50 // // Print frequency to produce a short summary print every printfreq events
53 // // Split level for the output structures
54 // q.SetSplitLevel(2);
56 // // Buffer size for the output structures
57 // q.SetBufferSize(32000);
59 // // The F2K input filename(s)
60 // q.AddInputFile("run7825.f2k");
62 // // Output file for the event structures
63 // q.SetOutputFile("events.root");
65 // ///////////////////////////////////////////////////////////////////
66 // // Here the user can specify his/her sub-tasks to be executed
67 // // on an event-by-event basis after the IceEvent structure
68 // // has been filled and before the data is written out.
69 // // Sub-tasks (i.e. a user classes derived from TTask) are entered
72 // // MyXtalk task1("task1","Cross talk correction");
73 // // MyClean task2("task2","Hit cleaning");
77 // // The sub-tasks will be executed in the order as they are entered.
78 // ///////////////////////////////////////////////////////////////////
80 // // Perform the conversion and execute subtasks (if any)
81 // // on an event-by-event basis
84 // // Select various objects to be added to the output file
86 // TFile* ofile=q.GetOutputFile();
90 // ofile->cd(); // Switch to the output file directory
92 // AliObjMatrix* omdb=q.GetOMdbase();
93 // if (omdb) omdb->Write();
95 // AliDevice* fitdefs=q.GetFitdefs();
96 // if (fitdefs) fitdefs->Write();
98 // TDatabasePDG* pdg=q.GetPDG();
99 // if (pdg) pdg->Write();
101 // // Flush additional objects to the output file.
102 // // The output file is not explicitly closed here
103 // // to allow interactive investigation of the data tree
104 // // when this macro is run in an interactive ROOT/CINT session.
108 //--- Author: Nick van Eijndhoven 11-mar-2005 Utrecht University
109 //- Modified: NvE $Date$ Utrecht University
110 ///////////////////////////////////////////////////////////////////////////
113 #include "Riostream.h"
115 ClassImp(IceF2k) // Class implementation to enable ROOT I/O
117 IceF2k::IceF2k(const char* name,const char* title) : AliJob(name,title)
119 // Default constructor.
120 // By default maxevent=-1, split=99, bsize=32000, printfreq=1.
134 ///////////////////////////////////////////////////////////////////////////
137 // Default destructor.
169 ///////////////////////////////////////////////////////////////////////////
170 void IceF2k::SetMaxEvents(Int_t n)
172 // Set the maximum number of events to be processed.
173 // n=-1 implies processing of the complete input file, which is the default
174 // initialisation in the constructor.
177 ///////////////////////////////////////////////////////////////////////////
178 void IceF2k::SetPrintFreq(Int_t f)
180 // Set the printfrequency to produce info every f events.
181 // f=1 is the default initialisation in the constructor.
182 if (f>=0) fPrintfreq=f;
184 ///////////////////////////////////////////////////////////////////////////
185 void IceF2k::SetSplitLevel(Int_t split)
187 // Set the split level for the ROOT data file.
188 // split=99 is the default initialisation in the constructor.
189 if (split>=0) fSplit=split;
191 ///////////////////////////////////////////////////////////////////////////
192 void IceF2k::SetBufferSize(Int_t bsize)
194 // Set the buffer size for the ROOT data file.
195 // bsize=32000 is the default initialisation in the constructor.
196 if (bsize>=0) fBsize=bsize;
198 ///////////////////////////////////////////////////////////////////////////
199 void IceF2k::SetInputFile(TString name)
201 // Set the name of the F2K input file.
202 // This function has become obsolete but is kept for backward compatibility.
203 // The user is advised to use AddInputFile() instead, which allows processing
204 // of multiple F2K input files.
205 // This function will reset the list of all F2K input files and put the specified
206 // filename at the first position.
207 // Additional F2K input files can be specified via AddInputFile().
209 if (fInfiles) delete fInfiles;
211 fInfiles=new TObjArray();
212 fInfiles->SetOwner();
214 TObjString* s=new TObjString();
218 ///////////////////////////////////////////////////////////////////////////
219 void IceF2k::AddInputFile(TString name)
221 // Add the name of this F2K input file to the list to be processed.
225 fInfiles=new TObjArray();
226 fInfiles->SetOwner();
229 TObjString* s=new TObjString();
233 ///////////////////////////////////////////////////////////////////////////
234 void IceF2k::SetOutputFile(TFile* ofile)
236 // Set the output file for the ROOT data.
237 if (fOutfile) delete fOutfile;
240 ///////////////////////////////////////////////////////////////////////////
241 void IceF2k::SetOutputFile(TString name)
243 // Create the output file for the ROOT data.
244 if (fOutfile) delete fOutfile;
245 fOutfile=new TFile(name.Data(),"RECREATE","F2K data in IceEvent structure");
247 ///////////////////////////////////////////////////////////////////////////
248 TFile* IceF2k::GetOutputFile()
250 // Provide pointer to the ROOT output file.
253 ///////////////////////////////////////////////////////////////////////////
254 TDatabasePDG* IceF2k::GetPDG()
256 // Provide pointer to the PDG database
259 ///////////////////////////////////////////////////////////////////////////
260 AliObjMatrix* IceF2k::GetOMdbase()
262 // Provide pointer to the OM geometry, calib. etc... database
265 ///////////////////////////////////////////////////////////////////////////
266 AliDevice* IceF2k::GetFitdefs()
268 // Provide pointer to the fit definitions
271 ///////////////////////////////////////////////////////////////////////////
272 AliDevice* IceF2k::GetTrigdefs()
274 // Provide pointer to the trigger definitions
277 ///////////////////////////////////////////////////////////////////////////
278 void IceF2k::Exec(Option_t* opt)
280 // Job to loop over the specified number of events and convert the
281 // F2K data into the IceEvent structure.
282 // If maxevents<0 (default) all the entries of the input file
283 // will be processed.
284 // Every "printfreq" events a short event summary will be printed.
285 // The default value is printfreq=1.
286 // The output will be written on a standard output tree named "T".
290 // 1) This class is derived from AliJob, allowing a task based processing.
291 // After the conversion of an F2K event into an IceEvent structure,
292 // the processing of all available sub-tasks (if any) is invoked.
293 // This provides an event-by-event (sub)task processing before the
294 // final data structures are written out.
295 // 2) The main object in this job environment is an IceEvent* pointer.
299 cout << " *IceF2k Exec* No data input file(s) specified." << endl;
303 Int_t ninfiles=fInfiles->GetEntries();
306 cout << " *IceF2k Exec* No data input file(s) specified." << endl;
313 otree=new TTree("T","F2K Data converted to IceEvent structures");
314 otree->SetDirectory(fOutfile);
317 IceEvent* evt=new IceEvent();
318 evt->SetTrackCopy(1);
321 // Branch in the tree for the event structure
322 if (otree) otree->Branch("IceEvent","IceEvent",&evt,fBsize,fSplit);
324 // Create the particle database and extend it with some F2000 specific definitions
325 if (!fPdg) fPdg=new TDatabasePDG();
326 Double_t me=fPdg->GetParticle(11)->Mass();
327 fPdg->AddParticle("brems" ,"brems" ,0,1,0,0,"none",10001001,0,0);
328 fPdg->AddParticle("deltae" ,"deltae" ,me,1,0,-3,"Lepton",10001002,0,0);
329 fPdg->AddParticle("pairprod","pairprod",0,1,0,0,"none",10001003,0,0);
330 fPdg->AddParticle("nucl_int","nucl_Int",0,1,0,0,"none",10001004,0,0);
331 fPdg->AddParticle("mu_pair" ,"mu_pair" ,0,1,0,0,"none",10001005,0,0);
332 fPdg->AddParticle("hadrons" ,"hadrons" ,0,1,0,0,"none",10001006,0,0);
333 fPdg->AddParticle("fiberlaser","fiberlaser",0,1,0,0,"none",10002100,0,0);
334 fPdg->AddParticle("n2laser" ,"n2laser" ,0,1,0,0,"none",10002101,0,0);
335 fPdg->AddParticle("yaglaser" ,"yaglaser" ,0,1,0,0,"none",10002201,0,0);
336 fPdg->AddParticle("z_primary","z_primary",0,1,0,0,"none",10003000,0,0);
337 fPdg->AddParticle("a_primary","a_primary",0,1,0,0,"none",10003500,0,0);
339 // Initialise the job working environment
349 cout << " ***" << endl;
350 cout << " *** Start processing of job " << GetName() << " ***" << endl;
351 cout << " ***" << endl;
352 for (Int_t i=0; i<ninfiles; i++)
354 TObjString* sx=(TObjString*)fInfiles->At(i);
356 inputfile=sx->GetString();
357 cout << " F2K input file : " << inputfile.Data() << endl;
359 cout << " Maximum number of events to be processed : " << fMaxevt << endl;
360 cout << " Print frequency : " << fPrintfreq << endl;
363 cout << " ROOT output file : " << fOutfile->GetName() << endl;
364 cout << " Output characteristics : splitlevel = " << fSplit << " buffersize = " << fBsize << endl;
370 for (Int_t ifile=0; ifile<ninfiles; ifile++)
372 TObjString* sx=(TObjString*)fInfiles->At(ifile);
375 inputfile=sx->GetString();
376 if (inputfile=="") continue;
378 // Open the input file in the default ascii format (autodetection) for reading
379 fInput=rdmc_mcopen(inputfile.Data(),"r",RDMC_DEFAULT_ASCII_F);
383 cout << " *IceF2k Exec* No input file found with name : " << inputfile.Data() << endl;
387 // Initialise the event structure
388 rdmc_init_mevt(&fEvent);
390 // Read the file header information
391 rdmc_rarr(fInput,&fHeader);
393 // Fill the database with geometry, calib. etc... parameters
394 // for all the devices
397 // Set the fit definitions according to the F2000 header info
400 // Set the trigger definitions according to the F2000 header info
403 while (!rdmc_revt(fInput,&fHeader,&fEvent))
405 if (fMaxevt>-1 && nevt>=fMaxevt) break;
407 // Reset the complete Event structure
410 evt->SetRunNumber(fEvent.nrun);
411 evt->SetEventNumber(fEvent.enr);
412 evt->SetMJD(fEvent.mjd,fEvent.secs,fEvent.nsecs);
422 // Invoke all available sub-tasks (if any)
428 if (!(nevt%fPrintfreq)) evt->HeaderData();
431 // Write the complete structure to the output Tree
432 if (otree) otree->Fill();
434 // Update event counter
437 if (fMaxevt>-1 && nevt>=fMaxevt) break;
440 // Flush possible memory resident data to the output file
441 if (fOutfile) fOutfile->Write();
443 // Remove the IceEvent object from the environment
444 // and delete it as well
451 ///////////////////////////////////////////////////////////////////////////
452 void IceF2k::FillOMdbase()
454 // Fill the database with geometry, calib. etc... parameters
455 // for all the devices.
467 Int_t adccal=fHeader.is_calib.adc;
468 Int_t tdccal=fHeader.is_calib.tdc;
469 Int_t totcal=fHeader.is_calib.tot;
471 TF1 fadccal("fadccal","(x-[1])*[0]");
472 TF1 fadcdecal("fadcdecal","(x/[0])+[1]");
473 fadccal.SetParName(0,"BETA-ADC");
474 fadccal.SetParName(1,"PED-ADC");
475 fadcdecal.SetParName(0,"BETA-ADC");
476 fadcdecal.SetParName(1,"PED-ADC");
478 TF1 ftdccal("ftdccal","(x*[0])-[1]-([0]-1.)*32767.-[2]/sqrt([3])");
479 TF1 ftdcdecal("ftdcdecal","(x+([0]-1.)*32767.+[1]+[2]/sqrt([3]))/[0]");
480 ftdccal.SetParName(0,"BETA-TDC");
481 ftdccal.SetParName(1,"T0");
482 ftdccal.SetParName(2,"ALPHA-TDC");
483 ftdccal.SetParName(3,"ADC-SLEW");
484 ftdcdecal.SetParName(0,"BETA-TDC");
485 ftdcdecal.SetParName(1,"T0");
486 ftdcdecal.SetParName(2,"ALPHA-TDC");
487 ftdcdecal.SetParName(3,"ADC-SLEW");
489 TF1 ftotcal("ftotcal","x*[0]");
490 TF1 ftotdecal("ftotdecal","x/[0]");
491 ftotcal.SetParName(0,"BETA-TOT");
492 ftotdecal.SetParName(0,"BETA-TOT");
500 fOmdb=new AliObjMatrix();
501 fOmdb->SetNameTitle("OMDBASE","The OM geometry, calib. etc... database");
506 Double_t pos[3]={0,0,0};
507 for (Int_t i=0; i<fHeader.nch; i++)
510 dev->SetUniqueID(i+1);
512 dev->SetSlotName("ADC",1);
513 dev->SetSlotName("LE",2);
514 dev->SetSlotName("TOT",3);
516 dev->SetSlotName("TYPE",4);
517 dev->SetSlotName("ORIENT",5);
518 dev->SetSlotName("THRESH",6);
519 dev->SetSlotName("SENSIT",7);
520 dev->SetSlotName("BETA-TDC",8);
521 dev->SetSlotName("T0",9);
522 dev->SetSlotName("ALPHA-TDC",10);
523 dev->SetSlotName("PED-ADC",11);
524 dev->SetSlotName("BETA-ADC",12);
525 dev->SetSlotName("KAPPA-ADC",13);
526 dev->SetSlotName("PED-TOT",14);
527 dev->SetSlotName("BETA-TOT",15);
528 dev->SetSlotName("KAPPA-TOT",16);
533 dev->SetPosition(pos,"car");
535 fadccal.SetParameter(0,fHeader.cal[i].beta_a);
536 fadccal.SetParameter(1,fHeader.cal[i].ped);
537 fadcdecal.SetParameter(0,fHeader.cal[i].beta_a);
538 if (!fHeader.cal[i].beta_a) fadcdecal.SetParameter(0,1);
539 fadcdecal.SetParameter(1,fHeader.cal[i].ped);
541 ftdccal.SetParameter(0,fHeader.cal[i].beta_t);
542 ftdccal.SetParameter(1,fHeader.cal[i].t_0);
543 ftdccal.SetParameter(2,fHeader.cal[i].alpha_t);
544 ftdccal.SetParameter(3,1.e20);
545 ftdcdecal.SetParameter(0,fHeader.cal[i].beta_t);
546 if (!fHeader.cal[i].beta_t) ftdcdecal.SetParameter(0,1);
547 ftdcdecal.SetParameter(1,fHeader.cal[i].t_0);
548 ftdcdecal.SetParameter(2,fHeader.cal[i].alpha_t);
549 ftdcdecal.SetParameter(3,1.e20);
551 ftotcal.SetParameter(0,fHeader.cal[i].beta_tot);
552 ftotdecal.SetParameter(0,fHeader.cal[i].beta_tot);
553 if (!fHeader.cal[i].beta_tot) ftotdecal.SetParameter(0,1);
557 dev->SetDecalFunction(&fadcdecal,1);
561 dev->SetCalFunction(&fadccal,1);
566 dev->SetDecalFunction(&ftdcdecal,2);
570 dev->SetCalFunction(&ftdccal,2);
575 dev->SetDecalFunction(&ftotdecal,3);
579 dev->SetCalFunction(&ftotcal,3);
582 dev->SetSignal(fHeader.type[i],4);
583 dev->SetSignal((Float_t)fHeader.costh[i],5);
584 dev->SetSignal(fHeader.thresh[i],6);
585 dev->SetSignal(fHeader.sensit[i],7);
586 dev->SetSignal(fHeader.cal[i].beta_t,8);
587 dev->SetSignal(fHeader.cal[i].t_0,9);
588 dev->SetSignal(fHeader.cal[i].alpha_t,10);
589 dev->SetSignal(fHeader.cal[i].ped,11);
590 dev->SetSignal(fHeader.cal[i].beta_a,12);
591 dev->SetSignal(fHeader.cal[i].kappa,13);
592 dev->SetSignal(fHeader.cal[i].ped_tot,14);
593 dev->SetSignal(fHeader.cal[i].beta_tot,15);
594 dev->SetSignal(fHeader.cal[i].kappa_tot,16);
596 fOmdb->EnterObject(i+1,1,dev);
599 ///////////////////////////////////////////////////////////////////////////
600 void IceF2k::SetFitdefs()
602 // Obtain the names of the variables for each fit procedure from the
603 // f2000 header. Each different fit procedure is then stored as a separate
604 // "hit" of an AliDevice object and the various fit variables are stored
605 // as separate signal slots of the corresponding "hit".
606 // Via the GetFitdefs() memberfunction this AliDevice object can be
607 // retrieved and stored in the ROOT output file if wanted.
608 // The name of the object is FitDefinitions and the stored data can be
609 // inspected via the AliDevice::Data() memberfunction and looks as follows :
611 // *AliDevice::Data* Id :0 Name : FitDefinitions
612 // Position Vector in car coordinates : 0 0 0
613 // Err. in car coordinates : 0 0 0
614 // The following 8 hits are registered :
615 // *AliSignal::Data* Id :0
616 // Position Vector in car coordinates : 0 0 0
617 // Err. in car coordinates : 0 0 0
618 // Owned by device : AliDevice Name : FitDefinitions
619 // Slot : 1 Signal value : 0 name : id
620 // Slot : 2 Signal value : 0 name : rchi2
621 // Slot : 3 Signal value : 0 name : prob
622 // Slot : 4 Signal value : 0 name : sigth
623 // Slot : 5 Signal value : 0 name : covmin
624 // Slot : 6 Signal value : 0 name : covmax
625 // Slot : 7 Signal value : 0 name : cutflag
626 // Slot : 8 Signal value : 0 name : chi2
627 // *AliSignal::Data* Id :1
628 // Position Vector in car coordinates : 0 0 0
629 // Err. in car coordinates : 0 0 0
630 // Owned by device : AliDevice Name : FitDefinitions
631 // Slot : 1 Signal value : 0 name : id
632 // Slot : 2 Signal value : 0 name : rchi2
633 // Slot : 3 Signal value : 0 name : prob
636 // This memberfunction is based on the original idea/code by Adam Bouchta.
638 if (fHeader.n_fit<=0)
654 fFitdefs=new AliDevice();
657 fFitdefs->SetName("FitDefinitions");
658 fFitdefs->SetHitCopy (1);
663 for (Int_t i=0; i<fHeader.n_fit; i++)
665 s.SetUniqueID(fHeader.def_fit[i].id);
666 s.SetName(TString(fHeader.def_fit[i].tag));
668 for (Int_t j=0; j<fHeader.def_fit[i].nwords; j++)
670 s.SetSlotName(TString(fHeader.def_fit[i].words[j]),j+1);
678 ///////////////////////////////////////////////////////////////////////////
679 void IceF2k::SetTrigdefs()
681 // Obtain the names of the variables for each trigger procedure from the
682 // f2000 header. Each different trigger procedure is then stored as a separate
683 // "hit" of an AliDevice object and the various trigger variables are stored
684 // as separate signal slots of the corresponding "hit".
685 // Via the GetFitdefs() memberfunction this AliDevice object can be
686 // retrieved and stored in the ROOT output file if wanted.
687 // The name of the object is TrigDefinitions and the stored data can be
688 // inspected via the AliDevice::Data() memberfunction and looks as follows :
690 // *AliDevice::Data* Id : 0 Name : TrigDefinitions
691 // Position Vector in car (rad) coordinates : 0 0 0
692 // Err. in car (rad) coordinates : 0 0 0
693 // The following 9 hits are registered :
694 // *AliSignal::Data* Id : 1 Name : main
695 // Position Vector in car (rad) coordinates : 0 0 0
696 // Err. in car (rad) coordinates : 0 0 0
697 // Owned by device : AliDevice Id : 0 Name : TrigDefinitions
698 // Slot : 1 Signal value : 0 name : trig_pulse_le
699 // Slot : 2 Signal value : 0 name : trig_pulse_tot
700 // Slot : 3 Signal value : 0 name : regi_flag
701 // *AliSignal::Data* Id : 2 Name : amaa
702 // Position Vector in car (rad) coordinates : 0 0 0
703 // Err. in car (rad) coordinates : 0 0 0
704 // Owned by device : AliDevice Id : 0 Name : TrigDefinitions
705 // Slot : 1 Signal value : 0 name : trig_pulse_le
706 // Slot : 2 Signal value : 0 name : trig_pulse_tot
707 // Slot : 3 Signal value : 0 name : regi_flag
708 // *AliSignal::Data* Id : 3 Name : amab10
709 // Position Vector in car (rad) coordinates : 0 0 0
710 // Err. in car (rad) coordinates : 0 0 0
711 // Owned by device : AliDevice Id : 0 Name : TrigDefinitions
712 // Slot : 1 Signal value : 0 name : trig_pulse_le
713 // Slot : 2 Signal value : 0 name : trig_pulse_tot
714 // Slot : 3 Signal value : 0 name : regi_flag
717 if (fHeader.n_trigger<=0)
733 fTrigdefs=new AliDevice();
736 fTrigdefs->SetName("TrigDefinitions");
737 fTrigdefs->SetHitCopy (1);
742 for (Int_t i=0; i<fHeader.n_trigger; i++)
744 s.SetUniqueID(fHeader.def_trig[i].id);
745 s.SetName(TString(fHeader.def_trig[i].tag));
747 for (Int_t j=0; j<fHeader.def_trig[i].nwords; j++)
749 s.SetSlotName(TString(fHeader.def_trig[i].words[j]),j+1);
753 fTrigdefs->AddHit(s);
757 ///////////////////////////////////////////////////////////////////////////
758 void IceF2k::PutMcTracks()
760 // Get the MC tracks from the F2000 file into the IcePack structure.
761 // Note : MC tracks are given negative track id's in the event structure.
762 // This memberfunction is based on the original code by Adam Bouchta.
764 IceEvent* evt=(IceEvent*)GetMainObject();
765 if (!evt || fEvent.ntrack<=0) return;
767 // Loop over all the tracks and add them to the current event
775 for (Int_t i=0; i<fEvent.ntrack; i++)
779 // Beginpoint of the track
780 vec[0]=fEvent.gen[i].x;
781 vec[1]=fEvent.gen[i].y;
782 vec[2]=fEvent.gen[i].z;
783 r.SetPosition(vec,"car");
786 // Endpoint of the track
787 vec[0]+=fEvent.gen[i].length*fEvent.gen[i].px;
788 vec[1]+=fEvent.gen[i].length*fEvent.gen[i].py;
789 vec[2]+=fEvent.gen[i].length*fEvent.gen[i].pz;
790 r.SetPosition(vec,"car");
794 vec[0]=fEvent.gen[i].e*fEvent.gen[i].px*1e-3;
795 vec[1]=fEvent.gen[i].e*fEvent.gen[i].py*1e-3;
796 vec[2]=fEvent.gen[i].e*fEvent.gen[i].pz*1e-3;
797 p.SetVector (vec,"car");
800 // MC tracks are indicated by negative track id's
801 tid=fEvent.gen[i].tag;
804 idf2k=fEvent.gen[i].id;
808 idpdg=idf2k+10000000;
810 else if (idf2k <= 48)
812 idpdg=fPdg->ConvertGeant3ToPdg(idf2k);
816 if (idf2k==201) idpdg=12;
817 if (idf2k==202) idpdg=14;
818 if (idf2k==203) idpdg=16;
819 if (idf2k==204) idpdg=-12;
820 if (idf2k==205) idpdg=-14;
821 if (idf2k==206) idpdg=-16;
824 t.SetParticleCode(idpdg);
825 t.SetName(fPdg->GetParticle(idpdg)->GetName());
826 t.SetTitle("MC track");
827 t.SetMass(fPdg->GetParticle(idpdg)->Mass());
828 t.SetCharge(fPdg->GetParticle(idpdg)->Charge()/3.);
833 // Create the pointers to each particle's parent particle.
836 for (Int_t itk=1; itk<=evt->GetNtracks (); itk++)
838 AliTrack* tx=evt->GetTrack(itk);
845 for (Int_t j=0; j<fEvent.ntrack; j++)
847 tid=fEvent.gen[j].tag;
848 if (-abs(tid) == txid) parid=fEvent.gen[j].parent;
851 if (parid<0) continue;
853 AliTrack* tpar=evt->GetIdTrack(-abs(parid));
857 tx->SetParentTrack(tpar);
860 ///////////////////////////////////////////////////////////////////////////
861 void IceF2k::PutRecoTracks()
863 // Get the reconstructed tracks from the F2000 file into the IcePack structure.
864 // Note : Reco tracks are given positive track id's in the event structure.
865 // This memberfunction is based on the original code by Adam Bouchta.
867 IceEvent* evt=(IceEvent*)GetMainObject();
868 if (!evt || fEvent.nfit<=0) return;
870 // Loop over all the tracks and add them to the current event
878 for (Int_t i=0; i<fEvent.nfit; i++)
882 // Beginpoint of the track
883 vec[0]=fEvent.rec[i].x;
884 vec[1]=fEvent.rec[i].y;
885 vec[2]=fEvent.rec[i].z;
886 r.SetPosition(vec,"car");
889 // Endpoint of the track
890 vec[0]+=fEvent.rec[i].length*fEvent.rec[i].px;
891 vec[1]+=fEvent.rec[i].length*fEvent.rec[i].py;
892 vec[2]+=fEvent.rec[i].length*fEvent.rec[i].pz;
893 r.SetPosition(vec,"car");
897 if (fEvent.rec[i].e > 0)
899 vec[0]=fEvent.rec[i].e*fEvent.rec[i].px*1e-3;
900 vec[1]=fEvent.rec[i].e*fEvent.rec[i].py*1e-3;
901 vec[2]=fEvent.rec[i].e*fEvent.rec[i].pz*1e-3;
903 else // Give the track a nominal momentum of 1 GeV/c
905 vec[0]=fEvent.rec[i].px;
906 vec[1]=fEvent.rec[i].py;
907 vec[2]=fEvent.rec[i].pz;
909 p.SetVector (vec,"car");
912 // Use the fit number as track id
913 tid=fEvent.rec[i].tag;
916 idf2k=fEvent.rec[i].id;
920 idpdg=idf2k+10000000;
922 else if (idf2k <= 48)
924 idpdg=fPdg->ConvertGeant3ToPdg(idf2k);
928 if (idf2k==201) idpdg=12;
929 if (idf2k==202) idpdg=14;
930 if (idf2k==203) idpdg=16;
931 if (idf2k==204) idpdg=-12;
932 if (idf2k==205) idpdg=-14;
933 if (idf2k==206) idpdg=-16;
936 t.SetParticleCode(idpdg);
937 t.SetNameTitle("Sieglinde","RECO track");
938 t.SetMass(fPdg->GetParticle(idpdg)->Mass());
939 t.SetCharge(fPdg->GetParticle(idpdg)->Charge()/3.);
941 // Retrieve the various fit parameters for this track
942 AliSignal* fitdata=fFitdefs->GetIdHit(i);
943 for (Int_t jval=0; jval<fEvent.fresult[i].nval; jval++)
945 fitdata->SetSignal(fEvent.fresult[i].val[jval],jval+1);
948 // Store the various fit parameters for this track
949 t.SetFitDetails(fitdata);
951 // Store the various reco tracks as track hypotheses.
952 // A copy of the first reco track is entered as a new track instance
953 // into the event and all reco tracks (incl. the first one) are
954 // stored as hypotheses linked to this new reco track.
958 AliTrack* tx=evt->GetTrack(evt->GetNtracks());
959 Int_t nrec=evt->GetNtracks(1);
962 AliTrack* tx=evt->GetTrack(evt->GetNtracks());
963 if (tx) tx->AddTrackHypothesis(t);
966 ///////////////////////////////////////////////////////////////////////////
967 void IceF2k::PutHits()
969 // Get the hit and waveform info from the F2000 file into the IcePack structure.
970 // This memberfunction is based on the original code by Adam Bouchta.
972 IceEvent* evt=(IceEvent*)GetMainObject();
975 // Loop over all the hits and add them to the current event
978 s.SetSlotName("ADC",1);
979 s.SetSlotName("LE",2);
980 s.SetSlotName("TOT",3);
983 if (fOmdb) maxchan=fHeader.nch;
989 for (Int_t i=0; i<fEvent.nhits; i++)
991 chan=fEvent.h[i].ch+1;
992 if (chan>maxchan) continue; // Channels 9001, 9002 etc are trigger channels
994 // Get corresponding device from the current event structure
995 omx=(IceAOM*)evt->GetIdDevice(chan);
1000 omx=(IceAOM*)fOmdb->GetObject(chan,1);
1001 evt->AddDevice(omx);
1006 om.SetUniqueID(chan);
1009 omx=(IceAOM*)evt->GetIdDevice(chan);
1015 s.SetUniqueID(fEvent.h[i].id);
1016 s.SetSignal(fEvent.h[i].amp,1);
1017 s.SetSignal((fEvent.h[i].t-fEvent.t_offset),2);
1018 s.SetSignal(fEvent.h[i].tot,3);
1022 sx=omx->GetHit(omx->GetNhits());
1025 // ADC dependent TDC (de)calibration function for this hit
1026 TF1* fcal=omx->GetCalFunction("LE");
1027 TF1* fdecal=omx->GetDecalFunction("LE");
1028 if (fcal) sx->SetCalFunction(fcal,2);
1029 if (fdecal) sx->SetDecalFunction(fdecal,2);
1030 fcal=sx->GetCalFunction(2);
1031 fdecal=sx->GetDecalFunction(2);
1032 adc=sx->GetSignal(1,-4);
1035 if (fcal) fcal->SetParameter(3,adc);
1036 if (fdecal) fdecal->SetParameter(3,adc);
1040 if (fcal) fcal->SetParameter(3,1.e20);
1041 if (fdecal) fdecal->SetParameter(3,1.e20);
1044 // Bi-directional link between this hit and the track that caused the ADC value.
1045 // This F2K info is probably only present for MC tracks.
1049 tx=evt->GetIdTrack(tid); // Reco tracks
1050 if (!tx) tx=evt->GetIdTrack(-tid); // MC tracks
1051 if (tx) sx->AddLink(tx);
1055 if (tid == -2) s.SetNameTitle("N","Noise");
1056 if (tid == -3) s.SetNameTitle("A","Afterpulse");
1060 // Loop over all the waveforms and add the histo(s) to the corresponding OM's
1066 for (Int_t iwf=0; iwf<fEvent.nwf; iwf++)
1068 chan=fEvent.wf[iwf].om;
1069 if (chan<=0 || chan>maxchan) continue; // Skip trigger channels
1071 // Get corresponding device from the current event structure
1072 omx=(IceAOM*)evt->GetIdDevice(chan);
1077 omx=(IceAOM*)fOmdb->GetObject(chan,1);
1078 evt->AddDevice(omx);
1083 om.SetUniqueID(chan);
1086 omx=(IceAOM*)evt->GetIdDevice(chan);
1091 omx->SetSlotName("BASELINE",omx->GetNnames()+1);
1092 omx->SetSignal(fEvent.wf[iwf].baseline,"BASELINE");
1094 // Fill the waveform histogram
1098 hname+=omx->GetNwaveforms()+1;
1101 histo.SetName(hname.Data());
1102 nbins=fEvent.wf[iwf].ndigi;
1103 xlow=fEvent.wf[iwf].t_start;
1104 xup=xlow+float(nbins)*fEvent.wf[iwf].t_bin;
1105 histo.SetBins(nbins,xlow,xup);
1107 for (Int_t jbin=1; jbin<=fEvent.wf[iwf].ndigi; jbin++)
1109 histo.SetBinContent(jbin,fEvent.wf[iwf].digi[jbin-1]);
1112 omx->SetWaveform(&histo,omx->GetNwaveforms()+1);
1115 // Set bi-directional links between hits and reco track hypotheses.
1116 // Note : Reco tracks are recognised by their positive id.
1118 TObjArray* rectracks=evt->GetTracks(1);
1119 for (Int_t jtk=0; jtk<rectracks->GetEntries(); jtk++)
1121 tx=(AliTrack*)rectracks->At(jtk);
1124 for (Int_t jhyp=1; jhyp<=tx->GetNhypotheses(); jhyp++)
1126 AliTrack* hypx=tx->GetTrackHypothesis(jhyp);
1127 if (!hypx) continue;
1129 // Loop over all combinations of F2K fits and used OM hits
1130 for (Int_t k=0; k<fEvent.nfit_uses; k++)
1132 if (fEvent.fit_uses[k].useid != hypx->GetId()) continue;
1133 hid=fEvent.fit_uses[k].hitid;
1134 sx=evt->GetIdHit(hid,"IceAOM");
1135 if (sx) sx->AddLink(hypx);
1140 ///////////////////////////////////////////////////////////////////////////
1141 void IceF2k::PutTrigger()
1143 // Get the trigger info from the F2000 file into the IcePack structure.
1145 if (!fTrigdefs) return;
1147 IceEvent* evt=(IceEvent*)GetMainObject();
1148 if (!evt || fEvent.ntrig<=0) return;
1151 trig.SetNameTitle("Trigger","Amanda/IceCube event triggers");
1157 for (Int_t i=0; i<fEvent.ntrig; i++)
1159 id=fEvent.ptrig[i].id;
1160 nval=fEvent.ptrig[i].nval;
1161 if (!nval) continue;
1162 AliSignal* tdef=fTrigdefs->GetIdHit(id+1);
1163 if (!tdef) continue;
1164 trigname=tdef->GetName();
1166 s.SetName(trigname);
1167 s.SetUniqueID(id+1);
1168 for (Int_t jval=0; jval<fEvent.ptrig[i].nval; jval++)
1170 slotname=tdef->GetSlotName(jval+1);
1171 s.SetSlotName(slotname,jval+1);
1172 s.SetSignal(fEvent.ptrig[i].val[jval],jval+1);
1177 // Store the trigger data into the IceEvent structure
1178 evt->AddDevice(trig);
1180 ///////////////////////////////////////////////////////////////////////////