1 ////////////////////////////////////////////////////////////////////////////////
3 // Author: Artur Szostak
4 // Email: artur@alice.phy.uct.ac.za | artursz@iafrica.com
6 ////////////////////////////////////////////////////////////////////////////////
8 #include "AliRoot/ClusterSource.hpp"
9 #include "AliRoot/Base.hpp"
10 #include "AliMUONConstants.h"
11 #include "AliMUONHit.h"
12 #include "AliMUONRawCluster.h"
13 #include "AliMUONDataInterface.h"
20 ClassImp(AliMUONHLT::ClusterSource)
21 ClassImp(AliMUONHLT::ClusterSource::BlockData)
22 ClassImp(AliMUONHLT::ClusterSource::EventData)
28 ClusterSource::ClusterSource()
29 : TObject(), fEventList(ClusterSource::EventData::Class())
31 fAreaToUse = FromWholePlane;
32 fDataToUse = FromRawClusters;
33 fMaxBlockSize = 0xFFFFFFFF;
40 ClusterSource::ClusterSource(AliMUONDataInterface* data)
41 : TObject(), fEventList(ClusterSource::EventData::Class())
43 fAreaToUse = FromWholePlane;
44 fDataToUse = FromRawClusters;
45 fMaxBlockSize = 0xFFFFFFFF;
53 ClusterSource::~ClusterSource()
55 fEventList.Clear("C");
59 void ClusterSource::FillFrom(AliMUONDataInterface* data)
61 DebugMsg(1, "FillFrom(AliMUONDataInterface*)");
63 if (FileAndFolderOk(data))
65 for (Int_t i = 0; i < data->NumberOfEvents(); i++)
67 AddEventFrom(data, i);
73 void ClusterSource::FillFrom(AliMUONDataInterface* data, Int_t event)
75 DebugMsg(1, "FillFrom(AliMUONDataInterface*, Int_t)");
77 if (FileAndFolderOk(data))
78 AddEventFrom(data, event);
82 void ClusterSource::FillFrom(AliMUONDataInterface* data, Int_t event, Int_t chamber)
84 DebugMsg(1, "FillFrom(AliMUONDataInterface*, Int_t)");
86 if (FileAndFolderOk(data))
88 if ( data->GetEvent(event) )
91 AddChamberFrom(data, chamber);
97 void ClusterSource::FillFrom(
98 AliMUONDataInterface* data,
99 Int_t event, Int_t chamber, Int_t cluster,
103 DebugMsg(1, "FillFrom(AliMUONDataInterface*, Int_t, Int_t, Int_t, Bool_t)");
105 if (FileAndFolderOk(data))
107 data->GetEvent(event);
109 // Check if the current event corresponds to the event number we are
110 // attempting to add to. If they do not or no event is selected then
111 // try find the event or create a new one.
112 if ( fCurrentEvent == NULL )
114 Bool_t found = GetEvent(event);
115 if (not found) AddEvent(event);
119 if (fCurrentEvent->fEventNumber != event)
121 Bool_t found = GetEvent(event);
122 if (not found) AddEvent(event);
126 if ( fCurrentBlock != 0)
128 Assert( fCurrentEvent != NULL );
130 if ( fCurrentBlock->fChamber != chamber)
132 // Create a new block if the current blocks chamber number does
133 // not correspond to the specified chamber.
138 // If the newblock flag is set then force a new block.
139 if (newblock) AddBlock(chamber);
143 AddBlock(chamber); // No block selected so we need to create a new block.
145 AddClusterFrom(data, chamber, cluster);
150 void ClusterSource::Clear(Option_t* /*option*/)
159 Bool_t ClusterSource::GetEvent(Int_t eventnumber) const
161 DebugMsg(1, "ClusterSource::GetEvent(" << eventnumber << ")" );
163 // Try find the corresponding event in the list of events.
164 for (Int_t i = 0; i < fEventList.GetEntriesFast(); i++)
166 EventData* current = (EventData*) fEventList[i];
167 if (current->fEventNumber == eventnumber)
170 fCurrentEvent = current;
172 DebugMsg(2, "\tfEventIndex = " << fEventIndex << " , fBlockIndex = " << fBlockIndex
173 << " , fClusterIndex = " << fClusterIndex
182 Bool_t ClusterSource::GetFirstEvent() const
184 DebugMsg(1, "ClusterSource::GetFirstEvent()");
185 if (fEventList.GetEntriesFast() > 0)
188 fCurrentEvent = (EventData*) fEventList[0];
190 DebugMsg(2, "\tfEventIndex = " << fEventIndex << " , fBlockIndex = " << fBlockIndex
191 << " , fClusterIndex = " << fClusterIndex
197 DebugMsg(2, "\tfEventIndex = " << fEventIndex << " , fBlockIndex = " << fBlockIndex
198 << " , fClusterIndex = " << fClusterIndex
205 Bool_t ClusterSource::MoreEvents() const
207 return 0 <= fEventIndex and fEventIndex < fEventList.GetEntriesFast();
211 Bool_t ClusterSource::GetNextEvent() const
213 DebugMsg(1, "ClusterSource::GetNextEvent()");
214 if (fEventIndex < fEventList.GetEntriesFast() - 1)
216 fCurrentEvent = (EventData*) fEventList[ ++fEventIndex ];
218 DebugMsg(2, "\tfEventIndex = " << fEventIndex << " , fBlockIndex = " << fBlockIndex
219 << " , fClusterIndex = " << fClusterIndex
231 Int_t ClusterSource::CurrentEvent() const
233 if (fCurrentEvent != NULL)
234 return fCurrentEvent->fEventNumber;
240 Int_t ClusterSource::NumberOfBlocks() const
242 DebugMsg(1, "ClusterSource::NumberOfBlocks()");
243 if (fCurrentEvent == NULL)
245 Error("NumberOfBlocks", "No event selected.");
249 return fCurrentEvent->fBlocks.GetEntriesFast();
253 Bool_t ClusterSource::GetBlock(Int_t index) const
255 DebugMsg(1, "ClusterSource::GetBlock(" << index << ")");
257 // Note NumberOfBlocks() also checks if the event was selected.
258 Int_t numberofblocks = NumberOfBlocks();
259 if (numberofblocks < 0) return kFALSE;
261 if ( 0 <= index and index < numberofblocks )
264 fCurrentBlock = (BlockData*) fCurrentEvent->fBlocks[index];
266 DebugMsg(2, "\tfEventIndex = " << fEventIndex << " , fBlockIndex = " << fBlockIndex
267 << " , fClusterIndex = " << fClusterIndex
273 // The index is out of bounds so inform the user.
274 if (numberofblocks > 0)
276 "The block index (%d) is out of bounds. Valid range is [0, %d]",
277 index, numberofblocks - 1
281 "The block index (%d) is out of bounds. No blocks found.",
289 Bool_t ClusterSource::GetFirstBlock() const
291 DebugMsg(1, "ClusterSource::GetFirstBlock()");
292 // Note: NumberOfBlocks() also checks if fCurrentEvent != NULL.
293 if (NumberOfBlocks() > 0)
296 fCurrentBlock = (BlockData*) fCurrentEvent->fBlocks[fBlockIndex];
298 DebugMsg(2, "\tfEventIndex = " << fEventIndex << " , fBlockIndex = " << fBlockIndex
299 << " , fClusterIndex = " << fClusterIndex
308 Bool_t ClusterSource::MoreBlocks() const
310 return 0 <= fBlockIndex and fBlockIndex < NumberOfBlocks();
314 Bool_t ClusterSource::GetNextBlock() const
316 DebugMsg(1, "ClusterSource::GetNextBlock()");
318 // Note: NumberOfBlocks() checks if fCurrentEvent != NULL. If it is then it returns -1
319 // and since fBlockIndex is always >= -1 the if statement must go to the else part.
320 if (fBlockIndex < NumberOfBlocks() - 1)
322 fCurrentBlock = (BlockData*) fCurrentEvent->fBlocks[ ++fBlockIndex ];
324 DebugMsg(2, "\tfEventIndex = " << fEventIndex << " , fBlockIndex = " << fBlockIndex
325 << " , fClusterIndex = " << fClusterIndex
331 ResetBlockPointers();
337 Int_t ClusterSource::Chamber() const
339 if (fCurrentBlock == NULL)
341 Error("Chamber", "No block selected.");
345 return fCurrentBlock->fChamber;
349 Int_t ClusterSource::NumberOfClusters() const
351 DebugMsg(1, "ClusterSource::NumberOfClusters()");
352 if (fCurrentBlock == NULL)
354 Error("NumberOfClusters", "No block selected.");
358 return fCurrentBlock->fClusters.GetEntriesFast();
362 const Point* ClusterSource::GetCluster(Int_t index) const
364 DebugMsg(1, "ClusterSource::GetCluster(" << index << ")");
366 // Note NumberOfClusters() also checks if the event and block was selected.
367 Int_t numberofclusters = NumberOfClusters();
368 if (numberofclusters < 0) return NULL;
370 if ( 0 <= index and index < numberofclusters )
372 fClusterIndex = index;
373 fCurrentCluster = (Point*) fCurrentBlock->fClusters[index];
374 DebugMsg(2, "\tfEventIndex = " << fEventIndex << " , fBlockIndex = " << fBlockIndex
375 << " , fClusterIndex = " << fClusterIndex
377 return fCurrentCluster;
381 // The index is out of bounds so inform the user.
382 if (numberofclusters > 0)
384 "The cluster index (%d) is out of bounds. Valid range is [0, %d]",
385 index, numberofclusters - 1
389 "The cluster index (%d) is out of bounds. No clusters found.",
397 const Point* ClusterSource::GetFirstCluster() const
399 DebugMsg(1, "ClusterSource::GetFirstCluster()");
400 // Note: NumberOfClusters() also checks if fCurrentBlock != NULL.
401 if (NumberOfClusters() > 0)
404 fCurrentCluster = (Point*) fCurrentBlock->fClusters[0];
405 DebugMsg(2, "\tfEventIndex = " << fEventIndex << " , fBlockIndex = " << fBlockIndex
406 << " , fClusterIndex = " << fClusterIndex
408 return fCurrentCluster;
415 Bool_t ClusterSource::MoreClusters() const
417 return 0 <= fClusterIndex and fClusterIndex < NumberOfClusters();
421 const Point* ClusterSource::GetNextCluster() const
423 DebugMsg(1, "ClusterSource::GetNextCluster()");
425 // Note: NumberOfClusters() checks if fCurrentBlock != NULL. If it is then it returns -1
426 // and since fClusterIndex is always >= -1 the if statement must go to the else part.
427 if (fClusterIndex < NumberOfClusters() - 1)
429 fCurrentCluster = (Point*) fCurrentBlock->fClusters[ ++fClusterIndex ];
430 DebugMsg(2, "\tfEventIndex = " << fEventIndex << " , fBlockIndex = " << fBlockIndex
431 << " , fClusterIndex = " << fClusterIndex
433 return fCurrentCluster;
437 ResetClusterPointers();
443 Bool_t ClusterSource::FetchCluster(Float_t& x, Float_t& y) const
445 if (fCurrentCluster != NULL)
447 x = fCurrentCluster->fX;
448 y = fCurrentCluster->fY;
453 Error("FetchCluster", "No cluster point selected.");
459 void ClusterSource::AddEvent(Int_t eventnumber)
461 DebugMsg(1, "ClusterSource::AddEvent(" << eventnumber << ")");
462 Assert( eventnumber >= 0 );
464 // Assume the eventnumber does not already exist in the event list.
465 fEventIndex = fEventList.GetEntriesFast();
466 new ( fEventList[fEventIndex] ) EventData(eventnumber);
467 fCurrentEvent = (EventData*) fEventList[fEventIndex];
469 // Remember to reset the other pointers because the new event is empty.
470 ResetBlockPointers();
472 DebugMsg(2, "\tfEventIndex = " << fEventIndex << " , fBlockIndex = " << fBlockIndex
473 << " , fClusterIndex = " << fClusterIndex
478 void ClusterSource::AddBlock(Int_t chamber)
480 DebugMsg(1, "ClusterSource::AddBlock()");
482 if (fCurrentEvent == NULL)
484 Error("AddBlock", "No event selected.");
488 fBlockIndex = fCurrentEvent->fBlocks.GetEntriesFast();
489 new ( fCurrentEvent->fBlocks[fBlockIndex] ) BlockData(chamber);
490 fCurrentBlock = (BlockData*) fCurrentEvent->fBlocks[fBlockIndex];
492 // Remember to reset the trigger pointer because the new block is empty.
493 ResetClusterPointers();
495 DebugMsg(2, "\tfEventIndex = " << fEventIndex << " , fBlockIndex = " << fBlockIndex
496 << " , fClusterIndex = " << fClusterIndex
501 void ClusterSource::AddPoint(Float_t x, Float_t y)
503 DebugMsg(1, "ClusterSource::AddPoint(" << x << ", " << y << ")");
505 if (fCurrentBlock == NULL)
507 Error("AddPoint", "No block selected.");
511 fClusterIndex = fCurrentBlock->fClusters.GetEntriesFast();
512 new ( fCurrentBlock->fClusters[fClusterIndex] ) Point(x, y);
513 fCurrentCluster = (Point*) fCurrentBlock->fClusters[fClusterIndex];
515 DebugMsg(2, "\tfEventIndex = " << fEventIndex << " , fBlockIndex = " << fBlockIndex
516 << " , fClusterIndex = " << fClusterIndex
521 Bool_t ClusterSource::FileAndFolderOk(AliMUONDataInterface* data)
525 // Nothing filled yet so set the file and folder names.
526 fFilename = data->CurrentFile();
527 fFoldername = data->CurrentFolder();
531 if ( fFilename != data->CurrentFile() )
533 Error( "FileAndFolderOk",
534 "The cluster source already contains data from file '%s', cannot add data from file '%s'",
535 fFilename.Data(), data->CurrentFile().Data()
540 if ( fFoldername != data->CurrentFolder() )
542 Error( "FileAndFolderOk",
543 "The cluster source already contains data from folder '%s', cannot add data from folder '%s'",
544 fFoldername.Data(), data->CurrentFolder().Data()
553 void ClusterSource::AddEventFrom(AliMUONDataInterface* data, Int_t event)
555 if ( data->GetEvent(event) )
558 for (Int_t chamber = 0; chamber < AliMUONConstants::NTrackingCh(); chamber++)
560 AddChamberFrom(data, chamber);
566 void ClusterSource::AddChamberFrom(AliMUONDataInterface* data, Int_t chamber)
568 DebugMsg(1, "Entering AddChamberFrom");
571 UInt_t currentblocksize = 0;
574 Float_t x = NAN, y = NAN;
576 Float_t x = 0, y = 0;
579 Float_t x = FLT_QNAN, y = FLT_QNAN;
585 for (Int_t track = 0; track < data->NumberOfTracks(); track++)
587 // Find the hit that corresponds to the current chamber number.
589 for (i = 0; i < data->NumberOfHits(track); i++)
591 AliMUONHit* h = data->Hit(track, i);
592 // Note AliMUONHit::Chamber() returns a value in the range 1..14
593 if (h->Chamber() == chamber + 1)
601 // Continue to the next track if we could not find a hit
602 // on the current track and chamber.
603 if (i >= data->NumberOfHits(track))
605 Warning("AddChamberFrom", "Could not find hit on chamber: %d , track: %d , event: %d",
606 chamber, track, data->CurrentEvent()
611 if (InFillRegion(x, y))
615 // Create a new block if we reached the maximum block size.
616 if ( ++currentblocksize == fMaxBlockSize )
619 currentblocksize = 0;
625 case FromRawClusters:
626 for (Int_t i = 0; i < data->NumberOfRawClusters(chamber); i++)
628 AliMUONRawCluster* rc = data->RawCluster(chamber, i);
632 if (InFillRegion(x, y))
636 // Create a new block if we reached the maximum block size.
637 if ( ++currentblocksize == fMaxBlockSize )
640 currentblocksize = 0;
647 Error("AddChamberFrom", "fDataToUse is not set to a valid value.");
650 DebugMsg(1, "Leaving AddChamberFrom");
654 void ClusterSource::AddClusterFrom(
655 AliMUONDataInterface* data, Int_t chamber, Int_t cluster
658 DebugMsg(1, "Entering AddClusterFrom");
661 Float_t x = NAN, y = NAN;
663 Float_t x = 0, y = 0;
666 Float_t x = FLT_QNAN, y = FLT_QNAN;
674 // Note: cluster is now treated as the track number.
675 for (i = 0; i < data->NumberOfHits(cluster); i++)
677 AliMUONHit* h = data->Hit(cluster, i);
678 // Note AliMUONHit::Chamber() returns a value in the range 1..14
679 if (h->Chamber() == chamber + 1)
687 if (i >= data->NumberOfHits(cluster))
689 // Could not find a hit on the specified chamber so just return.
690 Warning("AddClusterFrom", "Could not find hit on chamber: %d , track: %d , event: %d",
691 chamber, cluster, data->CurrentEvent()
693 DebugMsg(1, "Leaving AddClusterFrom");
699 case FromRawClusters:
701 AliMUONRawCluster* rc = data->RawCluster(chamber, cluster);
708 Error("AddClusterFrom", "fDataToUse is not set to a valid value.");
714 DebugMsg(1, "Leaving AddClusterFrom");
718 Bool_t ClusterSource::InFillRegion(Float_t x, Float_t /*y*/)
722 case FromWholePlane: return kTRUE;
723 case FromLeftHalfPlane: return x <= 0;
724 case FromRightHalfPlane: return x > 0;
727 Error("InFillRegion", "fAreaToUse is not set to a valid value.");
733 void ClusterSource::ResetAllPointers() const
736 fCurrentEvent = NULL;
738 fCurrentBlock = NULL;
740 fCurrentCluster = NULL;
741 DebugMsg(2, "\tfEventIndex = " << fEventIndex << " , fBlockIndex = " << fBlockIndex
742 << " , fClusterIndex = " << fClusterIndex
747 void ClusterSource::ResetBlockPointers() const
750 fCurrentBlock = NULL;
752 fCurrentCluster = NULL;
753 DebugMsg(2, "\tfEventIndex = " << fEventIndex << " , fBlockIndex = " << fBlockIndex
754 << " , fClusterIndex = " << fClusterIndex
759 void ClusterSource::ResetClusterPointers() const
762 fCurrentCluster = NULL;
763 DebugMsg(2, "\tfEventIndex = " << fEventIndex << " , fBlockIndex = " << fBlockIndex
764 << " , fClusterIndex = " << fClusterIndex
769 ClusterSource::BlockData::BlockData() : fClusters(Point::Class())
774 ClusterSource::BlockData::BlockData(Int_t chamber) : fClusters(Point::Class())
779 ClusterSource::BlockData::~BlockData()
781 fClusters.Clear("C");
784 ClusterSource::EventData::EventData() : fBlocks(ClusterSource::BlockData::Class())
789 ClusterSource::EventData::EventData(Int_t eventnumber)
790 : fBlocks(ClusterSource::BlockData::Class())
792 fEventNumber = eventnumber;
794 // If the following is not set then we do not write the fBlocks properly.
795 fBlocks.BypassStreamer(kFALSE);
798 ClusterSource::EventData::~EventData()