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.
25 // gSystem->Load("ralice");
26 // gSystem->Load("icepack");
27 // gSystem->Load("iceconvert");
29 // // Output file for the event structures
30 // TFile* ofile=new TFile("events.root","RECREATE","F2K data in IceEvent structure");
31 // TTree* otree=new TTree("T","Data of an Amanda run");
33 // // Limit the number of entries for testing
34 // Int_t nentries=300;
36 // // Print frequency to produce a short summary print every printfreq events
37 // Int_t printfreq=10;
39 // // Split level for the output structures
42 // // Buffer size for the output structures
45 // IceF2k q("run8000.f2k",split,bsize);
46 // q.Loop(otree,nentries,printfreq);
48 // // Select various objects to be added to the output file
50 // AliObjMatrix* omdb=q.GetOMdbase();
51 // if (omdb) omdb->Write();
53 // AliDevice* fitdefs=q.GetFitdefs();
54 // if (fitdefs) fitdefs->Write();
56 // TDatabasePDG* pdg=q.GetPDG();
57 // if (pdg) pdg->Write();
59 // // Close output file
63 //--- Author: Nick van Eijndhoven 11-mar-2005 Utrecht University
64 //- Modified: NvE $Date$ Utrecht University
65 ///////////////////////////////////////////////////////////////////////////
68 #include "Riostream.h"
70 ClassImp(IceF2k) // Class implementation to enable ROOT I/O
72 IceF2k::IceF2k(char* fname,Int_t split,Int_t bsize)
74 // Default constructor.
75 // Initialise the input file and data structres to be converted.
76 // Also the required split level and buffer size of the output tree
77 // can be specified in this constructor.
78 // By default tree=0, split=0 and bsize=32000.
89 cout << " *IceF2k ctor* No data input file specified." << endl;
93 // Open the input file in the default ascii format (autodetection) for reading
94 fInput=rdmc_mcopen(fname,"r",RDMC_DEFAULT_ASCII_F);
98 cout << " *IceF2k ctor* No input file found with name : " << fname << endl;
102 // Initialise the event structure
103 rdmc_init_mevt(&fEvent);
105 // Read the file header information
106 rdmc_rarr(fInput,&fHeader);
108 ///////////////////////////////////////////////////////////////////////////
111 // Default destructor.
130 ///////////////////////////////////////////////////////////////////////////
131 TDatabasePDG* IceF2k::GetPDG()
133 // Provide pointer to the PDG database
136 ///////////////////////////////////////////////////////////////////////////
137 AliObjMatrix* IceF2k::GetOMdbase()
139 // Provide pointer to the OM geometry, calib. etc... database
142 ///////////////////////////////////////////////////////////////////////////
143 AliDevice* IceF2k::GetFitdefs()
145 // Provide pointer to the fit definitions
148 ///////////////////////////////////////////////////////////////////////////
149 void IceF2k::Loop(TTree* otree,Int_t nentries,Int_t printfreq)
151 // Loop over the specified number of entries and convert the
152 // F2K data into the IceEvent structure.
153 // The output will be written on the output tree specified as "otree".
154 // If otree=0, a default standard output tree will be created.
155 // If nentries<0 (default) all the entries of the input file
156 // will be processed.
157 // Every "printfreq" events a short event summary will be printed.
158 // The default value is printfreq=1.
160 if (!fInput || fSplit<0) return;
162 if (!otree) otree=new TTree("T","F2K Data");
164 IceEvent* evt=new IceEvent();
166 evt->SetTrackCopy(1);
169 // Branch in the tree for the event structure
170 otree->Branch("IceEvent","IceEvent",&evt,fBsize,fSplit);
172 // Create the particle database and extend it with some F2000 specific definitions
173 if (!fPdg) fPdg=new TDatabasePDG();
174 Double_t me=fPdg->GetParticle(11)->Mass();
175 fPdg->AddParticle("brems" ,"brems" ,0,1,0,0,"none",10001001,0,0);
176 fPdg->AddParticle("deltae" ,"deltae" ,me,1,0,-3,"Lepton",10001002,0,0);
177 fPdg->AddParticle("pairprod","pairprod",0,1,0,0,"none",10001003,0,0);
178 fPdg->AddParticle("nucl_int","nucl_Int",0,1,0,0,"none",10001004,0,0);
179 fPdg->AddParticle("mu_pair" ,"mu_pair" ,0,1,0,0,"none",10001005,0,0);
180 fPdg->AddParticle("hadrons" ,"hadrons" ,0,1,0,0,"none",10001006,0,0);
181 fPdg->AddParticle("fiberlaser","fiberlaser",0,1,0,0,"none",10002100,0,0);
182 fPdg->AddParticle("n2laser" ,"n2laser" ,0,1,0,0,"none",10002101,0,0);
183 fPdg->AddParticle("yaglaser" ,"yaglaser" ,0,1,0,0,"none",10002201,0,0);
184 fPdg->AddParticle("z_primary","z_primary",0,1,0,0,"none",10003000,0,0);
185 fPdg->AddParticle("a_primary","a_primary",0,1,0,0,"none",10003500,0,0);
187 // Fill the database with geometry, calib. etc... parameters
188 // for all the devices
191 // Set the fit definitions according to the F2000 header info
194 for (Int_t jentry=0; jentry<nentries; jentry++)
196 if (rdmc_revt(fInput,&fHeader,&fEvent) != 0) break;
198 // Reset the complete Event structure
201 evt->SetRunNumber(fEvent.nrun);
202 evt->SetEventNumber(fEvent.enr);
203 evt->SetMJD(fEvent.mjd,fEvent.secs,fEvent.nsecs);
211 if (!(jentry%printfreq))
216 // Write the complete structure to the output Tree
222 ///////////////////////////////////////////////////////////////////////////
223 void IceF2k::FillOMdbase()
225 // Fill the database with geometry, calib. etc... parameters
226 // for all the devices.
228 if (fHeader.nch<=0) return;
236 fOmdb=new AliObjMatrix();
237 fOmdb->SetNameTitle("OMDBASE","The OM geometry, calib. etc... database");
242 Double_t pos[3]={0,0,0};
243 for (Int_t i=0; i<fHeader.nch; i++)
246 dev->SetUniqueID(i+1);
247 dev->SetSlotName("TYPE",1);
248 dev->SetSlotName("ORIENT",2);
249 dev->SetSlotName("T0",3);
250 dev->SetSlotName("ALPHA",4);
251 dev->SetSlotName("KADC",5);
252 dev->SetSlotName("KTOT",6);
253 dev->SetSlotName("KTDC",7);
258 dev->SetPosition(pos,"car");
259 dev->SetSignal(fHeader.type[i],1);
260 dev->SetSignal((Float_t)fHeader.costh[i],2);
261 dev->SetSignal(fHeader.cal[i].t_0,3);
262 dev->SetSignal(fHeader.cal[i].alpha_t,4);
263 dev->SetSignal(fHeader.cal[i].beta_a,5);
264 dev->SetSignal(fHeader.cal[i].beta_tot,6);
265 dev->SetSignal(fHeader.cal[i].beta_t,7);
266 fOmdb->EnterObject(i+1,1,dev);
269 ///////////////////////////////////////////////////////////////////////////
270 void IceF2k::SetFitdefs()
272 // Obtain the names of the variables for each fit procedure from the
273 // f2000 header. Each different fit procedure is then stored as a separate
274 // hit of an AliDevice object and the various fit variables are stored
275 // as separate signal slots of the corresponding hit.
276 // Via the GetFitdefs() memberfunction this AliDevice object can be
277 // retrieved and stored in the ROOT output file if wanted.
278 // The name of the object is FitDefinitions and the stored data can be
279 // inspected via the AliDevice::Data() memberfunction and looks as follows :
281 // *AliDevice::Data* Id :0 Name : FitDefinitions
282 // Position Vector in car coordinates : 0 0 0
283 // Err. in car coordinates : 0 0 0
284 // The following 8 hits are registered :
285 // *AliSignal::Data* Id :0
286 // Position Vector in car coordinates : 0 0 0
287 // Err. in car coordinates : 0 0 0
288 // Owned by device : AliDevice Name : FitDefinitions
289 // Slot : 1 Signal value : 1 name : id
290 // Slot : 2 Signal value : 2 name : rchi2
291 // Slot : 3 Signal value : 3 name : prob
292 // Slot : 4 Signal value : 4 name : sigth
293 // Slot : 5 Signal value : 5 name : covmin
294 // Slot : 6 Signal value : 6 name : covmax
295 // Slot : 7 Signal value : 7 name : cutflag
296 // Slot : 8 Signal value : 8 name : chi2
297 // *AliSignal::Data* Id :1
298 // Position Vector in car coordinates : 0 0 0
299 // Err. in car coordinates : 0 0 0
300 // Owned by device : AliDevice Name : FitDefinitions
301 // Slot : 1 Signal value : 1 name : id
302 // Slot : 2 Signal value : 2 name : rchi2
303 // Slot : 3 Signal value : 3 name : prob
306 // This memberfunction is based on the original idea/code by Adam Bouchta.
308 if (fHeader.n_fit<=0) return;
316 fFitdefs=new AliDevice();
319 fFitdefs->SetName("FitDefinitions");
320 fFitdefs->SetHitCopy (1);
325 for (Int_t i=0; i<fHeader.n_fit; i++)
327 s.SetUniqueID(fHeader.def_fit[i].id);
329 for (Int_t j=0; j<fHeader.def_fit[i].nwords; j++)
331 s.SetSlotName(TString(fHeader.def_fit[i].words[j]),j+1);
332 s.SetSignal(j+1,j+1);
339 ///////////////////////////////////////////////////////////////////////////
340 void IceF2k::PutMcTracks(IceEvent* evt)
342 // Get the MC tracks from the F2000 file into the IcePack structure.
343 // Note : MC tracks are given negative track id's in the event structure.
344 // This memberfunction is based on the original code by Adam Bouchta.
346 if (!evt || fEvent.ntrack<=0) return;
348 // Loop over all the tracks and add them to the current event
356 for (Int_t i=0; i<fEvent.ntrack; i++)
360 // Beginpoint of the track
361 vec[0]=fEvent.gen[i].x;
362 vec[1]=fEvent.gen[i].y;
363 vec[2]=fEvent.gen[i].z;
364 r.SetPosition(vec,"car");
367 // Endpoint of the track
368 vec[0]+=fEvent.gen[i].length*fEvent.gen[i].px;
369 vec[1]+=fEvent.gen[i].length*fEvent.gen[i].py;
370 vec[2]+=fEvent.gen[i].length*fEvent.gen[i].pz;
371 r.SetPosition(vec,"car");
375 vec[0]=fEvent.gen[i].e*fEvent.gen[i].px*1e-3;
376 vec[1]=fEvent.gen[i].e*fEvent.gen[i].py*1e-3;
377 vec[2]=fEvent.gen[i].e*fEvent.gen[i].pz*1e-3;
378 p.SetVector (vec,"car");
381 // MC tracks are indicated by negative track id's
382 tid=fEvent.gen[i].tag;
385 idf2k=fEvent.gen[i].id;
389 idpdg=idf2k+10000000;
391 else if (idf2k <= 48)
393 idpdg=fPdg->ConvertGeant3ToPdg(idf2k);
397 if (idf2k==201) idpdg=12;
398 if (idf2k==202) idpdg=14;
399 if (idf2k==203) idpdg=16;
400 if (idf2k==204) idpdg=-12;
401 if (idf2k==205) idpdg=-14;
402 if (idf2k==206) idpdg=-16;
405 t.SetParticleCode(idpdg);
406 t.SetName(fPdg->GetParticle(idpdg)->GetName());
407 t.SetTitle("MC track");
408 t.SetMass(fPdg->GetParticle(idpdg)->Mass());
409 t.SetCharge(fPdg->GetParticle(idpdg)->Charge()/3.);
414 // Create the pointers to each particle's parent particle.
417 for (Int_t itk=1; itk<=evt->GetNtracks (); itk++)
419 AliTrack* tx=evt->GetTrack(itk);
426 for (Int_t j=0; j<fEvent.ntrack; j++)
428 tid=fEvent.gen[j].tag;
429 if (-abs(tid) == txid) parid=fEvent.gen[j].parent;
432 if (parid<0) continue;
434 AliTrack* tpar=evt->GetIdTrack(-abs(parid));
438 tx->SetParentTrack(tpar);
441 ///////////////////////////////////////////////////////////////////////////
442 void IceF2k::PutRecoTracks(IceEvent* evt)
444 // Get the reconstructed tracks from the F2000 file into the IcePack structure.
445 // Note : Reco tracks are given positive track id's in the event structure.
446 // This memberfunction is based on the original code by Adam Bouchta.
448 if (!evt || fEvent.nfit<=0) return;
450 // Loop over all the tracks and add them to the current event
458 for (Int_t i=0; i<fEvent.nfit; i++)
462 // Beginpoint of the track
463 vec[0]=fEvent.rec[i].x;
464 vec[1]=fEvent.rec[i].y;
465 vec[2]=fEvent.rec[i].z;
466 r.SetPosition(vec,"car");
469 // Endpoint of the track
470 vec[0]+=fEvent.rec[i].length*fEvent.rec[i].px;
471 vec[1]+=fEvent.rec[i].length*fEvent.rec[i].py;
472 vec[2]+=fEvent.rec[i].length*fEvent.rec[i].pz;
473 r.SetPosition(vec,"car");
477 if (fEvent.rec[i].e > 0)
479 vec[0]=fEvent.rec[i].e*fEvent.rec[i].px*1e-3;
480 vec[1]=fEvent.rec[i].e*fEvent.rec[i].py*1e-3;
481 vec[2]=fEvent.rec[i].e*fEvent.rec[i].pz*1e-3;
483 else // Give the track a nominal momentum of 1 GeV/c
485 vec[0]=fEvent.rec[i].px;
486 vec[1]=fEvent.rec[i].py;
487 vec[2]=fEvent.rec[i].pz;
489 p.SetVector (vec,"car");
492 // Use the fit number as track id
493 tid=fEvent.rec[i].tag;
496 idf2k=fEvent.rec[i].id;
500 idpdg=idf2k+10000000;
502 else if (idf2k <= 48)
504 idpdg=fPdg->ConvertGeant3ToPdg(idf2k);
508 if (idf2k==201) idpdg=12;
509 if (idf2k==202) idpdg=14;
510 if (idf2k==203) idpdg=16;
511 if (idf2k==204) idpdg=-12;
512 if (idf2k==205) idpdg=-14;
513 if (idf2k==206) idpdg=-16;
516 t.SetParticleCode(idpdg);
517 t.SetName(fPdg->GetParticle(idpdg)->GetName());
518 t.SetTitle("RECO track");
519 t.SetMass(fPdg->GetParticle(idpdg)->Mass());
520 t.SetCharge(fPdg->GetParticle(idpdg)->Charge()/3.);
522 // Retrieve the various fit parameters for this track
523 AliSignal* fitdata=fFitdefs->GetIdHit(i);
524 for (Int_t jval=0; jval<fEvent.fresult[i].nval; jval++)
526 fitdata->SetSignal(fEvent.fresult[i].val[jval],jval+1);
529 // Store the various fit parameters for this track
530 t.SetFitDetails(fitdata);
532 // Store the various reco tracks as track hypotheses.
533 // A copy of the first reco track is entered as a new track instance
534 // into the event and all reco tracks (incl. the first one) are
535 // stored as hypotheses linked to this new reco track.
539 AliTrack* tx=evt->GetTrack(evt->GetNtracks());
540 Int_t nrec=evt->GetNtracks(1);
543 AliTrack* tx=evt->GetTrack(evt->GetNtracks());
544 if (tx) tx->AddTrackHypothesis(t);
547 ///////////////////////////////////////////////////////////////////////////
548 void IceF2k::PutHits(IceEvent* evt)
550 // Get the hit and waveform info from the F2000 file into the IcePack structure.
551 // This memberfunction is based on the original code by Adam Bouchta.
555 // Loop over all the hits and add them to the current event
558 s.SetSlotName("ADC",1);
559 s.SetSlotName("LE",2);
560 s.SetSlotName("TOT",3);
563 if (fOmdb) maxchan=fHeader.nch;
568 for (Int_t i=0; i<fEvent.nhits; i++)
570 chan=fEvent.h[i].ch+1;
571 if (chan>maxchan) continue; // Channels 9001, 9002 etc are trigger channels
573 // Get corresponding device from the current event structure
574 omx=(IceAOM*)evt->GetIdDevice(chan);
579 omx=(IceAOM*)fOmdb->GetObject(chan,1);
585 om.SetUniqueID(chan);
588 omx=(IceAOM*)evt->GetIdDevice(chan);
594 s.SetUniqueID(fEvent.h[i].id);
595 s.SetSignal(fEvent.h[i].amp,1);
596 s.SetSignal(fEvent.h[i].t,2);
597 s.SetSignal(fEvent.h[i].tot,3);
601 sx=omx->GetHit(omx->GetNhits());
604 // Bi-directional link between this hit and the track that caused the ADC value.
605 // This F2K info is probably only present for MC tracks.
609 tx=evt->GetIdTrack(tid); // Reco tracks
610 if (!tx) tx=evt->GetIdTrack(-tid); // MC tracks
611 if (tx) sx->AddLink(tx);
615 if (tid == -2) s.SetNameTitle("N","Noise");
616 if (tid == -3) s.SetNameTitle("A","Afterpulse");
620 // Loop over all the waveforms and add the histo(s) to the corresponding OM's
626 for (Int_t iwf=0; iwf<fEvent.nwf; iwf++)
628 chan=fEvent.wf[iwf].om;
629 if (chan<=0 || chan>maxchan) continue; // Skip trigger channels
631 // Get corresponding device from the current event structure
632 omx=(IceAOM*)evt->GetIdDevice(chan);
637 omx=(IceAOM*)fOmdb->GetObject(chan,1);
643 om.SetUniqueID(chan);
646 omx=(IceAOM*)evt->GetIdDevice(chan);
651 omx->SetSlotName("BASELINE",omx->GetNnames()+1);
652 omx->SetSignal(fEvent.wf[iwf].baseline,"BASELINE");
654 // Fill the waveform histogram
658 hname+=omx->GetNwaveforms()+1;
661 histo.SetName(hname.Data());
662 nbins=fEvent.wf[iwf].ndigi;
663 xlow=fEvent.wf[iwf].t_start;
664 xup=xlow+float(nbins)*fEvent.wf[iwf].t_bin;
665 histo.SetBins(nbins,xlow,xup);
667 for (Int_t jbin=1; jbin<=fEvent.wf[iwf].ndigi; jbin++)
669 histo.SetBinContent(jbin,fEvent.wf[iwf].digi[jbin]);
672 omx->SetWaveform(&histo,omx->GetNwaveforms()+1);
675 // Set bi-directional links between hits and reco track hypotheses.
676 // Note : Reco tracks are recognised by their positive id.
678 TObjArray* rectracks=evt->GetTracks(1);
679 for (Int_t jtk=0; jtk<rectracks->GetEntries(); jtk++)
681 tx=(AliTrack*)rectracks->At(jtk);
684 for (Int_t jhyp=1; jhyp<=tx->GetNhypotheses(); jhyp++)
686 AliTrack* hypx=tx->GetTrackHypothesis(jhyp);
689 // Loop over all combinations of F2K fits and used OM hits
690 for (Int_t k=0; k<fEvent.nfit_uses; k++)
692 if (fEvent.fit_uses[k].useid != hypx->GetId()) continue;
693 hid=fEvent.fit_uses[k].hitid;
694 sx=evt->GetIdHit(hid,"IceAOM");
695 if (sx) sx->AddLink(hypx);
700 ///////////////////////////////////////////////////////////////////////////