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