]>
Commit | Line | Data |
---|---|---|
8356cc1d | 1 | //////////////////////////////////////////////////////////////////////////////// |
2 | // | |
3 | // Author: Artur Szostak | |
4 | // Email: artur@alice.phy.uct.ac.za | artursz@iafrica.com | |
5 | // | |
6 | //////////////////////////////////////////////////////////////////////////////// | |
7 | ||
8 | #include "AliRoot/TriggerSource.hpp" | |
9 | #include "AliRoot/Base.hpp" | |
10 | #include "Tracking/Calculations.hpp" | |
11 | #include "AliRun.h" | |
12 | #include "AliRunLoader.h" | |
13 | #include "AliModule.h" | |
14 | #include "AliMUON.h" | |
15 | #include "AliMUONConstants.h" | |
16 | #include "AliMUONHit.h" | |
17 | #include "AliMUONLocalTrigger.h" | |
18 | #include "AliMUONTriggerCircuit.h" | |
19 | #include "AliMUONDataInterface.h" | |
20 | #include "TDatabasePDG.h" | |
98af1577 | 21 | #ifndef __alpha |
22 | #include <math.h> | |
23 | #else | |
24 | #include <float.h> | |
25 | #endif | |
8356cc1d | 26 | |
27 | ClassImp(AliMUONHLT::TriggerSource); | |
28 | ClassImp(AliMUONHLT::TriggerSource::EventData); | |
29 | ||
30 | namespace AliMUONHLT | |
31 | { | |
32 | ||
33 | TriggerSource::TriggerSource() | |
34 | : TObject(), fEventList(TriggerSource::EventData::Class()) | |
35 | { | |
36 | fAreaToUse = FromWholePlane; | |
37 | fDataToUse = FromLocalTriggers; | |
38 | fMaxBlockSize = 0xFFFFFFFF; | |
39 | fUseLookupTable = kTRUE; | |
40 | fFilename = ""; | |
41 | fFoldername = ""; | |
42 | ResetAllPointers(); | |
43 | fHadToLoadgAlice = kFALSE; | |
44 | }; | |
45 | ||
46 | ||
47 | TriggerSource::TriggerSource(AliMUONDataInterface* data) | |
48 | : TObject(), fEventList(TriggerSource::EventData::Class()) | |
49 | { | |
50 | fAreaToUse = FromWholePlane; | |
51 | fDataToUse = FromLocalTriggers; | |
52 | fMaxBlockSize = 0xFFFFFFFF; | |
53 | fUseLookupTable = kTRUE; | |
54 | fFilename = ""; | |
55 | fFoldername = ""; | |
56 | ResetAllPointers(); | |
57 | fHadToLoadgAlice = kFALSE; | |
58 | FillFrom(data); | |
59 | }; | |
60 | ||
61 | ||
62 | TriggerSource::~TriggerSource() | |
63 | { | |
64 | fEventList.Clear("C"); | |
65 | }; | |
66 | ||
67 | ||
68 | void TriggerSource::FillFrom(AliMUONDataInterface* data) | |
69 | { | |
70 | DebugMsg(1, "FillFrom(AliMUONDataInterface*)"); | |
71 | ||
72 | if (FileAndFolderOk(data)) | |
73 | { | |
74 | AliMUON* module = NULL; | |
75 | if ( not FetchAliMUON(module) ) return; | |
76 | ||
77 | for (Int_t i = 0; i < data->NumberOfEvents(); i++) | |
78 | { | |
79 | AddEventFrom(data, module, i); | |
80 | }; | |
81 | ||
82 | FinishedWithAliMUON(); | |
83 | }; | |
84 | }; | |
85 | ||
86 | ||
87 | void TriggerSource::FillFrom(AliMUONDataInterface* data, const Int_t event) | |
88 | { | |
89 | DebugMsg(1, "FillFrom(AliMUONDataInterface*, Int_t)"); | |
90 | ||
91 | if (FileAndFolderOk(data)) | |
92 | { | |
93 | AliMUON* module = NULL; | |
94 | if ( not FetchAliMUON(module) ) return; | |
95 | AddEventFrom(data, module, event); | |
96 | FinishedWithAliMUON(); | |
97 | }; | |
98 | }; | |
99 | ||
100 | ||
101 | void TriggerSource::FillFrom( | |
102 | AliMUONDataInterface* data, | |
103 | const Int_t event, const Int_t trigger, const Bool_t newblock | |
104 | ) | |
105 | { | |
106 | DebugMsg(1, "FillFrom(AliMUONDataInterface*, Int_t, Int_t, Bool_t)"); | |
107 | ||
108 | if (FileAndFolderOk(data)) | |
109 | { | |
110 | data->GetEvent(event); | |
111 | AliMUON* module = NULL; | |
112 | if ( not FetchAliMUON(module) ) return; | |
113 | ||
114 | // Check if the current event corresponds to the event number we are | |
115 | // attempting to add to. If they do not or no event is selected then | |
116 | // try find the event or create a new one. | |
117 | if ( fCurrentEvent == NULL ) | |
118 | { | |
119 | Bool_t found = GetEvent(event); | |
120 | if (not found) AddEvent(event); | |
121 | } | |
122 | else | |
123 | { | |
124 | if (fCurrentEvent->fEventNumber != event) | |
125 | { | |
126 | Bool_t found = GetEvent(event); | |
127 | if (not found) AddEvent(event); | |
128 | }; | |
129 | }; | |
130 | ||
131 | if ( fCurrentBlock != NULL ) | |
132 | { | |
133 | Assert( fCurrentEvent != NULL ); | |
134 | // If the newblock flag is set then force a new block. | |
135 | if (newblock) AddBlock(); | |
136 | } | |
137 | else | |
138 | AddBlock(); // No block selected so we need to create a new block. | |
139 | ||
140 | AddTriggerFrom(data, module, trigger); | |
141 | FinishedWithAliMUON(); | |
142 | }; | |
143 | }; | |
144 | ||
145 | ||
146 | void TriggerSource::Clear() | |
147 | { | |
148 | fFilename = ""; | |
149 | fFoldername = ""; | |
150 | ResetAllPointers(); | |
151 | fEventList.Clear("C"); | |
152 | }; | |
153 | ||
154 | ||
155 | Bool_t TriggerSource::GetEvent(const Int_t eventnumber) const | |
156 | { | |
157 | DebugMsg(1, "TriggerSource::GetEvent(" << eventnumber << ")" ); | |
158 | ||
159 | // Try find the corresponding event in the list of events. | |
160 | for (Int_t i = 0; i < fEventList.GetEntriesFast(); i++) | |
161 | { | |
162 | EventData* current = (EventData*) fEventList[i]; | |
163 | if (current->fEventNumber == eventnumber) | |
164 | { | |
165 | fEventIndex = i; | |
166 | fCurrentEvent = current; | |
167 | GetFirstBlock(); | |
168 | DebugMsg(2, "\tfEventIndex = " << fEventIndex << " , fBlockIndex = " << fBlockIndex | |
169 | << " , fTriggerIndex = " << fTriggerIndex | |
170 | ); | |
171 | return kTRUE; | |
172 | }; | |
173 | }; | |
174 | return kFALSE; | |
175 | }; | |
176 | ||
177 | ||
178 | Bool_t TriggerSource::GetFirstEvent() const | |
179 | { | |
180 | DebugMsg(1, "TriggerSource::GetFirstEvent()"); | |
181 | if (fEventList.GetEntriesFast() > 0) | |
182 | { | |
183 | fEventIndex = 0; | |
184 | fCurrentEvent = (EventData*) fEventList[0]; | |
185 | GetFirstBlock(); | |
186 | DebugMsg(2, "\tfEventIndex = " << fEventIndex << " , fBlockIndex = " << fBlockIndex | |
187 | << " , fTriggerIndex = " << fTriggerIndex | |
188 | ); | |
189 | return kTRUE; | |
190 | } | |
191 | else | |
192 | { | |
193 | DebugMsg(2, "\tfEventIndex = " << fEventIndex << " , fBlockIndex = " << fBlockIndex | |
194 | << " , fTriggerIndex = " << fTriggerIndex | |
195 | ); | |
196 | return kFALSE; | |
197 | }; | |
198 | }; | |
199 | ||
200 | ||
201 | Bool_t TriggerSource::MoreEvents() const | |
202 | { | |
203 | return 0 <= fEventIndex and fEventIndex < fEventList.GetEntriesFast(); | |
204 | }; | |
205 | ||
206 | ||
207 | Bool_t TriggerSource::GetNextEvent() const | |
208 | { | |
209 | DebugMsg(1, "TriggerSource::GetNextEvent()"); | |
210 | if (fEventIndex < fEventList.GetEntriesFast() - 1) | |
211 | { | |
212 | fCurrentEvent = (EventData*) fEventList[ ++fEventIndex ]; | |
213 | GetFirstBlock(); | |
214 | DebugMsg(2, "\tfEventIndex = " << fEventIndex << " , fBlockIndex = " << fBlockIndex | |
215 | << " , fTriggerIndex = " << fTriggerIndex | |
216 | ); | |
217 | return kTRUE; | |
218 | } | |
219 | else | |
220 | { | |
221 | ResetAllPointers(); | |
222 | return kFALSE; | |
223 | }; | |
224 | }; | |
225 | ||
226 | ||
227 | Int_t TriggerSource::CurrentEvent() const | |
228 | { | |
229 | if (fCurrentEvent != NULL) | |
230 | return fCurrentEvent->fEventNumber; | |
231 | else | |
232 | return -1; | |
233 | }; | |
234 | ||
235 | ||
236 | Int_t TriggerSource::NumberOfBlocks() const | |
237 | { | |
238 | DebugMsg(1, "TriggerSource::NumberOfBlocks()"); | |
239 | if (fCurrentEvent == NULL) | |
240 | { | |
241 | Error("NumberOfBlocks", "No event selected."); | |
242 | return -1; | |
243 | } | |
244 | else | |
245 | return fCurrentEvent->fBlocks.GetEntriesFast(); | |
246 | }; | |
247 | ||
248 | ||
249 | Bool_t TriggerSource::GetBlock(const Int_t index) const | |
250 | { | |
251 | DebugMsg(1, "TriggerSource::GetBlock(" << index << ")"); | |
252 | ||
253 | // Note NumberOfBlocks() also checks if the event was selected. | |
254 | Int_t numberofblocks = NumberOfBlocks(); | |
255 | if (numberofblocks < 0) return kFALSE; | |
256 | ||
257 | if ( 0 <= index and index < numberofblocks ) | |
258 | { | |
259 | fBlockIndex = index; | |
260 | fCurrentBlock = (TClonesArray*) fCurrentEvent->fBlocks[index]; | |
261 | GetFirstTrigger(); | |
262 | DebugMsg(2, "\tfEventIndex = " << fEventIndex << " , fBlockIndex = " << fBlockIndex | |
263 | << " , fTriggerIndex = " << fTriggerIndex | |
264 | ); | |
265 | return kTRUE; | |
266 | } | |
267 | else | |
268 | { | |
269 | // The index is out of bounds so inform the user. | |
270 | if (numberofblocks > 0) | |
271 | Error( "GetBlock", | |
272 | "The block index (%d) is out of bounds. Valid range is [0, %d]", | |
273 | index, numberofblocks - 1 | |
274 | ); | |
275 | else | |
276 | Error( "GetBlock", | |
277 | "The block index (%d) is out of bounds. No blocks found.", | |
278 | index | |
279 | ); | |
280 | return kFALSE; | |
281 | }; | |
282 | }; | |
283 | ||
284 | ||
285 | Bool_t TriggerSource::GetFirstBlock() const | |
286 | { | |
287 | DebugMsg(1, "TriggerSource::GetFirstBlock()"); | |
288 | // Note: NumberOfBlocks() also checks if fCurrentEvent != NULL. | |
289 | if (NumberOfBlocks() > 0) | |
290 | { | |
291 | fBlockIndex = 0; | |
292 | fCurrentBlock = (TClonesArray*) fCurrentEvent->fBlocks[fBlockIndex]; | |
293 | GetFirstTrigger(); | |
294 | DebugMsg(2, "\tfEventIndex = " << fEventIndex << " , fBlockIndex = " << fBlockIndex | |
295 | << " , fTriggerIndex = " << fTriggerIndex | |
296 | ); | |
297 | return kTRUE; | |
298 | } | |
299 | else | |
300 | return kFALSE; | |
301 | }; | |
302 | ||
303 | ||
304 | Bool_t TriggerSource::MoreBlocks() const | |
305 | { | |
306 | return 0 <= fBlockIndex and fBlockIndex < NumberOfBlocks(); | |
307 | }; | |
308 | ||
309 | ||
310 | Bool_t TriggerSource::GetNextBlock() const | |
311 | { | |
312 | DebugMsg(1, "TriggerSource::GetNextBlock()"); | |
313 | ||
314 | // Note: NumberOfBlocks() checks if fCurrentEvent != NULL. If it is then it returns -1 | |
315 | // and since fBlockIndex is always >= -1 the if statement must go to the else part. | |
316 | if (fBlockIndex < NumberOfBlocks() - 1) | |
317 | { | |
318 | fCurrentBlock = (TClonesArray*) fCurrentEvent->fBlocks[ ++fBlockIndex ]; | |
319 | GetFirstTrigger(); | |
320 | DebugMsg(2, "\tfEventIndex = " << fEventIndex << " , fBlockIndex = " << fBlockIndex | |
321 | << " , fTriggerIndex = " << fTriggerIndex | |
322 | ); | |
323 | return kTRUE; | |
324 | } | |
325 | else | |
326 | { | |
327 | ResetBlockPointers(); | |
328 | return kFALSE; | |
329 | }; | |
330 | }; | |
331 | ||
332 | ||
333 | Int_t TriggerSource::NumberOfTriggers() const | |
334 | { | |
335 | DebugMsg(1, "TriggerSource::NumberOfTriggers()"); | |
336 | if (fCurrentBlock == NULL) | |
337 | { | |
338 | Error("NumberOfTriggers", "No block selected."); | |
339 | return -1; | |
340 | } | |
341 | else | |
342 | return fCurrentBlock->GetEntriesFast(); | |
343 | }; | |
344 | ||
345 | ||
346 | const TriggerRecord* TriggerSource::GetTrigger(const Int_t triggernumber) const | |
347 | { | |
348 | DebugMsg(1, "TriggerSource::GetTrigger(" << triggernumber << ")"); | |
349 | ||
350 | if (fCurrentBlock == NULL) | |
351 | { | |
352 | Error("GetTrigger", "No block selected."); | |
353 | return NULL; | |
354 | }; | |
355 | ||
356 | // Try find the corresponding trigger record in the list of events. | |
357 | for (Int_t i = 0; i < fCurrentBlock->GetEntriesFast(); i++) | |
358 | { | |
359 | TriggerRecord* current = (TriggerRecord*) fCurrentBlock->At(i); | |
360 | if (current->TriggerNumber() == triggernumber) | |
361 | { | |
362 | fTriggerIndex = i; | |
363 | fCurrentTrigger = current; | |
364 | DebugMsg(2, "\tfEventIndex = " << fEventIndex << " , fBlockIndex = " << fBlockIndex | |
365 | << " , fTriggerIndex = " << fTriggerIndex | |
366 | ); | |
367 | return current; | |
368 | }; | |
369 | }; | |
370 | return NULL; | |
371 | }; | |
372 | ||
373 | ||
374 | const TriggerRecord* TriggerSource::GetFirstTrigger() const | |
375 | { | |
376 | DebugMsg(1, "TriggerSource::GetFirstTrigger()"); | |
377 | // Note: NumberOfTriggers() also checks if fCurrentBlock != NULL. | |
378 | if (NumberOfTriggers() > 0) | |
379 | { | |
380 | fTriggerIndex = 0; | |
381 | fCurrentTrigger = (TriggerRecord*) fCurrentBlock->At(0); | |
382 | DebugMsg(2, "\tfEventIndex = " << fEventIndex << " , fBlockIndex = " << fBlockIndex | |
383 | << " , fTriggerIndex = " << fTriggerIndex | |
384 | ); | |
385 | return fCurrentTrigger; | |
386 | } | |
387 | else | |
388 | return NULL; | |
389 | }; | |
390 | ||
391 | ||
392 | Bool_t TriggerSource::MoreTriggers() const | |
393 | { | |
394 | return 0 <= fTriggerIndex and fTriggerIndex < NumberOfTriggers(); | |
395 | }; | |
396 | ||
397 | ||
398 | const TriggerRecord* TriggerSource::GetNextTrigger() const | |
399 | { | |
400 | DebugMsg(1, "TriggerSource::GetNextTrigger()"); | |
401 | ||
402 | // Note: NumberOfTriggers() checks if fCurrentBlock != NULL. If it is then it returns -1 | |
403 | // and since fTriggerIndex is always >= -1 the if statement must go to the else part. | |
404 | if (fTriggerIndex < NumberOfTriggers() - 1) | |
405 | { | |
406 | fCurrentTrigger = (TriggerRecord*) fCurrentBlock->At( ++fTriggerIndex ); | |
407 | DebugMsg(2, "\tfEventIndex = " << fEventIndex << " , fBlockIndex = " << fBlockIndex | |
408 | << " , fTriggerIndex = " << fTriggerIndex | |
409 | ); | |
410 | return fCurrentTrigger; | |
411 | } | |
412 | else | |
413 | { | |
414 | ResetTriggerPointers(); | |
415 | return NULL; | |
416 | }; | |
417 | }; | |
418 | ||
419 | ||
420 | Int_t TriggerSource::CurrentTrigger() const | |
421 | { | |
422 | if (fCurrentTrigger != NULL) | |
423 | { | |
424 | return fCurrentTrigger->TriggerNumber(); | |
425 | } | |
426 | else | |
427 | { | |
428 | Error("CurrentTrigger", "No trigger record selected."); | |
429 | return -1; | |
430 | }; | |
431 | }; | |
432 | ||
433 | ||
434 | void TriggerSource::AddEvent(const Int_t eventnumber) | |
435 | { | |
436 | DebugMsg(1, "TriggerSource::AddEvent(" << eventnumber << ")"); | |
437 | Assert( eventnumber >= 0 ); | |
438 | ||
439 | // Assume the eventnumber does not already exist in the event list. | |
440 | fEventIndex = fEventList.GetEntriesFast(); | |
441 | new ( fEventList[fEventIndex] ) EventData(eventnumber); | |
442 | fCurrentEvent = (EventData*) fEventList[fEventIndex]; | |
443 | ||
444 | // Remember to reset the other pointers because the new event is empty. | |
445 | ResetBlockPointers(); | |
446 | ||
447 | DebugMsg(2, "\tfEventIndex = " << fEventIndex << " , fBlockIndex = " << fBlockIndex | |
448 | << " , fTriggerIndex = " << fTriggerIndex | |
449 | ); | |
450 | }; | |
451 | ||
452 | ||
453 | void TriggerSource::AddBlock() | |
454 | { | |
455 | DebugMsg(1, "TriggerSource::AddBlock()"); | |
456 | ||
457 | if (fCurrentEvent == NULL) | |
458 | { | |
459 | Error("AddBlock", "No event selected."); | |
460 | return; | |
461 | }; | |
462 | ||
463 | fBlockIndex = fCurrentEvent->fBlocks.GetEntriesFast(); | |
464 | new ( fCurrentEvent->fBlocks[fBlockIndex] ) TClonesArray(TriggerRecord::Class()); | |
465 | fCurrentBlock = (TClonesArray*) fCurrentEvent->fBlocks[fBlockIndex]; | |
466 | ||
467 | // Remember to reset the trigger pointer because the new block is empty. | |
468 | ResetTriggerPointers(); | |
469 | ||
470 | DebugMsg(2, "\tfEventIndex = " << fEventIndex << " , fBlockIndex = " << fBlockIndex | |
471 | << " , fTriggerIndex = " << fTriggerIndex | |
472 | ); | |
473 | }; | |
474 | ||
475 | ||
476 | void TriggerSource::AddTrigger(const TriggerRecord& data) | |
477 | { | |
478 | DebugMsg(1, "TriggerSource::AddTrigger(" << (void*)&data << ")"); | |
479 | ||
480 | if (fCurrentBlock == NULL) | |
481 | { | |
482 | Error("AddTrigger", "No block selected."); | |
483 | return; | |
484 | }; | |
485 | ||
486 | fTriggerIndex = fCurrentBlock->GetEntriesFast(); | |
487 | new ( (*fCurrentBlock)[fTriggerIndex] ) TriggerRecord(data); | |
488 | fCurrentTrigger = (TriggerRecord*) (*fCurrentBlock)[fTriggerIndex]; | |
489 | ||
490 | DebugMsg(2, "\tfEventIndex = " << fEventIndex << " , fBlockIndex = " << fBlockIndex | |
491 | << " , fTriggerIndex = " << fTriggerIndex | |
492 | ); | |
493 | }; | |
494 | ||
495 | ||
496 | Bool_t TriggerSource::FileAndFolderOk(AliMUONDataInterface* data) | |
497 | { | |
498 | if (fFilename == "") | |
499 | { | |
500 | // Nothing filled yet so set the file and folder names. | |
501 | fFilename = data->CurrentFile(); | |
502 | fFoldername = data->CurrentFolder(); | |
503 | return kTRUE; | |
504 | }; | |
505 | ||
506 | if ( fFilename != data->CurrentFile() ) | |
507 | { | |
508 | Error( "FileAndFolderOk", | |
509 | "The Trigger source already contains data from file '%s', cannot add data from file '%s'", | |
510 | fFilename.Data(), data->CurrentFile().Data() | |
511 | ); | |
512 | return kFALSE; | |
513 | }; | |
514 | ||
515 | if ( fFoldername != data->CurrentFolder() ) | |
516 | { | |
517 | Error( "FileAndFolderOk", | |
518 | "The Trigger source already contains data from folder '%s', cannot add data from folder '%s'", | |
519 | fFoldername.Data(), data->CurrentFolder().Data() | |
520 | ); | |
521 | return kFALSE; | |
522 | }; | |
523 | ||
524 | return kTRUE; | |
525 | }; | |
526 | ||
527 | ||
528 | void TriggerSource::AddEventFrom(AliMUONDataInterface* data, AliMUON* module, const Int_t event) | |
529 | { | |
530 | if ( data->GetEvent(event) ) | |
531 | { | |
532 | AddEvent(event); | |
533 | ||
534 | AddBlock(); | |
535 | UInt_t currentblocksize = 0; | |
536 | TriggerRecord trigdata; | |
537 | ||
538 | switch (fDataToUse) | |
539 | { | |
540 | case FromHits: | |
541 | for (Int_t track = 0; track < data->NumberOfTracks(); track++) | |
542 | { | |
543 | if ( not FillTriggerFromHits(data, track, trigdata) ) | |
544 | continue; // Continue if unable to find hits. | |
545 | ||
546 | if (InFillRegion(trigdata)) | |
547 | { | |
548 | AddTrigger(trigdata); | |
549 | ||
550 | // Create a new block if we reached the maximum block size. | |
551 | if ( ++currentblocksize == fMaxBlockSize ) | |
552 | { | |
553 | AddBlock(); | |
554 | currentblocksize = 0; | |
555 | }; | |
556 | }; | |
557 | }; | |
558 | break; | |
559 | ||
560 | case FromLocalTriggers: | |
561 | Assert( module != NULL ); | |
562 | DebugMsg(4, "Taking FromLocalTriggers branch..."); | |
563 | for (Int_t i = 0; i < data->NumberOfLocalTriggers(); i++) | |
564 | { | |
565 | DebugMsg(4, "for loop: i = " << i); | |
566 | AliMUONLocalTrigger* lt = data->LocalTrigger(i); | |
567 | FillTriggerFromLocalTrigger(lt, module, trigdata); | |
568 | trigdata.TriggerNumber(i); | |
569 | ||
570 | if (InFillRegion(trigdata)) | |
571 | { | |
572 | AddTrigger(trigdata); | |
573 | ||
574 | // Create a new block if we reached the maximum block size. | |
575 | if ( ++currentblocksize == fMaxBlockSize ) | |
576 | { | |
577 | AddBlock(); | |
578 | currentblocksize = 0; | |
579 | }; | |
580 | }; | |
581 | }; | |
582 | break; | |
583 | ||
584 | default: | |
585 | Error("AddChamberFrom", "fDataToUse is not set to a valid value."); | |
586 | }; | |
587 | }; // Loop on events. | |
588 | }; | |
589 | ||
590 | ||
591 | void TriggerSource::AddTriggerFrom(AliMUONDataInterface* data, AliMUON* module, const Int_t trigger) | |
592 | { | |
593 | DebugMsg(1, "Entering AddTriggerFrom"); | |
594 | ||
595 | TriggerRecord trigdata; | |
596 | ||
597 | switch (fDataToUse) | |
598 | { | |
599 | case FromHits: | |
600 | { | |
601 | // Note: in this case we treat the trigger parameter as a track number. | |
602 | if ( not FillTriggerFromHits(data, trigger, trigdata) ) | |
603 | return; // Continue if unable to find hits. | |
604 | } | |
605 | break; | |
606 | ||
607 | case FromLocalTriggers: | |
608 | { | |
609 | Assert( module != NULL ); | |
610 | AliMUONLocalTrigger* lt = data->LocalTrigger(trigger); | |
611 | FillTriggerFromLocalTrigger(lt, module, trigdata); | |
612 | trigdata.TriggerNumber(trigger); | |
613 | } | |
614 | break; | |
615 | ||
616 | default: | |
617 | Error("AddTriggerFrom", "fDataToUse is not set to a valid value."); | |
618 | return; | |
619 | }; | |
620 | ||
621 | AddTrigger(trigdata); | |
622 | ||
623 | DebugMsg(1, "Leaving AddTriggerFrom"); | |
624 | }; | |
625 | ||
626 | ||
627 | Bool_t TriggerSource::InFillRegion(const TriggerRecord& data) | |
628 | { | |
629 | switch (fAreaToUse) | |
630 | { | |
631 | case FromWholePlane: return kTRUE; | |
632 | case FromLeftHalfPlane: return data.Station1Point().fX <= 0; | |
633 | case FromRightHalfPlane: return data.Station1Point().fX > 0; | |
634 | ||
635 | default: | |
636 | Error("InFillRegion", "fAreaToUse is not set to a valid value."); | |
637 | return kFALSE; | |
638 | }; | |
639 | }; | |
640 | ||
641 | ||
642 | void TriggerSource::FillTriggerFromLocalTrigger( | |
643 | AliMUONLocalTrigger* trigger, AliMUON* module, TriggerRecord& record | |
644 | ) | |
645 | { | |
646 | DebugMsg(2, "Creating TriggerRecord from AliMUONLocalTrigger object: " << (void*)trigger ); | |
647 | AliMUONTriggerCircuit& circuit = module->TriggerCircuit(trigger->LoCircuit()); | |
648 | ||
649 | // Get the sign of the particle the sign of the muon. | |
650 | if (trigger->LoLpt() == 1 || trigger->LoHpt() == 1 || trigger->LoApt() == 1) | |
651 | { | |
652 | record.ParticleSign(-1); | |
653 | } | |
654 | else | |
655 | if (trigger->LoLpt() == 2 || trigger->LoHpt() == 2 || trigger->LoApt() == 2) | |
656 | { | |
657 | record.ParticleSign(+1); | |
658 | } | |
659 | else | |
660 | { | |
661 | record.ParticleSign(0); | |
662 | }; | |
663 | DebugMsg(2, "Particle sign = " << record.ParticleSign() ); | |
664 | ||
665 | // Compute the transverse momentum. | |
666 | if (fUseLookupTable) | |
667 | { | |
668 | // TODO: implement use of the L0 lookup table. | |
669 | Error("FillTriggerFromLocalTrigger", "Use of L0 lookup table is not yet implemented!"); | |
670 | } | |
671 | else | |
672 | { | |
673 | Float_t pt = circuit.PtCal( trigger->LoStripX(), trigger->LoDev(), trigger->LoStripY() ); | |
674 | record.Pt(pt); | |
675 | }; | |
676 | DebugMsg(2, "Pt = " << record.Pt() ); | |
677 | ||
678 | // Build the impact points. | |
679 | record.Station1Point().fX = circuit.GetX11Pos(trigger->LoStripY()); | |
680 | record.Station1Point().fY = circuit.GetY11Pos(trigger->LoStripX()); | |
681 | record.Station2Point().fY = circuit.GetY21Pos(trigger->LoStripX() + trigger->LoDev() + 1); // Why + 1? | |
682 | record.Station2Point().fX = module->Chamber(12).Z() * record.Station1Point().fX / module->Chamber(10).Z(); | |
683 | DebugMsg(2, "fStation1x = " << record.Station1Point().fX); | |
684 | DebugMsg(2, "fStation1y = " << record.Station1Point().fY); | |
685 | DebugMsg(2, "fStation2x = " << record.Station2Point().fX); | |
686 | DebugMsg(2, "fStation2y = " << record.Station2Point().fY); | |
687 | }; | |
688 | ||
689 | ||
690 | Bool_t TriggerSource::FillTriggerFromHits(AliMUONDataInterface* data, const Int_t track, TriggerRecord& record) | |
691 | { | |
692 | DebugMsg(2, "Creating TriggerRecord from hits on track: " << track ); | |
693 | ||
694 | Float_t x1, y1, z1, x2, y2, z2, x3, y3, z3, x4, y4, z4; | |
98af1577 | 695 | #ifndef __alpha |
8356cc1d | 696 | x1 = y1 = z1 = x2 = y2 = z2 = x3 = y3 = z3 = x4 = y4 = z4 = NAN; |
98af1577 | 697 | #else |
698 | x1 = y1 = z1 = x2 = y2 = z2 = x3 = y3 = z3 = x4 = y4 = z4 = FLT_QNAN; | |
699 | #endif | |
8356cc1d | 700 | // Find the hit that corresponds to chambers. 11 to 14. We can ignore any |
701 | // hits above the first 14. If there are that many it means the particle | |
702 | // is cycling in the detector. | |
703 | for (Int_t i = 0; i < data->NumberOfHits(track) and i < 14; i++) | |
704 | { | |
705 | AliMUONHit* h = data->Hit(track, i); | |
706 | ||
707 | // Note AliMUONHit::Chamber() returns a value in the range 1..14 | |
708 | // It is also important to have positive Z coordinates and under the | |
709 | // new version of Aliroot we use GEANT coordinates which return | |
710 | // negatives. So we use the fabs routine. | |
711 | switch ( h->Chamber() ) | |
712 | { | |
713 | case 11: x1 = h->X(); y1 = h->Y(); z1 = (Float_t)fabs(h->Z()); break; | |
714 | case 12: x2 = h->X(); y2 = h->Y(); z2 = (Float_t)fabs(h->Z()); break; | |
715 | case 13: x3 = h->X(); y3 = h->Y(); z3 = (Float_t)fabs(h->Z()); break; | |
716 | case 14: x4 = h->X(); y4 = h->Y(); z4 = (Float_t)fabs(h->Z()); break; | |
717 | }; | |
718 | }; | |
719 | DebugMsg(4, "Found: x1 = " << x1 << ", y1 = " << y1 << ", z1 = " << z1); | |
720 | DebugMsg(4, "Found: x2 = " << x2 << ", y2 = " << y2 << ", z2 = " << z2); | |
721 | DebugMsg(4, "Found: x3 = " << x3 << ", y3 = " << y3 << ", z3 = " << z3); | |
722 | DebugMsg(4, "Found: x4 = " << x4 << ", y4 = " << y4 << ", z4 = " << z4); | |
723 | ||
724 | // Get a coordinate for station 1, perferably from chamber 11 otherwise | |
725 | // use hits from chamber 12. | |
726 | if (not TMath::IsNaN(x1)) | |
727 | { | |
728 | record.Station1Point().fX = x1; | |
729 | record.Station1Point().fY = y1; | |
730 | DebugMsg(3, "Using value from chamber 11: x1 = " << x1 << ", y1 = " << y1 << ", z1 = " << z1 ); | |
731 | } | |
732 | else if (not TMath::IsNaN(x2)) | |
733 | { | |
734 | record.Station1Point().fX = x2; | |
735 | record.Station1Point().fY = y2; | |
736 | z1 = z2; | |
737 | DebugMsg(3, "Using value from chamber 12: x2 = " << x2 << ", y2 = " << y2 << ", z2 = " << z2 ); | |
738 | } | |
739 | else | |
740 | { | |
741 | // Return false if we could not find any hits on chambers 11 or 12. | |
742 | Warning("FillTriggerFromHits", "Could not find any hits on chambers 11 and 12."); | |
743 | return kFALSE; | |
744 | }; | |
745 | ||
746 | // Get a coordinate for station 2, perferably from chamber 13 otherwise | |
747 | // use hits from chamber 14. | |
748 | if (not TMath::IsNaN(x3)) | |
749 | { | |
750 | record.Station2Point().fX = x3; | |
751 | record.Station2Point().fY = y3; | |
752 | z2 = z3; | |
753 | DebugMsg(3, "Using value from chamber 13: x3 = " << x3 << ", y3 = " << y3 << ", z3 = " << z3 ); | |
754 | } | |
755 | else if (not TMath::IsNaN(x4)) | |
756 | { | |
757 | record.Station2Point().fX = x4; | |
758 | record.Station2Point().fY = y4; | |
759 | z2 = z4; | |
760 | DebugMsg(3, "Using value from chamber 14: x4 = " << x4 << ", y4 = " << y4 << ", z4 = " << z4 ); | |
761 | } | |
762 | else | |
763 | { | |
764 | // Return false if we could not find any hits on chambers 13 or 14. | |
765 | Warning("FillTriggerFromHits", "Could not find any hits on chambers 13 and 14."); | |
766 | return kFALSE; | |
767 | }; | |
768 | ||
769 | record.TriggerNumber(track); | |
770 | ||
771 | // Get the sign of the particle. | |
772 | Int_t particlecode = (Int_t) data->Hit(track, 0)->Particle(); | |
773 | DebugMsg(3, "particle code = " << particlecode); | |
774 | TDatabasePDG* pdb = TDatabasePDG::Instance(); | |
775 | TParticlePDG* pdata = pdb->GetParticle(particlecode); | |
776 | if (pdata->Charge() < 0) | |
777 | record.ParticleSign(-1); | |
778 | else if (pdata->Charge() > 0) | |
779 | record.ParticleSign(+1); | |
780 | else | |
781 | record.ParticleSign(0); | |
782 | DebugMsg(3, "Particle sign = " << record.ParticleSign()); | |
783 | ||
784 | DebugMsg(3, "Calculating Pt: x1 = " << record.Station1Point().fX | |
785 | << ", y1 = " << record.Station1Point().fY | |
786 | << ", y2 = " << record.Station2Point().fY | |
787 | << ", z1 = " << z1 | |
788 | << ", z2 = " << z2 | |
789 | ); | |
790 | // Calculate and assign the transverse momentum. | |
791 | Float_t pt = dHLT::Tracking::CalculatePt( | |
792 | record.Station1Point().fX, | |
793 | record.Station1Point().fY, record.Station2Point().fY, | |
794 | z1, z2 | |
795 | ); | |
796 | record.Pt(pt); | |
797 | ||
798 | DebugMsg(3, "Pt = " << record.Pt()); | |
799 | ||
800 | return kTRUE; | |
801 | }; | |
802 | ||
803 | ||
804 | Bool_t TriggerSource::FetchAliMUON(AliMUON*& module) | |
805 | { | |
806 | // Check if we even need the MUON module. Not having to load it will | |
807 | // save a lot of loading time for AliRoot. | |
808 | if (fDataToUse == FromHits) | |
809 | { | |
810 | // Make sure we do not attempt to unload gAlice in FinishedWithAliMUON, | |
811 | // by setting the fHadToLoadgAlice to false. | |
812 | fHadToLoadgAlice = kFALSE; | |
813 | return kTRUE; | |
814 | }; | |
815 | ||
816 | AliRunLoader* runloader = AliRunLoader::GetRunLoader(); | |
817 | if ( runloader == NULL ) | |
818 | { | |
819 | Error("FetchAliMUON", "AliRunLoader not initialised!"); | |
820 | return kFALSE; | |
821 | }; | |
822 | ||
823 | // Try fetch the AliRun object. If it is not found then try load it using | |
824 | // the runloader. | |
825 | AliRun* alirun = runloader->GetAliRun(); | |
826 | if (alirun == NULL) | |
827 | { | |
828 | if (runloader->LoadgAlice() != 0) | |
829 | { | |
830 | // Error. | |
831 | DebugMsg(1, "Leaving FillFrom(AliMUONDataInterface*)"); | |
832 | return kFALSE; | |
833 | }; | |
834 | fHadToLoadgAlice = kTRUE; | |
835 | alirun = runloader->GetAliRun(); | |
836 | } | |
837 | else | |
838 | fHadToLoadgAlice = kFALSE; | |
839 | ||
840 | // Get the MUON module pointer and return it. | |
841 | module = dynamic_cast<AliMUON*>( alirun->GetModule("MUON") ); | |
842 | return kTRUE; | |
843 | }; | |
844 | ||
845 | ||
846 | void TriggerSource::FinishedWithAliMUON() | |
847 | { | |
848 | // Only unload the gAlice object if we had to load it ourselves. | |
849 | if (fHadToLoadgAlice) | |
850 | AliRunLoader::GetRunLoader()->UnloadgAlice(); | |
851 | }; | |
852 | ||
853 | ||
854 | void TriggerSource::ResetAllPointers() const | |
855 | { | |
856 | fEventIndex = -1; | |
857 | fCurrentEvent = NULL; | |
858 | fBlockIndex = -1; | |
859 | fCurrentBlock = NULL; | |
860 | fTriggerIndex = -1; | |
861 | fCurrentTrigger = NULL; | |
862 | DebugMsg(2, "\tfEventIndex = " << fEventIndex << " , fBlockIndex = " << fBlockIndex | |
863 | << " , fTriggerIndex = " << fTriggerIndex | |
864 | ); | |
865 | }; | |
866 | ||
867 | ||
868 | void TriggerSource::ResetBlockPointers() const | |
869 | { | |
870 | fBlockIndex = -1; | |
871 | fCurrentBlock = NULL; | |
872 | fTriggerIndex = -1; | |
873 | fCurrentTrigger = NULL; | |
874 | DebugMsg(2, "\tfEventIndex = " << fEventIndex << " , fBlockIndex = " << fBlockIndex | |
875 | << " , fTriggerIndex = " << fTriggerIndex | |
876 | ); | |
877 | }; | |
878 | ||
879 | ||
880 | void TriggerSource::ResetTriggerPointers() const | |
881 | { | |
882 | fTriggerIndex = -1; | |
883 | fCurrentTrigger = NULL; | |
884 | DebugMsg(2, "\tfEventIndex = " << fEventIndex << " , fBlockIndex = " << fBlockIndex | |
885 | << " , fTriggerIndex = " << fTriggerIndex | |
886 | ); | |
887 | }; | |
888 | ||
889 | ||
890 | TriggerSource::EventData::EventData() : fBlocks(TClonesArray::Class()) | |
891 | { | |
892 | fEventNumber = -1; | |
893 | }; | |
894 | ||
895 | ||
896 | TriggerSource::EventData::EventData(const Int_t eventnumber) | |
897 | : fBlocks(TClonesArray::Class()) | |
898 | { | |
899 | fEventNumber = eventnumber; | |
900 | ||
901 | // If the following is not set then we do not write the fBlocks properly. | |
902 | fBlocks.BypassStreamer(kFALSE); | |
903 | }; | |
904 | ||
905 | ||
906 | TriggerSource::EventData::~EventData() | |
907 | { | |
908 | fBlocks.Clear("C"); | |
909 | }; | |
910 | ||
911 | ||
912 | }; // AliMUONHLT |