]> git.uio.no Git - u/mrichter/AliRoot.git/blob - MUON/AliMUON.cxx
Test routine for simulation result (charge spread on pads).
[u/mrichter/AliRoot.git] / MUON / AliMUON.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 $Log$
17 Revision 1.32  2000/10/06 09:08:10  morsch
18 Built geometry includes slat geometry for event display.
19
20 Revision 1.31  2000/10/02 21:28:08  fca
21 Removal of useless dependecies via forward declarations
22
23 Revision 1.30  2000/10/02 16:58:29  egangler
24 Cleaning of the code :
25 -> coding conventions
26 -> void Streamers
27 -> some useless includes removed or replaced by "class" statement
28
29 Revision 1.29  2000/07/28 13:49:38  morsch
30 SetAcceptance defines inner and outer chamber radii according to angular acceptance.
31 Can be used for simple acceptance studies.
32
33 Revision 1.28  2000/07/22 16:43:15  morsch
34 Same comment as before, but now done correctly I hope (sorry it's Saturday evening)
35
36 Revision 1.27  2000/07/22 16:36:50  morsch
37 Change order of indices in creation (new) of xhit and yhit
38
39 Revision 1.26  2000/07/03 11:54:57  morsch
40 AliMUONSegmentation and AliMUONHitMap have been replaced by AliSegmentation and AliHitMap in STEER
41 The methods GetPadIxy and GetPadXxy of AliMUONSegmentation have changed name to GetPadI and GetPadC.
42
43 Revision 1.25  2000/06/29 12:34:09  morsch
44 AliMUONSegmentation class has been made independent of AliMUONChamber. This makes
45 it usable with any other geometry class. The link to the object to which it belongs is
46 established via an index. This assumes that there exists a global geometry manager
47 from which the pointer to the parent object can be obtained (in our case gAlice).
48
49 Revision 1.24  2000/06/28 15:16:35  morsch
50 (1) Client code adapted to new method signatures in AliMUONSegmentation (see comments there)
51 to allow development of slat-muon chamber simulation and reconstruction code in the MUON
52 framework. The changes should have no side effects (mostly dummy arguments).
53 (2) Hit disintegration uses 3-dim hit coordinates to allow simulation
54 of chambers with overlapping modules (MakePadHits, Disintegration).
55
56 Revision 1.23  2000/06/28 12:19:17  morsch
57 More consequent seperation of global input data services (AliMUONClusterInput singleton) and the
58 cluster and hit reconstruction algorithms in AliMUONClusterFinderVS.
59 AliMUONClusterFinderVS becomes the base class for clustering and hit reconstruction.
60 It requires two cathode planes. Small modifications in the code will make it usable for
61 one cathode plane and, hence, more general (for test beam data).
62 AliMUONClusterFinder is now obsolete.
63
64 Revision 1.22  2000/06/28 08:06:10  morsch
65 Avoid global variables in AliMUONClusterFinderVS by seperating the input data for the fit from the
66 algorithmic part of the class. Input data resides inside the AliMUONClusterInput singleton.
67 It also naturally takes care of the TMinuit instance.
68
69 Revision 1.21  2000/06/27 08:54:41  morsch
70 Problems with on constant array sizes (in hitMap, nmuon, xhit, yhit) corrected.
71
72 Revision 1.20  2000/06/26 14:02:38  morsch
73 Add class AliMUONConstants with MUON specific constants using static memeber data and access methods.
74
75 Revision 1.19  2000/06/22 13:40:51  morsch
76 scope problem on HP, "i" declared once
77 pow changed to TMath::Power (PH, AM)
78
79 Revision 1.18  2000/06/15 07:58:48  morsch
80 Code from MUON-dev joined
81
82 Revision 1.14.4.17  2000/06/14 14:36:46  morsch
83 - add TriggerCircuit (PC)
84 - add GlobalTrigger and LocalTrigger and specific methods (PC)
85
86 Revision 1.14.4.16  2000/06/09 21:20:28  morsch
87 Most coding rule violations corrected
88
89 Revision 1.14.4.15  2000/05/02 09:54:32  morsch
90 RULE RN17 violations corrected
91
92 Revision 1.14.4.12  2000/04/26 12:25:02  morsch
93 Code revised by P. Crochet:
94 - Z position of TriggerChamber changed according to A.Tournaire Priv.Comm.
95 - ToF included in the method MakePadHits
96 - inner radius of flange between beam shielding and trigger corrected
97 - Trigger global volume updated (according to the new geometry)
98
99 Revision 1.14.4.11  2000/04/19 19:42:08  morsch
100 Some changes of variable names curing viols and methods concerning
101 correlated clusters removed.
102
103 Revision 1.14.4.10  2000/03/22 16:44:07  gosset
104 Memory leak suppressed in function Digitise:
105 p_adr->Delete() instead of Clear (I.Chevrot and A.Baldisseri)
106
107 Revision 1.14.4.9  2000/03/20 18:15:25  morsch
108 Positions of trigger chambers corrected (P.C.)
109
110 Revision 1.14.4.8  2000/02/21 15:38:01  morsch
111 Call to AddHitList introduced to make this version compatible with head.
112
113 Revision 1.14.4.7  2000/02/20 07:45:53  morsch
114 Bugs in Trigger part of BuildGeomemetry corrected (P.C)
115
116 Revision 1.14.4.6  2000/02/17 14:28:54  morsch
117 Trigger included into initialization and digitization
118
119 Revision 1.14.4.5  2000/02/15 10:02:58  morsch
120 Log messages of previous revisions added
121
122 Revision 1.14.4.2  2000/02/04 10:57:34  gosset
123 Z position of the chambers:
124 it was the Z position of the stations;
125 it is now really the Z position of the chambers.
126    !!!! WARNING: THE CALLS TO "AliMUONChamber::SetZPOS"
127    !!!!                   AND "AliMUONChamber::ZPosition"
128    !!!! HAVE TO BE CHANGED TO "AliMUONChamber::"SetZ"
129    !!!!                   AND "AliMUONChamber::Z"
130
131 Revision 1.14.4.3  2000/02/04 16:19:04  gosset
132 Correction for mis-spelling of NCH 
133
134 Revision 1.14.4.4  2000/02/15 09:43:38  morsch
135 Log message added
136
137 */
138
139
140 ///////////////////////////////////////////////
141 //  Manager and hits classes for set:MUON     //
142 ////////////////////////////////////////////////
143
144 #include <TTUBE.h>
145 #include <TBRIK.h>
146 #include <TRotMatrix.h>
147 #include <TGeometry.h>
148 #include <TNode.h> 
149 #include <TTree.h> 
150 #include <TRandom.h> 
151 #include <TObject.h>
152 #include <TVector.h>
153 #include <TObjArray.h>
154 #include <TMinuit.h>
155 #include <TParticle.h>
156 #include <TROOT.h>
157 #include <TFile.h>
158 #include <TNtuple.h>
159 #include <TCanvas.h>
160 #include <TPad.h>
161 #include <TDirectory.h>
162 #include <TObjectTable.h>
163 #include <AliPDG.h>
164 #include <TTUBE.h>
165
166 #include "AliMUON.h"
167 #include "AliMUONHit.h"
168 #include "AliMUONPadHit.h"
169 #include "AliMUONDigit.h"
170 #include "AliMUONTransientDigit.h"
171 #include "AliMUONRawCluster.h"
172 #include "AliMUONLocalTrigger.h"
173 #include "AliMUONGlobalTrigger.h"
174 #include "AliMUONTriggerCircuit.h"
175 #include "AliHitMap.h"
176 #include "AliMUONHitMapA1.h"
177 #include "AliMUONChamberTrigger.h"
178 #include "AliMUONConstants.h"
179 #include "AliMUONClusterFinderVS.h"
180 #include "AliMUONTriggerDecision.h"
181 #include "AliRun.h"
182 #include "AliMC.h"
183 #include "AliMUONClusterInput.h"
184 #include "iostream.h"
185 #include "AliCallf77.h" 
186 #include "AliConst.h" 
187
188 // Defaults parameters for Z positions of chambers
189 // taken from values for "stations" in AliMUON::AliMUON
190 //     const Float_t zch[7]={528, 690., 975., 1249., 1449., 1610, 1710.};
191 // and from array "dstation" in AliMUONv1::CreateGeometry
192 //          Float_t dstation[5]={20., 20., 20, 20., 20.};
193 //     for tracking chambers,
194 //          according to (Z1 = zch - dstation) and  (Z2 = zch + dstation)
195 //          for the first and second chambers in the station, respectively,
196 // and from "DTPLANES" in AliMUONv1::CreateGeometry
197 //           const Float_t DTPLANES = 15.;
198 //     for trigger chambers,
199 //          according to (Z1 = zch) and  (Z2 = zch + DTPLANES)
200 //          for the first and second chambers in the station, respectively
201
202 ClassImp(AliMUON)
203 //___________________________________________
204 AliMUON::AliMUON()
205 {
206    fIshunt       = 0;
207    fHits         = 0;
208    fPadHits      = 0;
209    fNPadHits     = 0;
210    fDchambers    = 0;
211    fTriggerCircuits = 0;     // cp new design of AliMUONTriggerDecision
212    fNdch         = 0;
213    fRawClusters  = 0;
214    fNrawch       = 0;
215    fGlobalTrigger   = 0;
216    fNLocalTrigger   = 0;
217    fLocalTrigger    = 0;
218    fNLocalTrigger   = 0;
219    fAccMin          = 0.;
220    fAccMax          = 0.;   
221    fAccCut          = kFALSE;
222 }
223  
224 //___________________________________________
225 AliMUON::AliMUON(const char *name, const char *title)
226        : AliDetector(name,title)
227 {
228 //Begin_Html
229 /*
230 <img src="gif/alimuon.gif">
231 */
232 //End_Html
233
234    fHits     = new TClonesArray("AliMUONHit",1000);
235    gAlice->AddHitList(fHits);
236    fPadHits = new TClonesArray("AliMUONPadHit",10000);
237    fNPadHits  =  0;
238    fIshunt     =  0;
239
240    fNdch      = new Int_t[AliMUONConstants::NCh()];
241
242    fDchambers = new TObjArray(AliMUONConstants::NCh());
243
244    Int_t i;
245    
246    for (i=0; i<AliMUONConstants::NCh() ;i++) {
247        (*fDchambers)[i] = new TClonesArray("AliMUONDigit",10000); 
248        fNdch[i]=0;
249    }
250
251    fNrawch      = new Int_t[AliMUONConstants::NTrackingCh()];
252
253    fRawClusters = new TObjArray(AliMUONConstants::NTrackingCh());
254
255    for (i=0; i<AliMUONConstants::NTrackingCh();i++) {
256        (*fRawClusters)[i] = new TClonesArray("AliMUONRawCluster",10000); 
257        fNrawch[i]=0;
258    }
259
260    fGlobalTrigger = new TClonesArray("AliMUONGlobalTrigger",1);    
261    fNGlobalTrigger = 0;
262    fLocalTrigger  = new TClonesArray("AliMUONLocalTrigger",234);    
263    fNLocalTrigger = 0;
264
265    SetMarkerColor(kRed);
266 //
267 //
268 //
269 //
270
271     Int_t ch;
272
273     fChambers = new TObjArray(AliMUONConstants::NCh());
274
275     // Loop over stations
276     for (Int_t st = 0; st < AliMUONConstants::NCh() / 2; st++) {
277       // Loop over 2 chambers in the station
278         for (Int_t stCH = 0; stCH < 2; stCH++) {
279 //
280 //    
281 //    Default Parameters for Muon Tracking Stations
282
283
284             ch = 2 * st + stCH;
285 //
286             if (ch < AliMUONConstants::NTrackingCh()) {
287                 (*fChambers)[ch] = new AliMUONChamber(ch);
288             } else {
289                 (*fChambers)[ch] = new AliMUONChamberTrigger(ch);
290             }
291             
292             AliMUONChamber* chamber = (AliMUONChamber*) (*fChambers)[ch];
293             
294             chamber->SetGid(0);
295             // Default values for Z of chambers
296             chamber->SetZ(AliMUONConstants::DefaultChamberZ(ch));
297 //
298             chamber->InitGeo(AliMUONConstants::DefaultChamberZ(ch));
299 //          Set chamber inner and outer radius to default
300             chamber->SetRInner(AliMUONConstants::Dmin(st)/2);
301             chamber->SetROuter(AliMUONConstants::Dmax(st)/2);
302 //
303         } // Chamber stCH (0, 1) in 
304     }     // Station st (0...)
305     fMaxStepGas=0.01; 
306     fMaxStepAlu=0.1; 
307     fMaxDestepGas=-1;
308     fMaxDestepAlu=-1;
309 //
310    fMaxIterPad   = 0;
311    fCurIterPad   = 0;
312 //
313    fAccMin          = 0.;
314    fAccMax          = 0.;   
315    fAccCut          = kFALSE;
316
317    // cp new design of AliMUONTriggerDecision
318    fTriggerCircuits = new TObjArray(AliMUONConstants::NTriggerCircuit());
319    for (Int_t circ=0; circ<AliMUONConstants::NTriggerCircuit(); circ++) {
320      (*fTriggerCircuits)[circ] = new AliMUONTriggerCircuit();     
321    }
322    // cp new design of AliMUONTriggerDecision
323
324 }
325  
326 //___________________________________________
327 AliMUON::AliMUON(const AliMUON& rMUON)
328 {
329 // Dummy copy constructor
330     ;
331     
332 }
333
334 AliMUON::~AliMUON()
335 {
336     printf("Calling AliMUON destructor !!!\n");
337     
338     Int_t i;
339     fIshunt  = 0;
340     delete fHits;
341     delete fPadHits;
342     
343     delete fGlobalTrigger;
344     fNGlobalTrigger = 0;
345     
346     delete fLocalTrigger;
347     fNLocalTrigger = 0;
348
349     for (i=0;i<AliMUONConstants::NCh();i++) {
350         delete (*fDchambers)[i];
351         fNdch[i]=0;
352     }
353     delete fDchambers;
354     
355     for (i=0;i<AliMUONConstants::NTrackingCh();i++) {
356         delete (*fRawClusters)[i];
357         fNrawch[i]=0;
358     }
359     delete fRawClusters;
360     
361     for (Int_t circ=0; circ<AliMUONConstants::NTriggerCircuit(); circ++) {
362         delete (*fTriggerCircuits)[circ];
363     }
364     delete fTriggerCircuits;
365 }
366  
367 //___________________________________________
368 void AliMUON::AddHit(Int_t track, Int_t *vol, Float_t *hits)
369 {
370   TClonesArray &lhits = *fHits;
371   new(lhits[fNhits++]) AliMUONHit(fIshunt,track,vol,hits);
372 }
373 //___________________________________________
374 void AliMUON::AddPadHit(Int_t *clhits)
375 {
376    TClonesArray &lclusters = *fPadHits;
377    new(lclusters[fNPadHits++]) AliMUONPadHit(clhits);
378 }
379 //_____________________________________________________________________________
380 void AliMUON::AddDigits(Int_t id, Int_t *tracks, Int_t *charges, Int_t *digits)
381 {
382     //
383     // Add a MUON digit to the list
384     //
385
386     TClonesArray &ldigits = *((TClonesArray*)(*fDchambers)[id]);
387     new(ldigits[fNdch[id]++]) AliMUONDigit(tracks,charges,digits);
388 }
389
390 //_____________________________________________________________________________
391 void AliMUON::AddRawCluster(Int_t id, const AliMUONRawCluster& c)
392 {
393     //
394     // Add a MUON digit to the list
395     //
396
397     TClonesArray &lrawcl = *((TClonesArray*)(*fRawClusters)[id]);
398     new(lrawcl[fNrawch[id]++]) AliMUONRawCluster(c);
399 }
400
401 //___________________________________________
402 void AliMUON::AddGlobalTrigger(Int_t *singlePlus, Int_t *singleMinus,
403                                Int_t *singleUndef,
404                                Int_t *pairUnlike, Int_t *pairLike)
405 {
406 // add a MUON Global Trigger to the list (only one GlobalTrigger per event !)
407   TClonesArray &globalTrigger = *fGlobalTrigger;
408   new(globalTrigger[fNGlobalTrigger++]) 
409     AliMUONGlobalTrigger(singlePlus, singleMinus,  singleUndef, pairUnlike, 
410                          pairLike);
411 }
412 //___________________________________________
413 void AliMUON::AddLocalTrigger(Int_t *localtr)
414 {
415 // add a MUON Local Trigger to the list
416   TClonesArray &localTrigger = *fLocalTrigger;
417   new(localTrigger[fNLocalTrigger++]) AliMUONLocalTrigger(localtr);
418 }
419
420 //___________________________________________
421 void AliMUON::BuildGeometry()
422 {
423     TNode *node, *nodeF, *top, *nodeS;
424     const int kColorMUON  = kBlue;
425     const int kColorMUON2 = kYellow;
426     const int kColorMUON3 = kBlue; 
427     //
428     top=gAlice->GetGeometry()->GetNode("alice");
429 // MUON
430 //
431 //  z-Positions of Chambers
432     const Float_t kCz[7]={511., 686., 971., 1245., 1445., 1600, 1700.};
433 //  inner diameter (Xlenght for trigger chamber -> active area)
434     const Float_t kDmin[7]={ 35.,  47.,  67.,   86.,  100., 544., 544.};
435 //  outer diameter (Ylenght for trigger chamber -> active area)
436     const Float_t kDmax[7]={183., 245., 346.,  520.,  520., 612., 612.};
437
438     TRotMatrix* rot000 = new TRotMatrix("Rot000"," ", 90,  0, 90, 90, 0, 0);
439     TRotMatrix* rot090 = new TRotMatrix("Rot090"," ", 90, 90, 90,180, 0, 0);
440     TRotMatrix* rot180 = new TRotMatrix("Rot180"," ", 90,180, 90,270, 0, 0);
441     TRotMatrix* rot270 = new TRotMatrix("Rot270"," ", 90,270, 90,  0, 0, 0);
442     
443     Float_t rmin, rmax, dx, dy, dz, dr, xpos, ypos, zpos;
444     Float_t dzc1=4.;           // tracking chambers
445     Float_t dzc2=15.;          // trigger chambers
446     Float_t hole=102.;          // x-y hole around beam pipe for trig. chambers
447     Float_t zscale;            // scaling parameter trigger chambers
448     Float_t halfx, halfy;   
449     char nameChamber[9], nameSense[9], nameFrame[9], nameNode[9];
450     char nameSense1[9], nameSense2[9];    
451     for (Int_t i=0; i<7; i++) {
452         for (Int_t j=0; j<2; j++) {
453             Int_t id=2*i+j+1;
454             if (i<5) {               // tracking chambers
455                 if (j==0) {
456                     zpos=kCz[i]-dzc1;
457                 } else {
458                     zpos=kCz[i]+dzc1;
459                 }
460             } else {
461                 if (j==0) {
462                     zpos=kCz[i];
463                 } else {            
464                     zpos=kCz[i]+dzc2;
465                 }
466             }
467             sprintf(nameChamber,"C_MUON%d",id);
468             sprintf(nameSense,"S_MUON%d",id);
469             sprintf(nameSense1,"S1_MUON%d",id);
470             sprintf(nameSense2,"S2_MUON%d",id);
471             sprintf(nameFrame,"F_MUON%d",id);   
472             if (i<3) {                        // tracking chambers
473                 rmin = kDmin[i]/2.-3;
474                 rmax = kDmax[i]/2.+3;
475                 new TTUBE(nameChamber,"Mother","void",rmin,rmax,0.25,1.);
476                 rmin = kDmin[i]/2.;
477                 rmax = kDmax[i]/2.;
478                 new TTUBE(nameSense,"Sens. region","void",rmin,rmax,0.25, 1.);
479                 dx=(rmax-rmin)/2;
480                 dy=3.;
481                 dz=0.25;
482                 TBRIK* frMUON = new TBRIK(nameFrame,"Frame","void",dx,dy,dz);
483                 top->cd();
484                 sprintf(nameNode,"MUON%d",100+id);
485                 node = new TNode(nameNode,"ChamberNode",nameChamber,0,0,zpos,"");
486                 node->SetLineColor(kColorMUON);
487                 fNodes->Add(node);
488                 node->cd();
489                 sprintf(nameNode,"MUON%d",200+id);
490                 node = new TNode(nameNode,"Sens. Region Node",nameSense,0,0,0,"");
491                 node->SetLineColor(kColorMUON);
492                 node->cd();
493                 dr=dx+rmin;
494                 sprintf(nameNode,"MUON%d",300+id);
495                 nodeF = new TNode(nameNode,"Frame0",frMUON,dr, 0, 0,rot000,"");
496                 nodeF->SetLineColor(kColorMUON);
497                 node->cd();
498                 sprintf(nameNode,"MUON%d",400+id);
499                 nodeF = new TNode(nameNode,"Frame1",frMUON,0 ,dr,0,rot090,"");
500                 nodeF->SetLineColor(kColorMUON);
501                 node->cd();
502                 sprintf(nameNode,"MUON%d",500+id);
503                 nodeF = new TNode(nameNode,"Frame2",frMUON,-dr,0,0,rot180,"");
504                 nodeF->SetLineColor(kColorMUON);
505                 node  ->cd();
506                 sprintf(nameNode,"MUON%d",600+id);   
507                 nodeF = new TNode(nameNode,"Frame3",frMUON,0,-dr,0,rot270,"");
508                 nodeF->SetLineColor(kColorMUON);
509             } else if (i == 3 || i == 4) {
510                 Int_t   npcb[7] = {7, 7, 6, 6, 5, 4, 3};
511                 char nameSlat[9];
512                 
513                 Float_t xpos=4.;
514                 Float_t ypos1=-0.75+20.;
515                 Float_t ypos2= 0.75-20.;
516                 
517                 new TBRIK(nameChamber,"Mother","void",340,340,5.);
518                 top->cd();
519                 sprintf(nameNode,"MUON%d",100+id);
520                 node = new TNode(nameNode,"Chambernode",nameChamber,0,0,zpos,"");
521                 node->SetLineColor(kBlack);
522                 fNodes->Add(node);
523                 TNode* nodeSlat;
524                 Int_t color;
525                 
526                 for (Int_t j=0; j<7; j++)
527                 {
528                     printf("\n BuildGeometry %d", j);
529                     
530                     sprintf(nameSlat,"SLAT%d",100*id+j);
531                     new TBRIK(nameSlat,"Slat Module","void",20.*npcb[j],20.,0.25);
532                     node->cd();
533                     xpos=20.*npcb[j]+4;
534                     if (j==0) xpos+=30;
535
536                     color =  TMath::Even(j) ? kColorMUON2 : kColorMUON3;
537                     
538                     sprintf(nameNode,"SLAT%d",100*id+j);
539                     nodeSlat = 
540                         new TNode(nameNode,"Slat Module",nameSlat,xpos,ypos1,0,"");
541                     nodeSlat->SetLineColor(color);
542
543                     node->cd();
544                     sprintf(nameNode,"SLAT%d",100*id+j+7);
545                     nodeSlat = 
546                         new TNode(nameNode,"Slat Module",nameSlat,-xpos,ypos1,0,"");
547                     nodeSlat->SetLineColor(color);
548                     
549                     color =  TMath::Even(j) ? kColorMUON3 : kColorMUON2;
550                     sprintf(nameNode,"SLAT%d",100*id+j+14);
551                     nodeSlat = 
552                         new TNode(nameNode,"Slat Module",nameSlat,xpos,ypos2,0,"");
553                     nodeSlat->SetLineColor(color);
554
555                     node->cd();
556                     sprintf(nameNode,"SLAT%d",100*id+j+21);
557                     nodeSlat = 
558                         new TNode(nameNode,"Slat Module",nameSlat,-xpos,ypos2,0,"");
559                     nodeSlat->SetLineColor(color);
560                     
561                     ypos1+=38.5;
562                     ypos2-=38.5;
563                 }
564                 
565             } else { 
566                 zscale=zpos/kCz[5];
567                 Float_t xsize=kDmin[i]*zscale;
568                 Float_t ysize=kDmax[i]*zscale;
569                 Float_t holeScaled=hole*zscale;
570                 
571                 halfx=xsize/2.+3.;
572                 halfy=ysize/2.+3.;          
573                 new TBRIK(nameChamber,"Mother","void",halfx,halfy,0.25);
574                 top->cd();
575                 sprintf(nameNode,"MUON%d",100+id);
576                 node = new TNode(nameNode,"Chambernode",nameChamber,0,0,zpos,"");
577                 node->SetLineColor(kColorMUON2);
578                 fNodes->Add(node);
579                 
580 // up/down of beam pipe
581                 halfx=xsize/2.;
582                 halfy=(ysize/2.-holeScaled/2.)/2.;          
583                 new TBRIK(nameSense,"Sens. region","void",halfx,halfy,0.25);
584                 
585                 node->cd();
586                 ypos=holeScaled/2.+((ysize/2.-holeScaled/2.)/2.);
587                 sprintf(nameNode,"MUON%d",200+id);
588                 nodeS = new TNode(nameNode,"Sens. Region Node",nameSense,0,ypos,0,"");
589                 nodeS->SetLineColor(kColorMUON2);
590                 
591                 node->cd();
592                 ypos=-1.*ypos;
593                 sprintf(nameNode,"MUON%d",300+id);
594                 nodeS = new TNode(nameNode,"Sens. Region Node",nameSense,0,ypos,0,"");
595                 nodeS->SetLineColor(kColorMUON2);
596                 
597 // left/right of beam pipe
598                 halfx=(xsize/2.-holeScaled/2.)/2.;
599                 halfy=holeScaled/2.;    
600                 new TBRIK(nameSense1,"Sens. region","void",halfx,halfy,0.25);
601                 
602                 node->cd();
603                 xpos=holeScaled/2.+((xsize/2.-holeScaled/2.)/2.);           
604                 sprintf(nameNode,"MUON%d",400+id);
605                 nodeS = new TNode(nameNode,"Sens. Region Node",nameSense1,xpos,0,0,"");
606                 nodeS->SetLineColor(kColorMUON2);
607                 
608                 node->cd();
609                 xpos=-1.*xpos;
610                 sprintf(nameNode,"MUON%d",500+id);
611                 nodeS = new TNode(nameNode,"Sens. Region Node",nameSense1,xpos,0,0,"");
612                 nodeS->SetLineColor(kColorMUON2);
613                 
614 // missing corners
615                 halfx=17.*zscale/2.;
616                 halfy=halfx;
617                 new TBRIK(nameSense2,"Sens. region","void",halfx,halfy,0.25);
618                 
619                 node->cd();
620                 xpos=holeScaled/2.-halfx;
621                 ypos=xpos;
622                 sprintf(nameNode,"MUON%d",600+id);
623                 nodeS = new TNode(nameNode,"Sens. Region Node",nameSense2,xpos,ypos,0,"");
624                 nodeS->SetLineColor(kColorMUON2);
625                 
626                 node->cd();
627                 ypos=-1.*xpos;
628                 sprintf(nameNode,"MUON%d",700+id);
629                 nodeS = new TNode(nameNode,"Sens. Region Node",nameSense2,xpos,ypos,0,"");
630                 nodeS->SetLineColor(kColorMUON2);
631                 
632                 node->cd();
633                 xpos=-1.*xpos;
634                 sprintf(nameNode,"MUON%d",800+id);
635                 nodeS = new TNode(nameNode,"Sens. Region Node",nameSense2,xpos,ypos,0,"");
636                 nodeS->SetLineColor(kColorMUON2);
637                 
638                 node->cd();
639                 ypos=-1.*xpos;
640                 sprintf(nameNode,"MUON%d",900+id);
641                 nodeS = new TNode(nameNode,"Sens. Region Node",nameSense2,xpos,ypos,0,"");
642                 nodeS->SetLineColor(kColorMUON2);
643             } 
644         }
645     }
646 }
647
648
649 //___________________________________________
650 Int_t AliMUON::DistancetoPrimitive(Int_t , Int_t )
651 {
652    return 9999;
653 }
654
655 //___________________________________________
656 void AliMUON::MakeBranch(Option_t* option)
657 {
658     // Create Tree branches for the MUON.
659     const Int_t kBufferSize = 4000;
660     char branchname[30];
661     sprintf(branchname,"%sCluster",GetName());
662     
663     AliDetector::MakeBranch(option);
664     
665     if (fPadHits   && gAlice->TreeH()) {
666         gAlice->TreeH()->Branch(branchname,&fPadHits, kBufferSize);
667         printf("Making Branch %s for clusters\n",branchname);
668     }
669     
670 // one branch for digits per chamber
671     Int_t i;
672     
673     for (i=0; i<AliMUONConstants::NCh() ;i++) {
674         sprintf(branchname,"%sDigits%d",GetName(),i+1);
675         
676         if (fDchambers   && gAlice->TreeD()) {
677             gAlice->TreeD()->Branch(branchname,&((*fDchambers)[i]), kBufferSize);
678             printf("Making Branch %s for digits in chamber %d\n",branchname,i+1);
679         }       
680     }
681     
682     printf("Make Branch - TreeR address %p\n",gAlice->TreeR());
683     
684 // one branch for raw clusters per chamber
685     for (i=0; i<AliMUONConstants::NTrackingCh() ;i++) {
686         sprintf(branchname,"%sRawClusters%d",GetName(),i+1);
687         
688         if (fRawClusters   && gAlice->TreeR()) {
689             gAlice->TreeR()->Branch(branchname,&((*fRawClusters)[i]), kBufferSize);
690             printf("Making Branch %s for raw clusters in chamber %d\n",branchname,i+1);
691         }       
692     }
693     
694 // one branch for global trigger
695     sprintf(branchname,"%sGlobalTrigger",GetName());
696     if (fGlobalTrigger && gAlice->TreeR()) {  
697         gAlice->TreeR()->Branch(branchname,&fGlobalTrigger,kBufferSize);
698         printf("Making Branch %s for Global Trigger\n",branchname);
699     }
700 // one branch for local trigger
701     sprintf(branchname,"%sLocalTrigger",GetName());
702     if (fLocalTrigger && gAlice->TreeR()) {  
703         gAlice->TreeR()->Branch(branchname,&fLocalTrigger,kBufferSize);
704         printf("Making Branch %s for Local Trigger\n",branchname);
705     }
706     
707 }
708
709 //___________________________________________
710 void AliMUON::SetTreeAddress()
711 {
712   // Set branch address for the Hits and Digits Tree.
713   char branchname[30];
714   AliDetector::SetTreeAddress();
715
716   TBranch *branch;
717   TTree *treeH = gAlice->TreeH();
718   TTree *treeD = gAlice->TreeD();
719   TTree *treeR = gAlice->TreeR();
720
721   if (treeH) {
722     if (fPadHits) {
723       branch = treeH->GetBranch("MUONCluster");
724       if (branch) branch->SetAddress(&fPadHits);
725     }
726   }
727
728   if (treeD) {
729       for (int i=0; i<AliMUONConstants::NCh(); i++) {
730           sprintf(branchname,"%sDigits%d",GetName(),i+1);
731           if (fDchambers) {
732               branch = treeD->GetBranch(branchname);
733               if (branch) branch->SetAddress(&((*fDchambers)[i]));
734           }
735       }
736   }
737
738   // printf("SetTreeAddress --- treeR address  %p \n",treeR);
739
740   if (treeR) {
741       for (int i=0; i<AliMUONConstants::NTrackingCh(); i++) {
742           sprintf(branchname,"%sRawClusters%d",GetName(),i+1);
743           if (fRawClusters) {
744               branch = treeR->GetBranch(branchname);
745               if (branch) branch->SetAddress(&((*fRawClusters)[i]));
746           }
747       }
748
749       if (fLocalTrigger) {
750         branch = treeR->GetBranch("MUONLocalTrigger");
751         if (branch) branch->SetAddress(&fLocalTrigger);
752       }
753       if (fGlobalTrigger) {
754         branch = treeR->GetBranch("MUONGlobalTrigger");
755         if (branch) branch->SetAddress(&fGlobalTrigger);
756       }
757   }
758 }
759 //___________________________________________
760 void AliMUON::ResetHits()
761 {
762   // Reset number of clusters and the cluster array for this detector
763   AliDetector::ResetHits();
764   fNPadHits = 0;
765   if (fPadHits) fPadHits->Clear();
766 }
767
768 //____________________________________________
769 void AliMUON::ResetDigits()
770 {
771     //
772     // Reset number of digits and the digits array for this detector
773     //
774     for ( int i=0;i<AliMUONConstants::NCh();i++ ) {
775         if ((*fDchambers)[i])    ((TClonesArray*)(*fDchambers)[i])->Clear();
776         if (fNdch)  fNdch[i]=0;
777     }
778 }
779 //____________________________________________
780 void AliMUON::ResetRawClusters()
781 {
782     //
783     // Reset number of raw clusters and the raw clust array for this detector
784     //
785     for ( int i=0;i<AliMUONConstants::NTrackingCh();i++ ) {
786         if ((*fRawClusters)[i])    ((TClonesArray*)(*fRawClusters)[i])->Clear();
787         if (fNrawch)  fNrawch[i]=0;
788     }
789 }
790
791 //____________________________________________
792 void AliMUON::ResetTrigger()
793 {
794   //  Reset Local and Global Trigger 
795   fNGlobalTrigger = 0;
796   if (fGlobalTrigger) fGlobalTrigger->Clear();
797   fNLocalTrigger = 0;
798   if (fLocalTrigger) fLocalTrigger->Clear();
799 }
800
801 //____________________________________________
802 void AliMUON::SetPadSize(Int_t id, Int_t isec, Float_t p1, Float_t p2)
803 {
804     Int_t i=2*(id-1);
805     ((AliMUONChamber*) (*fChambers)[i])  ->SetPadSize(isec,p1,p2);
806     ((AliMUONChamber*) (*fChambers)[i+1])->SetPadSize(isec,p1,p2);
807 }
808
809 //___________________________________________
810 void AliMUON::SetChambersZ(const Float_t *Z)
811 {
812   // Set Z values for all chambers (tracking and trigger)
813   // from the array pointed to by "Z"
814     for (Int_t ch = 0; ch < AliMUONConstants::NCh(); ch++)
815         ((AliMUONChamber*) ((*fChambers)[ch]))->SetZ(Z[ch]);
816     return;
817 }
818
819 //___________________________________________
820 void AliMUON::SetChambersZToDefault()
821 {
822   // Set Z values for all chambers (tracking and trigger)
823   // to default values
824   SetChambersZ(AliMUONConstants::DefaultChamberZ());
825   return;
826 }
827
828 //___________________________________________
829 void AliMUON::SetChargeSlope(Int_t id, Float_t p1)
830 {
831     Int_t i=2*(id-1);
832     ((AliMUONChamber*) (*fChambers)[i])->SetChargeSlope(p1);
833     ((AliMUONChamber*) (*fChambers)[i+1])->SetChargeSlope(p1);
834 }
835
836 //___________________________________________
837 void AliMUON::SetChargeSpread(Int_t id, Float_t p1, Float_t p2)
838 {
839     Int_t i=2*(id-1);
840     ((AliMUONChamber*) (*fChambers)[i])->SetChargeSpread(p1,p2);
841     ((AliMUONChamber*) (*fChambers)[i+1])->SetChargeSpread(p1,p2);
842 }
843
844 //___________________________________________
845 void AliMUON::SetSigmaIntegration(Int_t id, Float_t p1)
846 {
847     Int_t i=2*(id-1);
848     ((AliMUONChamber*) (*fChambers)[i])->SetSigmaIntegration(p1);
849     ((AliMUONChamber*) (*fChambers)[i+1])->SetSigmaIntegration(p1);
850 }
851
852 //___________________________________________
853 void AliMUON::SetMaxAdc(Int_t id, Int_t p1)
854 {
855     Int_t i=2*(id-1);
856     ((AliMUONChamber*) (*fChambers)[i])->SetMaxAdc(p1);
857     ((AliMUONChamber*) (*fChambers)[i+1])->SetMaxAdc(p1);
858 }
859
860 //___________________________________________
861 void AliMUON::SetMaxStepGas(Float_t p1)
862 {
863      fMaxStepGas=p1;
864 }
865
866 //___________________________________________
867 void AliMUON::SetMaxStepAlu(Float_t p1)
868 {
869     fMaxStepAlu=p1;
870 }
871
872 //___________________________________________
873 void AliMUON::SetMaxDestepGas(Float_t p1)
874 {
875     fMaxDestepGas=p1;
876 }
877
878 //___________________________________________
879 void AliMUON::SetMaxDestepAlu(Float_t p1)
880 {
881     fMaxDestepAlu=p1;
882 }
883 //___________________________________________
884 void AliMUON::SetAcceptance(Bool_t acc, Float_t angmin, Float_t angmax)
885 {
886    fAccCut=acc;
887    fAccMin=angmin*TMath::Pi()/180;
888    fAccMax=angmax*TMath::Pi()/180;
889    Int_t ch;
890    if (acc) {
891        for (Int_t st = 0; st < AliMUONConstants::NCh() / 2; st++) {
892            // Loop over 2 chambers in the station
893            for (Int_t stCH = 0; stCH < 2; stCH++) {
894                ch = 2 * st + stCH;
895 //         Set chamber inner and outer radius according to acceptance cuts
896                Chamber(ch).SetRInner(AliMUONConstants::DefaultChamberZ(ch)*TMath::Tan(fAccMin));
897                Chamber(ch).SetROuter(AliMUONConstants::DefaultChamberZ(ch)*TMath::Tan(fAccMax));
898            } // chamber loop
899        } // station loop
900    }
901 }
902 //___________________________________________
903 void   AliMUON::SetSegmentationModel(Int_t id, Int_t isec, AliSegmentation *segmentation)
904 {
905     ((AliMUONChamber*) (*fChambers)[id])->SetSegmentationModel(isec, segmentation);
906
907 }
908 //___________________________________________
909 void   AliMUON::SetResponseModel(Int_t id, AliMUONResponse *response)
910 {
911     ((AliMUONChamber*) (*fChambers)[id])->SetResponseModel(response);
912 }
913
914 void   AliMUON::SetReconstructionModel(Int_t id, AliMUONClusterFinderVS *reconst)
915 {
916     ((AliMUONChamber*) (*fChambers)[id])->SetReconstructionModel(reconst);
917 }
918
919 void   AliMUON::SetNsec(Int_t id, Int_t nsec)
920 {
921     ((AliMUONChamber*) (*fChambers)[id])->SetNsec(nsec);
922 }
923
924
925 //___________________________________________
926
927
928
929 void AliMUON::MakePadHits(Float_t xhit,Float_t yhit, Float_t zhit,
930                           Float_t eloss, Float_t tof,  Int_t idvol)
931 {
932 //
933 //  Calls the charge disintegration method of the current chamber and adds
934 //  the simulated cluster to the root treee 
935 //
936     Int_t clhits[7];
937     Float_t newclust[6][500];
938     Int_t nnew;
939     
940     
941 //
942 //  Integrated pulse height on chamber
943
944     
945     clhits[0]=fNhits+1;
946 //
947 //
948 //    if (idvol == 6) printf("\n ->Disintegration %f %f %f", xhit, yhit, eloss );
949     
950
951     ((AliMUONChamber*) (*fChambers)[idvol])
952         ->DisIntegration(eloss, tof, xhit, yhit, zhit, nnew, newclust);
953     Int_t ic=0;
954 //    if (idvol == 6) printf("\n nnew  %d \n", nnew);
955 //
956 //  Add new clusters
957     for (Int_t i=0; i<nnew; i++) {
958         if (Int_t(newclust[3][i]) > 0) {
959             ic++;
960 // Cathode plane
961             clhits[1] = Int_t(newclust[5][i]);
962 //  Cluster Charge
963             clhits[2] = Int_t(newclust[0][i]);
964 //  Pad: ix
965             clhits[3] = Int_t(newclust[1][i]);
966 //  Pad: iy 
967             clhits[4] = Int_t(newclust[2][i]);
968 //  Pad: charge
969             clhits[5] = Int_t(newclust[3][i]);
970 //  Pad: chamber sector
971             clhits[6] = Int_t(newclust[4][i]);
972             
973             AddPadHit(clhits);
974         }
975     }
976 }
977
978 //----------------------------------------------------------------------
979
980 void AliMUON::Digitise(Int_t nev,Int_t bgrEvent,Option_t *option,Option_t *opt,Text_t *filename)
981 {
982     // keep galice.root for signal and name differently the file for 
983     // background when add! otherwise the track info for signal will be lost !
984   
985     static Bool_t first=kTRUE;
986     static TFile *file;
987     char *addBackground = strstr(option,"Add");
988
989
990     AliMUONChamber*   iChamber;
991     AliSegmentation*  segmentation;
992
993     
994     Int_t trk[50];
995     Int_t chtrk[50];  
996     TObjArray *list=new TObjArray;
997     static TClonesArray *pAddress=0;
998     if(!pAddress) pAddress=new TClonesArray("TVector",1000);
999     Int_t digits[5]; 
1000
1001     AliMUON *pMUON  = (AliMUON *) gAlice->GetModule("MUON");
1002     AliHitMap** hitMap= new AliHitMap* [AliMUONConstants::NCh()];
1003     for (Int_t i=0; i<AliMUONConstants::NCh(); i++) {hitMap[i]=0;}
1004     if (addBackground ) {
1005         if(first) {
1006             fFileName=filename;
1007             cout<<"filename"<<fFileName<<endl;
1008             file=new TFile(fFileName);
1009             cout<<"I have opened "<<fFileName<<" file "<<endl;
1010             fHits2     = new TClonesArray("AliMUONHit",1000  );
1011             fPadHits2 = new TClonesArray("AliMUONPadHit",10000);
1012         }           
1013         first=kFALSE;
1014         file->cd();
1015         //file->ls();
1016         // Get Hits Tree header from file
1017         if(fHits2) fHits2->Clear();
1018         if(fPadHits2) fPadHits2->Clear();
1019         if(fTrH1) delete fTrH1;
1020         fTrH1=0;
1021         
1022         char treeName[20];
1023         sprintf(treeName,"TreeH%d",bgrEvent);
1024         fTrH1 = (TTree*)gDirectory->Get(treeName);
1025         //printf("fTrH1 %p of treename %s for event %d \n",fTrH1,treeName,bgrEvent);
1026         
1027         if (!fTrH1) {
1028             printf("ERROR: cannot find Hits Tree for event:%d\n",bgrEvent);
1029         }
1030         // Set branch addresses
1031         TBranch *branch;
1032         char branchname[20];
1033         sprintf(branchname,"%s",GetName());
1034         if (fTrH1 && fHits2) {
1035             branch = fTrH1->GetBranch(branchname);
1036             if (branch) branch->SetAddress(&fHits2);
1037         }
1038         if (fTrH1 && fPadHits2) {
1039             branch = fTrH1->GetBranch("MUONCluster");
1040             if (branch) branch->SetAddress(&fPadHits2);
1041         }
1042 // test
1043         //Int_t ntracks1 =(Int_t)fTrH1->GetEntries();
1044         //printf("background - ntracks1 - %d\n",ntracks1);
1045     }
1046     //
1047     // loop over cathodes
1048     //
1049     AliHitMap* hm;
1050     Int_t countadr=0;
1051     for (int icat=0; icat<2; icat++) { 
1052         Int_t counter=0;
1053         Int_t * nmuon = new Int_t [AliMUONConstants::NCh()];
1054         for (Int_t i =0; i<AliMUONConstants::NCh(); i++) {
1055             iChamber=(AliMUONChamber*) (*fChambers)[i];
1056             if (iChamber->Nsec()==1 && icat==1) {
1057                 continue;
1058             } else {
1059                 segmentation=iChamber->SegmentationModel(icat+1);
1060             }
1061             hitMap[i] = new AliMUONHitMapA1(segmentation, list);
1062             nmuon[i]=0;
1063         }
1064         //printf("Start loop over tracks \n");     
1065 //
1066 //   Loop over tracks
1067 //
1068
1069         TTree *treeH = gAlice->TreeH();
1070         Int_t ntracks =(Int_t) treeH->GetEntries();
1071         Int_t jj;
1072
1073         Float_t ** xhit = new Float_t * [AliMUONConstants::NCh()];
1074         for (jj=0; jj<AliMUONConstants::NCh(); jj++) xhit[jj] = new Float_t[2];
1075         Float_t ** yhit = new Float_t * [AliMUONConstants::NCh()];
1076         for (jj=0; jj<AliMUONConstants::NCh(); jj++) yhit[jj] = new Float_t[2];
1077
1078         for (Int_t track=0; track<ntracks; track++) {
1079             gAlice->ResetHits();
1080             treeH->GetEvent(track);
1081 //
1082 //   Loop over hits
1083             for(AliMUONHit* mHit=(AliMUONHit*)pMUON->FirstHit(-1); 
1084                 mHit;
1085                 mHit=(AliMUONHit*)pMUON->NextHit()) 
1086             {
1087                 Int_t   nch   = mHit->fChamber-1;  // chamber number
1088                 if (nch > AliMUONConstants::NCh()-1) continue;
1089 //              if (nch > 9) continue;
1090                 iChamber = &(pMUON->Chamber(nch));
1091                 // new 17.07.99
1092                 if (addBackground) {
1093
1094                     if (mHit->fParticle == kMuonPlus 
1095                         || mHit->fParticle == kMuonMinus) {
1096                         xhit[nch][nmuon[nch]]=mHit->X();
1097                         yhit[nch][nmuon[nch]]=mHit->Y();
1098                         nmuon[nch]++;
1099                         if (nmuon[nch] >2) printf("nmuon %d\n",nmuon[nch]);
1100                     }
1101                 }
1102                 
1103
1104
1105                 
1106 //
1107 // Loop over pad hits
1108                 for (AliMUONPadHit* mPad=
1109                          (AliMUONPadHit*)pMUON->FirstPad(mHit,fPadHits);
1110                      mPad;
1111                      mPad=(AliMUONPadHit*)pMUON->NextPad(fPadHits))
1112                 {
1113                     Int_t cathode  = mPad->fCathode;    // cathode number
1114                     Int_t ipx      = mPad->fPadX;       // pad number on X
1115                     Int_t ipy      = mPad->fPadY;       // pad number on Y
1116                     Int_t iqpad    = Int_t(mPad->fQpad);// charge per pad
1117 //                  printf("\n Pad: %d %d %d %d", ipx, ipy, cathode,nch);
1118 //
1119 //
1120                     
1121                     if (cathode != (icat+1)) continue;
1122                     // fill the info array
1123 //                  Float_t thex, they, thez;
1124                     segmentation=iChamber->SegmentationModel(cathode);
1125 //                  segmentation->GetPadC(ipx,ipy,thex,they,thez);
1126 //                  Float_t rpad=TMath::Sqrt(thex*thex+they*they);
1127 //                  if (rpad < rmin || iqpad ==0 || rpad > rmax) continue;
1128
1129                     new((*pAddress)[countadr++]) TVector(2);
1130                     TVector &trinfo=*((TVector*) (*pAddress)[countadr-1]);
1131                     trinfo(0)=(Float_t)track;
1132                     trinfo(1)=(Float_t)iqpad;
1133
1134                     digits[0]=ipx;
1135                     digits[1]=ipy;
1136                     digits[2]=iqpad;
1137                     digits[3]=iqpad;
1138                     if (mHit->fParticle == kMuonPlus ||
1139                         mHit->fParticle == kMuonMinus) {
1140                         digits[4]=mPad->fHitNumber;
1141                     } else digits[4]=-1;
1142
1143                     AliMUONTransientDigit* pdigit;
1144                     // build the list of fired pads and update the info
1145                     if (!hitMap[nch]->TestHit(ipx, ipy)) {
1146
1147                         list->AddAtAndExpand(
1148                             new AliMUONTransientDigit(nch,digits),counter);
1149                         
1150                         hitMap[nch]->SetHit(ipx, ipy, counter);
1151                         counter++;
1152                         pdigit=(AliMUONTransientDigit*)list->At(list->GetLast());
1153                         // list of tracks
1154                         TObjArray *trlist=(TObjArray*)pdigit->TrackList();
1155                         trlist->Add(&trinfo);
1156                     } else {
1157                         pdigit=(AliMUONTransientDigit*) hitMap[nch]->GetHit(ipx, ipy);
1158                         // update charge
1159                         (*pdigit).fSignal+=iqpad;
1160                         (*pdigit).fPhysics+=iqpad;                      
1161                         // update list of tracks
1162                         TObjArray* trlist=(TObjArray*)pdigit->TrackList();
1163                         Int_t lastEntry=trlist->GetLast();
1164                         TVector *pTrack=(TVector*)trlist->At(lastEntry);
1165                         TVector &ptrk=*pTrack;
1166                         Int_t lastTrack  = Int_t(ptrk(0));
1167                         Int_t lastCharge = Int_t(ptrk(1));
1168                         if (lastTrack==track) {
1169                             lastCharge+=iqpad;
1170                             trlist->RemoveAt(lastEntry);
1171                             trinfo(0)=lastTrack;
1172                             trinfo(1)=lastCharge;
1173                             trlist->AddAt(&trinfo,lastEntry);
1174                         } else {
1175                             trlist->Add(&trinfo);
1176                         }
1177                         // check the track list
1178                         Int_t nptracks=trlist->GetEntriesFast();
1179                         if (nptracks > 2) {
1180                             for (Int_t tr=0;tr<nptracks;tr++) {
1181                                 TVector *ppTrack=(TVector*)trlist->At(tr);
1182                                 TVector &pptrk=*ppTrack;
1183                                 trk[tr]   = Int_t(pptrk(0));
1184                                 chtrk[tr] = Int_t(pptrk(1));
1185                             }
1186                         } // end if nptracks
1187                     } //  end if pdigit
1188                 } //end loop over clusters
1189             } // hit loop
1190         } // track loop
1191
1192         // open the file with background
1193        
1194         if (addBackground) {
1195             ntracks =(Int_t)fTrH1->GetEntries();
1196 //
1197 //   Loop over tracks
1198 //
1199             for (Int_t track=0; track<ntracks; track++) {
1200
1201                 if (fHits2)       fHits2->Clear();
1202                 if (fPadHits2)   fPadHits2->Clear();
1203
1204                 fTrH1->GetEvent(track);
1205 //
1206 //   Loop over hits
1207                 AliMUONHit* mHit;
1208                 for(int i=0;i<fHits2->GetEntriesFast();++i) 
1209                 {       
1210                     mHit=(AliMUONHit*) (*fHits2)[i];
1211                     Int_t   nch   = mHit->fChamber-1;  // chamber number
1212                     if (nch >9) continue;
1213                     iChamber = &(pMUON->Chamber(nch));
1214 //                  Int_t rmin = (Int_t)iChamber->RInner();
1215 //                  Int_t rmax = (Int_t)iChamber->ROuter();
1216                     Float_t xbgr=mHit->X();
1217                     Float_t ybgr=mHit->Y();
1218                     Bool_t cond=kFALSE;
1219                     
1220                     for (Int_t imuon =0; imuon < nmuon[nch]; imuon++) {
1221                         Float_t dist= (xbgr-xhit[nch][imuon])*(xbgr-xhit[nch][imuon])
1222                             +(ybgr-yhit[nch][imuon])*(ybgr-yhit[nch][imuon]);
1223                         if (dist<100) cond=kTRUE;
1224                     }
1225                     if (!cond) continue;
1226                     
1227 //
1228 // Loop over pad hits
1229                     for (AliMUONPadHit* mPad=
1230                              (AliMUONPadHit*)pMUON->FirstPad(mHit,fPadHits2);
1231                          mPad;
1232                          mPad=(AliMUONPadHit*)pMUON->NextPad(fPadHits2))
1233                     {
1234                         //                  mPad = (AliMUONPadHit*) (*fPadHits2)[j];
1235                         Int_t cathode  = mPad->fCathode;    // cathode number
1236                         Int_t ipx      = mPad->fPadX;       // pad number on X
1237                         Int_t ipy      = mPad->fPadY;       // pad number on Y
1238                         Int_t iqpad    = Int_t(mPad->fQpad);// charge per pad
1239
1240                         if (cathode != (icat+1)) continue;
1241                         printf("\n Pad: %d %d %d", ipx, ipy, cathode);
1242                         
1243 //                      Float_t thex, they, thez;
1244 //                      segmentation=iChamber->SegmentationModel(cathode);
1245 //                      segmentation->GetPadC(ipx,ipy,thex,they,thez);
1246 //                      Float_t rpad=TMath::Sqrt(thex*thex+they*they);
1247 //                      if (rpad < rmin || iqpad ==0 || rpad > rmax) continue;
1248                         new((*pAddress)[countadr++]) TVector(2);
1249                         TVector &trinfo=*((TVector*) (*pAddress)[countadr-1]);
1250                         trinfo(0)=-1;  // tag background
1251                         trinfo(1)=-1;
1252                         
1253                         digits[0]=ipx;
1254                         digits[1]=ipy;
1255                         digits[2]=iqpad;
1256                         digits[3]=0;
1257                         digits[4]=-1;
1258                         
1259                         AliMUONTransientDigit* pdigit;
1260                         // build the list of fired pads and update the info
1261                         if (!hitMap[nch]->TestHit(ipx, ipy)) {
1262                             list->AddAtAndExpand(new AliMUONTransientDigit(nch,digits),counter);
1263                             
1264                             hitMap[nch]->SetHit(ipx, ipy, counter);
1265                             counter++;
1266                             
1267                             pdigit=(AliMUONTransientDigit*)list->At(list->GetLast());
1268                             // list of tracks
1269                             TObjArray *trlist=(TObjArray*)pdigit->
1270                                 TrackList();
1271                             trlist->Add(&trinfo);
1272                         } else {
1273                             pdigit=(AliMUONTransientDigit*) hitMap[nch]->GetHit(ipx, ipy);
1274                             // update charge
1275                             (*pdigit).fSignal+=iqpad;
1276                             
1277                             // update list of tracks
1278                             TObjArray* trlist=(TObjArray*)pdigit->
1279                                 TrackList();
1280                             Int_t lastEntry=trlist->GetLast();
1281                             TVector *pTrack=(TVector*)trlist->
1282                                 At(lastEntry);
1283                             TVector &ptrk=*pTrack;
1284                             Int_t lastTrack=Int_t(ptrk(0));
1285                             if (lastTrack==-1) {
1286                                 continue;
1287                             } else {
1288                                 trlist->Add(&trinfo);
1289                             }
1290                                 // check the track list
1291                             Int_t nptracks=trlist->GetEntriesFast();
1292                             if (nptracks > 0) {
1293                                 for (Int_t tr=0;tr<nptracks;tr++) {
1294                                     TVector *ppTrack=(TVector*)trlist->At(tr);
1295                                     TVector &pptrk=*ppTrack;
1296                                     trk[tr]=Int_t(pptrk(0));
1297                                     chtrk[tr]=Int_t(pptrk(1));
1298                                 }
1299                             } // end if nptracks
1300                         } //  end if pdigit
1301                     } //end loop over clusters
1302                 } // hit loop
1303             } // track loop
1304             //Int_t nentr2=list->GetEntriesFast();
1305             //printf(" \n counter2, nentr2 %d %d \n",counter,nentr2);
1306             TTree *fAli=gAlice->TreeK();
1307             TFile *file=NULL;
1308             
1309             if (fAli) file =fAli->GetCurrentFile();
1310             file->cd();
1311         } // if addBackground
1312         delete [] xhit;
1313         delete [] yhit;
1314
1315         Int_t tracks[10];
1316         Int_t charges[10];
1317         Int_t nentries=list->GetEntriesFast();
1318         
1319         for (Int_t nent=0;nent<nentries;nent++) {
1320             AliMUONTransientDigit *address=(AliMUONTransientDigit*)list->At(nent);
1321             if (address==0) continue; 
1322             Int_t ich=address->fChamber;
1323             Int_t q=address->fSignal; 
1324             iChamber=(AliMUONChamber*) (*fChambers)[ich];
1325 //
1326 //  Digit Response (noise, threshold, saturation, ...)
1327 //              if (address->fPhysics !=0 ) address->fPhysics+=(Int_t)Noise; 
1328             AliMUONResponse * response=iChamber->ResponseModel();
1329             q=response->DigitResponse(q);
1330             
1331             if (!q) continue;
1332             
1333             digits[0]=address->fPadX;
1334             digits[1]=address->fPadY;
1335             digits[2]=q;
1336             digits[3]=address->fPhysics;
1337             digits[4]=address->fHit;
1338             
1339             TObjArray* trlist=(TObjArray*)address->TrackList();
1340             Int_t nptracks=trlist->GetEntriesFast();
1341             //printf("nptracks, trlist   %d  %p\n",nptracks,trlist);
1342
1343             // this was changed to accomodate the real number of tracks
1344             if (nptracks > 10) {
1345                 cout<<"Attention - nptracks > 10 "<<nptracks<<endl;
1346                 nptracks=10;
1347             }
1348             if (nptracks > 2) {
1349                 printf("Attention - nptracks > 2  %d \n",nptracks);
1350                 printf("cat,ich,ix,iy,q %d %d %d %d %d \n",icat,ich,digits[0],digits[1],q);
1351             }
1352             for (Int_t tr=0;tr<nptracks;tr++) {
1353                 TVector *ppP=(TVector*)trlist->At(tr);
1354                 if(!ppP ) printf("ppP - %p\n",ppP);
1355                 TVector &pp  =*ppP;
1356                 tracks[tr]=Int_t(pp(0));
1357                 charges[tr]=Int_t(pp(1));
1358                 //printf("tracks, charges - %d %d\n",tracks[tr],charges[tr]);
1359             }      //end loop over list of tracks for one pad
1360             // Sort list of tracks according to charge
1361             if (nptracks > 1) {
1362                 SortTracks(tracks,charges,nptracks);
1363             }
1364             if (nptracks < 10 ) {
1365                 for (Int_t i=nptracks; i<10; i++) {
1366                     tracks[i]=0;
1367                     charges[i]=0;
1368                 }
1369             }
1370             
1371             // fill digits
1372             pMUON->AddDigits(ich,tracks,charges,digits);
1373             // delete trlist;
1374         }
1375         //cout<<"I'm out of the loops for digitisation"<<endl;
1376         //      gAlice->GetEvent(nev);
1377         gAlice->TreeD()->Fill();
1378         pMUON->ResetDigits();
1379         list->Delete();
1380
1381         
1382         for(Int_t ii=0;ii<AliMUONConstants::NCh();++ii) {
1383             if (hitMap[ii]) {
1384                 hm=hitMap[ii];
1385                 delete hm;
1386                 hitMap[ii]=0;
1387             }
1388         }
1389         delete [] nmuon;    
1390     } //end loop over cathodes
1391     delete [] hitMap;
1392     char hname[30];
1393     sprintf(hname,"TreeD%d",nev);
1394     gAlice->TreeD()->Write(hname);
1395     // reset tree
1396     gAlice->TreeD()->Reset();
1397     delete list;
1398     
1399     pAddress->Delete();
1400     // gObjectTable->Print();
1401 }
1402
1403 void AliMUON::SortTracks(Int_t *tracks,Int_t *charges,Int_t ntr)
1404 {
1405   //
1406   // Sort the list of tracks contributing to a given digit
1407   // Only the 3 most significant tracks are acctually sorted
1408   //
1409   
1410   //
1411   //  Loop over signals, only 3 times
1412   //
1413   
1414   Int_t qmax;
1415   Int_t jmax;
1416   Int_t idx[3] = {-2,-2,-2};
1417   Int_t jch[3] = {-2,-2,-2};
1418   Int_t jtr[3] = {-2,-2,-2};
1419   Int_t i,j,imax;
1420   
1421   if (ntr<3) imax=ntr;
1422   else imax=3;
1423   for(i=0;i<imax;i++){
1424     qmax=0;
1425     jmax=0;
1426     
1427     for(j=0;j<ntr;j++){
1428       
1429       if((i == 1 && j == idx[i-1]) 
1430          ||(i == 2 && (j == idx[i-1] || j == idx[i-2]))) continue;
1431       
1432       if(charges[j] > qmax) {
1433         qmax = charges[j];
1434         jmax=j;
1435       }       
1436     } 
1437     
1438     if(qmax > 0) {
1439       idx[i]=jmax;
1440       jch[i]=charges[jmax]; 
1441       jtr[i]=tracks[jmax]; 
1442     }
1443     
1444   } 
1445   
1446   for(i=0;i<3;i++){
1447     if (jtr[i] == -2) {
1448          charges[i]=0;
1449          tracks[i]=0;
1450     } else {
1451          charges[i]=jch[i];
1452          tracks[i]=jtr[i];
1453     }
1454   }
1455
1456 }
1457
1458 //___________________________________________
1459 void AliMUON::Trigger(Int_t nev){
1460 // call the Trigger Algorithm and fill TreeR
1461
1462   Int_t singlePlus[3]  = {0,0,0}; 
1463   Int_t singleMinus[3] = {0,0,0}; 
1464   Int_t singleUndef[3] = {0,0,0};
1465   Int_t pairUnlike[3]  = {0,0,0}; 
1466   Int_t pairLike[3]    = {0,0,0};
1467
1468   ResetTrigger();
1469   AliMUONTriggerDecision* decision= new AliMUONTriggerDecision(1);
1470   decision->Trigger();   
1471   decision->GetGlobalTrigger(singlePlus, singleMinus, singleUndef,
1472                              pairUnlike, pairLike);
1473 // add a local trigger in the list 
1474   AddGlobalTrigger(singlePlus, singleMinus, singleUndef, pairUnlike, pairLike);
1475   Int_t i;
1476   
1477   for (Int_t icirc=0; icirc<AliMUONConstants::NTriggerCircuit(); icirc++) { 
1478       if(decision->GetITrigger(icirc)==1) {
1479           Int_t localtr[7]={0,0,0,0,0,0,0};      
1480           Int_t loLpt[2]={0,0}; Int_t loHpt[2]={0,0}; Int_t loApt[2]={0,0};
1481           decision->GetLutOutput(icirc, loLpt, loHpt, loApt);
1482           localtr[0] = icirc;
1483           localtr[1] = decision->GetStripX11(icirc);
1484           localtr[2] = decision->GetDev(icirc);
1485           localtr[3] = decision->GetStripY11(icirc);
1486           for (i=0; i<2; i++) {    // convert the Lut output in 1 digit 
1487               localtr[4] = localtr[4]+Int_t(loLpt[i]*TMath::Power(2,i));
1488               localtr[5] = localtr[5]+Int_t(loHpt[i]*TMath::Power(2,i));
1489               localtr[6] = localtr[6]+Int_t(loApt[i]*TMath::Power(2,i));
1490           }
1491           AddLocalTrigger(localtr);  // add a local trigger in the list
1492       }
1493   }
1494   delete decision;
1495
1496   gAlice->TreeR()->Fill();
1497   ResetTrigger();
1498   char hname[30];
1499   sprintf(hname,"TreeR%d",nev);
1500   gAlice->TreeR()->Write(hname);
1501   gAlice->TreeR()->Reset();
1502   printf("\n End of trigger for event %d", nev);
1503 }
1504
1505
1506 //____________________________________________
1507 void AliMUON::FindClusters(Int_t nev,Int_t lastEntry)
1508 {
1509     TClonesArray *dig1, *dig2;
1510     Int_t ndig, k;
1511     dig1 = new TClonesArray("AliMUONDigit",1000);
1512     dig2 = new TClonesArray("AliMUONDigit",1000);
1513     AliMUONDigit *digit;
1514 //
1515 // Loop on chambers and on cathode planes
1516 //
1517     
1518     for (Int_t ich=0;ich<10;ich++) {
1519         AliMUONChamber* iChamber=(AliMUONChamber*) (*fChambers)[ich];
1520         AliMUONClusterFinderVS* rec = iChamber->ReconstructionModel();    
1521         gAlice->ResetDigits();
1522         gAlice->TreeD()->GetEvent(lastEntry);
1523         TClonesArray *muonDigits  = this->DigitsAddress(ich);
1524         ndig=muonDigits->GetEntriesFast();
1525         printf("\n 1 Found %d digits in %p %d", ndig, muonDigits,ich);
1526         TClonesArray &lhits1 = *dig1;
1527         Int_t n=0;
1528         for (k=0; k<ndig; k++) {
1529             digit=(AliMUONDigit*) muonDigits->UncheckedAt(k);
1530             if (rec->TestTrack(digit->fTracks[0]))
1531                 new(lhits1[n++]) AliMUONDigit(*digit);
1532         }
1533         gAlice->ResetDigits();
1534         gAlice->TreeD()->GetEvent(lastEntry+1);
1535         muonDigits  = this->DigitsAddress(ich);
1536         ndig=muonDigits->GetEntriesFast();
1537         printf("\n 2 Found %d digits in %p %d", ndig, muonDigits, ich);
1538         TClonesArray &lhits2 = *dig2;
1539         n=0;
1540         
1541         for (k=0; k<ndig; k++) {
1542             digit= (AliMUONDigit*) muonDigits->UncheckedAt(k);
1543             if (rec->TestTrack(digit->fTracks[0]))
1544             new(lhits2[n++]) AliMUONDigit(*digit);
1545         }
1546
1547         if (rec) {       
1548             AliMUONClusterInput::Instance()->SetDigits(ich, dig1, dig2);
1549             rec->FindRawClusters();
1550         }
1551         dig1->Delete();
1552         dig2->Delete();
1553     } // for ich
1554     gAlice->TreeR()->Fill();
1555     ResetRawClusters();
1556     char hname[30];
1557     sprintf(hname,"TreeR%d",nev);
1558     gAlice->TreeR()->Write(hname);
1559     gAlice->TreeR()->Reset();
1560     printf("\n End of cluster finding for event %d", nev);
1561     
1562     delete dig1;
1563     delete dig2;
1564     //gObjectTable->Print();
1565 }
1566  
1567
1568 void AliMUON::Streamer(TBuffer &R__b)
1569 {
1570    // Stream an object of class AliMUON.
1571       AliMUONChamber        *iChamber;
1572       AliMUONTriggerCircuit *iTriggerCircuit;
1573       AliSegmentation       *segmentation;
1574       AliMUONResponse       *response;
1575       TClonesArray          *digitsaddress;
1576       TClonesArray          *rawcladdress;
1577       Int_t i;
1578       if (R__b.IsReading()) {
1579           Version_t R__v = R__b.ReadVersion(); if (R__v) { }
1580           AliDetector::Streamer(R__b);
1581           R__b >> fNPadHits;
1582           R__b >> fPadHits; // diff
1583           R__b >> fNLocalTrigger;       
1584           R__b >> fLocalTrigger;       
1585           R__b >> fNGlobalTrigger;       
1586           R__b >> fGlobalTrigger;   
1587           R__b >> fDchambers;
1588           R__b >> fRawClusters;
1589           R__b.ReadArray(fNdch);
1590           R__b.ReadArray(fNrawch);
1591           R__b >> fAccCut;
1592           R__b >> fAccMin;
1593           R__b >> fAccMax; 
1594           R__b >> fChambers;
1595           R__b >> fTriggerCircuits;
1596           for (i =0; i<AliMUONConstants::NTriggerCircuit(); i++) {
1597               iTriggerCircuit=(AliMUONTriggerCircuit*) (*fTriggerCircuits)[i];
1598               iTriggerCircuit->Streamer(R__b);
1599           }
1600 // Stream chamber related information
1601           for (i =0; i<AliMUONConstants::NCh(); i++) {
1602               iChamber=(AliMUONChamber*) (*fChambers)[i];
1603               iChamber->Streamer(R__b);
1604               if (iChamber->Nsec()==1) {
1605                   segmentation=iChamber->SegmentationModel(1);
1606                   if (segmentation)
1607                       segmentation->Streamer(R__b);
1608               } else {
1609                   segmentation=iChamber->SegmentationModel(1);
1610                   if (segmentation)
1611                       segmentation->Streamer(R__b);
1612                   if (segmentation)
1613                       segmentation=iChamber->SegmentationModel(2);
1614                   segmentation->Streamer(R__b);
1615               }
1616               response=iChamber->ResponseModel();
1617               if (response)
1618                   response->Streamer(R__b);       
1619               digitsaddress=(TClonesArray*) (*fDchambers)[i];
1620               digitsaddress->Streamer(R__b);
1621               if (i < AliMUONConstants::NTrackingCh()) {
1622                   rawcladdress=(TClonesArray*) (*fRawClusters)[i];
1623                   rawcladdress->Streamer(R__b);
1624               }
1625           }
1626           
1627       } else {
1628           R__b.WriteVersion(AliMUON::IsA());
1629           AliDetector::Streamer(R__b);
1630           R__b << fNPadHits;
1631           R__b << fPadHits; // diff
1632           R__b << fNLocalTrigger;       
1633           R__b << fLocalTrigger;       
1634           R__b << fNGlobalTrigger;       
1635           R__b << fGlobalTrigger; 
1636           R__b << fDchambers;
1637           R__b << fRawClusters;
1638           R__b.WriteArray(fNdch, AliMUONConstants::NCh());
1639           R__b.WriteArray(fNrawch, AliMUONConstants::NTrackingCh());
1640           
1641           R__b << fAccCut;
1642           R__b << fAccMin;
1643           R__b << fAccMax; 
1644           
1645           R__b << fChambers;
1646           R__b << fTriggerCircuits;
1647           for (i =0; i<AliMUONConstants::NTriggerCircuit(); i++) {
1648               iTriggerCircuit=(AliMUONTriggerCircuit*) (*fTriggerCircuits)[i];
1649               iTriggerCircuit->Streamer(R__b);
1650           }
1651           for (i =0; i<AliMUONConstants::NCh(); i++) {
1652               iChamber=(AliMUONChamber*) (*fChambers)[i];
1653               iChamber->Streamer(R__b);
1654               if (iChamber->Nsec()==1) {
1655                   segmentation=iChamber->SegmentationModel(1);
1656                   if (segmentation)
1657                       segmentation->Streamer(R__b);
1658               } else {
1659                   segmentation=iChamber->SegmentationModel(1);
1660                   if (segmentation)
1661                       segmentation->Streamer(R__b);
1662                   segmentation=iChamber->SegmentationModel(2);
1663                   if (segmentation)
1664                       segmentation->Streamer(R__b);
1665               }
1666               response=iChamber->ResponseModel();
1667               if (response)
1668                   response->Streamer(R__b);
1669               digitsaddress=(TClonesArray*) (*fDchambers)[i];
1670               digitsaddress->Streamer(R__b);
1671               if (i < AliMUONConstants::NTrackingCh()) {
1672                   rawcladdress=(TClonesArray*) (*fRawClusters)[i];
1673                   rawcladdress->Streamer(R__b);
1674               }
1675           }
1676       }
1677 }
1678 AliMUONPadHit* AliMUON::FirstPad(AliMUONHit*  hit, TClonesArray *clusters) 
1679 {
1680 //
1681     // Initialise the pad iterator
1682     // Return the address of the first padhit for hit
1683     TClonesArray *theClusters = clusters;
1684     Int_t nclust = theClusters->GetEntriesFast();
1685     if (nclust && hit->fPHlast > 0) {
1686         AliMUON::fMaxIterPad=hit->fPHlast;
1687         AliMUON::fCurIterPad=hit->fPHfirst;
1688         return (AliMUONPadHit*) clusters->UncheckedAt(AliMUON::fCurIterPad-1);
1689     } else {
1690         return 0;
1691     }
1692 }
1693
1694 AliMUONPadHit* AliMUON::NextPad(TClonesArray *clusters) 
1695 {
1696     AliMUON::fCurIterPad++;
1697     if (AliMUON::fCurIterPad <= AliMUON::fMaxIterPad) {
1698         return (AliMUONPadHit*) clusters->UncheckedAt(AliMUON::fCurIterPad-1);
1699     } else {
1700         return 0;
1701     }
1702 }
1703
1704
1705 AliMUONRawCluster *AliMUON::RawCluster(Int_t ichamber, Int_t icathod, Int_t icluster)
1706 {
1707     TClonesArray *muonRawCluster  = RawClustAddress(ichamber);
1708     ResetRawClusters();
1709     TTree *treeR = gAlice->TreeR();
1710     Int_t nent=(Int_t)treeR->GetEntries();
1711     treeR->GetEvent(nent-2+icathod-1);
1712     //treeR->GetEvent(icathod);
1713     //Int_t nrawcl = (Int_t)muonRawCluster->GetEntriesFast();
1714
1715     AliMUONRawCluster * mRaw = (AliMUONRawCluster*)muonRawCluster->UncheckedAt(icluster);
1716     //printf("RawCluster _ nent nrawcl icluster mRaw %d %d %d%p\n",nent,nrawcl,icluster,mRaw);
1717     
1718     return  mRaw;
1719 }
1720
1721 AliMUON& AliMUON::operator = (const AliMUON& rhs)
1722 {
1723 // copy operator
1724 // dummy version
1725     return *this;
1726 }
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745