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