]> git.uio.no Git - u/mrichter/AliRoot.git/blob - RALICE/AliDevice.cxx
Message commented out
[u/mrichter/AliRoot.git] / RALICE / AliDevice.cxx
1 /**************************************************************************
2  * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
3  *                                                                        *
4  * Author: The ALICE Off-line 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. 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  **************************************************************************/
15
16 // $Id$
17
18 ///////////////////////////////////////////////////////////////////////////
19 // Class AliDevice
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.
25 //
26 // Example :
27 // =========
28 //
29 // AliDevice m;
30 // m.SetHitCopy(1);
31 // m.SetName("OM123");
32 //
33 // Float_t pos[3]={1,2,3};
34 // m.SetPosition(pos,"car");
35 //
36 // AliSignal s;
37 //
38 // s.Reset(1);
39 // s.SetName("OM123 Hit 1");
40 // s.SetSlotName("ADC");
41 // s.SetSignal(10);
42 // s.SetSlotName("LE",2);
43 // s.SetSignal(-100,2);
44 // s.SetSlotName("TOT",3);
45 // s.SetSignal(-1000,3);
46 // m.AddHit(s);
47 //
48 // s.Reset(1);
49 // s.SetName("OM123 Hit 2");
50 // s.SetSlotName("ADC");
51 // s.SetSignal(11);
52 // s.SetSlotName("LE",2);
53 // s.SetSignal(-101,2);
54 // s.SetSlotName("TOT",3);
55 // s.SetSignal(1001,3);
56 // m.AddHit(s);
57 //
58 // s.Reset(1);
59 // s.SetName("OM123 Hit 3");
60 // s.SetSlotName("ADC");
61 // s.SetSignal(12);
62 // s.SetSlotName("LE",2);
63 // s.SetSignal(-102,2);
64 // s.SetSlotName("TOT",3);
65 // s.SetSignal(-1002,3);
66 // m.AddHit(s);
67 //
68 // TObjArray* ordered=m.SortHits("TOT");
69 // nhits=ordered->GetEntries();
70 // for (Int_t i=0; i<nhits; i++)
71 // {
72 //  AliSignal* sx=(AliSignal*)ordered->At(i);
73 //  if (sx) sx->Data();
74 // }
75 //
76 //--- Author: Nick van Eijndhoven 23-jun-2004 Utrecht University
77 //- Modified: NvE $Date$ Utrecht University
78 ///////////////////////////////////////////////////////////////////////////
79
80 #include "AliDevice.h"
81 #include "Riostream.h"
82  
83 ClassImp(AliDevice) // Class implementation to enable ROOT I/O
84  
85 AliDevice::AliDevice() : AliSignal()
86 {
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.
91  fHitCopy=1;
92  fHits=0;
93  fOrdered=0;
94  fMarkers=0;
95 }
96 ///////////////////////////////////////////////////////////////////////////
97 AliDevice::~AliDevice()
98 {
99 // Default destructor.
100
101  // Remove backward links to this device from the hits
102  // which were not owned by it.
103  if (!fHitCopy)
104  {
105   for (Int_t ih=1; ih<=GetNhits(); ih++)
106   {
107    AliSignal* sx=GetHit(ih);
108    if (sx) sx->ResetLinks(this);
109   }
110  }
111
112  if (fHits)
113  {
114   delete fHits;
115   fHits=0;
116  }
117
118  if (fOrdered)
119  {
120   delete fOrdered;
121   fOrdered=0;
122  }
123
124  if (fMarkers)
125  {
126   delete fMarkers;
127   fMarkers=0;
128  }
129 }
130 ///////////////////////////////////////////////////////////////////////////
131 AliDevice::AliDevice(const AliDevice& dev) : AliSignal(dev)
132 {
133 // Copy constructor.
134
135  fHits=0;
136  fOrdered=0;
137  fMarkers=0;
138
139  fHitCopy=dev.GetHitCopy();
140
141  Int_t nhits=dev.GetNhits();
142  if (nhits)
143  {
144   fHits=new TObjArray(nhits);
145   if (fHitCopy) fHits->SetOwner();
146   for (Int_t ih=1; ih<=nhits; ih++)
147   {
148    AliSignal* sx=dev.GetHit(ih);
149    if (fHitCopy)
150    {
151     fHits->Add(sx->Clone());
152     AliSignal* s=(AliSignal*)fHits->Last();
153     s->ResetLinks((AliDevice*)&dev);
154     s->SetDevice(this);
155    }
156    else
157    {
158     sx->AddLink(this);
159     fHits->Add(sx);
160    }
161   }
162  }
163 }
164 ///////////////////////////////////////////////////////////////////////////
165 void AliDevice::Reset(Int_t mode)
166 {
167 // Reset registered hits and AliSignal attributes.
168 // See AliSignal::Reset() for further details.
169  RemoveHits();
170  AliSignal::Reset(mode);
171 }
172 ///////////////////////////////////////////////////////////////////////////
173 void AliDevice::SetHitCopy(Int_t j)
174 {
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.
178 //
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().
183  if (!fHits)
184  {
185   if (j==0 || j==1)
186   {
187    fHitCopy=j;
188   }
189   else
190   {
191    cout << "*AliDevice::SetHitCopy* Invalid argument : " << j << endl;
192   }
193  }
194  else
195  {
196   cout << "*AliDevice::SetHitCopy* Storage already contained hits."
197        << "  ==> HitCopy mode not changed." << endl; 
198  }
199 }
200 ///////////////////////////////////////////////////////////////////////////
201 Int_t AliDevice::GetHitCopy() const
202 {
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.
206  return fHitCopy;
207 }
208 ///////////////////////////////////////////////////////////////////////////
209 void AliDevice::AddHit(AliSignal& s)
210 {
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.
218
219  if (!fHits)
220  {
221   fHits=new TObjArray(1);
222   if (fHitCopy) fHits->SetOwner();
223  }
224
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++)
228  {
229   if (&s==fHits->At(i)) return; 
230  }
231
232  // Check for existing (backward) link to this device.
233  Int_t nlinks=s.GetNlinks(this);
234
235  if (fHitCopy)
236  {
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);
242   sx->SetDevice(this);
243  }
244  else
245  {
246   fHits->Add(&s);
247   // Set (backward) link to the this device
248   if (!nlinks) s.AddLink(this);
249  }
250 }
251 ///////////////////////////////////////////////////////////////////////////
252 void AliDevice::RemoveHit(AliSignal& s)
253 {
254 // Remove AliSignal object registered as a hit from this device.
255  if (fHits)
256  {
257   AliSignal* test=(AliSignal*)fHits->Remove(&s);
258   if (test)
259   {
260    fHits->Compress();
261    if (fHitCopy) delete test;
262   }
263  }
264  if (fOrdered)
265  {
266   AliSignal* test=(AliSignal*)fOrdered->Remove(&s);
267   if (test) fOrdered->Compress();
268  }
269 }
270 ///////////////////////////////////////////////////////////////////////////
271 void AliDevice::RemoveHits()
272 {
273 // Remove all AliSignal objects registered as hits from this device.
274  if (fHits)
275  {
276   delete fHits;
277   fHits=0;
278  }
279  if (fOrdered)
280  {
281   delete fOrdered;
282   fOrdered=0;
283  }
284  if (fMarkers)
285  {
286   delete fMarkers;
287   fMarkers=0;
288  }
289 }
290 ///////////////////////////////////////////////////////////////////////////
291 Int_t AliDevice::GetNhits() const
292 {
293 // Provide the number of registered hits for this device.
294  Int_t nhits=0;
295  if (fHits) nhits=fHits->GetEntries();
296  return nhits;
297 }
298 ///////////////////////////////////////////////////////////////////////////
299 AliSignal* AliDevice::GetHit(Int_t j) const
300 {
301 // Provide the AliSignal object registered as hit number j.
302 // Note : j=1 denotes the first hit.
303  if (!fHits) return 0;
304
305  if ((j >= 1) && (j <= GetNhits()))
306  {
307   return (AliSignal*)fHits->At(j-1);
308  }
309  else
310  {
311   return 0;
312  }
313 }
314 ///////////////////////////////////////////////////////////////////////////
315 TObjArray* AliDevice::GetHits()
316 {
317 // Provide the references to all the registered hits.
318  return fHits;
319 }
320 ///////////////////////////////////////////////////////////////////////////
321 void AliDevice::ShowHit(Int_t j) const
322 {
323 // Show data of the registered j-th hit.
324 // If j=0 all associated hits will be shown.
325 // The default is j=0.
326  if (!j)
327  {
328   Int_t nhits=GetNhits();
329   for (Int_t ih=1; ih<=nhits; ih++)
330   {
331    AliSignal* sx=GetHit(ih);
332    if (sx) sx->Data();
333   }
334  }
335  else
336  {
337   AliSignal* s=GetHit(j);
338   if (s) s->Data();
339  }
340 }
341 ///////////////////////////////////////////////////////////////////////////
342 void AliDevice::Data(TString f) const
343 {
344 // Print the device and all registered hit info according to the specified
345 // coordinate frame.
346  AliSignal::Data(f);
347  Int_t nhits=GetNhits();
348  if (nhits)
349  {
350   cout << " The following " << nhits << " hits are registered : " << endl;
351   ShowHit();
352  }
353  else
354  {
355   cout << " No hits have been registered for this device." << endl;
356  }
357 }
358 ///////////////////////////////////////////////////////////////////////////
359 void AliDevice::GetExtremes(Float_t& vmin,Float_t& vmax,Int_t idx,TObjArray* hits) const
360 {
361 // Provide the min. and max. signal values of an array of hits.
362 // The input argument "idx" denotes the index of the signal slots to be investigated.
363 // The default is idx=1;
364 // In case hits=0 (default), the registered hits of the current device are used. 
365 // Signals which were declared as "Dead" will be rejected.
366 // The gain etc... corrected signals will be used in the process.
367
368  vmin=0;
369  vmax=0;
370
371  if (!hits) hits=fHits;
372  
373  if (idx<=0 || !hits) return;
374
375  Int_t nhits=hits->GetEntries();
376
377  Float_t sig=0;
378  for (Int_t i=0; i<nhits; i++)
379  {
380   AliSignal* sx=(AliSignal*)hits->At(i);
381
382   if (!sx) continue;
383   if (idx > sx->GetNvalues()) continue; // User specified slotindex out of range for this signal
384   if (sx->GetDeadValue(idx)) continue;  // Only take alive signals
385
386   sig=sx->GetSignal(idx,1);
387   if (i==0)
388   {
389    vmin=sig;
390    vmax=sig;
391   }
392   else
393   {
394    if (sig<vmin) vmin=sig;
395    if (sig>vmax) vmax=sig;
396   }
397  }
398 }
399 ///////////////////////////////////////////////////////////////////////////
400 void AliDevice::GetExtremes(Float_t& vmin,Float_t& vmax,TString name,TObjArray* hits) const
401 {
402 // Provide the min. and max. signal values of an array of hits.
403 // The input argument "name" denotes the name of the signal slots to be investigated.
404 // In case hits=0 (default), the registered hits of the current device are used. 
405 // Signals which were declared as "Dead" will be rejected.
406 // The gain etc... corrected signals will be used in the process.
407
408  vmin=0;
409  vmax=0;
410
411  if (!hits) hits=fHits;
412  
413  if (!hits) return;
414
415  Int_t nhits=hits->GetEntries();
416
417  Int_t idx=0; // The signal slotindex to perform the sorting on
418
419  Float_t sig=0;
420  for (Int_t i=0; i<nhits; i++)
421  {
422   AliSignal* sx=(AliSignal*)hits->At(i);
423
424   if (!sx) continue;
425
426   // Obtain the slotindex corresponding to the user selection
427   idx=sx->GetSlotIndex(name);
428   if (!idx) continue;
429
430   if (sx->GetDeadValue(idx)) continue; // Only take alive signals
431
432   sig=sx->GetSignal(idx,1);
433   if (i==0)
434   {
435    vmin=sig;
436    vmax=sig;
437   }
438   else
439   {
440    if (sig<vmin) vmin=sig;
441    if (sig>vmax) vmax=sig;
442   }
443  }
444 }
445 ///////////////////////////////////////////////////////////////////////////
446 TObjArray* AliDevice::SortHits(Int_t idx,Int_t mode,TObjArray* hits)
447 {
448 // Order the references to an array of hits by looping over the input array "hits"
449 // and checking the signal value. The ordered array is returned as a TObjArray.
450 // In case hits=0 (default), the registered hits of the current device are used. 
451 // Note that the original hit array is not modified.
452 // A "hit" represents an abstract object which is derived from AliSignal.
453 // The user can specify the index of the signal slot to perform the sorting on.
454 // By default the slotindex will be 1.
455 // Via the "mode" argument the user can specify ordering in decreasing
456 // order (mode=-1) or ordering in increasing order (mode=1).
457 // The default is mode=-1.
458 // Signals which were declared as "Dead" will be rejected.
459 // The gain etc... corrected signals will be used in the ordering process.
460
461  if (fOrdered)
462  {
463   delete fOrdered;
464   fOrdered=0;
465  }
466
467  if (!hits) hits=fHits;
468  
469  if (idx<=0 || abs(mode)!=1 || !hits) return fOrdered;
470
471  Int_t nhits=hits->GetEntries();
472  if (!nhits)
473  {
474   return fOrdered;
475  }
476  else
477  {
478   fOrdered=new TObjArray(nhits);
479  }
480
481  Int_t nord=0;
482  for (Int_t i=0; i<nhits; i++) // Loop over all hits of the array
483  {
484   AliSignal* s=(AliSignal*)hits->At(i);
485
486   if (!s) continue;
487
488   if (idx > s->GetNvalues()) continue; // User specified slotindex out of range for this signal
489   if (s->GetDeadValue(idx)) continue;  // Only take alive signals
490  
491   if (nord == 0) // store the first hit with a signal at the first ordered position
492   {
493    nord++;
494    fOrdered->AddAt(s,nord-1);
495    continue;
496   }
497  
498   for (Int_t j=0; j<=nord; j++) // put hit in the right ordered position
499   {
500    if (j == nord) // module has smallest (mode=-1) or largest (mode=1) signal seen so far
501    {
502     nord++;
503     fOrdered->AddAt(s,j); // add hit at the end
504     break; // go for next hit
505    }
506  
507    if (mode==-1 && s->GetSignal(idx,1) < ((AliSignal*)fOrdered->At(j))->GetSignal(idx,1)) continue;
508    if (mode==1 && s->GetSignal(idx,1) > ((AliSignal*)fOrdered->At(j))->GetSignal(idx,1)) continue;
509  
510    nord++;
511    for (Int_t k=nord-1; k>j; k--) // create empty position
512    {
513     fOrdered->AddAt(fOrdered->At(k-1),k);
514    }
515    fOrdered->AddAt(s,j); // put hit at empty position
516    break; // go for next matrix module
517   }
518  }
519  return fOrdered;
520 }
521 ///////////////////////////////////////////////////////////////////////////
522 TObjArray* AliDevice::SortHits(TString name,Int_t mode,TObjArray* hits)
523 {
524 // Order the references to an array of hits by looping over the input array "hits"
525 // and checking the signal value. The ordered array is returned as a TObjArray.
526 // In case hits=0 (default), the registered hits of the current device are used. 
527 // Note that the input array is not modified.
528 // A "hit" represents an abstract object which is derived from AliSignal.
529 // The user can specify the name of the signal slot to perform the sorting on.
530 // In case no matching slotname is found, the signal will be skipped.
531 // Via the "mode" argument the user can specify ordering in decreasing
532 // order (mode=-1) or ordering in increasing order (mode=1).
533 // The default is mode=-1.
534 // Signals which were declared as "Dead" will be rejected.
535 // The gain etc... corrected signals will be used in the ordering process.
536
537  if (fOrdered)
538  {
539   delete fOrdered;
540   fOrdered=0;
541  }
542
543  if (!hits) hits=fHits;
544  
545  if (abs(mode)!=1 || !hits) return fOrdered;
546
547  Int_t nhits=hits->GetEntries();
548  if (!nhits)
549  {
550   return fOrdered;
551  }
552  else
553  {
554   fOrdered=new TObjArray(nhits);
555  }
556
557  Int_t idx=0; // The signal slotindex to perform the sorting on
558
559  Int_t nord=0;
560  for (Int_t i=0; i<nhits; i++) // loop over all hits of the array
561  {
562   AliSignal* s=(AliSignal*)hits->At(i);
563
564   if (!s) continue;
565
566   // Obtain the slotindex corresponding to the user selection
567   idx=s->GetSlotIndex(name);
568   if (!idx) continue;
569
570   if (s->GetDeadValue(idx)) continue; // only take alive signals
571  
572   if (nord == 0) // store the first hit with a signal at the first ordered position
573   {
574    nord++;
575    fOrdered->AddAt(s,nord-1);
576    continue;
577   }
578  
579   for (Int_t j=0; j<=nord; j++) // put hit in the right ordered position
580   {
581    if (j == nord) // module has smallest (mode=-1) or largest (mode=1) signal seen so far
582    {
583     nord++;
584     fOrdered->AddAt(s,j); // add hit at the end
585     break; // go for next hit
586    }
587  
588    if (mode==-1 && s->GetSignal(idx,1) < ((AliSignal*)fOrdered->At(j))->GetSignal(idx,1)) continue;
589    if (mode==1 && s->GetSignal(idx,1) > ((AliSignal*)fOrdered->At(j))->GetSignal(idx,1)) continue;
590  
591    nord++;
592    for (Int_t k=nord-1; k>j; k--) // create empty position
593    {
594     fOrdered->AddAt(fOrdered->At(k-1),k);
595    }
596    fOrdered->AddAt(s,j); // put hit at empty position
597    break; // go for next matrix module
598   }
599  }
600  return fOrdered;
601 }
602 ///////////////////////////////////////////////////////////////////////////
603 void AliDevice::DisplayHits(Int_t idx,Float_t scale,TObjArray* hits,Int_t dp,Int_t mstyle,Int_t mcol)
604 {
605 // 3D color display of an array hits.
606 // The user can specify the index (default=1) of the signal slot to perform the display for.
607 // The marker size will indicate the absolute value of the signal (specified by the slotindex)
608 // as a percentage of the input argument "scale".
609 // In case scale<0 the maximum absolute signal value encountered in the hit array will be used
610 // to define the 100% scale. The default is scale=-1.
611 // In case hits=0 (default), the registered hits of the current device are used. 
612 // Note that the input array is not modified.
613 // In case dp=1 the device position will be used, otherwise the hit position will
614 // be used in the display. The default is dp=0.
615 // Via the "mstyle" and "mcol" arguments the user can specify the marker style
616 // and color (see TPolyMarker3D) respectively.
617 // The defaults are mstyle="large scalable dot" and mcol=blue.
618 // Signals which were declared as "Dead" will not be displayed.
619 // The gain etc... corrected signals will be used to determine the marker size.
620 //
621 // Note :
622 // ------
623 // Before any display activity, a TCanvas and a TView have to be initiated
624 // first by the user like for instance
625 // 
626 // TCanvas* c1=new TCanvas("c1","c1");
627 // TView* view=new TView(1);
628 // view->SetRange(-1000,-1000,-1000,1000,1000,1000);
629 // view->ShowAxis();
630
631  Int_t thisdev=0; // Indicate whether this is the owning device or not 
632  if (!hits)
633  {
634   hits=fHits;
635   thisdev=1;
636  }
637  
638  if (idx<=0 || !hits) return;
639
640  Int_t nhits=hits->GetEntries();
641  if (!nhits) return;
642
643  Float_t sigmax=fabs(scale);
644  if (scale<0)
645  {
646   Float_t vmin,vmax;
647   GetExtremes(vmin,vmax,idx,hits);
648   sigmax=fabs(vmax);
649   if (fabs(vmin)>sigmax) sigmax=fabs(vmin);
650  }
651
652  if (sigmax <=0) return;
653
654  if (fMarkers)
655  {
656   delete fMarkers;
657   fMarkers=0;
658  }
659  fMarkers=new TObjArray(nhits);
660  fMarkers->SetOwner();
661
662  Float_t pos[3];
663  GetPosition(pos,"car");
664
665  Float_t sig=0;
666  for (Int_t ih=0; ih<nhits; ih++)
667  {
668   AliSignal* sx=(AliSignal*)hits->At(ih);
669   if (!sx) continue;
670   if (!dp)
671   {
672    sx->GetPosition(pos,"car");
673   }
674   else
675   {
676    if (!thisdev)
677    {
678     AliDevice* dev=sx->GetDevice();
679     if (dev) dev->GetPosition(pos,"car");
680    }
681   }
682   sig=sx->GetSignal(idx,1);
683   TPolyMarker3D* m=new TPolyMarker3D();
684   m->SetMarkerStyle(mstyle);
685   m->SetMarkerColor(mcol);
686   m->SetMarkerSize(100.*fabs(sig)/sigmax);
687   m->SetPoint(0,pos[0],pos[1],pos[2]);
688   fMarkers->Add(m);
689   m->Draw();
690  }
691 }
692 ///////////////////////////////////////////////////////////////////////////
693 void AliDevice::DisplayHits(TString name,Float_t scale,TObjArray* hits,Int_t dp,Int_t mstyle,Int_t mcol)
694 {
695 // 3D color display of an array hits.
696 // The user can specify the name of the signal slot to perform the display for.
697 // The marker size will indicate the absolute value of the signal (specified by the slotname)
698 // as a percentage of the input argument "scale".
699 // In case scale<0 the maximum absolute signal value encountered in the hit array will be used
700 // to define the 100% scale. The default is scale=-1.
701 // In case hits=0 (default), the registered hits of the current device are used. 
702 // Note that the input array is not modified.
703 // In case dp=1 the device position will be used, otherwise the hit position will
704 // be used in the display. The default is dp=0.
705 // The marker size will indicate the percentage of the maximum encountered value
706 // of the absolute value of the name-specified input signal slots.
707 // Via the "mstyle" and "mcol" arguments the user can specify the marker style
708 // and color (see TPolyMarker3D) respectively.
709 // The defaults are mstyle="large scalable dot" and mcol=blue.
710 // Signals which were declared as "Dead" will not be displayed.
711 // The gain etc... corrected signals will be used to determine the marker size.
712 //
713 // Note :
714 // ------
715 // Before any display activity, a TCanvas and a TView have to be initiated
716 // first by the user like for instance
717 // 
718 // TCanvas* c1=new TCanvas("c1","c1");
719 // TView* view=new TView(1);
720 // view->SetRange(-1000,-1000,-1000,1000,1000,1000);
721 // view->ShowAxis();
722
723  Int_t thisdev=0; // Indicate whether this is the owning device or not 
724  if (!hits)
725  {
726   hits=fHits;
727   thisdev=1;
728  }
729  
730  if (!hits) return;
731
732  Int_t nhits=hits->GetEntries();
733
734  if (!nhits) return;
735
736  Float_t sigmax=fabs(scale);
737  if (scale<0)
738  {
739   Float_t vmin,vmax;
740   GetExtremes(vmin,vmax,name,hits);
741   sigmax=fabs(vmax);
742   if (fabs(vmin)>sigmax) sigmax=fabs(vmin);
743  }
744
745  if (sigmax <=0) return;
746
747  if (fMarkers)
748  {
749   delete fMarkers;
750   fMarkers=0;
751  }
752  fMarkers=new TObjArray(nhits);
753  fMarkers->SetOwner();
754
755  Float_t pos[3];
756  GetPosition(pos,"car");
757
758  Int_t idx=0; // The slot index corresponding to the user specified name
759  Float_t sig=0;
760  for (Int_t ih=0; ih<nhits; ih++)
761  {
762   AliSignal* sx=(AliSignal*)hits->At(ih);
763   if (!sx) continue;
764   idx=sx->GetSlotIndex(name);
765   if (!idx) continue;
766   if (!dp)
767   {
768    sx->GetPosition(pos,"car");
769   }
770   else
771   {
772    if (!thisdev)
773    {
774     AliDevice* dev=sx->GetDevice();
775     if (dev) dev->GetPosition(pos,"car");
776    }
777   }
778   sig=sx->GetSignal(idx,1);
779   TPolyMarker3D* m=new TPolyMarker3D();
780   m->SetMarkerStyle(mstyle);
781   m->SetMarkerColor(mcol);
782   m->SetMarkerSize(100.*fabs(sig)/sigmax);
783   m->SetPoint(0,pos[0],pos[1],pos[2]);
784   fMarkers->Add(m);
785   m->Draw();
786  }
787 }
788 ///////////////////////////////////////////////////////////////////////////
789 TObject* AliDevice::Clone(const char* name) const
790 {
791 // Make a deep copy of the current object and provide the pointer to the copy.
792 // This memberfunction enables automatic creation of new objects of the
793 // correct type depending on the object type, a feature which may be very useful
794 // for containers like AliEvent when adding objects in case the
795 // container owns the objects. This feature allows e.g. AliEvent
796 // to store either AliDevice objects or objects derived from AliDevice
797 // via tha AddDevice memberfunction, provided these derived classes also have
798 // a proper Clone memberfunction. 
799
800  AliDevice* dev=new AliDevice(*this);
801  if (name)
802  {
803   if (strlen(name)) dev->SetName(name);
804  }
805  return dev;
806 }
807 ///////////////////////////////////////////////////////////////////////////