]> git.uio.no Git - u/mrichter/AliRoot.git/blob - MUON/AliMUONDisplay.cxx
New class replacing AliCluster
[u/mrichter/AliRoot.git] / MUON / AliMUONDisplay.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 /*
17 $Log$
18 Revision 1.6  2000/07/03 11:54:57  morsch
19 AliMUONSegmentation and AliMUONHitMap have been replaced by AliSegmentation and AliHitMap in STEER
20 The methods GetPadIxy and GetPadXxy of AliMUONSegmentation have changed name to GetPadI and GetPadC.
21
22 Revision 1.5  2000/06/28 15:16:35  morsch
23 (1) Client code adapted to new method signatures in AliMUONSegmentation (see comments there)
24 to allow development of slat-muon chamber simulation and reconstruction code in the MUON
25 framework. The changes should have no side effects (mostly dummy arguments).
26 (2) Hit disintegration uses 3-dim hit coordinates to allow simulation
27 of chambers with overlapping modules (MakePadHits, Disintegration).
28
29 Revision 1.4  2000/06/27 09:46:57  morsch
30 kMAXZOOM global constant now in AliMUONConstants
31
32 Revision 1.3  2000/06/26 14:02:38  morsch
33 Add class AliMUONConstants with MUON specific constants using static memeber data and access methods.
34
35 Revision 1.2  2000/06/15 07:58:48  morsch
36 Code from MUON-dev joined
37
38 Revision 1.1.2.15  2000/06/14 14:37:53  morsch
39 method Trigger() modified
40
41 Revision 1.1.2.14  2000/06/09 21:57:09  morsch
42 Bug in color scale diplay corrected.
43 Most coding rule violations corrected.
44
45 Revision 1.1.2.13  2000/05/02 11:57:27  morsch
46 Coding rules RN3, RN13, RN17 violations corrected.
47
48 Revision 1.1.2.12  2000/04/26 12:27:33  morsch
49 Mods for trigger display (P. Crochet):
50 - color code versus time for pad hits in trigger chambers
51 - call to TriggerDecision corrected
52
53 Revision 1.1.2.11  2000/04/26 09:04:46  morsch
54 Obsolete cathode correlation related code removed.
55
56 Revision 1.1.2.10  2000/04/19 19:43:47  morsch
57 change NCH to kNCH as in AliMUON.h
58 no more TreeC related methods
59
60 Revision 1.1.2.9  2000/03/20 18:10:33  morsch
61 Trigger method for "online" trigger decission added
62
63 Revision 1.1.2.8  2000/02/23 10:12:01  morsch
64 Dont't try to draw reconstructed hit coordinates for Trigger Chambers.
65 General clean-up of commented code.
66
67 Revision 1.1.2.7  2000/02/17 14:36:55  morsch
68 Display of Trigger hits and clusters added.
69 Displacement between clusters and hits has to be investigated and corrected ! (A.M.)
70
71 Revision 1.1.2.6  2000/02/15 10:19:42  morsch
72 Previous log messages included
73
74 Revision 1.1.2.5  2000/02/15 10:09:09  morsch
75 Log Message added
76
77 Revision 1.1.2.4  2000/02/08 09:17:16  gosset    
78 One more improvement of MUON display:
79 same zoom for both cathode planes in a chamber
80
81 Revision 1.1.2.3  2000/02/07 15:37:21  gosset
82 A few improvements of the MUON display:
83 new buttons to change either chamber or cathode,
84 added to the more complicated way
85 (right mouse click and explicit filling of chamber and cathode)
86
87 Revision 1.1.2.2  2000/02/04 10:57:34  gosset
88 Z position of the chambers:
89 it was the Z position of the stations;
90 it is now really the Z position of the chambers.
91    !!!! WARNING: THE CALLS TO "AliMUONChamber::SetZPOS"
92    !!!!                   AND "AliMUONChamber::ZPosition"
93    !!!! HAVE TO BE CHANGED TO "AliMUONChamber::"SetZ"
94    !!!!                   AND "AliMUONChamber::Z"                                                           
95 */
96
97 //////////////////////////////////////////////////////////////////////////
98 //                                                                      //
99 // AliDisplay                                                           //
100 //                                                                      //
101 // Utility class to display ALICE outline, tracks, hits,..              //
102 //                                                                      //
103 //////////////////////////////////////////////////////////////////////////
104
105 #include <TROOT.h>
106 #include <TTree.h>
107 #include <TButton.h>
108 #include <TColor.h>
109 #include <TCanvas.h>
110 #include <TView.h>
111 #include <TText.h>
112 #include <TPolyMarker3D.h>
113 #include <TPaveLabel.h>
114 #include <TPaveText.h>
115 #include <TList.h>
116 #include <TDiamond.h>
117 #include <TNode.h>
118 #include <TArc.h>
119 #include <TTUBE.h>
120 #include <TSlider.h>
121 #include <TSliderBox.h>
122 #include <TGaxis.h>
123 #include <TVirtualX.h>
124 #include <TMath.h>
125 #include <TMatrix.h>
126 #include <TGeometry.h>
127 #include <X3DBuffer.h>
128 #include <TMarker3DBox.h>
129
130 #include "AliRun.h"
131 #include "AliDetector.h"
132 #include "AliMUON.h"
133 #include "AliMUONDisplay.h"
134 #include "AliMUONPoints.h"
135 #include "TParticle.h"
136 #include "AliMUONTriggerDecision.h"
137
138 #include "AliMUONHit.h"
139 #include "AliMUONPadHit.h"
140 #include "AliMUONDigit.h"
141 #include "AliMUONRawCluster.h"
142
143 #include "AliSegmentation.h"
144 #include "AliMUONResponse.h"
145 #include "AliMUONChamber.h"
146 #include "AliMUONConstants.h"
147 // to manage the same zoom on both cathodes
148
149
150
151 ClassImp(AliMUONDisplay)
152
153
154 //_____________________________________________________________________________
155 AliMUONDisplay::AliMUONDisplay()
156 {
157 // Constructor
158     fPoints = 0;
159     fPhits = 0;
160     fRpoints = 0;
161     fR2points = 0;
162     fCpoints = 0;
163     fCanvas = 0;
164     fNextCathode = kFALSE; 
165 }
166
167 //_____________________________________________________________________________
168 AliMUONDisplay::AliMUONDisplay(Int_t size)
169 {
170 // Create an event display object.
171 // A canvas named "edisplay" is created with a vertical size in pixels
172 //
173 //    A QUICK Overview of the Event Display functions
174 //    ===============================================
175 //
176 //  The event display can ve invoked by executing the macro "display.C"
177 // A canvas like in the picture below will appear.
178 //
179 //  On the left side of the canvas, the following buttons appear:
180 //   *Next*       to move to the next event
181 //   *Previous*   to move to the previous event
182
183 //   *Pick*       Select this option to be able to point on a track with the
184 //                mouse. Once on the track, use the right button to select
185 //                an action. For example, select SetMarkerAttributes to
186 //                change the marker type/color/size for the track.
187 //   *Zoom*       Select this option (default) if you want to zoom.
188 //                To zoom, simply select the selected area with the left button.
189 //   *UnZoom*     To revert to the previous picture size.
190 //
191 //   slider R     On the left side, the vertical slider can be used to
192 //                set the default picture size.
193 //
194 //    When you are in Zoom mode, you can click on the black part of the canvas
195 //  to select special options with the right mouse button.
196
197 //
198 //  When you are in pick mode, you can "Inspect" the object pointed by the mouse.
199 //  When you are on a track, select the menu item "InspectParticle"
200 //  to display the current particle attributes.
201 //
202 //  You can activate the Root browser by selecting the Inspect menu
203 //  in the canvas tool bar menu. Then select "Start Browser"
204 //  This will open a new canvas with the browser. At this point, you may want
205 //  to display some histograms (from the Trees). Go to the "File" menu
206 //  of the browser and click on "New canvas".
207 //  In the browser, click on item "ROOT files" in the left pane.
208 //  Click on galice.root.
209 //  Click on TH
210 //  Click on TPC for example
211 //  Click on any variable (eg TPC.fX) to histogram the variable.
212 //
213 //   If you are lost, you can click on HELP in any Root canvas or browser.
214 //Begin_Html
215 /*
216 <img src="gif/AliMUONDisplay.gif">
217 */
218 //End_Html
219
220
221     fPad = 0;
222     
223     gAlice->SetDisplay(this);
224    
225    // Initialize display default parameters
226     SetRange(200,2000);
227    // Set front view by default
228     fTheta =   0;
229     fPhi   = -90;
230     fPsi   =   0;
231     fChamber = 1;
232     fCathode = 1;
233     //   fRzone   = 1.e10;
234     fDrawClusters  = kTRUE;
235     fDrawCoG       = kTRUE;
236     fDrawCoG  = kTRUE;
237     fZoomMode      = 1;
238     fZooms         = 0;
239     fClustersCuts  = 0;
240     fPoints        = 0;
241     fPhits         = 0;
242     fRpoints       = 0;
243     fR2points = 0;
244     fCpoints = 0;
245     // Create colors
246     CreateColors();
247     // Create display canvas
248     Int_t ysize = size;
249     if (ysize < 100) ysize = 750;
250     Int_t xsize = Int_t(size*830./ysize);
251     fCanvas = new TCanvas("Canvas", "MUON Clusters Display",14,47,xsize,ysize);
252     fCanvas->ToggleEventStatus();
253     
254    // Create main display pad
255     fPad = new TPad("viewpad", "MUON display",0.15,0,0.9,1);
256     fPad->Draw();
257     fPad->Modified();
258     fPad->SetFillColor(30);
259     fPad->SetBorderSize(2);
260
261     fCanvas->cd();
262
263    // Create colors pad
264     fColPad = new TPad("colpad", "Colors pad",0.9,0,1,1);
265     fColPad->Draw();
266     fColPad->SetFillColor(17);
267     fColPad->SetBorderSize(2);
268     fColPad->cd();
269     DisplayColorScale();
270
271     fCanvas->cd();
272    // Create user interface control pad
273     DisplayButtons();
274     fCanvas->cd();
275
276    // Create Range and mode pad
277     Float_t dxtr     = 0.15;
278     Float_t dytr     = 0.45;
279     fTrigPad = new TPad("trigger", "range and mode pad",0,0,dxtr,dytr);
280     fTrigPad->SetEditable(kFALSE);
281     fTrigPad->Draw();
282     fTrigPad->cd();
283     fTrigPad->SetFillColor(22);
284     fTrigPad->SetBorderSize(2);
285     fRangeSlider = new TSlider("range","range",0.7,0.42,0.9,0.98);
286     fRangeSlider->SetObject(this);
287     char pickmode[] = "gAlice->Display()->SetPickMode()";
288     Float_t db = 0.09;
289     fPickButton = new TButton("Pick",pickmode,0.05,0.32,0.65,0.32+db);
290     fPickButton->SetFillColor(38);
291     fPickButton->Draw();
292     char zoommode[] = "gAlice->Display()->SetZoomMode()";
293     fZoomButton = new TButton("Zoom",zoommode,0.05,0.21,0.65,0.21+db);
294     fZoomButton->SetFillColor(38);
295     fZoomButton->Draw();
296     fArcButton = new TArc(.8,fZoomButton->GetYlowNDC()+0.5*db,0.33*db);
297     fArcButton->SetFillColor(kGreen);
298     fArcButton->Draw();
299     char butUnzoom[] = "gAlice->Display()->UnZoom()";
300     TButton *button = new TButton("UnZoom",butUnzoom,0.05,0.05,0.95,0.15);
301     button->SetFillColor(38);
302     button->Draw();
303     AppendPad(); // append display object as last object to force selection
304     
305     fCanvas->cd();
306     fCanvas->Update();
307     fNextCathode = kFALSE; 
308 }
309
310 AliMUONDisplay::AliMUONDisplay(const AliMUONDisplay & display)
311 {
312 // Dummy copy constructor    
313     ;
314 }
315
316
317
318 //_____________________________________________________________________________
319 AliMUONDisplay::~AliMUONDisplay()
320 {
321   // Delete space point structure
322     if (fPoints) fPoints->Delete();
323     delete fPoints;
324     fPoints     = 0;
325     //
326     if (fPhits) fPhits->Delete();
327     delete fPhits;
328     fPhits     = 0;
329     //
330     if (fRpoints) fRpoints->Delete();
331     delete fRpoints;
332     fRpoints     = 0;
333 //
334     if (fR2points) fR2points->Delete();
335     delete fR2points;
336     fR2points     = 0;
337 //
338     if (fCpoints) fCpoints->Delete();
339     delete fCpoints;
340     fCpoints     = 0;
341 }
342
343 //_____________________________________________________________________________
344 void AliMUONDisplay::Clear(Option_t *)
345 {
346 //    Delete graphics temporary objects
347 }
348
349 //_____________________________________________________________________________
350 void AliMUONDisplay::DisplayButtons()
351 {
352 //    Create the user interface buttons
353
354
355     fButtons = new TPad("buttons", "newpad",0,0.45,0.15,1);
356     fButtons->SetEditable(kFALSE);
357     fButtons->Draw();
358     fButtons->SetFillColor(38);
359     fButtons->SetBorderSize(2);
360     fButtons->cd();
361     
362 //   Int_t butcolor = 33;
363     Float_t dbutton = 0.08;
364     Float_t y  = 0.96;
365     Float_t dy = 0.014;
366     Float_t x0 = 0.05;
367     Float_t x1 = 0.95;
368     
369     TButton *button;
370     char but1[] = "gAlice->Display()->ShowNextEvent(1)";
371     button = new TButton("Event +", but1, x0, y - dbutton, x1, y);
372     button->SetFillColor(38);
373     button->Draw();
374     
375     y -= dbutton + dy;
376     char but2[] = "gAlice->Display()->ShowNextEvent(-1)";
377     button = new TButton("Event -", but2, x0, y - dbutton, x1, y);
378     button->SetFillColor(38);
379     button->Draw();
380    
381     y -= dbutton + dy;
382     char but3[] = "((AliMUONDisplay*)(gAlice->Display()))->NextChamber(1)";
383     button = new TButton("Chamber +", but3, x0, y - dbutton, x1, y);
384     button->SetFillColor(38);
385     button->Draw();
386     
387     y -= dbutton + dy;
388     char but4[] = "((AliMUONDisplay*)(gAlice->Display()))->NextChamber(-1)";
389     button = new TButton("Chamber -", but4, x0, y - dbutton, x1, y);
390     button->SetFillColor(38);
391     button->Draw();
392     
393     y -= dbutton + dy;
394     char but5[] = "((AliMUONDisplay*)(gAlice->Display()))->SetChamberAndCathode(1,1)";
395     button = new TButton("Chamber 1", but5, x0, y - dbutton, x1, y);
396     button->SetFillColor(38);
397     button->Draw();
398    
399     y -= dbutton + dy;
400     char but6[] = "((AliMUONDisplay*)(gAlice->Display()))->NextCathode()";
401     button = new TButton("Cathode <>", but6, x0, y - dbutton, x1, y);
402     button->SetFillColor(38);
403     button->Draw();
404
405     y -= dbutton + dy;
406     char but7[] = "((AliMUONDisplay*)(gAlice->Display()))->Trigger()";
407     button = new TButton("Trigger", but7, x0, y - dbutton, x1, y);
408     button->SetFillColor(38);
409     button->Draw();
410     
411    // display logo
412     TDiamond *diamond = new TDiamond(0.05,0.015,0.95,0.22);
413     diamond->SetFillColor(50);
414     diamond->SetTextAlign(22);
415     diamond->SetTextColor(5);
416     diamond->SetTextSize(0.11);
417     diamond->Draw();
418     diamond->AddText(".. ");
419     diamond->AddText("ROOT");
420     diamond->AddText("MUON");
421     diamond->AddText("... ");
422     diamond->AddText(" ");
423 }
424
425 //_____________________________________________________________________________
426 void AliMUONDisplay::CreateColors()
427 {
428 //    Create the colors palette used to display clusters
429
430     Int_t k,i;
431     Int_t color;
432     Float_t r,g,b;
433     
434     for (k=1;k<=5;k++) {
435         switch(k) {
436         case 1:
437             for (i=1;i<=5;i++) {
438                 r=1.;
439                 g=i*0.2;  
440                 b=0.;
441                 color=i;
442                 color=260+23-color;
443                 new TColor(color,r,g,b);
444             } 
445             break;
446         case 2:
447             for (i=1;i<=4;i++) {
448                 r=1.1-i*0.2;
449                 g=1.;  
450                 b=0.;
451                 color=i+5;
452                 color=260+23-color;
453                 new TColor(color,r,g,b);
454             } 
455             break;
456         case 3:
457             for (i=1;i<=4;i++) {
458                 r=0.;
459                 g=1.;  
460                 b=i*0.2+0.2;
461                 color=i+9;
462                 color=260+23-color;
463                 new TColor(color,r,g,b);
464             } 
465             break;
466         case 4:
467             for (i=1;i<=4;i++) {
468                 r=0.;
469                 g=1.1-i*0.2;  
470                 b=1.;
471                 color=i+13;
472                 color=260+23-color;
473                 new TColor(color,r,g,b);
474             } 
475             break;
476         case 5:
477             for (i=1;i<=5;i++) {
478                 r=i*0.2;
479                 g=0.;  
480                 b=1.;
481                 color=i+17;
482                 color=260+23-color;
483                 new TColor(color,r,g,b);
484             } 
485             break;
486         }
487     }
488 }
489
490 //_____________________________________________________________________________
491 void AliMUONDisplay::DisplayColorScale()
492 {
493 // Display pulse height color scale
494     Int_t i;
495     Int_t color;
496     Float_t xlow, ylow, xup, yup, hs;
497     Float_t x1, y1, x2, y2;
498     x1 = y1 = 0;
499     x2 = y2 = 1.0;
500     
501     TText *text = new TText(0,0,"");
502     text->SetTextFont(61);
503     text->SetTextSize(0.2);
504     text->SetTextAlign(22);
505     
506     AliMUON *pMUON  = (AliMUON*)gAlice->GetModule("MUON");
507     AliMUONChamber *iChamber = &(pMUON->Chamber(fChamber-1));
508     AliMUONResponse * response=iChamber->ResponseModel();
509     Int_t adcmax=1024;
510     if (response) adcmax= (Int_t) response->MaxAdc();
511     
512
513     TBox *box;
514     char label[8];
515 //*-* draw colortable boxes
516     hs = (y2-y1)/Float_t(22);
517     xlow=x1+.05;
518     xup=x2-0.5;
519     for (i=0;i<22;i++) {
520         ylow = y1 + hs*(Float_t(i));
521         yup  = y1 + hs*(Float_t(i+1));
522         color = 261+i;
523         Double_t logscale=Double_t(i+1)*(TMath::Log(adcmax)/22);
524         Int_t scale=(Int_t)TMath::Exp(logscale);
525         sprintf(label,"%d",scale);
526         box = new TBox(xlow, ylow, xup, yup);
527         box->Draw();
528         box->SetFillColor(color);
529         text->DrawText(xlow+0.7, 0.5*(ylow+yup),label);
530     }
531 }
532
533 //______________________________________________________________________________
534 Int_t AliMUONDisplay::DistancetoPrimitive(Int_t px, Int_t)
535 {
536 // Compute distance from point px,py to objects in event
537
538     gPad->SetCursor(kCross);
539     
540     if (gPad == fTrigPad) return 9999;
541     
542     const Int_t kBig = 9999;
543     Int_t dist   = kBig;
544     Float_t xmin = gPad->GetX1();
545     Float_t xmax = gPad->GetX2();
546     Float_t dx   = 0.02*(xmax - xmin);
547     Float_t x    = gPad->AbsPixeltoX(px);
548     if (x < xmin+dx || x > xmax-dx) return dist;
549     
550     if (fZoomMode) return 0;
551     else           return 7;
552 }
553
554 //_____________________________________________________________________________
555 void AliMUONDisplay::Draw(Option_t *)
556 {
557 //    Display current event
558
559     fPad->cd();
560
561     DrawView(fTheta, fPhi, fPsi);   
562     // Display the event number and title
563     fPad->cd();
564     DrawTitle();
565 }
566
567 void AliMUONDisplay::DrawSegmentation()
568 {
569 // Draw graphical representation of segmenatation
570 // Attention: still experimental code
571     Int_t icat=1;
572     
573     AliMUON *pMUON  = (AliMUON*)gAlice->GetModule("MUON");
574     AliMUONChamber*   iChamber;
575     AliSegmentation*  seg;
576     iChamber = &(pMUON->Chamber(fChamber));
577     seg=iChamber->SegmentationModel(icat);
578     Float_t zpos=iChamber->Z();
579     Float_t r=iChamber->ROuter();
580     
581     TMarker3DBox *marker;
582     if (icat == 1) {
583         for (Int_t j=0; j<seg->Npy(); j++) {
584             Float_t y0;
585             y0=j*seg->Dpy()-seg->Dpy()/2.;
586             for (seg->FirstPad(0.,y0,0,300,0.); 
587                  seg->MorePads();
588                  seg->NextPad())
589             {
590                 if (seg->ISector()==0) continue;
591                 Float_t x,y,z;
592                 seg->GetPadC(seg->Ix(), seg->Iy(), x, y, z);
593                 Float_t dpx=seg->Dpx(seg->ISector())/2;
594                 Float_t dpy=seg->Dpy(seg->ISector())/2;
595                 marker=new TMarker3DBox(x,y,zpos,dpx,dpy,0,0,0);
596                 marker->SetLineColor(seg->ISector()+1);
597                 marker->SetFillStyle(1001);
598                 marker->SetFillColor(0);
599                 marker->Draw();
600             }
601         }
602     } else {
603         for (Int_t j=0; j<250; j++) {
604             Float_t x0=j*seg->Dpx();
605             Float_t y0=TMath::Sqrt(r*r-x0*x0);
606             
607             for (seg->FirstPad(x0,0,0,0,y0); 
608                  seg->MorePads();
609                  seg->NextPad())
610             {
611                 if (seg->ISector()==0) continue;
612                 
613                 Float_t x,y,z;
614                 seg->GetPadC(seg->Ix(), seg->Iy(), x, y, z);
615                 Float_t dpx=seg->Dpx(seg->ISector())/2;
616                 Float_t dpy=seg->Dpy(seg->ISector())/2;
617                 marker=new TMarker3DBox(x,y,zpos,dpx,dpy,0,0,0);
618                 marker->SetLineColor(seg->ISector()+1);
619                 marker->SetFillStyle(1001);
620                 marker->SetFillColor(0);
621                 marker->Draw();
622             }
623         }
624     }
625 }
626
627 //_____________________________________________________________________________
628 void AliMUONDisplay::DrawClusters()
629 {
630 //    Draw clusters for MUON chambers
631
632     Int_t ndigits, digit;
633     TObjArray *points;
634     AliMUONPoints *pm;
635
636       
637     fClustersCuts = 0;
638     points = Points();
639     if (!points) return;
640     ndigits = points->GetEntriesFast();
641     for (digit=0;digit<ndigits;digit++){
642         pm = (AliMUONPoints*)points->UncheckedAt(digit);
643         if (!pm) continue;
644         Float_t *pxyz;
645         pxyz=pm->GetP();
646         for (Int_t im=0;im<3;im++) {
647             TMarker3DBox *marker=pm->GetMarker(im);
648             if (marker)
649                 marker->Draw();
650         }
651         pm->Draw();
652         fClustersCuts +=pm->GetN();
653     }
654 }
655
656 //_____________________________________________________________________________
657 void AliMUONDisplay::DrawHits()
658 {
659 //    Draw hits for MUON chambers
660
661     LoadHits(fChamber);
662
663     Int_t ntracks, track;
664     TObjArray *points;
665     AliMUONPoints *pm;
666     
667     fHitsCuts = 0;
668     points = Phits();
669     if (!points) return;
670     ntracks = points->GetEntriesFast();
671     for (track=0;track<ntracks;track++) {
672         pm = (AliMUONPoints*)points->UncheckedAt(track);
673         if (!pm) continue;
674         pm->Draw();
675         fHitsCuts += pm->GetN();
676     }
677 }
678
679
680 //_____________________________________________________________________________
681 void AliMUONDisplay::DrawCoG()
682 {
683 //    Draw hits for MUON chambers
684     if (!fDrawCoG) return;
685     if (fChamber > 10) return;
686     LoadCoG(fChamber,fCathode);
687     
688     Int_t ncog, icog;
689     TObjArray *points;
690     AliMUONPoints *pm;
691
692     points = Rpoints();
693     if (!points) return;
694     ncog = points->GetEntriesFast();
695     for (icog=0;icog<ncog;icog++) {
696         pm = (AliMUONPoints*)points->UncheckedAt(icog);
697         if (!pm) continue;
698         pm->Draw();
699     }
700 }
701 void AliMUONDisplay::DrawCoG2()
702 {
703 //    Draw hits for MUON chambers
704
705     if (!fDrawCoG) return;
706     if (fChamber > 10) return;  
707
708     if (fCathode==1) {
709         LoadCoG2(fChamber,2);
710     } else if (fCathode==2) {
711         LoadCoG2(fChamber,1);
712     }
713
714     Int_t ncog, icog;
715     TObjArray *points;
716     AliMUONPoints *pm;
717     
718     points = R2points();
719     if (!points) return;
720     ncog = points->GetEntriesFast();
721     for (icog=0;icog<ncog;icog++) {
722         pm = (AliMUONPoints*)points->UncheckedAt(icog);
723         if (!pm) continue;
724         pm->Draw();
725     }
726 }
727 //_____________________________________________________________________________
728
729 void AliMUONDisplay::DrawTitle(Option_t *option)
730 {
731 //    Draw the event title
732
733     Float_t xmin = gPad->GetX1();
734     Float_t xmax = gPad->GetX2();
735     Float_t ymin = gPad->GetY1();
736     Float_t ymax = gPad->GetY2();
737     Float_t dx   = xmax-xmin;
738     Float_t dy   = ymax-ymin;
739     
740     if (strlen(option) == 0) {
741         TPaveText *title = new TPaveText(xmin +0.01*dx, ymax-0.09*dy, xmin +0.5*dx, ymax-0.01*dy);
742 //      title->SetTextSize(0.023932);
743         title->SetTextSize(0.02);
744         title->SetBit(kCanDelete);
745         title->SetFillColor(42);
746         title->Draw();
747         char ptitle[100];
748         sprintf(ptitle, "Alice event:%d Run:%d Chamber:%d Cathode:%d",
749                 gAlice->GetHeader()->GetEvent(),
750                 gAlice->GetHeader()->GetRun(),
751                 fChamber,
752                 fCathode);
753         title->AddText(ptitle);
754         Int_t nparticles = gAlice->Particles()->GetEntriesFast();
755         sprintf(ptitle,"Nparticles = %d Nhits = %d Npads fired = %d",
756                 nparticles, fHitsCuts,fClustersCuts);
757         title->AddText(ptitle);
758     } else {
759         TPaveLabel *label = new TPaveLabel(xmin +0.01*dx, ymax-0.07*dy, xmin +0.2*dx, ymax-0.01*dy,option);
760         label->SetBit(kCanDelete);
761         label->SetFillColor(42);
762         label->Draw();
763     }
764 }
765
766 //_____________________________________________________________________________
767 void AliMUONDisplay::DrawView(Float_t theta, Float_t phi, Float_t psi)
768 {
769 //    Draw a view of MUON clusters
770     printf("\n Draw View");
771     
772     gPad->SetCursor(kWatch);
773     // gPad->SetFillColor(39);
774     gPad->SetFillColor(1);
775     gPad->Clear();
776     // gPad->SetFillColor(39);
777     gPad->SetFillColor(1);
778     
779
780     Int_t iret=0;
781     TView *view = new TView(1);
782     
783     Float_t range = fRrange*fRangeSlider->GetMaximum();
784     view->SetRange(-range,-range,-range,range, range, range);
785     // zoom back to full scale only if DrawView not called from NextCathode
786     if (!fNextCathode) {
787         fZoomX0[0] = -1;
788         fZoomY0[0] = -1;
789         fZoomX1[0] =  1;
790         fZoomY1[0] =  1;
791         fZooms = 0;
792     }
793
794 // Display MUON Chamber Geometry
795 // gAlice->GetGeometry()->Draw("same");
796     char nodeName[7];
797     sprintf(nodeName,"MUON%d",100+fChamber);
798     printf("\n Node name %s", nodeName);
799     
800     TNode *node1=gAlice->GetGeometry()->GetNode(nodeName);
801     if (node1) node1->Draw("same");  
802 //add clusters to the pad
803     DrawClusters();
804     printf("Node name %s", nodeName);   
805     DrawHits();
806     DrawCoG();
807     DrawCoG2();
808 //     DrawSegmentation();
809     // add itself to the list (must be last)
810     AppendPad();
811     view->SetView(phi, theta, psi, iret);
812 }
813
814
815 //______________________________________________________________________________
816 void AliMUONDisplay::ExecuteEvent(Int_t event, Int_t px, Int_t py)
817 {
818 //  Execute action corresponding to the mouse event
819
820     static Float_t x0, y0, x1, y1;
821     
822     static Int_t pxold, pyold;
823     static Int_t px0, py0;
824     static Int_t linedrawn;
825     Float_t temp;
826     
827     if (px == 0 && py == 0) { //when called by sliders
828         if (event == kButton1Up) {
829             Draw();
830         }
831         return;
832     }
833     if (!fZoomMode && gPad->GetView()) {
834         gPad->GetView()->ExecuteRotateView(event, px, py);
835         return;
836     }
837
838     // something to zoom ?
839     gPad->SetCursor(kCross);
840     
841     switch (event) {
842
843     case kButton1Down:
844         gVirtualX->SetLineColor(-1);
845         gPad->TAttLine::Modify();  //Change line attributes only if necessary
846         x0 = gPad->AbsPixeltoX(px);
847         y0 = gPad->AbsPixeltoY(py);
848         px0   = px; py0   = py;
849         pxold = px; pyold = py;
850         linedrawn = 0;
851         return;
852         
853     case kButton1Motion:
854         if (linedrawn) gVirtualX->DrawBox(px0, py0, pxold, pyold, TVirtualX::kHollow);
855         pxold = px;
856         pyold = py;
857         linedrawn = 1;
858         gVirtualX->DrawBox(px0, py0, pxold, pyold,  TVirtualX::kHollow);
859         return;
860         
861     case kButton1Up:
862         gPad->GetCanvas()->FeedbackMode(kFALSE);
863         if (px == px0) return;
864         if (py == py0) return;
865         x1 = gPad->AbsPixeltoX(px);
866         y1 = gPad->AbsPixeltoY(py);
867         
868         if (x1 < x0) {temp = x0; x0 = x1; x1 = temp;}
869         if (y1 < y0) {temp = y0; y0 = y1; y1 = temp;}
870         gPad->Range(x0,y0,x1,y1);
871         if (fZooms < AliMUONConstants::MaxZoom()-1) {
872             fZooms++;
873             fZoomX0[fZooms] = x0;
874             fZoomY0[fZooms] = y0;
875             fZoomX1[fZooms] = x1;
876             fZoomY1[fZooms] = y1;
877         }
878         gPad->Modified(kTRUE);
879         return;
880     }
881 }
882  
883 //___________________________________________
884 void AliMUONDisplay::LoadDigits(Int_t chamber, Int_t cathode)
885 {
886 // Read digits info and store x,y,z info in arrays fPoints
887 // Loop on all detectors
888
889     if (chamber > 14) return;
890     printf(" chamber %d \n",chamber);
891     fChamber=chamber;
892     fCathode=cathode;
893     
894     ResetPoints();
895     
896     AliMUON *pMUON  = (AliMUON*)gAlice->GetModule("MUON");
897     AliMUONChamber*       iChamber;
898     AliSegmentation*      segmentation;
899     AliMUONResponse*      response;
900
901     TClonesArray *muonDigits  = pMUON->DigitsAddress(chamber-1);
902     if (muonDigits == 0) return;
903
904     gAlice->ResetDigits();
905
906     Int_t nent=(Int_t)gAlice->TreeD()->GetEntries();
907     gAlice->TreeD()->GetEvent(nent-2+cathode-1);
908     Int_t ndigits = muonDigits->GetEntriesFast();
909     if (ndigits == 0) return;
910     if (fPoints == 0) fPoints = new TObjArray(ndigits);
911     
912     iChamber = &(pMUON->Chamber(chamber-1));
913
914     segmentation = iChamber->SegmentationModel(cathode);
915     response     = iChamber->ResponseModel();
916     Float_t zpos=iChamber->Z();  
917     AliMUONDigit  *mdig;
918     AliMUONPoints *points = 0;
919     TMarker3DBox *marker=0;
920     //
921     //loop over all digits and store their position
922     
923     Int_t npoints=1;
924     Float_t adcmax=1024;
925     if (response) adcmax= response->MaxAdc();
926
927     for (Int_t digit=0;digit<ndigits;digit++) {
928         mdig    = (AliMUONDigit*)muonDigits->UncheckedAt(digit);
929         //
930         // First get all needed parameters
931         //
932         Int_t charge=mdig->fSignal;
933         Int_t index=Int_t(TMath::Log(charge)/(TMath::Log(adcmax)/22));
934         Int_t color=261+index;
935         Int_t colorTrigger=2;   
936         if (color>282) color=282;
937
938         if (chamber > 10) { // trigger chamber 
939             Int_t sumCharge=0;
940             for (Int_t icharge=0; icharge<10; icharge++) {
941                 sumCharge=sumCharge+mdig->fTcharges[icharge];
942             }
943             Int_t testCharge=sumCharge-(Int_t(sumCharge/10))*10;
944             if(sumCharge<=10||testCharge>0) {
945                 colorTrigger=color; 
946             } else {
947                 colorTrigger=5; 
948             }
949         }
950
951         // get the center of the pad - add on x and y half of pad size
952         Float_t xpad, ypad, zpad;
953         segmentation->GetPadC(mdig->fPadX, mdig->fPadY,xpad, ypad, zpad);
954         
955         Int_t isec=segmentation->Sector(mdig->fPadX, mdig->fPadY);
956         Float_t dpx=segmentation->Dpx(isec)/2;
957         Float_t dpy=segmentation->Dpy(isec)/2;
958         Int_t nPara, offset;
959         segmentation->GetNParallelAndOffset(mdig->fPadX,mdig->fPadY,
960                 &nPara,&offset);
961         //
962         // Then set the objects
963         //
964         points = new AliMUONPoints(npoints);
965         fPoints->AddAt(points,digit);
966         if (chamber > 10) {
967             points->SetMarkerColor(colorTrigger);
968         } else {  
969             points->SetMarkerColor(color);
970         }
971         points->SetMarkerStyle(21);
972         points->SetMarkerSize(0.5);
973         points->SetParticle(-1);
974         points->SetHitIndex(-1);
975         points->SetTrackIndex(-1);
976         points->SetDigitIndex(digit);
977         points->SetPoint(0,xpad,ypad,zpos);     
978         for (Int_t imark=0;imark<nPara; imark++)
979         {
980             segmentation->GetPadC(mdig->fPadX + imark*offset, mdig->fPadY,xpad, ypad, zpad);
981             marker=new TMarker3DBox(xpad,ypad,zpos,dpx,dpy,0,0,0);
982             marker->SetLineColor(2);
983             marker->SetFillStyle(1001);
984             marker->SetFillColor(color);
985             marker->SetRefObject((TObject*)points);
986             points->Set3DMarker(imark, marker);
987         }
988     }
989 }
990 //___________________________________________
991 void AliMUONDisplay::LoadCoG(Int_t chamber, Int_t cathode)
992 {
993 // Read raw clusters info and store x,y,z info in arrays fRpoints
994 // Loop on all detectors
995
996     if (chamber > 10) return;
997     
998     ResetRpoints();
999     
1000     AliMUON *pMUON  = (AliMUON*)gAlice->GetModule("MUON");
1001     AliMUONChamber*  iChamber;
1002     
1003     TClonesArray *muonRawClusters  = pMUON->RawClustAddress(chamber-1);
1004     if (muonRawClusters == 0) return;
1005
1006     pMUON->ResetRawClusters();
1007
1008
1009     Int_t nent=(Int_t)gAlice->TreeR()->GetEntries();
1010     gAlice->TreeR()->GetEvent(nent-2+cathode-1);
1011     Int_t nrawcl = muonRawClusters->GetEntriesFast();
1012     if (nrawcl == 0) return;
1013     if (fRpoints == 0) fRpoints = new TObjArray(nrawcl);
1014     
1015     iChamber = &(pMUON->Chamber(chamber-1));
1016     Float_t zpos=iChamber->Z();  
1017     AliMUONRawCluster  *mRaw;
1018     AliMUONPoints *points = 0;
1019     //
1020     //loop over all raw clusters and store their position
1021     points = new AliMUONPoints(nrawcl);
1022     for (Int_t iraw=0;iraw<nrawcl;iraw++) {
1023         mRaw   = (AliMUONRawCluster*)muonRawClusters->UncheckedAt(iraw);
1024         fRpoints->AddAt(points,iraw);
1025         points->SetMarkerColor(51);
1026         points->SetMarkerStyle(2);
1027         points->SetMarkerSize(1.);
1028         points->SetParticle(-1);
1029         points->SetHitIndex(-1);
1030         points->SetTrackIndex(-1);
1031         points->SetDigitIndex(-1);
1032         points->SetPoint(iraw,mRaw->fX[0],mRaw->fY[0],zpos);
1033     }
1034 }
1035 //___________________________________________
1036 void AliMUONDisplay::LoadCoG2(Int_t chamber, Int_t cathode)
1037 {
1038 // Read raw clusters info and store x,y,z info in arrays fRpoints
1039 // Loop on all detectors
1040
1041     if (chamber > 10) return;
1042
1043     ResetR2points();
1044
1045     AliMUON *pMUON  = (AliMUON*)gAlice->GetModule("MUON");
1046     AliMUONChamber*  iChamber;
1047     
1048     TClonesArray *muonRawClusters  = pMUON->RawClustAddress(chamber-1);
1049     if (muonRawClusters == 0) return;
1050     
1051     pMUON->ResetRawClusters();
1052
1053     Int_t nent=(Int_t)gAlice->TreeR()->GetEntries();
1054     gAlice->TreeR()->GetEvent(nent-2+cathode-1);
1055     Int_t nrawcl = muonRawClusters->GetEntriesFast();
1056     if (nrawcl == 0) return;
1057     if (fR2points == 0) fR2points = new TObjArray(nrawcl);
1058     
1059     iChamber = &(pMUON->Chamber(chamber-1));
1060     Float_t zpos=iChamber->Z();  
1061     AliMUONRawCluster  *mRaw;
1062     AliMUONPoints *points = 0;
1063     //
1064     //loop over all raw clusters and store their position
1065     points = new AliMUONPoints(nrawcl);
1066     for (Int_t iraw=0;iraw<nrawcl;iraw++) {
1067         mRaw   = (AliMUONRawCluster*)muonRawClusters->UncheckedAt(iraw);
1068         fR2points->AddAt(points,iraw);
1069         points->SetMarkerColor(51);
1070         points->SetMarkerStyle(4);
1071         points->SetMarkerSize(1.3);
1072         points->SetParticle(-1);
1073         points->SetHitIndex(-1);
1074         points->SetTrackIndex(-1);
1075         points->SetDigitIndex(-1);
1076         points->SetPoint(iraw,mRaw->fX[0],mRaw->fY[0],zpos);
1077    }
1078 }
1079 //___________________________________________
1080 void AliMUONDisplay::LoadHits(Int_t chamber)
1081 {
1082 // Read hits info and store x,y,z info in arrays fPhits
1083 // Loop on all detectors
1084
1085     if (chamber > 14) return;
1086     Int_t track;
1087
1088     fChamber=chamber;
1089  
1090     ResetPhits();
1091     
1092     AliMUON *pMUON  = (AliMUON*)gAlice->GetModule("MUON");
1093     AliMUONChamber*  iChamber;
1094
1095     iChamber = &(pMUON->Chamber(chamber-1));
1096     Float_t zpos=iChamber->Z();
1097
1098     Int_t ntracks = (Int_t)gAlice->TreeH()->GetEntries();
1099     Int_t nthits=0;
1100     for (track=0; track<ntracks;track++) {
1101         gAlice->ResetHits();
1102         gAlice->TreeH()->GetEvent(track);
1103         TClonesArray *muonHits  = pMUON->Hits();
1104         if (muonHits == 0) return;
1105         nthits += muonHits->GetEntriesFast();
1106     } 
1107     if (fPhits == 0) fPhits = new TObjArray(nthits);
1108     Int_t nhold=0;
1109     for (track=0; track<ntracks;track++) {
1110         gAlice->ResetHits();
1111         gAlice->TreeH()->GetEvent(track);
1112         TClonesArray *muonHits  = pMUON->Hits();
1113         if (muonHits == 0) return;
1114         Int_t nhits = muonHits->GetEntriesFast();
1115         if (nhits == 0) continue;
1116         AliMUONHit *mHit;
1117         AliMUONPoints *points = 0;
1118         Int_t npoints=1;
1119         for (Int_t hit=0;hit<nhits;hit++) {
1120             mHit = (AliMUONHit*)muonHits->UncheckedAt(hit);
1121             Int_t nch  = mHit->fChamber;              // chamber number
1122             if (nch != chamber) continue;
1123             //
1124             // Retrieve info and set the objects
1125             //
1126             points = new AliMUONPoints(npoints);
1127             fPhits->AddAt(points,nhold+hit);
1128             points->SetMarkerColor(kRed);
1129             points->SetMarkerStyle(5);
1130             points->SetMarkerSize(1.);
1131             points->SetParticle(mHit->Track());
1132             points->SetHitIndex(hit);
1133             points->SetTrackIndex(track);
1134             points->SetDigitIndex(-1);
1135             points->SetPoint(0,mHit->X(),mHit->Y(),zpos);
1136         }
1137         nhold+=nhits;
1138     }
1139 }
1140
1141 //_____________________________________________________________________________
1142 void AliMUONDisplay::Paint(Option_t *)
1143 {
1144 //    Paint miscellaneous items
1145 }
1146
1147 //_____________________________________________________________________________
1148 void AliMUONDisplay::SetPickMode()
1149 {
1150 // Set parameters for pick mode.
1151 // 
1152     fZoomMode = 0;
1153
1154     fArcButton->SetY1(fPickButton->GetYlowNDC()+0.5*fPickButton->GetHNDC());
1155     fTrigPad->Modified();
1156 }
1157
1158 //_____________________________________________________________________________
1159 void AliMUONDisplay::SetZoomMode()
1160 {
1161 //  Set parameters for zoom mode
1162     fZoomMode = 1;
1163     
1164     fArcButton->SetY1(fZoomButton->GetYlowNDC()+0.5*fZoomButton->GetHNDC());
1165     fTrigPad->Modified();
1166 }
1167
1168 //_____________________________________________________________________________
1169 void AliMUONDisplay::NextChamber(Int_t delta)
1170 {
1171   // to go from chamber to next chamber if delta = 1
1172   // or previous chamber otherwise
1173     if (delta == 1) {
1174         if (fChamber < AliMUONConstants::NCh()) fChamber++;
1175     } else {
1176         if (fChamber > 1) fChamber--;
1177     }
1178     if (!fPad) return;
1179     fPad->Clear();
1180     LoadDigits(fChamber, fCathode);
1181     Draw();
1182 }
1183
1184 //_____________________________________________________________________________
1185 void AliMUONDisplay::NextCathode()
1186 {
1187     // to switch to other cathode plane
1188     if (!fPad) return;
1189     fPad->Clear();
1190     if (fCathode == 1) {
1191         LoadDigits(fChamber, 2);        
1192     } else {
1193         LoadDigits(fChamber, 1);
1194     }
1195     fNextCathode = kTRUE; // to keep the same zoom
1196     Draw();
1197     fNextCathode = kFALSE;
1198     TPad *pad = (TPad*)gPad->GetPadSave();
1199     pad->Range(fZoomX0[fZooms], fZoomY0[fZooms],
1200                fZoomX1[fZooms], fZoomY1[fZooms]);
1201     pad->Modified();
1202     fPad->cd();
1203     DrawTitle();
1204 }
1205
1206 //_____________________________________________________________________________
1207 void AliMUONDisplay::Trigger()
1208 {
1209   // returns Trigger Decision for current event
1210   AliMUONTriggerDecision* decision= new AliMUONTriggerDecision(1);
1211   decision->Trigger(); 
1212 }
1213
1214
1215 //_____________________________________________________________________________
1216 void AliMUONDisplay::SetChamberAndCathode(Int_t chamber, Int_t cathode)
1217 {
1218 // Set chamber and cathode number
1219    fChamber = chamber;
1220    fCathode = cathode;
1221
1222    if (!fPad) return;
1223    fPad->Clear();
1224    LoadDigits(chamber,cathode);
1225    Draw();
1226 }
1227
1228 void AliMUONDisplay::SetEvent(Int_t newevent)
1229 {
1230 // Chose event 
1231     gAlice->GetEvent(newevent);
1232     fEvent=newevent;
1233     if (!gAlice->TreeD()) return; 
1234     if (!fPad) return;
1235     fPad->Clear();
1236     LoadDigits(fChamber,fCathode);
1237     Draw();
1238 }
1239
1240 //_____________________________________________________________________________
1241 void AliMUONDisplay::SetRange(Float_t rrange, Float_t zrange)
1242 {
1243 // Set view range along R and Z
1244     fRrange = rrange;
1245     fZrange = zrange;
1246
1247     if (!fPad) return;
1248     fPad->Clear();
1249     Draw();
1250 }
1251    
1252 //_____________________________________________________________________________
1253 void AliMUONDisplay::SetView(Float_t theta, Float_t phi, Float_t psi)
1254 {
1255 //  change viewing angles for current event
1256
1257     fPad->cd();
1258     fPhi   = phi;
1259     fTheta = theta;
1260     fPsi   = psi;
1261     Int_t iret = 0;
1262     
1263     TView *view = gPad->GetView();
1264     if (view) view->SetView(fPhi, fTheta, fPsi, iret);
1265     else      Draw();
1266     gPad->Modified();
1267 }
1268
1269 //_____________________________________________________________________________
1270 void AliMUONDisplay::ShowNextEvent(Int_t delta)
1271 {
1272 //  Display (current event_number + delta)
1273 //    delta =  1  shown next event
1274 //    delta = -1 show previous event
1275     if (delta) {
1276         gAlice->Clear();
1277         Int_t currentEvent = gAlice->GetHeader()->GetEvent();
1278         Int_t newEvent     = currentEvent + delta;
1279         gAlice->GetEvent(newEvent);
1280         fEvent=newEvent;
1281         if (!gAlice->TreeD()) return; 
1282     }
1283     
1284     LoadDigits(fChamber, fCathode);
1285     fPad->cd(); 
1286     Draw();
1287 }
1288
1289 //______________________________________________________________________________
1290 void AliMUONDisplay::UnZoom()
1291 {
1292 // Unzoom 
1293     if (fZooms <= 0) return;
1294     fZooms--;
1295     TPad *pad = (TPad*)gPad->GetPadSave();
1296     pad->Range(fZoomX0[fZooms],fZoomY0[fZooms], fZoomX1[fZooms],fZoomY1[fZooms]);
1297     pad->Modified();
1298 }
1299
1300 //_____________________________________________________________________________
1301 void AliMUONDisplay::ResetPoints()
1302 {
1303     //
1304     // Reset array of points
1305     //
1306     if (fPoints) {
1307         fPoints->Delete();
1308         delete fPoints;
1309         fPoints = 0;
1310     }
1311 }
1312 //_____________________________________________________________________________
1313 void AliMUONDisplay::ResetPhits()
1314 {
1315     //
1316     // Reset array of points
1317     //
1318     if (fPhits) {
1319         fPhits->Delete();
1320         delete fPhits;
1321         fPhits = 0;
1322     }
1323 }
1324 //_____________________________________________________________________________
1325 void AliMUONDisplay::ResetRpoints()
1326 {
1327   //
1328   // Reset array of points
1329   //
1330     if (fRpoints) {
1331         fRpoints->Delete();
1332         delete fRpoints;
1333         fRpoints = 0;
1334     }
1335 }
1336 //_____________________________________________________________________________
1337 void AliMUONDisplay::ResetR2points()
1338 {
1339   //
1340   // Reset array of points
1341   //
1342     if (fR2points) {
1343         fR2points->Delete();
1344         delete fR2points;
1345         fR2points = 0;
1346     }
1347 }
1348 //_____________________________________________________________________________
1349 void AliMUONDisplay::ResetCpoints()
1350 {
1351     //
1352     // Reset array of points
1353     //
1354   if (fCpoints) {
1355       fCpoints->Delete();
1356       delete fCpoints;
1357       fCpoints = 0;
1358   }
1359 }
1360
1361
1362 AliMUONDisplay & AliMUONDisplay::operator = (const AliMUONDisplay &)
1363 {
1364 // Dummy assignment operator
1365     return *this;
1366 }
1367
1368
1369
1370
1371
1372
1373
1374
1375