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.
31 // m.SetName("OM123");
33 // Float_t pos[3]={1,2,3};
34 // m.SetPosition(pos,"car");
39 // s.SetName("OM123 Hit 1");
40 // s.SetSlotName("ADC");
42 // s.SetSlotName("LE",2);
43 // s.SetSignal(-100,2);
44 // s.SetSlotName("TOT",3);
45 // s.SetSignal(-1000,3);
49 // s.SetName("OM123 Hit 2");
50 // s.SetSlotName("ADC");
52 // s.SetSlotName("LE",2);
53 // s.SetSignal(-101,2);
54 // s.SetSlotName("TOT",3);
55 // s.SetSignal(1001,3);
59 // s.SetName("OM123 Hit 3");
60 // s.SetSlotName("ADC");
62 // s.SetSlotName("LE",2);
63 // s.SetSignal(-102,2);
64 // s.SetSlotName("TOT",3);
65 // s.SetSignal(-1002,3);
68 // TObjArray* ordered=m.SortHits("TOT");
69 // nhits=ordered->GetEntries();
70 // for (Int_t i=0; i<nhits; i++)
72 // AliSignal* sx=(AliSignal*)ordered->At(i);
73 // if (sx) sx->Data();
76 //--- Author: Nick van Eijndhoven 23-jun-2004 Utrecht University
77 //- Modified: NvE $Date$ Utrecht University
78 ///////////////////////////////////////////////////////////////////////////
80 #include "AliDevice.h"
81 #include "Riostream.h"
83 ClassImp(AliDevice) // Class implementation to enable ROOT I/O
85 AliDevice::AliDevice() : AliSignal()
87 // Default constructor.
88 // By default private copies of the recorded hits will be made.
89 // This implies that by default the device will own the registered hits.
90 // See the SetHitCopy() memberfunction for further details.
96 ///////////////////////////////////////////////////////////////////////////
97 AliDevice::~AliDevice()
99 // Default destructor.
101 // Remove backward links to this device from the hits
102 // which were not owned by it.
105 for (Int_t ih=1; ih<=GetNhits(); ih++)
107 AliSignal* sx=GetHit(ih);
108 if (sx) sx->ResetLinks(this);
130 ///////////////////////////////////////////////////////////////////////////
131 AliDevice::AliDevice(const AliDevice& dev) : AliSignal(dev)
139 fHitCopy=dev.GetHitCopy();
141 Int_t nhits=dev.GetNhits();
144 fHits=new TObjArray(nhits);
145 if (fHitCopy) fHits->SetOwner();
146 for (Int_t ih=1; ih<=nhits; ih++)
148 AliSignal* sx=dev.GetHit(ih);
151 fHits->Add(sx->Clone());
152 AliSignal* s=(AliSignal*)fHits->Last();
153 s->ResetLinks((AliDevice*)&dev);
164 ///////////////////////////////////////////////////////////////////////////
165 void AliDevice::Reset(Int_t mode)
167 // Reset registered hits and AliSignal attributes.
168 // See AliSignal::Reset() for further details.
170 AliSignal::Reset(mode);
172 ///////////////////////////////////////////////////////////////////////////
173 void AliDevice::SetHitCopy(Int_t j)
175 // (De)activate the creation of private copies of the AliSignals added as hits.
176 // j=0 ==> No private copies are made; pointers of original hits are stored.
177 // j=1 ==> Private copies of the hits are made and these pointers are stored.
179 // Note : Once the storage contains pointer(s) to hit(s) one cannot
180 // change the HitCopy mode anymore.
181 // To change the HitCopy mode for an existing AliDevice containing
182 // hits one first has to invoke either RemoveHits() or Reset().
191 cout << "*AliDevice::SetHitCopy* Invalid argument : " << j << endl;
196 cout << "*AliDevice::SetHitCopy* Storage already contained hits."
197 << " ==> HitCopy mode not changed." << endl;
200 ///////////////////////////////////////////////////////////////////////////
201 Int_t AliDevice::GetHitCopy() const
203 // Provide value of the HitCopy mode.
204 // 0 ==> No private copies are made; pointers of original hits are stored.
205 // 1 ==> Private copies of the hits are made and these pointers are stored.
208 ///////////////////////////////////////////////////////////////////////////
209 void AliDevice::AddHit(AliSignal& s)
211 // Register an AliSignal object as a hit to this device.
212 // Note : In case this device owns the AliSignal object, the pointer to
213 // this device will be stored in the special owning device
214 // pointer of the AliSignal object.
215 // In case this device does not own the AliSignal object, a (backward)
216 // link to this device is added to the first slot of the AliSignal
217 // if there was no link to this device already present.
221 fHits=new TObjArray(1);
222 if (fHitCopy) fHits->SetOwner();
225 // Check if this signal is already stored for this device.
226 Int_t nhits=GetNhits();
227 for (Int_t i=0; i<nhits; i++)
229 if (&s==fHits->At(i)) return;
232 // Check for existing (backward) link to this device.
233 Int_t nlinks=s.GetNlinks(this);
237 fHits->Add(s.Clone());
238 // Remove unnecessary backward link(s) from the various slots
239 // and set the owning link to this device
240 AliSignal* sx=(AliSignal*)fHits->Last();
241 if (nlinks) sx->ResetLinks(this);
247 // Set (backward) link to the this device
248 if (!nlinks) s.AddLink(this);
251 ///////////////////////////////////////////////////////////////////////////
252 void AliDevice::RemoveHit(AliSignal& s)
254 // Remove AliSignal object registered as a hit from this device.
257 AliSignal* test=(AliSignal*)fHits->Remove(&s);
261 if (fHitCopy) delete test;
266 AliSignal* test=(AliSignal*)fOrdered->Remove(&s);
267 if (test) fOrdered->Compress();
270 ///////////////////////////////////////////////////////////////////////////
271 void AliDevice::RemoveHits()
273 // Remove all AliSignal objects registered as hits from this device.
290 ///////////////////////////////////////////////////////////////////////////
291 Int_t AliDevice::GetNhits() const
293 // Provide the number of registered hits for this device.
295 if (fHits) nhits=fHits->GetEntries();
298 ///////////////////////////////////////////////////////////////////////////
299 AliSignal* AliDevice::GetHit(Int_t j) const
301 // Provide the AliSignal object registered as hit number j.
302 // Note : j=1 denotes the first hit.
303 if (!fHits) return 0;
305 if ((j >= 1) && (j <= GetNhits()))
307 return (AliSignal*)fHits->At(j-1);
314 ///////////////////////////////////////////////////////////////////////////
315 AliSignal* AliDevice::GetIdHit(Int_t id) const
317 // Return the hit with unique identifier "id".
318 if (!fHits || id<0) return 0;
322 for (Int_t i=0; i<GetNhits(); i++)
324 sx=(AliSignal*)fHits->At(i);
327 sid=sx->GetUniqueID();
328 if (id==sid) return sx;
331 return 0; // No matching id found
333 ///////////////////////////////////////////////////////////////////////////
334 TObjArray* AliDevice::GetHits()
336 // Provide the references to all the registered hits.
339 ///////////////////////////////////////////////////////////////////////////
340 void AliDevice::ShowHit(Int_t j) const
342 // Show data of the registered j-th hit.
343 // If j=0 all associated hits will be shown.
344 // The default is j=0.
347 Int_t nhits=GetNhits();
348 for (Int_t ih=1; ih<=nhits; ih++)
350 AliSignal* sx=GetHit(ih);
356 AliSignal* s=GetHit(j);
360 ///////////////////////////////////////////////////////////////////////////
361 void AliDevice::Data(TString f) const
363 // Print the device and all registered hit info according to the specified
366 Int_t nhits=GetNhits();
369 cout << " The following " << nhits << " hits are registered : " << endl;
374 cout << " No hits have been registered for this device." << endl;
377 ///////////////////////////////////////////////////////////////////////////
378 void AliDevice::GetExtremes(Float_t& vmin,Float_t& vmax,Int_t idx,TObjArray* hits) const
380 // Provide the min. and max. signal values of an array of hits.
381 // The input argument "idx" denotes the index of the signal slots to be investigated.
382 // The default is idx=1;
383 // In case hits=0 (default), the registered hits of the current device are used.
384 // Signals which were declared as "Dead" will be rejected.
385 // The gain etc... corrected signals will be used in the process.
390 if (!hits) hits=fHits;
392 if (idx<=0 || !hits) return;
394 Int_t nhits=hits->GetEntries();
397 for (Int_t i=0; i<nhits; i++)
399 AliSignal* sx=(AliSignal*)hits->At(i);
402 if (idx > sx->GetNvalues()) continue; // User specified slotindex out of range for this signal
403 if (sx->GetDeadValue(idx)) continue; // Only take alive signals
405 sig=sx->GetSignal(idx,1);
413 if (sig<vmin) vmin=sig;
414 if (sig>vmax) vmax=sig;
418 ///////////////////////////////////////////////////////////////////////////
419 void AliDevice::GetExtremes(Float_t& vmin,Float_t& vmax,TString name,TObjArray* hits) const
421 // Provide the min. and max. signal values of an array of hits.
422 // The input argument "name" denotes the name of the signal slots to be investigated.
423 // In case hits=0 (default), the registered hits of the current device are used.
424 // Signals which were declared as "Dead" will be rejected.
425 // The gain etc... corrected signals will be used in the process.
430 if (!hits) hits=fHits;
434 Int_t nhits=hits->GetEntries();
436 Int_t idx=0; // The signal slotindex to perform the sorting on
439 for (Int_t i=0; i<nhits; i++)
441 AliSignal* sx=(AliSignal*)hits->At(i);
445 // Obtain the slotindex corresponding to the user selection
446 idx=sx->GetSlotIndex(name);
449 if (sx->GetDeadValue(idx)) continue; // Only take alive signals
451 sig=sx->GetSignal(idx,1);
459 if (sig<vmin) vmin=sig;
460 if (sig>vmax) vmax=sig;
464 ///////////////////////////////////////////////////////////////////////////
465 TObjArray* AliDevice::SortHits(Int_t idx,Int_t mode,TObjArray* hits)
467 // Order the references to an array of hits by looping over the input array "hits"
468 // and checking the signal value. The ordered array is returned as a TObjArray.
469 // In case hits=0 (default), the registered hits of the current device are used.
470 // Note that the original hit array is not modified.
471 // A "hit" represents an abstract object which is derived from AliSignal.
472 // The user can specify the index of the signal slot to perform the sorting on.
473 // By default the slotindex will be 1.
474 // Via the "mode" argument the user can specify ordering in decreasing
475 // order (mode=-1) or ordering in increasing order (mode=1).
476 // The default is mode=-1.
477 // Signals which were declared as "Dead" will be rejected.
478 // The gain etc... corrected signals will be used in the ordering process.
486 if (!hits) hits=fHits;
488 if (idx<=0 || abs(mode)!=1 || !hits) return fOrdered;
490 Int_t nhits=hits->GetEntries();
497 fOrdered=new TObjArray(nhits);
501 for (Int_t i=0; i<nhits; i++) // Loop over all hits of the array
503 AliSignal* s=(AliSignal*)hits->At(i);
507 if (idx > s->GetNvalues()) continue; // User specified slotindex out of range for this signal
508 if (s->GetDeadValue(idx)) continue; // Only take alive signals
510 if (nord == 0) // store the first hit with a signal at the first ordered position
513 fOrdered->AddAt(s,nord-1);
517 for (Int_t j=0; j<=nord; j++) // put hit in the right ordered position
519 if (j == nord) // module has smallest (mode=-1) or largest (mode=1) signal seen so far
522 fOrdered->AddAt(s,j); // add hit at the end
523 break; // go for next hit
526 if (mode==-1 && s->GetSignal(idx,1) < ((AliSignal*)fOrdered->At(j))->GetSignal(idx,1)) continue;
527 if (mode==1 && s->GetSignal(idx,1) > ((AliSignal*)fOrdered->At(j))->GetSignal(idx,1)) continue;
530 for (Int_t k=nord-1; k>j; k--) // create empty position
532 fOrdered->AddAt(fOrdered->At(k-1),k);
534 fOrdered->AddAt(s,j); // put hit at empty position
535 break; // go for next matrix module
540 ///////////////////////////////////////////////////////////////////////////
541 TObjArray* AliDevice::SortHits(TString name,Int_t mode,TObjArray* hits)
543 // Order the references to an array of hits by looping over the input array "hits"
544 // and checking the signal value. The ordered array is returned as a TObjArray.
545 // In case hits=0 (default), the registered hits of the current device are used.
546 // Note that the input array is not modified.
547 // A "hit" represents an abstract object which is derived from AliSignal.
548 // The user can specify the name of the signal slot to perform the sorting on.
549 // In case no matching slotname is found, the signal will be skipped.
550 // Via the "mode" argument the user can specify ordering in decreasing
551 // order (mode=-1) or ordering in increasing order (mode=1).
552 // The default is mode=-1.
553 // Signals which were declared as "Dead" will be rejected.
554 // The gain etc... corrected signals will be used in the ordering process.
562 if (!hits) hits=fHits;
564 if (abs(mode)!=1 || !hits) return fOrdered;
566 Int_t nhits=hits->GetEntries();
573 fOrdered=new TObjArray(nhits);
576 Int_t idx=0; // The signal slotindex to perform the sorting on
579 for (Int_t i=0; i<nhits; i++) // loop over all hits of the array
581 AliSignal* s=(AliSignal*)hits->At(i);
585 // Obtain the slotindex corresponding to the user selection
586 idx=s->GetSlotIndex(name);
589 if (s->GetDeadValue(idx)) continue; // only take alive signals
591 if (nord == 0) // store the first hit with a signal at the first ordered position
594 fOrdered->AddAt(s,nord-1);
598 for (Int_t j=0; j<=nord; j++) // put hit in the right ordered position
600 if (j == nord) // module has smallest (mode=-1) or largest (mode=1) signal seen so far
603 fOrdered->AddAt(s,j); // add hit at the end
604 break; // go for next hit
607 if (mode==-1 && s->GetSignal(idx,1) < ((AliSignal*)fOrdered->At(j))->GetSignal(idx,1)) continue;
608 if (mode==1 && s->GetSignal(idx,1) > ((AliSignal*)fOrdered->At(j))->GetSignal(idx,1)) continue;
611 for (Int_t k=nord-1; k>j; k--) // create empty position
613 fOrdered->AddAt(fOrdered->At(k-1),k);
615 fOrdered->AddAt(s,j); // put hit at empty position
616 break; // go for next matrix module
621 ///////////////////////////////////////////////////////////////////////////
622 void AliDevice::DisplayHits(Int_t idx,Float_t scale,TObjArray* hits,Int_t dp,Int_t mstyle,Int_t mcol)
624 // 3D color display of an array hits.
625 // The user can specify the index (default=1) of the signal slot to perform the display for.
626 // The marker size will indicate the absolute value of the signal (specified by the slotindex)
627 // as a percentage of the input argument "scale".
628 // In case scale<0 the maximum absolute signal value encountered in the hit array will be used
629 // to define the 100% scale. The default is scale=-1.
630 // In case hits=0 (default), the registered hits of the current device are used.
631 // Note that the input array is not modified.
632 // In case dp=1 the device position will be used, otherwise the hit position will
633 // be used in the display. The default is dp=0.
634 // Via the "mstyle" and "mcol" arguments the user can specify the marker style
635 // and color (see TPolyMarker3D) respectively.
636 // The defaults are mstyle="large scalable dot" and mcol=blue.
637 // Signals which were declared as "Dead" will not be displayed.
638 // The gain etc... corrected signals will be used to determine the marker size.
642 // Before any display activity, a TCanvas and a TView have to be initiated
643 // first by the user like for instance
645 // TCanvas* c1=new TCanvas("c1","c1");
646 // TView* view=new TView(1);
647 // view->SetRange(-1000,-1000,-1000,1000,1000,1000);
650 Int_t thisdev=0; // Indicate whether this is the owning device or not
657 if (idx<=0 || !hits) return;
659 Int_t nhits=hits->GetEntries();
662 Float_t sigmax=fabs(scale);
666 GetExtremes(vmin,vmax,idx,hits);
668 if (fabs(vmin)>sigmax) sigmax=fabs(vmin);
671 if (sigmax <=0) return;
678 fMarkers=new TObjArray(nhits);
679 fMarkers->SetOwner();
682 GetPosition(pos,"car");
685 for (Int_t ih=0; ih<nhits; ih++)
687 AliSignal* sx=(AliSignal*)hits->At(ih);
691 sx->GetPosition(pos,"car");
697 AliDevice* dev=sx->GetDevice();
698 if (dev) dev->GetPosition(pos,"car");
701 sig=sx->GetSignal(idx,1);
702 TPolyMarker3D* m=new TPolyMarker3D();
703 m->SetMarkerStyle(mstyle);
704 m->SetMarkerColor(mcol);
705 m->SetMarkerSize(100.*fabs(sig)/sigmax);
706 m->SetPoint(0,pos[0],pos[1],pos[2]);
711 ///////////////////////////////////////////////////////////////////////////
712 void AliDevice::DisplayHits(TString name,Float_t scale,TObjArray* hits,Int_t dp,Int_t mstyle,Int_t mcol)
714 // 3D color display of an array hits.
715 // The user can specify the name of the signal slot to perform the display for.
716 // The marker size will indicate the absolute value of the signal (specified by the slotname)
717 // as a percentage of the input argument "scale".
718 // In case scale<0 the maximum absolute signal value encountered in the hit array will be used
719 // to define the 100% scale. The default is scale=-1.
720 // In case hits=0 (default), the registered hits of the current device are used.
721 // Note that the input array is not modified.
722 // In case dp=1 the device position will be used, otherwise the hit position will
723 // be used in the display. The default is dp=0.
724 // The marker size will indicate the percentage of the maximum encountered value
725 // of the absolute value of the name-specified input signal slots.
726 // Via the "mstyle" and "mcol" arguments the user can specify the marker style
727 // and color (see TPolyMarker3D) respectively.
728 // The defaults are mstyle="large scalable dot" and mcol=blue.
729 // Signals which were declared as "Dead" will not be displayed.
730 // The gain etc... corrected signals will be used to determine the marker size.
734 // Before any display activity, a TCanvas and a TView have to be initiated
735 // first by the user like for instance
737 // TCanvas* c1=new TCanvas("c1","c1");
738 // TView* view=new TView(1);
739 // view->SetRange(-1000,-1000,-1000,1000,1000,1000);
742 Int_t thisdev=0; // Indicate whether this is the owning device or not
751 Int_t nhits=hits->GetEntries();
755 Float_t sigmax=fabs(scale);
759 GetExtremes(vmin,vmax,name,hits);
761 if (fabs(vmin)>sigmax) sigmax=fabs(vmin);
764 if (sigmax <=0) return;
771 fMarkers=new TObjArray(nhits);
772 fMarkers->SetOwner();
775 GetPosition(pos,"car");
777 Int_t idx=0; // The slot index corresponding to the user specified name
779 for (Int_t ih=0; ih<nhits; ih++)
781 AliSignal* sx=(AliSignal*)hits->At(ih);
783 idx=sx->GetSlotIndex(name);
787 sx->GetPosition(pos,"car");
793 AliDevice* dev=sx->GetDevice();
794 if (dev) dev->GetPosition(pos,"car");
797 sig=sx->GetSignal(idx,1);
798 TPolyMarker3D* m=new TPolyMarker3D();
799 m->SetMarkerStyle(mstyle);
800 m->SetMarkerColor(mcol);
801 m->SetMarkerSize(100.*fabs(sig)/sigmax);
802 m->SetPoint(0,pos[0],pos[1],pos[2]);
807 ///////////////////////////////////////////////////////////////////////////
808 TObject* AliDevice::Clone(const char* name) const
810 // Make a deep copy of the current object and provide the pointer to the copy.
811 // This memberfunction enables automatic creation of new objects of the
812 // correct type depending on the object type, a feature which may be very useful
813 // for containers like AliEvent when adding objects in case the
814 // container owns the objects. This feature allows e.g. AliEvent
815 // to store either AliDevice objects or objects derived from AliDevice
816 // via tha AddDevice memberfunction, provided these derived classes also have
817 // a proper Clone memberfunction.
819 AliDevice* dev=new AliDevice(*this);
822 if (strlen(name)) dev->SetName(name);
826 ///////////////////////////////////////////////////////////////////////////