1 /**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
7 * Permission to use, copy, modify and distribute this software and its *
8 * documentation strictly for non-commercial purposes is hereby granted *
9 * without fee, provided that the above copyright notice appears in all *
10 * copies and that both the copyright notice and this permission notice *
11 * appear in the supporting documentation. The authors make no claims *
12 * about the suitability of this software for any purpose. It is *
13 * provided "as is" without express or implied warranty. *
14 **************************************************************************/
18 ///////////////////////////////////////////////////////////////////////////
20 // Signal (Hit) handling of a generic device.
21 // Basically this class provides a user interface to group and handle
22 // various instances of AliSignal objects, called generically "hits".
23 // An AliDevice object itself has (in addition to hit storage) also the
24 // complete functionality of the class AliSignal.
30 // // Set user defined status word to indicate e.g. readout electronics version
31 // m.SetStatus(100201);
33 // m.SetName("OM123");
35 // Float_t pos[3]={1,2,3};
36 // m.SetPosition(pos,"car");
41 // s.SetName("OM123 Hit 1");
42 // s.SetSlotName("ADC");
44 // s.SetSlotName("LE",2);
45 // s.SetSignal(-100,2);
46 // s.SetSlotName("TOT",3);
47 // s.SetSignal(-1000,3);
51 // s.SetName("OM123 Hit 2");
52 // s.SetSlotName("ADC");
54 // s.SetSlotName("LE",2);
55 // s.SetSignal(-101,2);
56 // s.SetSlotName("TOT",3);
57 // s.SetSignal(1001,3);
61 // s.SetName("OM123 Hit 3");
62 // s.SetSlotName("ADC");
64 // s.SetSlotName("LE",2);
65 // s.SetSignal(-102,2);
66 // s.SetSlotName("TOT",3);
67 // s.SetSignal(-1002,3);
70 // TObjArray* ordered=m.SortHits("TOT");
71 // nhits=ordered->GetEntries();
72 // for (Int_t i=0; i<nhits; i++)
74 // AliSignal* sx=(AliSignal*)ordered->At(i);
75 // if (sx) sx->Data();
78 //--- Author: Nick van Eijndhoven 23-jun-2004 Utrecht University
79 //- Modified: NvE $Date$ Utrecht University
80 ///////////////////////////////////////////////////////////////////////////
82 #include "AliDevice.h"
83 #include "Riostream.h"
85 ClassImp(AliDevice) // Class implementation to enable ROOT I/O
87 AliDevice::AliDevice() : AliSignal()
89 // Default constructor.
90 // The user definable status word is set to zero.
91 // By default private copies of the recorded hits will be made.
92 // This implies that by default the device will own the registered hits.
93 // See the SetHitCopy() memberfunction for further details.
100 ///////////////////////////////////////////////////////////////////////////
101 AliDevice::~AliDevice()
103 // Default destructor.
105 // Remove backward links to this device from the hits
106 // which were not owned by it.
109 for (Int_t ih=1; ih<=GetNhits(); ih++)
111 AliSignal* sx=GetHit(ih);
112 if (sx) sx->ResetLinks(this);
134 ///////////////////////////////////////////////////////////////////////////
135 AliDevice::AliDevice(const AliDevice& dev) : AliSignal(dev)
143 fStatus=dev.GetStatus();
144 fHitCopy=dev.GetHitCopy();
146 Int_t nhits=dev.GetNhits();
149 fHits=new TObjArray(nhits);
150 if (fHitCopy) fHits->SetOwner();
151 for (Int_t ih=1; ih<=nhits; ih++)
153 AliSignal* sx=dev.GetHit(ih);
156 fHits->Add(sx->Clone());
157 AliSignal* s=(AliSignal*)fHits->Last();
158 s->ResetLinks((AliDevice*)&dev);
169 ///////////////////////////////////////////////////////////////////////////
170 void AliDevice::Reset(Int_t mode)
172 // Reset registered hits and AliSignal attributes.
173 // Note : The status word and HitCopy flag are NOT modified.
174 // Use SetStatus() and SetHitCopy() to modify these parameters.
175 // See AliSignal::Reset() for further details.
177 AliSignal::Reset(mode);
179 ///////////////////////////////////////////////////////////////////////////
180 void AliDevice::SetHitCopy(Int_t j)
182 // (De)activate the creation of private copies of the AliSignals added as hits.
183 // j=0 ==> No private copies are made; pointers of original hits are stored.
184 // j=1 ==> Private copies of the hits are made and these pointers are stored.
186 // Note : Once the storage contains pointer(s) to hit(s) one cannot
187 // change the HitCopy mode anymore.
188 // To change the HitCopy mode for an existing AliDevice containing
189 // hits one first has to invoke either RemoveHits() or Reset().
198 cout << "*AliDevice::SetHitCopy* Invalid argument : " << j << endl;
203 cout << "*AliDevice::SetHitCopy* Storage already contained hits."
204 << " ==> HitCopy mode not changed." << endl;
207 ///////////////////////////////////////////////////////////////////////////
208 Int_t AliDevice::GetHitCopy() const
210 // Provide value of the HitCopy mode.
211 // 0 ==> No private copies are made; pointers of original hits are stored.
212 // 1 ==> Private copies of the hits are made and these pointers are stored.
215 ///////////////////////////////////////////////////////////////////////////
216 void AliDevice::SetStatus(Int_t word)
218 // Set a user defined status word for this device.
221 ///////////////////////////////////////////////////////////////////////////
222 Int_t AliDevice::GetStatus() const
224 // Provide the user defined status word for this device.
227 ///////////////////////////////////////////////////////////////////////////
228 void AliDevice::AddHit(AliSignal& s)
230 // Register an AliSignal object as a hit to this device.
231 // Note : In case this device owns the AliSignal object, the pointer to
232 // this device will be stored in the special owning device
233 // pointer of the AliSignal object.
234 // In case this device does not own the AliSignal object, a (backward)
235 // link to this device is added to the first slot of the AliSignal
236 // if there was no link to this device already present.
240 fHits=new TObjArray(1);
241 if (fHitCopy) fHits->SetOwner();
244 // Check if this signal is already stored for this device.
245 Int_t nhits=GetNhits();
246 for (Int_t i=0; i<nhits; i++)
248 if (&s==fHits->At(i)) return;
251 // Check for existing (backward) link to this device.
252 Int_t nlinks=s.GetNlinks(this);
256 fHits->Add(s.Clone());
257 // Remove unnecessary backward link(s) from the various slots
258 // and set the owning link to this device
259 AliSignal* sx=(AliSignal*)fHits->Last();
260 if (nlinks) sx->ResetLinks(this);
266 // Set (backward) link to the this device
267 if (!nlinks) s.AddLink(this);
270 ///////////////////////////////////////////////////////////////////////////
271 void AliDevice::RemoveHit(AliSignal& s)
273 // Remove AliSignal object registered as a hit from this device.
276 AliSignal* test=(AliSignal*)fHits->Remove(&s);
280 if (fHitCopy) delete test;
285 AliSignal* test=(AliSignal*)fOrdered->Remove(&s);
286 if (test) fOrdered->Compress();
289 ///////////////////////////////////////////////////////////////////////////
290 void AliDevice::RemoveHits()
292 // Remove all AliSignal objects registered as hits from this device.
309 ///////////////////////////////////////////////////////////////////////////
310 Int_t AliDevice::GetNhits() const
312 // Provide the number of registered hits for this device.
314 if (fHits) nhits=fHits->GetEntries();
317 ///////////////////////////////////////////////////////////////////////////
318 AliSignal* AliDevice::GetHit(Int_t j) const
320 // Provide the AliSignal object registered as hit number j.
321 // Note : j=1 denotes the first hit.
322 if (!fHits) return 0;
324 if ((j >= 1) && (j <= GetNhits()))
326 return (AliSignal*)fHits->At(j-1);
333 ///////////////////////////////////////////////////////////////////////////
334 AliSignal* AliDevice::GetIdHit(Int_t id) const
336 // Return the hit with unique identifier "id".
337 if (!fHits || id<0) return 0;
341 for (Int_t i=0; i<GetNhits(); i++)
343 sx=(AliSignal*)fHits->At(i);
346 sid=sx->GetUniqueID();
347 if (id==sid) return sx;
350 return 0; // No matching id found
352 ///////////////////////////////////////////////////////////////////////////
353 TObjArray* AliDevice::GetHits()
355 // Provide the references to all the registered hits.
358 ///////////////////////////////////////////////////////////////////////////
359 void AliDevice::ShowHit(Int_t j) const
361 // Show data of the registered j-th hit.
362 // If j=0 all associated hits will be shown.
363 // The default is j=0.
366 Int_t nhits=GetNhits();
367 for (Int_t ih=1; ih<=nhits; ih++)
369 AliSignal* sx=GetHit(ih);
375 AliSignal* s=GetHit(j);
379 ///////////////////////////////////////////////////////////////////////////
380 void AliDevice::Data(TString f) const
382 // Print the device and all registered hit info according to the specified
385 Int_t nhits=GetNhits();
388 cout << " The following " << nhits << " hits are registered : " << endl;
393 cout << " No hits have been registered for this device." << endl;
396 ///////////////////////////////////////////////////////////////////////////
397 void AliDevice::GetExtremes(Float_t& vmin,Float_t& vmax,Int_t idx,TObjArray* hits) const
399 // Provide the min. and max. signal values of an array of hits.
400 // The input argument "idx" denotes the index of the signal slots to be investigated.
401 // The default is idx=1;
402 // In case hits=0 (default), the registered hits of the current device are used.
403 // Signals which were declared as "Dead" will be rejected.
404 // The gain etc... corrected signals will be used in the process.
409 if (!hits) hits=fHits;
411 if (idx<=0 || !hits) return;
413 Int_t nhits=hits->GetEntries();
416 for (Int_t i=0; i<nhits; i++)
418 AliSignal* sx=(AliSignal*)hits->At(i);
421 if (idx > sx->GetNvalues()) continue; // User specified slotindex out of range for this signal
422 if (sx->GetDeadValue(idx)) continue; // Only take alive signals
424 sig=sx->GetSignal(idx,1);
432 if (sig<vmin) vmin=sig;
433 if (sig>vmax) vmax=sig;
437 ///////////////////////////////////////////////////////////////////////////
438 void AliDevice::GetExtremes(Float_t& vmin,Float_t& vmax,TString name,TObjArray* hits) const
440 // Provide the min. and max. signal values of an array of hits.
441 // The input argument "name" denotes the name of the signal slots to be investigated.
442 // In case hits=0 (default), the registered hits of the current device are used.
443 // Signals which were declared as "Dead" will be rejected.
444 // The gain etc... corrected signals will be used in the process.
449 if (!hits) hits=fHits;
453 Int_t nhits=hits->GetEntries();
455 Int_t idx=0; // The signal slotindex to perform the sorting on
458 for (Int_t i=0; i<nhits; i++)
460 AliSignal* sx=(AliSignal*)hits->At(i);
464 // Obtain the slotindex corresponding to the user selection
465 idx=sx->GetSlotIndex(name);
468 if (sx->GetDeadValue(idx)) continue; // Only take alive signals
470 sig=sx->GetSignal(idx,1);
478 if (sig<vmin) vmin=sig;
479 if (sig>vmax) vmax=sig;
483 ///////////////////////////////////////////////////////////////////////////
484 TObjArray* AliDevice::SortHits(Int_t idx,Int_t mode,TObjArray* hits)
486 // Order the references to an array of hits by looping over the input array "hits"
487 // and checking the signal value. The ordered array is returned as a TObjArray.
488 // In case hits=0 (default), the registered hits of the current device are used.
489 // Note that the original hit array is not modified.
490 // A "hit" represents an abstract object which is derived from AliSignal.
491 // The user can specify the index of the signal slot to perform the sorting on.
492 // By default the slotindex will be 1.
493 // Via the "mode" argument the user can specify ordering in decreasing
494 // order (mode=-1) or ordering in increasing order (mode=1).
495 // The default is mode=-1.
496 // Signals which were declared as "Dead" will be rejected.
497 // The gain etc... corrected signals will be used in the ordering process.
505 if (!hits) hits=fHits;
507 if (idx<=0 || abs(mode)!=1 || !hits) return fOrdered;
509 Int_t nhits=hits->GetEntries();
516 fOrdered=new TObjArray(nhits);
520 for (Int_t i=0; i<nhits; i++) // Loop over all hits of the array
522 AliSignal* s=(AliSignal*)hits->At(i);
526 if (idx > s->GetNvalues()) continue; // User specified slotindex out of range for this signal
527 if (s->GetDeadValue(idx)) continue; // Only take alive signals
529 if (nord == 0) // store the first hit with a signal at the first ordered position
532 fOrdered->AddAt(s,nord-1);
536 for (Int_t j=0; j<=nord; j++) // put hit in the right ordered position
538 if (j == nord) // module has smallest (mode=-1) or largest (mode=1) signal seen so far
541 fOrdered->AddAt(s,j); // add hit at the end
542 break; // go for next hit
545 if (mode==-1 && s->GetSignal(idx,1) < ((AliSignal*)fOrdered->At(j))->GetSignal(idx,1)) continue;
546 if (mode==1 && s->GetSignal(idx,1) > ((AliSignal*)fOrdered->At(j))->GetSignal(idx,1)) continue;
549 for (Int_t k=nord-1; k>j; k--) // create empty position
551 fOrdered->AddAt(fOrdered->At(k-1),k);
553 fOrdered->AddAt(s,j); // put hit at empty position
554 break; // go for next matrix module
559 ///////////////////////////////////////////////////////////////////////////
560 TObjArray* AliDevice::SortHits(TString name,Int_t mode,TObjArray* hits)
562 // Order the references to an array of hits by looping over the input array "hits"
563 // and checking the signal value. The ordered array is returned as a TObjArray.
564 // In case hits=0 (default), the registered hits of the current device are used.
565 // Note that the input array is not modified.
566 // A "hit" represents an abstract object which is derived from AliSignal.
567 // The user can specify the name of the signal slot to perform the sorting on.
568 // In case no matching slotname is found, the signal will be skipped.
569 // Via the "mode" argument the user can specify ordering in decreasing
570 // order (mode=-1) or ordering in increasing order (mode=1).
571 // The default is mode=-1.
572 // Signals which were declared as "Dead" will be rejected.
573 // The gain etc... corrected signals will be used in the ordering process.
581 if (!hits) hits=fHits;
583 if (abs(mode)!=1 || !hits) return fOrdered;
585 Int_t nhits=hits->GetEntries();
592 fOrdered=new TObjArray(nhits);
595 Int_t idx=0; // The signal slotindex to perform the sorting on
598 for (Int_t i=0; i<nhits; i++) // loop over all hits of the array
600 AliSignal* s=(AliSignal*)hits->At(i);
604 // Obtain the slotindex corresponding to the user selection
605 idx=s->GetSlotIndex(name);
608 if (s->GetDeadValue(idx)) continue; // only take alive signals
610 if (nord == 0) // store the first hit with a signal at the first ordered position
613 fOrdered->AddAt(s,nord-1);
617 for (Int_t j=0; j<=nord; j++) // put hit in the right ordered position
619 if (j == nord) // module has smallest (mode=-1) or largest (mode=1) signal seen so far
622 fOrdered->AddAt(s,j); // add hit at the end
623 break; // go for next hit
626 if (mode==-1 && s->GetSignal(idx,1) < ((AliSignal*)fOrdered->At(j))->GetSignal(idx,1)) continue;
627 if (mode==1 && s->GetSignal(idx,1) > ((AliSignal*)fOrdered->At(j))->GetSignal(idx,1)) continue;
630 for (Int_t k=nord-1; k>j; k--) // create empty position
632 fOrdered->AddAt(fOrdered->At(k-1),k);
634 fOrdered->AddAt(s,j); // put hit at empty position
635 break; // go for next matrix module
640 ///////////////////////////////////////////////////////////////////////////
641 void AliDevice::DisplayHits(Int_t idx,Float_t scale,TObjArray* hits,Int_t dp,Int_t mstyle,Int_t mcol)
643 // 3D color display of an array hits.
644 // The user can specify the index (default=1) of the signal slot to perform the display for.
645 // The marker size will indicate the absolute value of the signal (specified by the slotindex)
646 // as a percentage of the input argument "scale".
647 // In case scale<0 the maximum absolute signal value encountered in the hit array will be used
648 // to define the 100% scale. The default is scale=-1.
649 // In case hits=0 (default), the registered hits of the current device are used.
650 // Note that the input array is not modified.
651 // In case dp=1 the device position will be used, otherwise the hit position will
652 // be used in the display. The default is dp=0.
653 // Via the "mstyle" and "mcol" arguments the user can specify the marker style
654 // and color (see TPolyMarker3D) respectively.
655 // The defaults are mstyle="large scalable dot" and mcol=blue.
656 // Signals which were declared as "Dead" will not be displayed.
657 // The gain etc... corrected signals will be used to determine the marker size.
661 // Before any display activity, a TCanvas and a TView have to be initiated
662 // first by the user like for instance
664 // TCanvas* c1=new TCanvas("c1","c1");
665 // TView* view=new TView(1);
666 // view->SetRange(-1000,-1000,-1000,1000,1000,1000);
669 Int_t thisdev=0; // Indicate whether this is the owning device or not
676 if (idx<=0 || !hits) return;
678 Int_t nhits=hits->GetEntries();
681 Float_t sigmax=fabs(scale);
685 GetExtremes(vmin,vmax,idx,hits);
687 if (fabs(vmin)>sigmax) sigmax=fabs(vmin);
690 if (sigmax <=0) return;
697 fMarkers=new TObjArray(nhits);
698 fMarkers->SetOwner();
701 GetPosition(pos,"car");
704 for (Int_t ih=0; ih<nhits; ih++)
706 AliSignal* sx=(AliSignal*)hits->At(ih);
710 sx->GetPosition(pos,"car");
716 AliDevice* dev=sx->GetDevice();
717 if (dev) dev->GetPosition(pos,"car");
720 sig=sx->GetSignal(idx,1);
721 TPolyMarker3D* m=new TPolyMarker3D();
722 m->SetMarkerStyle(mstyle);
723 m->SetMarkerColor(mcol);
724 m->SetMarkerSize(100.*fabs(sig)/sigmax);
725 m->SetPoint(0,pos[0],pos[1],pos[2]);
730 ///////////////////////////////////////////////////////////////////////////
731 void AliDevice::DisplayHits(TString name,Float_t scale,TObjArray* hits,Int_t dp,Int_t mstyle,Int_t mcol)
733 // 3D color display of an array hits.
734 // The user can specify the name of the signal slot to perform the display for.
735 // The marker size will indicate the absolute value of the signal (specified by the slotname)
736 // as a percentage of the input argument "scale".
737 // In case scale<0 the maximum absolute signal value encountered in the hit array will be used
738 // to define the 100% scale. The default is scale=-1.
739 // In case hits=0 (default), the registered hits of the current device are used.
740 // Note that the input array is not modified.
741 // In case dp=1 the device position will be used, otherwise the hit position will
742 // be used in the display. The default is dp=0.
743 // The marker size will indicate the percentage of the maximum encountered value
744 // of the absolute value of the name-specified input signal slots.
745 // Via the "mstyle" and "mcol" arguments the user can specify the marker style
746 // and color (see TPolyMarker3D) respectively.
747 // The defaults are mstyle="large scalable dot" and mcol=blue.
748 // Signals which were declared as "Dead" will not be displayed.
749 // The gain etc... corrected signals will be used to determine the marker size.
753 // Before any display activity, a TCanvas and a TView have to be initiated
754 // first by the user like for instance
756 // TCanvas* c1=new TCanvas("c1","c1");
757 // TView* view=new TView(1);
758 // view->SetRange(-1000,-1000,-1000,1000,1000,1000);
761 Int_t thisdev=0; // Indicate whether this is the owning device or not
770 Int_t nhits=hits->GetEntries();
774 Float_t sigmax=fabs(scale);
778 GetExtremes(vmin,vmax,name,hits);
780 if (fabs(vmin)>sigmax) sigmax=fabs(vmin);
783 if (sigmax <=0) return;
790 fMarkers=new TObjArray(nhits);
791 fMarkers->SetOwner();
794 GetPosition(pos,"car");
796 Int_t idx=0; // The slot index corresponding to the user specified name
798 for (Int_t ih=0; ih<nhits; ih++)
800 AliSignal* sx=(AliSignal*)hits->At(ih);
802 idx=sx->GetSlotIndex(name);
806 sx->GetPosition(pos,"car");
812 AliDevice* dev=sx->GetDevice();
813 if (dev) dev->GetPosition(pos,"car");
816 sig=sx->GetSignal(idx,1);
817 TPolyMarker3D* m=new TPolyMarker3D();
818 m->SetMarkerStyle(mstyle);
819 m->SetMarkerColor(mcol);
820 m->SetMarkerSize(100.*fabs(sig)/sigmax);
821 m->SetPoint(0,pos[0],pos[1],pos[2]);
826 ///////////////////////////////////////////////////////////////////////////
827 TObject* AliDevice::Clone(const char* name) const
829 // Make a deep copy of the current object and provide the pointer to the copy.
830 // This memberfunction enables automatic creation of new objects of the
831 // correct type depending on the object type, a feature which may be very useful
832 // for containers like AliEvent when adding objects in case the
833 // container owns the objects. This feature allows e.g. AliEvent
834 // to store either AliDevice objects or objects derived from AliDevice
835 // via tha AddDevice memberfunction, provided these derived classes also have
836 // a proper Clone memberfunction.
838 AliDevice* dev=new AliDevice(*this);
841 if (strlen(name)) dev->SetName(name);
845 ///////////////////////////////////////////////////////////////////////////