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 | |
105 | ClassImp(IceF2k) // Class implementation to enable ROOT I/O |
106 | |
5481c137 |
107 | IceF2k::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 | /////////////////////////////////////////////////////////////////////////// |
124 | IceF2k::~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 |
147 | void 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 | /////////////////////////////////////////////////////////////////////////// |
155 | void 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 | /////////////////////////////////////////////////////////////////////////// |
162 | void 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 | /////////////////////////////////////////////////////////////////////////// |
169 | void 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 | /////////////////////////////////////////////////////////////////////////// |
176 | void IceF2k::SetInputFile(TString name) |
177 | { |
178 | // Set the name of the F2K input file. |
179 | fInfile=name; |
180 | } |
181 | /////////////////////////////////////////////////////////////////////////// |
182 | void IceF2k::SetOutputFile(TFile* ofile) |
183 | { |
184 | // Set the output file for the ROOT data. |
185 | fOutfile=ofile; |
186 | } |
187 | /////////////////////////////////////////////////////////////////////////// |
f67e2651 |
188 | TDatabasePDG* IceF2k::GetPDG() |
189 | { |
190 | // Provide pointer to the PDG database |
191 | return fPdg; |
192 | } |
193 | /////////////////////////////////////////////////////////////////////////// |
194 | AliObjMatrix* IceF2k::GetOMdbase() |
195 | { |
196 | // Provide pointer to the OM geometry, calib. etc... database |
197 | return fOmdb; |
198 | } |
199 | /////////////////////////////////////////////////////////////////////////// |
200 | AliDevice* IceF2k::GetFitdefs() |
201 | { |
202 | // Provide pointer to the fit definitions |
203 | return fFitdefs; |
204 | } |
205 | /////////////////////////////////////////////////////////////////////////// |
5481c137 |
206 | void 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) |
323 | ExecuteTasks(opt); |
324 | |
64c21700 |
325 | if (fPrintfreq) |
326 | { |
327 | if (!(nevt%fPrintfreq)) evt->HeaderData(); |
328 | } |
f67e2651 |
329 | |
330 | // Write the complete structure to the output Tree |
1c9018c6 |
331 | if (otree) otree->Fill(); |
f67e2651 |
332 | |
5481c137 |
333 | // Update event counter |
334 | nevt++; |
335 | } |
1c9018c6 |
336 | |
337 | // Remove the IceEvent object from the environment |
338 | // and delete it as well |
339 | if (evt) |
340 | { |
341 | RemoveObject(evt); |
342 | delete evt; |
343 | } |
f67e2651 |
344 | } |
345 | /////////////////////////////////////////////////////////////////////////// |
346 | void IceF2k::FillOMdbase() |
347 | { |
348 | // Fill the database with geometry, calib. etc... parameters |
349 | // for all the devices. |
350 | |
351 | if (fHeader.nch<=0) return; |
352 | |
64c21700 |
353 | Int_t geocal=fHeader.is_calib.geo; |
354 | Int_t adccal=fHeader.is_calib.adc; |
355 | Int_t tdccal=fHeader.is_calib.tdc; |
356 | Int_t totcal=fHeader.is_calib.tot; |
357 | Int_t utccal=fHeader.is_calib.utc; |
358 | |
359 | TF1 fadccal("fadccal","(x-[1])*[0]"); |
360 | TF1 fadcdecal("fadcdecal","(x/[0])+[1]"); |
216d1d91 |
361 | fadccal.SetParName(0,"BETA-ADC"); |
362 | fadccal.SetParName(1,"PED-ADC"); |
363 | fadcdecal.SetParName(0,"BETA-ADC"); |
364 | fadcdecal.SetParName(1,"PED-ADC"); |
365 | |
64c21700 |
366 | TF1 ftdccal("ftdccal","(x*[0])-[1]-([0]-1.)*32767.-[2]/sqrt([3])"); |
367 | TF1 ftdcdecal("ftdcdecal","(x+([0]-1.)*32767.+[1]+[2]/sqrt([3]))/[0]"); |
216d1d91 |
368 | ftdccal.SetParName(0,"BETA-TDC"); |
369 | ftdccal.SetParName(1,"T0"); |
370 | ftdccal.SetParName(2,"ALPHA-TDC"); |
371 | ftdccal.SetParName(3,"ADC-SLEW"); |
372 | ftdcdecal.SetParName(0,"BETA-TDC"); |
373 | ftdcdecal.SetParName(1,"T0"); |
374 | ftdcdecal.SetParName(2,"ALPHA-TDC"); |
375 | ftdcdecal.SetParName(3,"ADC-SLEW"); |
376 | |
64c21700 |
377 | TF1 ftotcal("ftotcal","x*[0]"); |
378 | TF1 ftotdecal("ftotdecal","x/[0]"); |
216d1d91 |
379 | ftotcal.SetParName(0,"BETA-TOT"); |
380 | ftotdecal.SetParName(0,"BETA-TOT"); |
64c21700 |
381 | |
f67e2651 |
382 | if (fOmdb) |
383 | { |
384 | fOmdb->Reset(); |
385 | } |
386 | else |
387 | { |
388 | fOmdb=new AliObjMatrix(); |
389 | fOmdb->SetNameTitle("OMDBASE","The OM geometry, calib. etc... database"); |
390 | fOmdb->SetOwner(); |
391 | } |
392 | |
393 | IceAOM* dev=0; |
394 | Double_t pos[3]={0,0,0}; |
395 | for (Int_t i=0; i<fHeader.nch; i++) |
396 | { |
397 | dev=new IceAOM(); |
398 | dev->SetUniqueID(i+1); |
64c21700 |
399 | |
400 | dev->SetSlotName("ADC",1); |
401 | dev->SetSlotName("LE",2); |
402 | dev->SetSlotName("TOT",3); |
403 | |
404 | dev->SetSlotName("TYPE",4); |
405 | dev->SetSlotName("ORIENT",5); |
406 | dev->SetSlotName("THRESH",6); |
407 | dev->SetSlotName("SENSIT",7); |
408 | dev->SetSlotName("BETA-TDC",8); |
409 | dev->SetSlotName("T0",9); |
410 | dev->SetSlotName("ALPHA-TDC",10); |
411 | dev->SetSlotName("PED-ADC",11); |
412 | dev->SetSlotName("BETA-ADC",12); |
413 | dev->SetSlotName("KAPPA-ADC",13); |
414 | dev->SetSlotName("PED-TOT",14); |
415 | dev->SetSlotName("BETA-TOT",15); |
416 | dev->SetSlotName("KAPPA-TOT",16); |
f67e2651 |
417 | |
418 | pos[0]=fHeader.x[i]; |
419 | pos[1]=fHeader.y[i]; |
420 | pos[2]=fHeader.z[i]; |
421 | dev->SetPosition(pos,"car"); |
64c21700 |
422 | |
423 | fadccal.SetParameter(0,fHeader.cal[i].beta_a); |
424 | fadccal.SetParameter(1,fHeader.cal[i].ped); |
425 | fadcdecal.SetParameter(0,fHeader.cal[i].beta_a); |
426 | if (!fHeader.cal[i].beta_a) fadcdecal.SetParameter(0,1); |
427 | fadcdecal.SetParameter(1,fHeader.cal[i].ped); |
428 | |
429 | ftdccal.SetParameter(0,fHeader.cal[i].beta_t); |
430 | ftdccal.SetParameter(1,fHeader.cal[i].t_0); |
431 | ftdccal.SetParameter(2,fHeader.cal[i].alpha_t); |
432 | ftdccal.SetParameter(3,1.e20); |
433 | ftdcdecal.SetParameter(0,fHeader.cal[i].beta_t); |
434 | if (!fHeader.cal[i].beta_t) ftdcdecal.SetParameter(0,1); |
435 | ftdcdecal.SetParameter(1,fHeader.cal[i].t_0); |
436 | ftdcdecal.SetParameter(2,fHeader.cal[i].alpha_t); |
437 | ftdcdecal.SetParameter(3,1.e20); |
438 | |
439 | ftotcal.SetParameter(0,fHeader.cal[i].beta_tot); |
440 | ftotdecal.SetParameter(0,fHeader.cal[i].beta_tot); |
441 | if (!fHeader.cal[i].beta_tot) ftotdecal.SetParameter(0,1); |
442 | |
443 | if (adccal) |
444 | { |
445 | dev->SetDecalFunction(&fadcdecal,1); |
446 | } |
447 | else |
448 | { |
449 | dev->SetCalFunction(&fadccal,1); |
450 | } |
451 | |
452 | if (tdccal) |
453 | { |
454 | dev->SetDecalFunction(&ftdcdecal,2); |
455 | } |
456 | else |
457 | { |
458 | dev->SetCalFunction(&ftdccal,2); |
459 | } |
460 | |
461 | if (totcal) |
462 | { |
463 | dev->SetDecalFunction(&ftotdecal,3); |
464 | } |
465 | else |
466 | { |
467 | dev->SetCalFunction(&ftotcal,3); |
468 | } |
469 | |
470 | dev->SetSignal(fHeader.type[i],4); |
471 | dev->SetSignal((Float_t)fHeader.costh[i],5); |
472 | dev->SetSignal(fHeader.thresh[i],6); |
473 | dev->SetSignal(fHeader.sensit[i],7); |
474 | dev->SetSignal(fHeader.cal[i].beta_t,8); |
475 | dev->SetSignal(fHeader.cal[i].t_0,9); |
476 | dev->SetSignal(fHeader.cal[i].alpha_t,10); |
477 | dev->SetSignal(fHeader.cal[i].ped,11); |
478 | dev->SetSignal(fHeader.cal[i].beta_a,12); |
479 | dev->SetSignal(fHeader.cal[i].kappa,13); |
480 | dev->SetSignal(fHeader.cal[i].ped_tot,14); |
481 | dev->SetSignal(fHeader.cal[i].beta_tot,15); |
482 | dev->SetSignal(fHeader.cal[i].kappa_tot,16); |
483 | |
f67e2651 |
484 | fOmdb->EnterObject(i+1,1,dev); |
485 | } |
486 | } |
487 | /////////////////////////////////////////////////////////////////////////// |
488 | void IceF2k::SetFitdefs() |
489 | { |
490 | // Obtain the names of the variables for each fit procedure from the |
491 | // f2000 header. Each different fit procedure is then stored as a separate |
492 | // hit of an AliDevice object and the various fit variables are stored |
493 | // as separate signal slots of the corresponding hit. |
494 | // Via the GetFitdefs() memberfunction this AliDevice object can be |
495 | // retrieved and stored in the ROOT output file if wanted. |
496 | // The name of the object is FitDefinitions and the stored data can be |
497 | // inspected via the AliDevice::Data() memberfunction and looks as follows : |
498 | // |
499 | // *AliDevice::Data* Id :0 Name : FitDefinitions |
500 | // Position Vector in car coordinates : 0 0 0 |
501 | // Err. in car coordinates : 0 0 0 |
502 | // The following 8 hits are registered : |
503 | // *AliSignal::Data* Id :0 |
504 | // Position Vector in car coordinates : 0 0 0 |
505 | // Err. in car coordinates : 0 0 0 |
506 | // Owned by device : AliDevice Name : FitDefinitions |
507 | // Slot : 1 Signal value : 1 name : id |
508 | // Slot : 2 Signal value : 2 name : rchi2 |
509 | // Slot : 3 Signal value : 3 name : prob |
510 | // Slot : 4 Signal value : 4 name : sigth |
511 | // Slot : 5 Signal value : 5 name : covmin |
512 | // Slot : 6 Signal value : 6 name : covmax |
513 | // Slot : 7 Signal value : 7 name : cutflag |
514 | // Slot : 8 Signal value : 8 name : chi2 |
515 | // *AliSignal::Data* Id :1 |
516 | // Position Vector in car coordinates : 0 0 0 |
517 | // Err. in car coordinates : 0 0 0 |
518 | // Owned by device : AliDevice Name : FitDefinitions |
519 | // Slot : 1 Signal value : 1 name : id |
520 | // Slot : 2 Signal value : 2 name : rchi2 |
521 | // Slot : 3 Signal value : 3 name : prob |
522 | // etc.... |
523 | // |
524 | // This memberfunction is based on the original idea/code by Adam Bouchta. |
525 | |
526 | if (fHeader.n_fit<=0) return; |
527 | |
528 | if (fFitdefs) |
529 | { |
530 | fFitdefs->Reset(1); |
531 | } |
532 | else |
533 | { |
534 | fFitdefs=new AliDevice(); |
535 | } |
536 | |
537 | fFitdefs->SetName("FitDefinitions"); |
538 | fFitdefs->SetHitCopy (1); |
539 | |
540 | AliSignal s; |
541 | s.Reset(); |
542 | |
543 | for (Int_t i=0; i<fHeader.n_fit; i++) |
544 | { |
545 | s.SetUniqueID(fHeader.def_fit[i].id); |
546 | |
547 | for (Int_t j=0; j<fHeader.def_fit[i].nwords; j++) |
548 | { |
549 | s.SetSlotName(TString(fHeader.def_fit[i].words[j]),j+1); |
550 | s.SetSignal(j+1,j+1); |
551 | } |
552 | |
553 | fFitdefs->AddHit(s); |
554 | s.Reset(1); |
555 | } |
556 | } |
557 | /////////////////////////////////////////////////////////////////////////// |
5481c137 |
558 | void IceF2k::PutMcTracks() |
f67e2651 |
559 | { |
560 | // Get the MC tracks from the F2000 file into the IcePack structure. |
561 | // Note : MC tracks are given negative track id's in the event structure. |
562 | // This memberfunction is based on the original code by Adam Bouchta. |
563 | |
5481c137 |
564 | IceEvent* evt=(IceEvent*)GetMainObject(); |
f67e2651 |
565 | if (!evt || fEvent.ntrack<=0) return; |
566 | |
567 | // Loop over all the tracks and add them to the current event |
568 | AliTrack t; |
569 | Double_t vec[3]; |
570 | AliPosition r; |
571 | Ali3Vector p; |
572 | Int_t tid=0; |
573 | Int_t idpdg=0; |
574 | Int_t idf2k=0; |
575 | for (Int_t i=0; i<fEvent.ntrack; i++) |
576 | { |
577 | t.Reset (); |
578 | |
579 | // Beginpoint of the track |
580 | vec[0]=fEvent.gen[i].x; |
581 | vec[1]=fEvent.gen[i].y; |
582 | vec[2]=fEvent.gen[i].z; |
583 | r.SetPosition(vec,"car"); |
584 | t.SetBeginPoint(r); |
585 | |
586 | // Endpoint of the track |
587 | vec[0]+=fEvent.gen[i].length*fEvent.gen[i].px; |
588 | vec[1]+=fEvent.gen[i].length*fEvent.gen[i].py; |
589 | vec[2]+=fEvent.gen[i].length*fEvent.gen[i].pz; |
590 | r.SetPosition(vec,"car"); |
591 | t.SetEndPoint(r); |
592 | |
593 | // Momentum in GeV/c |
594 | vec[0]=fEvent.gen[i].e*fEvent.gen[i].px*1e-3; |
595 | vec[1]=fEvent.gen[i].e*fEvent.gen[i].py*1e-3; |
596 | vec[2]=fEvent.gen[i].e*fEvent.gen[i].pz*1e-3; |
597 | p.SetVector (vec,"car"); |
598 | t.Set3Momentum(p); |
599 | |
600 | // MC tracks are indicated by negative track id's |
601 | tid=fEvent.gen[i].tag; |
602 | t.SetId(-abs(tid)); |
603 | |
604 | idf2k=fEvent.gen[i].id; |
605 | idpdg=0; |
606 | if (idf2k>1000) |
607 | { |
608 | idpdg=idf2k+10000000; |
609 | } |
610 | else if (idf2k <= 48) |
611 | { |
612 | idpdg=fPdg->ConvertGeant3ToPdg(idf2k); |
613 | } |
614 | else |
615 | { |
616 | if (idf2k==201) idpdg=12; |
617 | if (idf2k==202) idpdg=14; |
618 | if (idf2k==203) idpdg=16; |
619 | if (idf2k==204) idpdg=-12; |
620 | if (idf2k==205) idpdg=-14; |
621 | if (idf2k==206) idpdg=-16; |
622 | } |
623 | |
624 | t.SetParticleCode(idpdg); |
625 | t.SetName(fPdg->GetParticle(idpdg)->GetName()); |
626 | t.SetTitle("MC track"); |
627 | t.SetMass(fPdg->GetParticle(idpdg)->Mass()); |
628 | t.SetCharge(fPdg->GetParticle(idpdg)->Charge()/3.); |
629 | |
630 | evt->AddTrack(t); |
631 | } |
632 | |
633 | // Create the pointers to each particle's parent particle. |
634 | Int_t txid=0; |
635 | Int_t parid=0; |
636 | for (Int_t itk=1; itk<=evt->GetNtracks (); itk++) |
637 | { |
638 | AliTrack* tx=evt->GetTrack(itk); |
639 | |
640 | if (!tx) continue; |
641 | |
642 | txid=tx->GetId(); |
643 | |
644 | parid=-1; |
645 | for (Int_t j=0; j<fEvent.ntrack; j++) |
646 | { |
647 | tid=fEvent.gen[j].tag; |
648 | if (-abs(tid) == txid) parid=fEvent.gen[j].parent; |
649 | } |
650 | |
651 | if (parid<0) continue; |
652 | |
653 | AliTrack* tpar=evt->GetIdTrack(-abs(parid)); |
654 | |
655 | if (!tpar) continue; |
656 | |
657 | tx->SetParentTrack(tpar); |
658 | } |
659 | } |
660 | /////////////////////////////////////////////////////////////////////////// |
5481c137 |
661 | void IceF2k::PutRecoTracks() |
f67e2651 |
662 | { |
663 | // Get the reconstructed tracks from the F2000 file into the IcePack structure. |
664 | // Note : Reco tracks are given positive track id's in the event structure. |
665 | // This memberfunction is based on the original code by Adam Bouchta. |
666 | |
5481c137 |
667 | IceEvent* evt=(IceEvent*)GetMainObject(); |
f67e2651 |
668 | if (!evt || fEvent.nfit<=0) return; |
669 | |
670 | // Loop over all the tracks and add them to the current event |
671 | AliTrack t; |
672 | Double_t vec[3]; |
673 | AliPosition r; |
674 | Ali3Vector p; |
675 | Int_t tid=0; |
676 | Int_t idpdg=0; |
677 | Int_t idf2k=0; |
678 | for (Int_t i=0; i<fEvent.nfit; i++) |
679 | { |
680 | t.Reset (); |
681 | |
682 | // Beginpoint of the track |
683 | vec[0]=fEvent.rec[i].x; |
684 | vec[1]=fEvent.rec[i].y; |
685 | vec[2]=fEvent.rec[i].z; |
686 | r.SetPosition(vec,"car"); |
687 | t.SetBeginPoint(r); |
688 | |
689 | // Endpoint of the track |
690 | vec[0]+=fEvent.rec[i].length*fEvent.rec[i].px; |
691 | vec[1]+=fEvent.rec[i].length*fEvent.rec[i].py; |
692 | vec[2]+=fEvent.rec[i].length*fEvent.rec[i].pz; |
693 | r.SetPosition(vec,"car"); |
694 | t.SetEndPoint(r); |
695 | |
696 | // Momentum in GeV/c |
697 | if (fEvent.rec[i].e > 0) |
698 | { |
699 | vec[0]=fEvent.rec[i].e*fEvent.rec[i].px*1e-3; |
700 | vec[1]=fEvent.rec[i].e*fEvent.rec[i].py*1e-3; |
701 | vec[2]=fEvent.rec[i].e*fEvent.rec[i].pz*1e-3; |
702 | } |
703 | else // Give the track a nominal momentum of 1 GeV/c |
704 | { |
705 | vec[0]=fEvent.rec[i].px; |
706 | vec[1]=fEvent.rec[i].py; |
707 | vec[2]=fEvent.rec[i].pz; |
708 | } |
709 | p.SetVector (vec,"car"); |
710 | t.Set3Momentum(p); |
711 | |
712 | // Use the fit number as track id |
713 | tid=fEvent.rec[i].tag; |
714 | t.SetId(abs(tid)); |
715 | |
716 | idf2k=fEvent.rec[i].id; |
717 | idpdg=0; |
718 | if (idf2k>1000) |
719 | { |
720 | idpdg=idf2k+10000000; |
721 | } |
722 | else if (idf2k <= 48) |
723 | { |
724 | idpdg=fPdg->ConvertGeant3ToPdg(idf2k); |
725 | } |
726 | else |
727 | { |
728 | if (idf2k==201) idpdg=12; |
729 | if (idf2k==202) idpdg=14; |
730 | if (idf2k==203) idpdg=16; |
731 | if (idf2k==204) idpdg=-12; |
732 | if (idf2k==205) idpdg=-14; |
733 | if (idf2k==206) idpdg=-16; |
734 | } |
735 | |
736 | t.SetParticleCode(idpdg); |
737 | t.SetName(fPdg->GetParticle(idpdg)->GetName()); |
738 | t.SetTitle("RECO track"); |
739 | t.SetMass(fPdg->GetParticle(idpdg)->Mass()); |
740 | t.SetCharge(fPdg->GetParticle(idpdg)->Charge()/3.); |
741 | |
742 | // Retrieve the various fit parameters for this track |
743 | AliSignal* fitdata=fFitdefs->GetIdHit(i); |
744 | for (Int_t jval=0; jval<fEvent.fresult[i].nval; jval++) |
745 | { |
746 | fitdata->SetSignal(fEvent.fresult[i].val[jval],jval+1); |
747 | } |
748 | |
749 | // Store the various fit parameters for this track |
750 | t.SetFitDetails(fitdata); |
751 | |
752 | // Store the various reco tracks as track hypotheses. |
753 | // A copy of the first reco track is entered as a new track instance |
754 | // into the event and all reco tracks (incl. the first one) are |
755 | // stored as hypotheses linked to this new reco track. |
756 | if (i==0) |
757 | { |
758 | evt->AddTrack(t); |
759 | AliTrack* tx=evt->GetTrack(evt->GetNtracks()); |
760 | Int_t nrec=evt->GetNtracks(1); |
761 | tx->SetId(nrec+1); |
762 | } |
763 | AliTrack* tx=evt->GetTrack(evt->GetNtracks()); |
764 | if (tx) tx->AddTrackHypothesis(t); |
765 | } |
766 | } |
767 | /////////////////////////////////////////////////////////////////////////// |
5481c137 |
768 | void IceF2k::PutHits() |
f67e2651 |
769 | { |
770 | // Get the hit and waveform info from the F2000 file into the IcePack structure. |
771 | // This memberfunction is based on the original code by Adam Bouchta. |
772 | |
5481c137 |
773 | IceEvent* evt=(IceEvent*)GetMainObject(); |
f67e2651 |
774 | if (!evt) return; |
775 | |
776 | // Loop over all the hits and add them to the current event |
777 | IceAOM om; |
778 | AliSignal s; |
779 | s.SetSlotName("ADC",1); |
780 | s.SetSlotName("LE",2); |
781 | s.SetSlotName("TOT",3); |
782 | Int_t chan=0; |
783 | Int_t maxchan=800; |
784 | if (fOmdb) maxchan=fHeader.nch; |
785 | IceAOM* omx=0; |
786 | AliSignal* sx=0; |
787 | Int_t tid=0; |
788 | AliTrack* tx=0; |
64c21700 |
789 | Float_t adc=0; |
f67e2651 |
790 | for (Int_t i=0; i<fEvent.nhits; i++) |
791 | { |
792 | chan=fEvent.h[i].ch+1; |
793 | if (chan>maxchan) continue; // Channels 9001, 9002 etc are trigger channels |
794 | |
795 | // Get corresponding device from the current event structure |
796 | omx=(IceAOM*)evt->GetIdDevice(chan); |
797 | if (!omx) |
798 | { |
799 | if (fOmdb) |
800 | { |
801 | omx=(IceAOM*)fOmdb->GetObject(chan,1); |
802 | evt->AddDevice(omx); |
803 | } |
804 | else |
805 | { |
806 | om.Reset(1); |
807 | om.SetUniqueID(chan); |
808 | evt->AddDevice(om); |
809 | } |
810 | omx=(IceAOM*)evt->GetIdDevice(chan); |
811 | } |
812 | |
813 | if (!omx) continue; |
814 | |
815 | s.Reset(); |
816 | s.SetUniqueID(fEvent.h[i].id); |
817 | s.SetSignal(fEvent.h[i].amp,1); |
818 | s.SetSignal(fEvent.h[i].t,2); |
819 | s.SetSignal(fEvent.h[i].tot,3); |
820 | |
821 | omx->AddHit(s); |
822 | |
823 | sx=omx->GetHit(omx->GetNhits()); |
824 | if (!sx) continue; |
825 | |
64c21700 |
826 | // ADC dependent TDC (de)calibration function for this hit |
827 | TF1* fcal=omx->GetCalFunction("LE"); |
828 | TF1* fdecal=omx->GetDecalFunction("LE"); |
829 | if (fcal) sx->SetCalFunction(fcal,2); |
830 | if (fdecal) sx->SetDecalFunction(fdecal,2); |
831 | fcal=sx->GetCalFunction(2); |
832 | fdecal=sx->GetDecalFunction(2); |
833 | adc=sx->GetSignal(1,-4); |
834 | if (adc>0) |
835 | { |
836 | if (fcal) fcal->SetParameter(3,adc); |
837 | if (fdecal) fdecal->SetParameter(3,adc); |
838 | } |
839 | else |
840 | { |
a4b77ddf |
841 | if (fcal) fcal->SetParameter(3,1.e20); |
842 | if (fdecal) fdecal->SetParameter(3,1.e20); |
64c21700 |
843 | } |
844 | |
f67e2651 |
845 | // Bi-directional link between this hit and the track that caused the ADC value. |
846 | // This F2K info is probably only present for MC tracks. |
847 | tid=fEvent.h[i].ma; |
848 | if (tid > 0) |
849 | { |
850 | tx=evt->GetIdTrack(tid); // Reco tracks |
851 | if (!tx) tx=evt->GetIdTrack(-tid); // MC tracks |
852 | if (tx) sx->AddLink(tx); |
853 | } |
854 | else |
855 | { |
856 | if (tid == -2) s.SetNameTitle("N","Noise"); |
857 | if (tid == -3) s.SetNameTitle("A","Afterpulse"); |
858 | } |
859 | } |
860 | |
861 | // Loop over all the waveforms and add the histo(s) to the corresponding OM's |
862 | TH1F histo; |
863 | Int_t nbins=0; |
864 | Float_t xlow=0; |
865 | Float_t xup=0; |
866 | TString hname; |
867 | for (Int_t iwf=0; iwf<fEvent.nwf; iwf++) |
868 | { |
869 | chan=fEvent.wf[iwf].om; |
870 | if (chan<=0 || chan>maxchan) continue; // Skip trigger channels |
871 | |
872 | // Get corresponding device from the current event structure |
873 | omx=(IceAOM*)evt->GetIdDevice(chan); |
874 | if (!omx) |
875 | { |
876 | if (fOmdb) |
877 | { |
878 | omx=(IceAOM*)fOmdb->GetObject(chan,1); |
879 | evt->AddDevice(omx); |
880 | } |
881 | else |
882 | { |
883 | om.Reset(1); |
884 | om.SetUniqueID(chan); |
885 | evt->AddDevice(om); |
886 | } |
887 | omx=(IceAOM*)evt->GetIdDevice(chan); |
888 | } |
889 | |
890 | if (!omx) continue; |
891 | |
892 | omx->SetSlotName("BASELINE",omx->GetNnames()+1); |
893 | omx->SetSignal(fEvent.wf[iwf].baseline,"BASELINE"); |
894 | |
895 | // Fill the waveform histogram |
896 | hname="OM"; |
897 | hname+=chan; |
898 | hname+="-WF"; |
899 | hname+=omx->GetNwaveforms()+1; |
900 | |
901 | histo.Reset(); |
902 | histo.SetName(hname.Data()); |
903 | nbins=fEvent.wf[iwf].ndigi; |
904 | xlow=fEvent.wf[iwf].t_start; |
905 | xup=xlow+float(nbins)*fEvent.wf[iwf].t_bin; |
906 | histo.SetBins(nbins,xlow,xup); |
907 | |
908 | for (Int_t jbin=1; jbin<=fEvent.wf[iwf].ndigi; jbin++) |
909 | { |
0e50ad4d |
910 | histo.SetBinContent(jbin,fEvent.wf[iwf].digi[jbin-1]); |
f67e2651 |
911 | } |
912 | |
913 | omx->SetWaveform(&histo,omx->GetNwaveforms()+1); |
914 | } |
915 | |
916 | // Set bi-directional links between hits and reco track hypotheses. |
917 | // Note : Reco tracks are recognised by their positive id. |
918 | Int_t hid=0; |
919 | TObjArray* rectracks=evt->GetTracks(1); |
920 | for (Int_t jtk=0; jtk<rectracks->GetEntries(); jtk++) |
921 | { |
922 | tx=(AliTrack*)rectracks->At(jtk); |
923 | if (!tx) continue; |
924 | |
925 | for (Int_t jhyp=1; jhyp<=tx->GetNhypotheses(); jhyp++) |
926 | { |
927 | AliTrack* hypx=tx->GetTrackHypothesis(jhyp); |
928 | if (!hypx) continue; |
929 | |
930 | // Loop over all combinations of F2K fits and used OM hits |
931 | for (Int_t k=0; k<fEvent.nfit_uses; k++) |
932 | { |
933 | if (fEvent.fit_uses[k].useid != hypx->GetId()) continue; |
934 | hid=fEvent.fit_uses[k].hitid; |
935 | sx=evt->GetIdHit(hid,"IceAOM"); |
936 | if (sx) sx->AddLink(hypx); |
937 | } |
938 | } |
939 | } |
940 | } |
941 | /////////////////////////////////////////////////////////////////////////// |