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