]>
Commit | Line | Data |
---|---|---|
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. | |
21 | // | |
22 | // Usage example : | |
23 | // --------------- | |
24 | // | |
25 | // gSystem->Load("ralice"); | |
26 | // gSystem->Load("icepack"); | |
27 | // gSystem->Load("iceconvert"); | |
28 | // | |
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"); | |
32 | // | |
33 | // // Limit the number of entries for testing | |
34 | // Int_t nentries=300; | |
35 | // | |
36 | // // Print frequency to produce a short summary print every printfreq events | |
37 | // Int_t printfreq=10; | |
38 | // | |
39 | // // Split level for the output structures | |
40 | // Int_t split=2; | |
41 | // | |
42 | // // Buffer size for the output structures | |
43 | // Int_t bsize=32000; | |
44 | // | |
45 | // IceF2k q("run8000.f2k",split,bsize); | |
46 | // q.Loop(otree,nentries,printfreq); | |
47 | // | |
48 | // // Select various objects to be added to the output file | |
49 | // | |
50 | // AliObjMatrix* omdb=q.GetOMdbase(); | |
51 | // if (omdb) omdb->Write(); | |
52 | // | |
53 | // AliDevice* fitdefs=q.GetFitdefs(); | |
54 | // if (fitdefs) fitdefs->Write(); | |
55 | // | |
56 | // TDatabasePDG* pdg=q.GetPDG(); | |
57 | // if (pdg) pdg->Write(); | |
58 | // | |
59 | // // Close output file | |
60 | // ofile->Write(); | |
61 | // ofile->Close(); | |
62 | // | |
63 | //--- Author: Nick van Eijndhoven 11-mar-2005 Utrecht University | |
64 | //- Modified: NvE $Date$ Utrecht University | |
65 | /////////////////////////////////////////////////////////////////////////// | |
66 | ||
67 | #include "IceF2k.h" | |
68 | #include "Riostream.h" | |
69 | ||
70 | ClassImp(IceF2k) // Class implementation to enable ROOT I/O | |
71 | ||
72 | IceF2k::IceF2k(char* fname,Int_t split,Int_t bsize) | |
73 | { | |
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. | |
79 | ||
80 | fSplit=split; | |
81 | fBsize=bsize; | |
82 | ||
83 | fPdg=0; | |
84 | fOmdb=0; | |
85 | fFitdefs=0; | |
86 | ||
87 | if (!fname) | |
88 | { | |
89 | cout << " *IceF2k ctor* No data input file specified." << endl; | |
90 | return; | |
91 | } | |
92 | ||
93 | // Open the input file in the default ascii format (autodetection) for reading | |
94 | fInput=rdmc_mcopen(fname,"r",RDMC_DEFAULT_ASCII_F); | |
95 | ||
96 | if (!fInput) | |
97 | { | |
98 | cout << " *IceF2k ctor* No input file found with name : " << fname << endl; | |
99 | return; | |
100 | } | |
101 | ||
102 | // Initialise the event structure | |
103 | rdmc_init_mevt(&fEvent); | |
104 | ||
105 | // Read the file header information | |
106 | rdmc_rarr(fInput,&fHeader); | |
107 | } | |
108 | /////////////////////////////////////////////////////////////////////////// | |
109 | IceF2k::~IceF2k() | |
110 | { | |
111 | // Default destructor. | |
112 | if (fPdg) | |
113 | { | |
114 | delete fPdg; | |
115 | fPdg=0; | |
116 | } | |
117 | ||
118 | if (fOmdb) | |
119 | { | |
120 | delete fOmdb; | |
121 | fOmdb=0; | |
122 | } | |
123 | ||
124 | if (fFitdefs) | |
125 | { | |
126 | delete fFitdefs; | |
127 | fFitdefs=0; | |
128 | } | |
129 | } | |
130 | /////////////////////////////////////////////////////////////////////////// | |
131 | TDatabasePDG* IceF2k::GetPDG() | |
132 | { | |
133 | // Provide pointer to the PDG database | |
134 | return fPdg; | |
135 | } | |
136 | /////////////////////////////////////////////////////////////////////////// | |
137 | AliObjMatrix* IceF2k::GetOMdbase() | |
138 | { | |
139 | // Provide pointer to the OM geometry, calib. etc... database | |
140 | return fOmdb; | |
141 | } | |
142 | /////////////////////////////////////////////////////////////////////////// | |
143 | AliDevice* IceF2k::GetFitdefs() | |
144 | { | |
145 | // Provide pointer to the fit definitions | |
146 | return fFitdefs; | |
147 | } | |
148 | /////////////////////////////////////////////////////////////////////////// | |
149 | void IceF2k::Loop(TTree* otree,Int_t nentries,Int_t printfreq) | |
150 | { | |
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. | |
159 | ||
160 | if (!fInput || fSplit<0) return; | |
161 | ||
162 | if (!otree) otree=new TTree("T","F2K Data"); | |
163 | ||
f67e2651 | 164 | IceEvent* evt=new IceEvent(); |
165 | ||
166 | evt->SetTrackCopy(1); | |
167 | evt->SetDevCopy(1); | |
168 | ||
169 | // Branch in the tree for the event structure | |
170 | otree->Branch("IceEvent","IceEvent",&evt,fBsize,fSplit); | |
171 | ||
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); | |
186 | ||
187 | // Fill the database with geometry, calib. etc... parameters | |
188 | // for all the devices | |
189 | FillOMdbase(); | |
190 | ||
191 | // Set the fit definitions according to the F2000 header info | |
192 | SetFitdefs(); | |
193 | ||
f67e2651 | 194 | for (Int_t jentry=0; jentry<nentries; jentry++) |
195 | { | |
196 | if (rdmc_revt(fInput,&fHeader,&fEvent) != 0) break; | |
197 | ||
198 | // Reset the complete Event structure | |
199 | evt->Reset(); | |
200 | ||
201 | evt->SetRunNumber(fEvent.nrun); | |
202 | evt->SetEventNumber(fEvent.enr); | |
203 | evt->SetMJD(fEvent.mjd,fEvent.secs,fEvent.nsecs); | |
204 | ||
205 | PutMcTracks(evt); | |
206 | ||
207 | PutRecoTracks(evt); | |
208 | ||
209 | PutHits(evt); | |
210 | ||
f67e2651 | 211 | if (!(jentry%printfreq)) |
212 | { | |
213 | evt->HeaderData(); | |
214 | } | |
215 | ||
216 | // Write the complete structure to the output Tree | |
217 | otree->Fill(); | |
218 | } | |
219 | ||
220 | if (evt) delete evt; | |
221 | } | |
222 | /////////////////////////////////////////////////////////////////////////// | |
223 | void IceF2k::FillOMdbase() | |
224 | { | |
225 | // Fill the database with geometry, calib. etc... parameters | |
226 | // for all the devices. | |
227 | ||
228 | if (fHeader.nch<=0) return; | |
229 | ||
230 | if (fOmdb) | |
231 | { | |
232 | fOmdb->Reset(); | |
233 | } | |
234 | else | |
235 | { | |
236 | fOmdb=new AliObjMatrix(); | |
237 | fOmdb->SetNameTitle("OMDBASE","The OM geometry, calib. etc... database"); | |
238 | fOmdb->SetOwner(); | |
239 | } | |
240 | ||
241 | IceAOM* dev=0; | |
242 | Double_t pos[3]={0,0,0}; | |
243 | for (Int_t i=0; i<fHeader.nch; i++) | |
244 | { | |
245 | dev=new IceAOM(); | |
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); | |
254 | ||
255 | pos[0]=fHeader.x[i]; | |
256 | pos[1]=fHeader.y[i]; | |
257 | pos[2]=fHeader.z[i]; | |
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); | |
267 | } | |
268 | } | |
269 | /////////////////////////////////////////////////////////////////////////// | |
270 | void IceF2k::SetFitdefs() | |
271 | { | |
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 : | |
280 | // | |
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 | |
304 | // etc.... | |
305 | // | |
306 | // This memberfunction is based on the original idea/code by Adam Bouchta. | |
307 | ||
308 | if (fHeader.n_fit<=0) return; | |
309 | ||
310 | if (fFitdefs) | |
311 | { | |
312 | fFitdefs->Reset(1); | |
313 | } | |
314 | else | |
315 | { | |
316 | fFitdefs=new AliDevice(); | |
317 | } | |
318 | ||
319 | fFitdefs->SetName("FitDefinitions"); | |
320 | fFitdefs->SetHitCopy (1); | |
321 | ||
322 | AliSignal s; | |
323 | s.Reset(); | |
324 | ||
325 | for (Int_t i=0; i<fHeader.n_fit; i++) | |
326 | { | |
327 | s.SetUniqueID(fHeader.def_fit[i].id); | |
328 | ||
329 | for (Int_t j=0; j<fHeader.def_fit[i].nwords; j++) | |
330 | { | |
331 | s.SetSlotName(TString(fHeader.def_fit[i].words[j]),j+1); | |
332 | s.SetSignal(j+1,j+1); | |
333 | } | |
334 | ||
335 | fFitdefs->AddHit(s); | |
336 | s.Reset(1); | |
337 | } | |
338 | } | |
339 | /////////////////////////////////////////////////////////////////////////// | |
340 | void IceF2k::PutMcTracks(IceEvent* evt) | |
341 | { | |
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. | |
345 | ||
346 | if (!evt || fEvent.ntrack<=0) return; | |
347 | ||
348 | // Loop over all the tracks and add them to the current event | |
349 | AliTrack t; | |
350 | Double_t vec[3]; | |
351 | AliPosition r; | |
352 | Ali3Vector p; | |
353 | Int_t tid=0; | |
354 | Int_t idpdg=0; | |
355 | Int_t idf2k=0; | |
356 | for (Int_t i=0; i<fEvent.ntrack; i++) | |
357 | { | |
358 | t.Reset (); | |
359 | ||
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"); | |
365 | t.SetBeginPoint(r); | |
366 | ||
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"); | |
372 | t.SetEndPoint(r); | |
373 | ||
374 | // Momentum in GeV/c | |
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"); | |
379 | t.Set3Momentum(p); | |
380 | ||
381 | // MC tracks are indicated by negative track id's | |
382 | tid=fEvent.gen[i].tag; | |
383 | t.SetId(-abs(tid)); | |
384 | ||
385 | idf2k=fEvent.gen[i].id; | |
386 | idpdg=0; | |
387 | if (idf2k>1000) | |
388 | { | |
389 | idpdg=idf2k+10000000; | |
390 | } | |
391 | else if (idf2k <= 48) | |
392 | { | |
393 | idpdg=fPdg->ConvertGeant3ToPdg(idf2k); | |
394 | } | |
395 | else | |
396 | { | |
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; | |
403 | } | |
404 | ||
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.); | |
410 | ||
411 | evt->AddTrack(t); | |
412 | } | |
413 | ||
414 | // Create the pointers to each particle's parent particle. | |
415 | Int_t txid=0; | |
416 | Int_t parid=0; | |
417 | for (Int_t itk=1; itk<=evt->GetNtracks (); itk++) | |
418 | { | |
419 | AliTrack* tx=evt->GetTrack(itk); | |
420 | ||
421 | if (!tx) continue; | |
422 | ||
423 | txid=tx->GetId(); | |
424 | ||
425 | parid=-1; | |
426 | for (Int_t j=0; j<fEvent.ntrack; j++) | |
427 | { | |
428 | tid=fEvent.gen[j].tag; | |
429 | if (-abs(tid) == txid) parid=fEvent.gen[j].parent; | |
430 | } | |
431 | ||
432 | if (parid<0) continue; | |
433 | ||
434 | AliTrack* tpar=evt->GetIdTrack(-abs(parid)); | |
435 | ||
436 | if (!tpar) continue; | |
437 | ||
438 | tx->SetParentTrack(tpar); | |
439 | } | |
440 | } | |
441 | /////////////////////////////////////////////////////////////////////////// | |
442 | void IceF2k::PutRecoTracks(IceEvent* evt) | |
443 | { | |
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. | |
447 | ||
448 | if (!evt || fEvent.nfit<=0) return; | |
449 | ||
450 | // Loop over all the tracks and add them to the current event | |
451 | AliTrack t; | |
452 | Double_t vec[3]; | |
453 | AliPosition r; | |
454 | Ali3Vector p; | |
455 | Int_t tid=0; | |
456 | Int_t idpdg=0; | |
457 | Int_t idf2k=0; | |
458 | for (Int_t i=0; i<fEvent.nfit; i++) | |
459 | { | |
460 | t.Reset (); | |
461 | ||
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"); | |
467 | t.SetBeginPoint(r); | |
468 | ||
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"); | |
474 | t.SetEndPoint(r); | |
475 | ||
476 | // Momentum in GeV/c | |
477 | if (fEvent.rec[i].e > 0) | |
478 | { | |
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; | |
482 | } | |
483 | else // Give the track a nominal momentum of 1 GeV/c | |
484 | { | |
485 | vec[0]=fEvent.rec[i].px; | |
486 | vec[1]=fEvent.rec[i].py; | |
487 | vec[2]=fEvent.rec[i].pz; | |
488 | } | |
489 | p.SetVector (vec,"car"); | |
490 | t.Set3Momentum(p); | |
491 | ||
492 | // Use the fit number as track id | |
493 | tid=fEvent.rec[i].tag; | |
494 | t.SetId(abs(tid)); | |
495 | ||
496 | idf2k=fEvent.rec[i].id; | |
497 | idpdg=0; | |
498 | if (idf2k>1000) | |
499 | { | |
500 | idpdg=idf2k+10000000; | |
501 | } | |
502 | else if (idf2k <= 48) | |
503 | { | |
504 | idpdg=fPdg->ConvertGeant3ToPdg(idf2k); | |
505 | } | |
506 | else | |
507 | { | |
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; | |
514 | } | |
515 | ||
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.); | |
521 | ||
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++) | |
525 | { | |
526 | fitdata->SetSignal(fEvent.fresult[i].val[jval],jval+1); | |
527 | } | |
528 | ||
529 | // Store the various fit parameters for this track | |
530 | t.SetFitDetails(fitdata); | |
531 | ||
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. | |
536 | if (i==0) | |
537 | { | |
538 | evt->AddTrack(t); | |
539 | AliTrack* tx=evt->GetTrack(evt->GetNtracks()); | |
540 | Int_t nrec=evt->GetNtracks(1); | |
541 | tx->SetId(nrec+1); | |
542 | } | |
543 | AliTrack* tx=evt->GetTrack(evt->GetNtracks()); | |
544 | if (tx) tx->AddTrackHypothesis(t); | |
545 | } | |
546 | } | |
547 | /////////////////////////////////////////////////////////////////////////// | |
548 | void IceF2k::PutHits(IceEvent* evt) | |
549 | { | |
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. | |
552 | ||
553 | if (!evt) return; | |
554 | ||
555 | // Loop over all the hits and add them to the current event | |
556 | IceAOM om; | |
557 | AliSignal s; | |
558 | s.SetSlotName("ADC",1); | |
559 | s.SetSlotName("LE",2); | |
560 | s.SetSlotName("TOT",3); | |
561 | Int_t chan=0; | |
562 | Int_t maxchan=800; | |
563 | if (fOmdb) maxchan=fHeader.nch; | |
564 | IceAOM* omx=0; | |
565 | AliSignal* sx=0; | |
566 | Int_t tid=0; | |
567 | AliTrack* tx=0; | |
568 | for (Int_t i=0; i<fEvent.nhits; i++) | |
569 | { | |
570 | chan=fEvent.h[i].ch+1; | |
571 | if (chan>maxchan) continue; // Channels 9001, 9002 etc are trigger channels | |
572 | ||
573 | // Get corresponding device from the current event structure | |
574 | omx=(IceAOM*)evt->GetIdDevice(chan); | |
575 | if (!omx) | |
576 | { | |
577 | if (fOmdb) | |
578 | { | |
579 | omx=(IceAOM*)fOmdb->GetObject(chan,1); | |
580 | evt->AddDevice(omx); | |
581 | } | |
582 | else | |
583 | { | |
584 | om.Reset(1); | |
585 | om.SetUniqueID(chan); | |
586 | evt->AddDevice(om); | |
587 | } | |
588 | omx=(IceAOM*)evt->GetIdDevice(chan); | |
589 | } | |
590 | ||
591 | if (!omx) continue; | |
592 | ||
593 | s.Reset(); | |
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); | |
598 | ||
599 | omx->AddHit(s); | |
600 | ||
601 | sx=omx->GetHit(omx->GetNhits()); | |
602 | if (!sx) continue; | |
603 | ||
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. | |
606 | tid=fEvent.h[i].ma; | |
607 | if (tid > 0) | |
608 | { | |
609 | tx=evt->GetIdTrack(tid); // Reco tracks | |
610 | if (!tx) tx=evt->GetIdTrack(-tid); // MC tracks | |
611 | if (tx) sx->AddLink(tx); | |
612 | } | |
613 | else | |
614 | { | |
615 | if (tid == -2) s.SetNameTitle("N","Noise"); | |
616 | if (tid == -3) s.SetNameTitle("A","Afterpulse"); | |
617 | } | |
618 | } | |
619 | ||
620 | // Loop over all the waveforms and add the histo(s) to the corresponding OM's | |
621 | TH1F histo; | |
622 | Int_t nbins=0; | |
623 | Float_t xlow=0; | |
624 | Float_t xup=0; | |
625 | TString hname; | |
626 | for (Int_t iwf=0; iwf<fEvent.nwf; iwf++) | |
627 | { | |
628 | chan=fEvent.wf[iwf].om; | |
629 | if (chan<=0 || chan>maxchan) continue; // Skip trigger channels | |
630 | ||
631 | // Get corresponding device from the current event structure | |
632 | omx=(IceAOM*)evt->GetIdDevice(chan); | |
633 | if (!omx) | |
634 | { | |
635 | if (fOmdb) | |
636 | { | |
637 | omx=(IceAOM*)fOmdb->GetObject(chan,1); | |
638 | evt->AddDevice(omx); | |
639 | } | |
640 | else | |
641 | { | |
642 | om.Reset(1); | |
643 | om.SetUniqueID(chan); | |
644 | evt->AddDevice(om); | |
645 | } | |
646 | omx=(IceAOM*)evt->GetIdDevice(chan); | |
647 | } | |
648 | ||
649 | if (!omx) continue; | |
650 | ||
651 | omx->SetSlotName("BASELINE",omx->GetNnames()+1); | |
652 | omx->SetSignal(fEvent.wf[iwf].baseline,"BASELINE"); | |
653 | ||
654 | // Fill the waveform histogram | |
655 | hname="OM"; | |
656 | hname+=chan; | |
657 | hname+="-WF"; | |
658 | hname+=omx->GetNwaveforms()+1; | |
659 | ||
660 | histo.Reset(); | |
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); | |
666 | ||
667 | for (Int_t jbin=1; jbin<=fEvent.wf[iwf].ndigi; jbin++) | |
668 | { | |
669 | histo.SetBinContent(jbin,fEvent.wf[iwf].digi[jbin]); | |
670 | } | |
671 | ||
672 | omx->SetWaveform(&histo,omx->GetNwaveforms()+1); | |
673 | } | |
674 | ||
675 | // Set bi-directional links between hits and reco track hypotheses. | |
676 | // Note : Reco tracks are recognised by their positive id. | |
677 | Int_t hid=0; | |
678 | TObjArray* rectracks=evt->GetTracks(1); | |
679 | for (Int_t jtk=0; jtk<rectracks->GetEntries(); jtk++) | |
680 | { | |
681 | tx=(AliTrack*)rectracks->At(jtk); | |
682 | if (!tx) continue; | |
683 | ||
684 | for (Int_t jhyp=1; jhyp<=tx->GetNhypotheses(); jhyp++) | |
685 | { | |
686 | AliTrack* hypx=tx->GetTrackHypothesis(jhyp); | |
687 | if (!hypx) continue; | |
688 | ||
689 | // Loop over all combinations of F2K fits and used OM hits | |
690 | for (Int_t k=0; k<fEvent.nfit_uses; k++) | |
691 | { | |
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); | |
696 | } | |
697 | } | |
698 | } | |
699 | } | |
700 | /////////////////////////////////////////////////////////////////////////// |