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