]> git.uio.no Git - u/mrichter/AliRoot.git/blame - FMD/AliFMD.cxx
Implement the new logging system (AliLog)
[u/mrichter/AliRoot.git] / FMD / AliFMD.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 **************************************************************************/
88cb7938 15
16/* $Id$ */
17
4347b38f 18//////////////////////////////////////////////////////////////////////////////
19//
20// Forward Multiplicity Detector based on Silicon wafers This class
21// contains the base procedures for the Forward Multiplicity detector
22// Detector consists of 5 Si volumes covered pseudorapidity interval
23// from 1.7 to 5.1.
24//
25// The actual code is done by various separate classes. Below is
26// diagram showing the relationship between the various FMD classes
27// that handles the geometry
28//
29//
30// +----------+ +----------+
31// | AliFMDv1 | | AliFMDv1 |
32// +----------+ +----------+
33// | |
34// +----+--------------+
35// |
36// | +------------+ 1 +---------------+
37// | +- | AliFMDRing |<>--| AliFMDPolygon |
38// V 2 | +------------+ +---------------+
39// +--------+<>--+ |
40// | AliFMD | ^
41// +--------+<>--+ V 1..2
42// 3 | +-------------------+
43// +-| AliFMDSubDetector |
44// +-------------------+
45// ^
46// |
47// +-------------+-------------+
48// | | |
49// +---------+ +---------+ +---------+
50// | AliFMD1 | | AliFMD2 | | AliFMD3 |
51// +---------+ +---------+ +---------+
52//
53//
54// * AliFMD
55// This defines the interface for the various parts of AliROOT that
56// uses the FMD, like AliFMDDigitizer, AliFMDReconstructor, and so
57// on.
58//
59// * AliFMDv1
60// This is a concrete implementation of the AliFMD interface.
61// It is the responsibility of this class to create the FMD
62// geometry, process hits in the FMD, and serve hits and digits to
63// the various clients.
64//
65// It uses the objects of class AliFMDSubDetector to do the various
66// stuff for FMD1, 2, and 3
67//
68// * AliFMDRing
69// This class contains all stuff needed to do with a ring. It's
70// used by the AliFMDSubDetector objects to instantise inner and
71// outer rings. The AliFMDRing objects are shared by the
72// AliFMDSubDetector objects, and owned by the AliFMDv1 object.
73//
74// * AliFMDPolygon
75// The code I lifted from TGeoPolygon to help with the geometry of
76// the modules, as well as to decide wether a hit is actually with
77// in the real module shape. The point is, that the shape of the
78// various ring modules are really polygons (much like the lid of a
79// coffin), but it's segmented at constant radius. That is very
80// hard to implement using GEANT 3.21 shapes, so instead the
81// modules are implemented as TUBS (tube sections), and in the step
82// procedure we do the test whether the track was inside the real
83// shape of the module.
84//
85// * AliFMD1, AliFMD2, and AliFMD3
86// These are specialisation of AliFMDSubDetector, that contains the
87// particularities of each of the sub-detector system. It is
88// envisioned that the classes should also define the support
89// volumes and material for each of the detectors.
90//
fe4da5cc 91//Begin_Html
92/*
4347b38f 93 <img src="gif/AliFMDClass.gif">
94 </pre>
95 <br clear=left>
96 <p>
97 The responsible person for this module is
98 <a href="mailto:Alla.Maevskaia@cern.ch">Alla Maevskaia</a>.
99 </p>
100 <p>
101 Many modifications by <a href="mailto:cholm@nbi.dk">Christian
102 Holm Christensen</a>.
103 </p>
104 <pre>
fe4da5cc 105*/
106//End_Html
fe4da5cc 107
4347b38f 108#ifndef ROOT_TClonesArray
109#include <TClonesArray.h>
110#endif
111#ifndef ROOT_TGeomtry
112# include <TGeometry.h>
113#endif
114#ifndef ROOT_TNode
115# include <TNode.h>
116#endif
117#ifndef ROOT_TTUBE
118# include <TTUBE.h>
119#endif
120#ifndef ROOT_TTree
121# include <TTree.h>
122#endif
123#ifndef ROOT_TVirtualMC
124# include <TVirtualMC.h>
125#endif
126#ifndef ROOT_TBrowser
127# include <TBrowser.h>
128#endif
129#ifndef ROOT_TMath
130# include <TMath.h>
131#endif
88cb7938 132
4347b38f 133#ifndef ALIRUNDIGITIZER_H
134# include "AliRunDigitizer.h"
135#endif
136#ifndef ALILOADER_H
137# include "AliLoader.h"
138#endif
139#ifndef ALIRUN_H
140# include "AliRun.h"
141#endif
142#ifndef ALIMC_H
143# include "AliMC.h"
144#endif
145#ifndef ALILog_H
146# include "AliLog.h"
147#endif
148#ifndef ALIMAGF_H
149# include "AliMagF.h"
150#endif
151#ifndef ALIFMD_H
152# include "AliFMD.h"
153#endif
154#ifndef ALIFMDDIGIG_H
155# include "AliFMDDigit.h"
156#endif
157#ifndef ALIFMDHIT_H
158# include "AliFMDHit.h"
159#endif
160#ifndef ALIFMDDIGITIZER_H
161# include "AliFMDDigitizer.h"
162#endif
163#ifndef ALIFMD1_H
164# include "AliFMD1.h"
165#endif
166#ifndef ALIFMD2_H
167# include "AliFMD2.h"
168#endif
169#ifndef ALIFMD3_H
170# include "AliFMD3.h"
171#endif
172#ifndef ALIALTROBUFFER_H
173# include "AliAltroBuffer.h"
174#endif
88cb7938 175
4347b38f 176//____________________________________________________________________
177ClassImp(AliFMD);
178
179//____________________________________________________________________
180AliFMD::AliFMD()
181 : fInner(0),
182 fOuter(0),
183 fFMD1(0),
184 fFMD2(0),
185 fFMD3(0)
fe4da5cc 186{
187 //
188 // Default constructor for class AliFMD
189 //
4347b38f 190 AliDebug(0, "Default CTOR");
dc8af42e 191 fHits = 0;
192 fDigits = 0;
4347b38f 193 fSDigits = 0;
194 fNsdigits = 0;
195 fIshunt = 0;
fe4da5cc 196}
dc8af42e 197
4347b38f 198//____________________________________________________________________
199AliFMD::AliFMD(const char *name, const char *title, bool detailed)
200 : AliDetector (name, title),
201 fInner(0),
202 fOuter(0),
203 fFMD1(0),
204 fFMD2(0),
205 fFMD3(0)
fe4da5cc 206{
207 //
208 // Standard constructor for Forward Multiplicity Detector
209 //
4347b38f 210 AliDebug(0, "Standard CTOR");
dc8af42e 211
fe4da5cc 212 // Initialise Hit array
4347b38f 213 HitsArray();
214 gAlice->GetMCApp()->AddHitList(fHits);
d1280e40 215
4347b38f 216 // (S)Digits for the detectors disk
217 DigitsArray();
218 SDigitsArray();
219
220 // CHC: What is this?
dc8af42e 221 fIshunt = 0;
4347b38f 222 SetMarkerColor(kRed);
223 SetLineColor(kYellow);
224 SetSiDensity();
225
226 // Create sub-volume managers
227 fInner = new AliFMDRing('I', detailed);
228 fOuter = new AliFMDRing('O', detailed);
229 fFMD1 = new AliFMD1();
230 fFMD2 = new AliFMD2();
231 fFMD3 = new AliFMD3();
232
233 // Specify parameters of sub-volume managers
234 fFMD1->SetInner(fInner);
235 fFMD1->SetOuter(0);
236
237 fFMD2->SetInner(fInner);
238 fFMD2->SetOuter(fOuter);
239
240 fFMD3->SetInner(fInner);
241 fFMD3->SetOuter(fOuter);
242
243 SetLegLength();
244 SetLegRadius();
245 SetLegOffset();
246 SetModuleSpacing();
247
248 fInner->SetLowR(4.3);
249 fInner->SetHighR(17.2);
250 fInner->SetWaferRadius(13.4/2);
251 fInner->SetTheta(36/2);
252 fInner->SetNStrips(512);
253 fInner->SetSiThickness(.03);
254 fInner->SetPrintboardThickness(.11);
255 fInner->SetBondingWidth(.5);
256
257 fOuter->SetLowR(15.6);
258 fOuter->SetHighR(28.0);
259 fOuter->SetWaferRadius(13.4/2);
260 fOuter->SetTheta(18/2);
261 fOuter->SetNStrips( 256);
262 fOuter->SetSiThickness(.03);
263 fOuter->SetPrintboardThickness(.1);
264 fOuter->SetBondingWidth(.5);
265
266
267 fFMD1->SetHoneycombThickness(1);
268 fFMD1->SetInnerZ(340.0);
269
270 fFMD2->SetHoneycombThickness(1);
271 fFMD2->SetInnerZ(83.4);
272 fFMD2->SetOuterZ(75.2);
273
274 fFMD3->SetHoneycombThickness(1);
275 fFMD3->SetInnerZ(-62.8);
276 fFMD3->SetOuterZ(-75.2);
fe4da5cc 277}
d28dcc0d 278
4347b38f 279//____________________________________________________________________
dc8af42e 280AliFMD::~AliFMD ()
d28dcc0d 281{
4347b38f 282 // Destructor for base class AliFMD
283 if (fHits) {
284 fHits->Delete();
285 delete fHits;
286 fHits = 0;
287 }
288 if (fDigits) {
289 fDigits->Delete();
290 delete fDigits;
291 fDigits = 0;
292 }
293 if (fSDigits) {
294 fSDigits->Delete();
295 delete fSDigits;
296 fSDigits = 0;
297 }
298}
299
300//====================================================================
301//
302// GEometry ANd Traking
303//
304//____________________________________________________________________
305void
306AliFMD::CreateGeometry()
307{
308 //
309 // Create the geometry of Forward Multiplicity Detector version 0
310 //
311 // DebugGuard guard("AliFMD::CreateGeometry");
312 AliDebug(10, "Creating geometry");
dc8af42e 313
4347b38f 314 fInner->Init();
315 fOuter->Init();
316
317 TString name;
318 Double_t par[3];
319
320 par[0] = fLegRadius - .1;
321 par[1] = fLegRadius;
322 par[2] = fLegLength / 2;
323 name = "SLEG";
324 fShortLegId = gMC->Gsvolu(name.Data(),"TUBE",(*fIdtmed)[kPlasticId],par,3);
325
326 par[2] += fModuleSpacing / 2;
327 name = "LLEG";
328 fLongLegId = gMC->Gsvolu(name.Data(),"TUBE",(*fIdtmed)[kPlasticId],par,3);
329
330 fInner->SetupGeometry((*fIdtmed)[kAirId],
331 (*fIdtmed)[kSiId],
332 (*fIdtmed)[kPcbId],
333 fPrintboardRotationId,
334 fIdentityRotationId);
335 fOuter->SetupGeometry((*fIdtmed)[kAirId],
336 (*fIdtmed)[kSiId],
337 (*fIdtmed)[kPcbId],
338 fPrintboardRotationId,
339 fIdentityRotationId);
340
341 fFMD1->SetupGeometry((*fIdtmed)[kAirId], (*fIdtmed)[kKaptionId]);
342 fFMD2->SetupGeometry((*fIdtmed)[kAirId], (*fIdtmed)[kKaptionId]);
343 fFMD3->SetupGeometry((*fIdtmed)[kAirId], (*fIdtmed)[kKaptionId]);
344
345 fFMD1->Geometry("ALIC", fPrintboardRotationId, fIdentityRotationId);
346 fFMD2->Geometry("ALIC", fPrintboardRotationId, fIdentityRotationId);
347 fFMD3->Geometry("ALIC", fPrintboardRotationId, fIdentityRotationId);
348}
349
350//____________________________________________________________________
351void AliFMD::CreateMaterials()
352{
353 // Register various materials and tracking mediums with the
354 // backend.
355 //
356 // Currently defined materials and mediums are
357 //
358 // FMD Air Normal air
359 // FMD Si Active silicon of sensors
360 // FMD Carbon Normal carbon used in support, etc.
361 // FMD Kapton Carbon used in Honeycomb
362 // FMD PCB Printed circuit board material
363 // FMD Plastic Material for support legs
364 //
365 // Also defined are two rotation matricies.
366 //
367 // DebugGuard guard("AliFMD::CreateMaterials");
368 AliDebug(10, "Creating materials");
369 Int_t id;
370 Double_t a = 0;
371 Double_t z = 0;
372 Double_t density = 0;
373 Double_t radiationLength = 0;
374 Double_t absorbtionLength = 999;
375 Int_t fieldType = gAlice->Field()->Integ(); // Field type
376 Double_t maxField = gAlice->Field()->Max(); // Field max.
377 Double_t maxBending = 0; // Max Angle
378 Double_t maxStepSize = 0.001; // Max step size
379 Double_t maxEnergyLoss = 1; // Max Delta E
380 Double_t precision = 0.001; // Precision
381 Double_t minStepSize = 0.001; // Minimum step size
382
383 // Silicon
384 a = 28.0855;
385 z = 14.;
386 density = fSiDensity;
387 radiationLength = 9.36;
388 maxBending = 1;
389 maxStepSize = .001;
390 precision = .001;
391 minStepSize = .001;
392 id = kSiId;
393 AliMaterial(id, "FMD Si$", a, z, density, radiationLength, absorbtionLength);
394 AliMedium(kSiId, "FMD Si$",id,1,fieldType,maxField,maxBending,
395 maxStepSize,maxEnergyLoss,precision,minStepSize);
396
397
398 // Carbon
399 a = 12.011;
400 z = 6.;
401 density = 2.265;
402 radiationLength = 18.8;
403 maxBending = 10;
404 maxStepSize = .01;
405 precision = .003;
406 minStepSize = .003;
407 id = kCarbonId;
408 AliMaterial(id, "FMD Carbon$", a, z, density, radiationLength,
409 absorbtionLength);
410 AliMedium(kCarbonId, "FMD Carbon$",id,0,fieldType,maxField,maxBending,
411 maxStepSize,maxEnergyLoss,precision,minStepSize);
412
413 // Silicon chip
414 {
415 Float_t as[] = { 12.0107, 14.0067, 15.9994,
416 1.00794, 28.0855, 107.8682 };
417 Float_t zs[] = { 6., 7., 8.,
418 1., 14., 47. };
419 Float_t ws[] = { 0.039730642, 0.001396798, 0.01169634,
420 0.004367771, 0.844665, 0.09814344903 };
421 density = 2.36436;
422 maxBending = 10;
423 maxStepSize = .01;
424 precision = .003;
425 minStepSize = .003;
426 id = kSiChipId;
427 AliMixture(id, "FMD Si Chip$", as, zs, density, 6, ws);
428 AliMedium(kSiChipId, "FMD Si Chip$", id, 0, fieldType, maxField,
429 maxBending, maxStepSize, maxEnergyLoss, precision, minStepSize);
430 }
431
432
433 // Kaption
434 {
435 Float_t as[] = { 1.00794, 12.0107, 14.010, 15.9994};
436 Float_t zs[] = { 1., 6., 7., 8.};
437 Float_t ws[] = { 0.026362, 0.69113, 0.07327, 0.209235};
438 density = 1.42;
439 maxBending = 1;
440 maxStepSize = .001;
441 precision = .001;
442 minStepSize = .001;
443 id = kKaptionId;
444 AliMixture(id, "FMD Kaption$", as, zs, density, 4, ws);
445 AliMedium(kKaptionId, "FMD Kaption$",id,0,fieldType,maxField,maxBending,
446 maxStepSize,maxEnergyLoss,precision,minStepSize);
447 }
448
449 // Air
450 {
451 Float_t as[] = { 12.0107, 14.0067, 15.9994, 39.948 };
452 Float_t zs[] = { 6., 7., 8., 18. };
453 Float_t ws[] = { 0.000124, 0.755267, 0.231781, 0.012827 };
454 density = .00120479;
455 maxBending = 1;
456 maxStepSize = .001;
457 precision = .001;
458 minStepSize = .001;
459 id = kAirId;
460 AliMixture(id, "FMD Air$", as, zs, density, 4, ws);
461 AliMedium(kAirId, "FMD Air$", id,0,fieldType,maxField,maxBending,
462 maxStepSize,maxEnergyLoss,precision,minStepSize);
463 }
464
465 // PCB
466 {
467 Float_t zs[] = { 14., 20., 13., 12.,
468 5., 22., 11., 19.,
469 26., 9., 8., 6.,
470 7., 1.};
471 Float_t as[] = { 28.0855, 40.078, 26.981538, 24.305,
472 10.811, 47.867, 22.98977, 39.0983,
473 55.845, 18.9984, 15.9994, 12.0107,
474 14.0067, 1.00794};
475 Float_t ws[] = { 0.15144894, 0.08147477, 0.04128158, 0.00904554,
476 0.01397570, 0.00287685, 0.00445114, 0.00498089,
477 0.00209828, 0.00420000, 0.36043788, 0.27529426,
478 0.01415852, 0.03427566};
479 density = 1.8;
480 maxBending = 1;
481 maxStepSize = .001;
482 precision = .001;
483 minStepSize = .001;
484 id = kPcbId;
485 AliMixture(id, "FMD PCB$", as, zs, density, 14, ws);
486 AliMedium(kPcbId, "FMD PCB$", id,1,fieldType,maxField,maxBending,
487 maxStepSize,maxEnergyLoss,precision,minStepSize);
488 }
489
490 // Plastic
491 {
492 Float_t as[] = { 1.01, 12.01 };
493 Float_t zs[] = { 1., 6. };
494 Float_t ws[] = { 1., 1. };
495 density = 1.03;
496 maxBending = 10;
497 maxStepSize = .01;
498 precision = .003;
499 minStepSize = .003;
500 id = kPlasticId;
501 AliMixture(id, "FMD Plastic$", as, zs, density, -2, ws);
502 AliMedium(kPlasticId, "FMD Plastic$", id,0,fieldType,maxField,maxBending,
503 maxStepSize,maxEnergyLoss,precision,minStepSize);
504 }
505 AliMatrix(fPrintboardRotationId, 90, 90, 0, 90, 90, 0);
506 AliMatrix(fIdentityRotationId, 90, 0, 90, 90, 0, 0);
d28dcc0d 507}
dc8af42e 508
4347b38f 509//____________________________________________________________________
510void
511AliFMD::Init()
fe4da5cc 512{
513 //
4347b38f 514 // Initialis the FMD after it has been built
515 Int_t i;
516 //
517 if (fDebug) {
518 std::cout << "\n" << ClassName() << ": " << std::flush;
519 for (i = 0; i < 35; i++) std::cout << "*";
520 std::cout << " FMD_INIT ";
521 for (i = 0; i < 35; i++) std::cout << "*";
522 std::cout << "\n" << ClassName() << ": " << std::flush;
523 //
524 // Here the FMD initialisation code (if any!)
525 for (i = 0; i < 80; i++) std::cout << "*";
526 std::cout << std::endl;
527 }
528 //
fe4da5cc 529 //
fe4da5cc 530}
dc8af42e 531
4347b38f 532//====================================================================
533//
534// Graphics and event display
535//
536//____________________________________________________________________
537void
538AliFMD::BuildGeometry()
b9a2d5e4 539{
4347b38f 540 //
541 // Build simple ROOT TNode geometry for event display
542 //
543 // Build a simplified geometry of the FMD used for event display
544 //
545 AliDebug(10, "Creating a simplified geometry");
b9a2d5e4 546
4347b38f 547 TNode* top = gAlice->GetGeometry()->GetNode("alice");
548
549 fFMD1->SimpleGeometry(fNodes, top, GetLineColor(), 0);
550 fFMD2->SimpleGeometry(fNodes, top, GetLineColor(), 0);
551 fFMD3->SimpleGeometry(fNodes, top, GetLineColor(), 0);
37c55dc0 552}
88cb7938 553
4347b38f 554//____________________________________________________________________
555void
556AliFMD::DrawDetector()
fe4da5cc 557{
558 //
4347b38f 559 // Draw a shaded view of the Forward multiplicity detector version 0
fe4da5cc 560 //
4347b38f 561 // DebugGuard guard("AliFMD::DrawDetector");
562 AliDebug(10, "Draw detector");
563
564 //Set ALIC mother transparent
565 gMC->Gsatt("ALIC","SEEN",0);
566
567 //Set volumes visible
568 fFMD1->Gsatt();
569 fFMD2->Gsatt();
570 fFMD3->Gsatt();
571 fInner->Gsatt();
572 fOuter->Gsatt();
573
574 //
575 gMC->Gdopt("hide", "on");
576 gMC->Gdopt("shad", "on");
577 gMC->Gsatt("*", "fill", 7);
578 gMC->SetClipBox(".");
579 gMC->SetClipBox("*", 0, 1000, -1000, 1000, -1000, 1000);
580 gMC->DefaultRange();
581 gMC->Gdraw("alic", 40, 30, 0, 12, 12, .055, .055);
582 gMC->Gdhead(1111, "Forward Multiplicity Detector");
583 gMC->Gdman(16, 10, "MAN");
584 gMC->Gdopt("hide", "off");
fe4da5cc 585}
dc8af42e 586
4347b38f 587//____________________________________________________________________
588const Int_t
589AliFMD::DistanceToPrimitive(Int_t, Int_t)
fe4da5cc 590{
591 //
592 // Calculate the distance from the mouse to the FMD on the screen
593 // Dummy routine
594 //
595 return 9999;
596}
dc8af42e 597
4347b38f 598//====================================================================
599//
600// Hit and Digit managment
601//
602//____________________________________________________________________
603void
604AliFMD::MakeBranch(Option_t * option)
605{
606 // Create Tree branches for the FMD.
607 const Int_t kBufferSize = 16000;
608 TString branchname(GetName());
609 TString opt(option);
610
611 if (opt.Contains("H", TString::kIgnoreCase)) {
612 HitsArray();
613 AliDetector::MakeBranch(option);
614 }
615 if (opt.Contains("D", TString::kIgnoreCase)) {
616 DigitsArray();
617 MakeBranchInTree(fLoader->TreeD(), branchname.Data(),
618 &fDigits, kBufferSize, 0);
619 }
620 if (opt.Contains("S", TString::kIgnoreCase)) {
621 SDigitsArray();
622 MakeBranchInTree(fLoader->TreeS(), branchname.Data(),
623 &fSDigits, kBufferSize, 0);
624 }
625}
626
627//____________________________________________________________________
628void
629AliFMD::SetTreeAddress()
630{
631 // Set branch address for the Hits and Digits Tree.
632
633 if (fLoader->TreeH()) HitsArray();
634 AliDetector::SetTreeAddress();
635
636 TTree *treeD = fLoader->TreeD();
637 if (treeD) {
638 DigitsArray();
639 TBranch* branch = treeD->GetBranch ("FMD");
640 if (branch) branch->SetAddress(&fDigits);
641 }
642
643 TTree *treeS = fLoader->TreeS();
644 if (treeS) {
645 SDigitsArray();
646 TBranch* branch = treeS->GetBranch ("FMD");
647 if (branch) branch->SetAddress(&fSDigits);
648 }
649}
650
651
652
653//____________________________________________________________________
654void
655AliFMD::SetHitsAddressBranch(TBranch *b)
b9a2d5e4 656{
4347b38f 657 b->SetAddress(&fHits);
b9a2d5e4 658}
659
4347b38f 660//____________________________________________________________________
661void
662AliFMD::AddHit(Int_t track, Int_t *vol, Float_t *hits)
663{
664 // Add a hit to the hits tree
665 //
666 // The information of the two arrays are decoded as
667 //
668 // Parameters
669 // track Track #
670 // ivol[0] [UShort_t ] Detector #
671 // ivol[1] [Char_t ] Ring ID
672 // ivol[2] [UShort_t ] Sector #
673 // ivol[3] [UShort_t ] Strip #
674 // hits[0] [Float_t ] Track's X-coordinate at hit
675 // hits[1] [Float_t ] Track's Y-coordinate at hit
676 // hits[3] [Float_t ] Track's Z-coordinate at hit
677 // hits[4] [Float_t ] X-component of track's momentum
678 // hits[5] [Float_t ] Y-component of track's momentum
679 // hits[6] [Float_t ] Z-component of track's momentum
680 // hits[7] [Float_t ] Energy deposited by track
681 // hits[8] [Int_t ] Track's particle Id #
682 // hits[9] [Float_t ] Time when the track hit
683 AddHit(track,
684 UShort_t(vol[0]), // Detector #
685 Char_t(vol[1]), // Ring ID
686 UShort_t(vol[2]), // Sector #
687 UShort_t(vol[3]), // Strip #
688 hits[0], // X
689 hits[1], // Y
690 hits[2], // Z
691 hits[3], // Px
692 hits[4], // Py
693 hits[5], // Pz
694 hits[6], // Energy loss
695 Int_t(hits[7]), // PDG
696 hits[8]); // Time
697}
698
699//____________________________________________________________________
700void
701AliFMD::AddHit(Int_t track,
702 UShort_t detector,
703 Char_t ring,
704 UShort_t sector,
705 UShort_t strip,
706 Float_t x,
707 Float_t y,
708 Float_t z,
709 Float_t px,
710 Float_t py,
711 Float_t pz,
712 Float_t edep,
713 Int_t pdg,
714 Float_t t)
b9a2d5e4 715{
dc8af42e 716 //
4347b38f 717 // Add a hit to the list
dc8af42e 718 //
4347b38f 719 // Parameters:
720 //
721 // track Track #
722 // detector Detector # (1, 2, or 3)
723 // ring Ring ID ('I' or 'O')
724 // sector Sector # (For inner/outer rings: 0-19/0-39)
725 // strip Strip # (For inner/outer rings: 0-511/0-255)
726 // x Track's X-coordinate at hit
727 // y Track's Y-coordinate at hit
728 // z Track's Z-coordinate at hit
729 // px X-component of track's momentum
730 // py Y-component of track's momentum
731 // pz Z-component of track's momentum
732 // edep Energy deposited by track
733 // pdg Track's particle Id #
734 // t Time when the track hit
735 //
736 TClonesArray& a = *(HitsArray());
737 // Search through the list of already registered hits, and see if we
738 // find a hit with the same parameters. If we do, then don't create
739 // a new hit, but rather update the energy deposited in the hit.
740 // This is done, so that a FLUKA based simulation will get the
741 // number of hits right, not just the enerrgy deposition.
742 for (Int_t i = 0; i < fNhits; i++) {
743 if (!a.At(i)) continue;
744 AliFMDHit* hit = static_cast<AliFMDHit*>(a.At(i));
745 if (hit->Detector() == detector
746 && hit->Ring() == ring
747 && hit->Sector() == sector
748 && hit->Strip() == strip
749 && hit->Track() == track) {
750 hit->SetEdep(hit->Edep() + edep);
751 return;
752 }
753 }
754 // If hit wasn't already registered, do so know.
755 new (a[fNhits]) AliFMDHit(fIshunt, track, detector, ring, sector, strip,
756 x, y, z, px, py, pz, edep, pdg, t);
757 fNhits++;
b9a2d5e4 758}
fe4da5cc 759
4347b38f 760//____________________________________________________________________
761void
762AliFMD::AddDigit(Int_t* digits)
fe4da5cc 763{
4347b38f 764 // Add a digit to the Digit tree
765 //
766 // Paramters
fe4da5cc 767 //
4347b38f 768 // digits[0] [UShort_t] Detector #
769 // digits[1] [Char_t] Ring ID
770 // digits[2] [UShort_t] Sector #
771 // digits[3] [UShort_t] Strip #
772 // digits[4] [UShort_t] ADC Count
773 // digits[5] [Short_t] ADC Count, -1 if not used
774 // digits[6] [Short_t] ADC Count, -1 if not used
775 //
776 AddDigit(UShort_t(digits[0]), // Detector #
777 Char_t(digits[1]), // Ring ID
778 UShort_t(digits[2]), // Sector #
779 UShort_t(digits[3]), // Strip #
780 UShort_t(digits[4]), // ADC Count1
781 Short_t(digits[5]), // ADC Count2
782 Short_t(digits[6])); // ADC Count3
783}
784
785//____________________________________________________________________
786void
787AliFMD::AddDigit(UShort_t detector,
788 Char_t ring,
789 UShort_t sector,
790 UShort_t strip,
791 UShort_t count1,
792 Short_t count2,
793 Short_t count3)
794{
795 // add a real digit - as coming from data
796 //
797 // Parameters
fe4da5cc 798 //
4347b38f 799 // detector Detector # (1, 2, or 3)
800 // ring Ring ID ('I' or 'O')
801 // sector Sector # (For inner/outer rings: 0-19/0-39)
802 // strip Strip # (For inner/outer rings: 0-511/0-255)
803 // count1 ADC count (a 10-bit word)
804 // count2 ADC count (a 10-bit word), or -1 if not used
805 // count3 ADC count (a 10-bit word), or -1 if not used
806 TClonesArray& a = *(DigitsArray());
807
808 new (a[fNdigits++])
809 AliFMDDigit(detector, ring, sector, strip, count1, count2, count3);
810}
811
812//____________________________________________________________________
813void
814AliFMD::AddSDigit(Int_t* digits)
815{
816 // Add a digit to the SDigit tree
817 //
818 // Paramters
b9a2d5e4 819 //
4347b38f 820 // digits[0] [UShort_t] Detector #
821 // digits[1] [Char_t] Ring ID
822 // digits[2] [UShort_t] Sector #
823 // digits[3] [UShort_t] Strip #
824 // digits[4] [Float_t] Total energy deposited
825 // digits[5] [UShort_t] ADC Count
826 // digits[6] [Short_t] ADC Count, -1 if not used
827 // digits[7] [Short_t] ADC Count, -1 if not used
828 //
829 AddSDigit(UShort_t(digits[0]), // Detector #
830 Char_t(digits[1]), // Ring ID
831 UShort_t(digits[2]), // Sector #
832 UShort_t(digits[3]), // Strip #
833 Float_t(digits[4]), // Edep
834 UShort_t(digits[5]), // ADC Count1
835 Short_t(digits[6]), // ADC Count2
836 Short_t(digits[7])); // ADC Count3
837}
838
839//____________________________________________________________________
840void
841AliFMD::AddSDigit(UShort_t detector,
842 Char_t ring,
843 UShort_t sector,
844 UShort_t strip,
845 Float_t edep,
846 UShort_t count1,
847 Short_t count2,
848 Short_t count3)
849{
850 // add a summable digit
851 //
852 // Parameters
b9a2d5e4 853 //
4347b38f 854 // detector Detector # (1, 2, or 3)
855 // ring Ring ID ('I' or 'O')
856 // sector Sector # (For inner/outer rings: 0-19/0-39)
857 // strip Strip # (For inner/outer rings: 0-511/0-255)
858 // edep Total energy deposited
859 // count1 ADC count (a 10-bit word)
860 // count2 ADC count (a 10-bit word), or -1 if not used
861 // count3 ADC count (a 10-bit word), or -1 if not used
862 TClonesArray& a = *(SDigitsArray());
863
864 new (a[fNsdigits++])
865 AliFMDSDigit(detector, ring, sector, strip, edep, count1, count2, count3);
fe4da5cc 866}
4347b38f 867
868//____________________________________________________________________
869void
870AliFMD::ResetSDigits()
d28dcc0d 871{
4347b38f 872 //
873 // Reset number of digits and the digits array for this detector
874 //
875 fNsdigits = 0;
876 if (fSDigits) fSDigits->Clear();
877}
878
879
880//____________________________________________________________________
881TClonesArray*
882AliFMD::HitsArray()
883{
884 // Initialize hit array if not already, and return pointer to it.
885 if (!fHits) {
886 fHits = new TClonesArray("AliFMDHit", 1000);
887 fNhits = 0;
888 }
889 return fHits;
890}
891
892//____________________________________________________________________
893TClonesArray*
894AliFMD::DigitsArray()
895{
896 // Initialize digit array if not already, and return pointer to it.
897 if (!fDigits) {
898 fDigits = new TClonesArray("AliFMDDigit", 1000);
899 fNdigits = 0;
900 }
901 return fDigits;
902}
903
904//____________________________________________________________________
905TClonesArray*
906AliFMD::SDigitsArray()
907{
908 // Initialize digit array if not already, and return pointer to it.
909 if (!fSDigits) {
910 fSDigits = new TClonesArray("AliFMDSDigit", 1000);
911 fNsdigits = 0;
912 }
913 return fSDigits;
914}
915
916//====================================================================
917//
918// Digitization
919//
920//____________________________________________________________________
921void
922AliFMD::Hits2Digits()
923{
924 AliRunDigitizer* manager = new AliRunDigitizer(1, 1);
925 manager->SetInputStream(0, "galice.root");
926 manager->SetOutputFile("H2Dfile");
dc8af42e 927
4347b38f 928 /* AliDigitizer* dig =*/ CreateDigitizer(manager);
929 manager->Exec("");
930}
931
932//____________________________________________________________________
933void
934AliFMD::Hits2SDigits()
935{
936 AliDigitizer* sdig = new AliFMDSDigitizer("galice.root");
937 sdig->Exec("");
938}
939
dc8af42e 940
4347b38f 941//____________________________________________________________________
942AliDigitizer*
943AliFMD::CreateDigitizer(AliRunDigitizer* manager) const
944{
945 // Create a digitizer object
946 return new AliFMDDigitizer(manager);
947}
b9a2d5e4 948
4347b38f 949//====================================================================
950//
951// Raw data simulation
952//
953//__________________________________________________________________
954void
955AliFMD::Digits2Raw()
956{
957 AliFMD* fmd = static_cast<AliFMD*>(gAlice->GetDetector(GetName()));
958 fLoader->LoadDigits();
959 TTree* digitTree = fLoader->TreeD();
960 if (!digitTree) {
961 Error("Digits2Raw", "no digit tree");
962 return;
963 }
88cb7938 964
4347b38f 965 TClonesArray* digits = new TClonesArray("AliFMDDigit", 1000);
966 fmd->SetTreeAddress();
967 TBranch* digitBranch = digitTree->GetBranch(GetName());
968 if (!digitBranch) {
969 Error("Digits2Raw", "no branch for %s", GetName());
970 return;
dc8af42e 971 }
4347b38f 972 digitBranch->SetAddress(&digits);
973
e494a11a 974 Int_t nEvents = (Int_t)digitTree->GetEntries();
4347b38f 975 for (Int_t event = 0; event < nEvents; event++) {
976 fmd->ResetDigits();
977 digitTree->GetEvent(event);
978
979 Int_t nDigits = digits->GetEntries();
980 if (nDigits < 1) continue;
88cb7938 981
dc8af42e 982
4347b38f 983 UShort_t prevDetector = 0;
984 Char_t prevRing = '\0';
985 UShort_t prevSector = 0;
986 // UShort_t prevStrip = 0;
88cb7938 987
4347b38f 988 // The first seen strip number for a channel
989 UShort_t startStrip = 0;
990
991 // Which channel number in the ALTRO channel we're at
992 UShort_t offset = 0;
88cb7938 993
4347b38f 994 // How many times the ALTRO Samples one VA1_ALICE channel
995 Int_t sampleRate = 1;
b9a2d5e4 996
4347b38f 997 // A buffer to hold 1 ALTRO channel - Normally, one ALTRO channel
998 // holds 128 VA1_ALICE channels, sampled at a rate of `sampleRate'
999 TArrayI channel(128 * sampleRate);
1000
1001 // The Altro buffer
1002 AliAltroBuffer* altro = 0;
1003
1004 // Loop over the digits in the event. Note, that we assume the
1005 // the digits are in order in the branch. If they were not, we'd
1006 // have to cache all channels before we could write the data to
1007 // the ALTRO buffer, or we'd have to set up a map of the digits.
1008 for (Int_t i = 0; i < nDigits; i++) {
1009 // Get the digit
1010 AliFMDDigit* digit = static_cast<AliFMDDigit*>(digits->At(i));
1011
1012 UShort_t det = digit->Detector();
1013 Char_t ring = digit->Ring();
1014 UShort_t sector = digit->Sector();
1015 UShort_t strip = digit->Strip();
1016 if (det != prevDetector) {
1017 AliDebug(10, Form("FMD: New DDL, was %d, now %d",
1018 kBaseDDL + prevDetector - 1,
1019 kBaseDDL + det - 1));
1020 // If an altro exists, delete the object, flushing the data to
1021 // disk, and closing the file.
1022 if (altro) {
1023 // When the first argument is false, we write the real
1024 // header.
1025 AliDebug(10, Form("New altro: Write channel at %d Strip: %d "
1026 "Sector: %d Ring: %d",
1027 i, startStrip, prevSector, prevRing));
1028 // TPC to FMD translations
1029 //
1030 // TPC FMD
1031 // ----------+-----------
1032 // pad | strip
1033 // row | sector
1034 // sector | ring
1035 //
1036 altro->WriteChannel(Int_t(startStrip),
1037 Int_t(prevSector),
1038 Int_t((prevRing == 'I' ? 0 : 1)),
1039 channel.fN, channel.fArray, 0);
1040 altro->Flush();
1041 altro->WriteDataHeader(kFALSE, kFALSE);
1042 delete altro;
1043 altro = 0;
1044 }
1045
1046 prevDetector = det;
1047 // Need to open a new DDL!
1048 Int_t ddlId = kBaseDDL + det - 1;
1049 TString filename(Form("%s_%d.ddl", GetName(), ddlId));
1050
1051 AliDebug(10, Form("New altro buffer with DDL file %s",
1052 filename.Data()));
1053 AliDebug(10, Form("New altro at %d", i));
1054 // Create a new altro buffer - a `1' as the second argument
1055 // means `write mode'
1056 altro = new AliAltroBuffer(filename.Data(), 1);
1057
1058 // Write a dummy (first argument is true) header to the DDL
1059 // file - later on, when we close the file, we write the real
1060 // header
1061 altro->WriteDataHeader(kTRUE, kFALSE);
1062
1063 // Figure out the sample rate
1064 if (digit->Count2() > 0) sampleRate = 2;
1065 if (digit->Count3() > 0) sampleRate = 3;
1066
1067 channel.Set(128 * sampleRate);
1068 offset = 0;
1069 prevRing = ring;
1070 prevSector = sector;
1071 startStrip = strip;
1072 }
1073 else if (offset == 128
1074 || digit->Ring() != prevRing
1075 || digit->Sector() != prevSector) {
1076 // Force a new Altro channel
1077 AliDebug(10, Form("Flushing channel to disk because %s",
1078 (offset == 128 ? "channel is full" :
1079 (ring != prevRing ? "new ring up" :
1080 "new sector up"))));
1081 AliDebug(10, Form("New Channel: Write channel at %d Strip: %d "
1082 "Sector: %d Ring: %d",
1083 i, startStrip, prevSector, prevRing));
1084 altro->WriteChannel(Int_t(startStrip),
1085 Int_t(prevSector),
1086 Int_t((prevRing == 'I' ? 0 : 1)),
1087 channel.fN, channel.fArray, 0);
1088 // Reset and update channel variables
1089 channel.Reset(0);
1090 offset = 0;
1091 startStrip = strip;
1092 prevRing = ring;
1093 prevSector = sector;
1094 }
b9a2d5e4 1095
4347b38f 1096 // Store the counts of the ADC in the channel buffer
1097 channel[offset * sampleRate] = digit->Count1();
1098 if (sampleRate > 1)
1099 channel[offset * sampleRate + 1] = digit->Count2();
1100 if (sampleRate > 2)
1101 channel[offset * sampleRate + 2] = digit->Count3();
1102 offset++;
dc8af42e 1103 }
4347b38f 1104 // Finally, we need to close the final ALTRO buffer if it wasn't
1105 // already
1106 if (altro) {
1107 altro->Flush();
1108 altro->WriteDataHeader(kFALSE, kFALSE);
1109 delete altro;
1110 }
1111 }
1112 fLoader->UnloadDigits();
b9a2d5e4 1113}
1114
4347b38f 1115//==================================================================
1116//
1117// Various setter functions for the common paramters
1118//
b9a2d5e4 1119
4347b38f 1120//__________________________________________________________________
1121void
1122AliFMD::SetLegLength(Double_t length)
1123{
1124 // Set lenght of plastic legs that hold the hybrid (print board and
1125 // silicon sensor) onto the honeycomp support
1126 //
1127 // DebugGuard guard("AliFMD::SetLegLength");
1128 AliDebug(10, "AliFMD::SetLegLength");
1129 fLegLength = length;
1130 fInner->SetLegLength(fLegLength);
1131 fOuter->SetLegLength(fLegLength);
1132}
b9a2d5e4 1133
4347b38f 1134//__________________________________________________________________
1135void
1136AliFMD::SetLegOffset(Double_t offset)
1137{
1138 // Set offset from edge of hybrid to plastic legs that hold the
1139 // hybrid (print board and silicon sensor) onto the honeycomp
1140 // support
1141 //
1142 // DebugGuard guard("AliFMD::SetLegOffset");
1143 AliDebug(10, "AliFMD::SetLegOffset");
1144 fInner->SetLegOffset(offset);
1145 fOuter->SetLegOffset(offset);
1146}
4110645f 1147
4347b38f 1148//__________________________________________________________________
1149void
1150AliFMD::SetLegRadius(Double_t radius)
4110645f 1151{
4347b38f 1152 // Set the diameter of the plastic legs that hold the hybrid (print
1153 // board and silicon sensor) onto the honeycomp support
1154 //
1155 // DebugGuard guard("AliFMD::SetLegRadius");
1156 AliDebug(10, "AliFMD::SetLegRadius");
1157 fLegRadius = radius;
1158 fInner->SetLegRadius(fLegRadius);
1159 fOuter->SetLegRadius(fLegRadius);
4110645f 1160}
37c55dc0 1161
4347b38f 1162//__________________________________________________________________
1163void
1164AliFMD::SetModuleSpacing(Double_t spacing)
85a5290f 1165{
4347b38f 1166 // Set the distance between the front and back sensor modules
1167 // (module staggering).
1168 //
1169 // DebugGuard guard("AliFMD::SetModuleSpacing");
1170 AliDebug(10, "AliFMD::SetModuleSpacing");
1171 fModuleSpacing = spacing;
1172 fInner->SetModuleSpacing(fModuleSpacing);
1173 fOuter->SetModuleSpacing(fModuleSpacing);
1174}
1175
1176//====================================================================
1177//
1178// Utility
1179//
1180//__________________________________________________________________
1181void
1182AliFMD::Browse(TBrowser* b)
1183{
1184 AliDebug(10, "AliFMD::Browse");
1185 AliDetector::Browse(b);
1186 if (fInner) b->Add(fInner, "Inner Ring");
1187 if (fOuter) b->Add(fOuter, "Outer Ring");
1188 if (fFMD1) b->Add(fFMD1, "FMD1 SubDetector");
1189 if (fFMD2) b->Add(fFMD2, "FMD2 SubDetector");
1190 if (fFMD3) b->Add(fFMD3, "FMD3 SubDetector");
1191}
1192
1193
1194//********************************************************************
1195//
1196// AliFMDv0
1197//
1198//__________________________________________________________________
1199
1200ClassImp(AliFMDv0);
1201
1202//********************************************************************
1203//
1204// AliFMDv1
1205//
1206//__________________________________________________________________
1207
1208ClassImp(AliFMDv1);
1209
1210
1211//_//____________________________________________________________________
1212void
1213AliFMDv1::StepManager()
1214{
1215 //
1216 // Called for every step in the Forward Multiplicity Detector
1217 //
1218 // The procedure is as follows:
1219 //
1220 // - IF NOT track is alive THEN RETURN ENDIF
1221 // - IF NOT particle is charged THEN RETURN ENDIF
1222 // - IF NOT volume name is "STRI" or "STRO" THEN RETURN ENDIF
1223 // - Get strip number (volume copy # minus 1)
1224 // - Get phi division number (mother volume copy #)
1225 // - Get module number (grand-mother volume copy #)
1226 // - section # = 2 * module # + phi division # - 1
1227 // - Get ring Id from volume name
1228 // - Get detector # from grand-grand-grand-mother volume name
1229 // - Get pointer to sub-detector object.
1230 // - Get track position
1231 // - IF track is entering volume AND track is inside real shape THEN
1232 // - Reset energy deposited
1233 // - Get track momentum
1234 // - Get particle ID #
1235 /// - ENDIF
1236 // - IF track is inside volume AND inside real shape THEN
1237 /// - Update energy deposited
1238 // - ENDIF
1239 // - IF track is inside real shape AND (track is leaving volume,
1240 // or it died, or it is stopped THEN
1241 // - Create a hit
1242 // - ENDIF
1243 //
1244 //
1245 // DebugGuard guard("AliFMDv1::StepManager");
1246 AliDebug(10, "AliFMDv1::StepManager");
1247 // return;
1248
1249 // If the track is gone, return
1250 if (!gMC->IsTrackAlive()) return;
1251
1252 // Only process charged particles
1253 if(TMath::Abs(gMC->TrackCharge()) <= 0) return;
1254
1255 // Only do stuff is the track is in one of the strips.
1256 TString vol(gMC->CurrentVolName());
1257 if (!vol.Contains("STR")) return;
1258
1259
1260 // Get the strip number. Note, that GEANT numbers divisions from 1,
1261 // so we subtract one
1262 Int_t strip;
1263 gMC->CurrentVolID(strip);
1264 strip--;
1265
1266 // Get the phi division of the module
1267 Int_t phiDiv; // * The phi division number (1 or 2)
1268 gMC->CurrentVolOffID(1, phiDiv); // in the module
1269
1270 // Active volume number - not used.
1271 // Int_t active;
1272 // gMC->CurrentVolOffID(2, active);
1273
1274 // Get the module number in the ring.
1275 Int_t module;
1276 gMC->CurrentVolOffID(3, module);
1277
1278 // Ring copy number - the same as the detector number - not used
1279 // Int_t ringCopy; // * Ring copy number
1280 // gMC->CurrentVolOffID(4, ringCopy); // Same as detector number
1281
1282 // Get the detector number from the path name
1283 Int_t detector = Int_t((gMC->CurrentVolOffName(5)[3]) - 48);
1284
1285 // The sector number, calculated from module and phi division #
1286 Int_t sector = 2 * module + phiDiv - 1;
1287
1288 // The ring ID is encoded in the volume name
1289 Char_t ring = vol[3];
1290
1291 // Get a pointer to the sub detector structure
1292 AliFMDSubDetector* det = 0;
1293 switch (detector) {
1294 case 1: det = fFMD1; break;
1295 case 2: det = fFMD2; break;
1296 case 3: det = fFMD3; break;
1297 }
1298 if (!det) return;
1299
1300 // Get the current track position
1301 TLorentzVector v;
1302 gMC->TrackPosition(v);
1303 // Check that the track is actually within the active area
1304 Bool_t isWithin = det->CheckHit(ring, module, v.X(), v.Y());
1305 Bool_t entering = gMC->IsTrackEntering() && isWithin;
1306 Bool_t inside = gMC->IsTrackInside() && isWithin;
1307 Bool_t out = (gMC->IsTrackExiting()
1308 || gMC->IsTrackDisappeared()
1309 || gMC->IsTrackStop()
1310 || !isWithin);
1311// Reset the energy deposition for this track, and update some of
1312 // our parameters.
1313 if (entering) {
1314 fCurrentDeltaE = 0;
1315
1316 // Get production vertex and momentum of the track
1317 fCurrentV = v;
1318 gMC->TrackMomentum(fCurrentP);
1319 fCurrentPdg = gMC->IdFromPDG(gMC->TrackPid());
1320
1321 // if (fAnalyser)
1322 // fAnalyser->Update(detector, ring, isWithin, v.X(), v.Y());
1323 }
1324
1325 // If the track is inside, then update the energy deposition
1326 if (inside && fCurrentDeltaE >= 0)
1327 fCurrentDeltaE += 1000 * gMC->Edep();
1328
1329 // The track exits the volume, or it disappeared in the volume, or
1330 // the track is stopped because it no longer fulfills the cuts
1331 // defined, then we create a hit.
1332 if (out && fCurrentDeltaE >= 0) {
1333 fCurrentDeltaE += 1000 * gMC->Edep();
1334
1335 AddHit(gAlice->GetMCApp()->GetCurrentTrackNumber(),
1336 detector, ring, sector, strip,
1337 fCurrentV.X(), fCurrentV.Y(), fCurrentV.Z(),
1338 fCurrentP.X(), fCurrentP.Y(), fCurrentP.Z(),
1339 fCurrentDeltaE, fCurrentPdg, fCurrentV.T());
1340 fCurrentDeltaE = -1;
1341 }
85a5290f 1342}
4347b38f 1343//___________________________________________________________________
1344//
1345// EOF
1346//