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