]> git.uio.no Git - u/mrichter/AliRoot.git/blame - FMD/AliFMD.cxx
0. General code clean-up, including messages, and the like.
[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
e802be3e 18//____________________________________________________________________
4347b38f 19//
37c4363a 20// Forward Multiplicity Detector based on Silicon wafers. This class
21// contains the base procedures for the Forward Multiplicity detector
1a1fdef7 22// Detector consists of 3 sub-detectors FMD1, FMD2, and FMD3, each of
23// which has 1 or 2 rings of silicon sensors.
37c4363a 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
1a1fdef7 29// that handles the simulation
4347b38f 30//
31//
32// +----------+ +----------+
1a1fdef7 33// | AliFMDv1 | | AliFMDv0 |
4347b38f 34// +----------+ +----------+
1a1fdef7 35// | | +-----------------+
36// +----+--------------+ +--| AliFMDDigitizer |
37// | | +-----------------+
38// | +---------------------+ |
4ac75127 39// | +--| AliFMDBaseDigitizer |<--+
1a1fdef7 40// V 1 | +---------------------+ |
41// +--------+<>--+ | +------------------+
42// | AliFMD | +--| AliFMDSDigitizer |
43// +--------+<>--+ +------------------+
4ac75127 44// 1 | +-----------------+
45// +--| AliFMDSimulator |
46// +-----------------+
47// ^
48// |
49// +-------------+-------------+
50// | |
51// +--------------------+ +-------------------+
52// | AliFMDGeoSimulator | | AliFMDG3Simulator |
53// +--------------------+ +-------------------+
54// ^ ^
55// | |
56// +-----------------------+ +----------------------+
57// | AliFMDGeoOldSimulator | | AliFMDG3OldSimulator |
58// +-----------------------+ +----------------------+
4347b38f 59//
60//
61// * AliFMD
62// This defines the interface for the various parts of AliROOT that
1a1fdef7 63// uses the FMD, like AliFMDSimulator, AliFMDDigitizer,
64// AliFMDReconstructor, and so on.
65//
66// * AliFMDv0
67// This is a concrete implementation of the AliFMD interface.
68// It is the responsibility of this class to create the FMD
69// geometry.
4347b38f 70//
71// * AliFMDv1
72// This is a concrete implementation of the AliFMD interface.
73// It is the responsibility of this class to create the FMD
74// geometry, process hits in the FMD, and serve hits and digits to
75// the various clients.
76//
1a1fdef7 77// * AliFMDSimulator
78// This is the base class for the FMD simulation tasks. The
79// simulator tasks are responsible to implment the geoemtry, and
80// process hits.
4347b38f 81//
1a1fdef7 82// * AliFMDGeoSimulator
83// This is a concrete implementation of the AliFMDSimulator that
84// uses the TGeo classes directly only.
37c4363a 85//
1a1fdef7 86// * AliFMDG3Simulator
87// This is a concrete implementation of the AliFMDSimulator that
88// uses the TVirtualMC interface with GEANT 3.21-like messages.
37c4363a 89//
fe4da5cc 90
56b1929b 91// These files are not in the same directory, so there's no reason to
92// ask the preprocessor to search in the current directory for these
93// files by including them with `#include "..."'
1a1fdef7 94#include <math.h> // __CMATH__
56b1929b 95#include <TClonesArray.h> // ROOT_TClonesArray
96#include <TGeometry.h> // ROOT_TGeomtry
97#include <TNode.h> // ROOT_TNode
1a1fdef7 98#include <TXTRU.h> // ROOT_TXTRU
99#include <TRotMatrix.h> // ROOT_TRotMatrix
56b1929b 100#include <TTUBE.h> // ROOT_TTUBE
101#include <TTree.h> // ROOT_TTree
56b1929b 102#include <TBrowser.h> // ROOT_TBrowser
103#include <TMath.h> // ROOT_TMath
1a1fdef7 104#include <TVirtualMC.h> // ROOT_TVirtualMC
bf000c32 105#include <TVector2.h>
106#include <TVector3.h>
107#include <TMarker3DBox.h>
56b1929b 108
109#include <AliRunDigitizer.h> // ALIRUNDIGITIZER_H
110#include <AliLoader.h> // ALILOADER_H
111#include <AliRun.h> // ALIRUN_H
112#include <AliMC.h> // ALIMC_H
54e415a8 113#include "AliMagF.h" // ALIMAGF_H
56b1929b 114#include <AliLog.h> // ALILOG_H
e802be3e 115#include "AliFMD.h" // ALIFMD_H
116#include "AliFMDDigit.h" // ALIFMDDIGIG_H
117#include "AliFMDHit.h" // ALIFMDHIT_H
1a1fdef7 118#include "AliFMDGeometry.h" // ALIFMDGEOMETRY_H
119#include "AliFMDDetector.h" // ALIFMDDETECTOR_H
120#include "AliFMDRing.h" // ALIFMDRING_H
e802be3e 121#include "AliFMDDigitizer.h" // ALIFMDDIGITIZER_H
bf000c32 122#include "AliPoints.h" // ALIPOINTS_H
123#include "AliFMDGeometryBuilder.h"
e802be3e 124#include "AliFMDRawWriter.h" // ALIFMDRAWWRITER_H
bf000c32 125
126
127class AliFMDPoints : public AliPoints
128{
129public:
130 AliFMDPoints(AliFMDHit* hit, UInt_t color)
131 : AliPoints(1), fMarker(0)
132 {
133 if (!hit) return;
134 Float_t size = TMath::Min(TMath::Max(hit->Edep() * .1, .1), 1.);
135 TVector3 p(hit->Px(), hit->Py(), hit->Pz());
136 fMarker = new TMarker3DBox(hit->X(), hit->Y(), hit->Z(), size, size, size,
137 p.Theta(), p.Phi());
138 fMarker->SetLineColor(color);
139 fMarker->SetRefObject(this);
140 fP[0] = hit->X();
141 fP[1] = hit->Y();
142 fP[2] = hit->Z();
143 }
144 ~AliFMDPoints()
145 {
146 // if (fMarker) delete fMarker;
147 }
148 void SetXYZ(Double_t x, Double_t y, Double_t z)
149 {
150 if (fMarker) fMarker->SetPosition(x, y, z);
151 }
152 Int_t DistancetoPrimitive(Int_t px, Int_t py)
153 {
154 return fMarker->DistancetoPrimitive(px, py);
155 }
156 void Draw(Option_t* option)
157 {
158 if (fMarker) fMarker->Draw(option);
159 }
160 void Paint(Option_t* option)
161 {
162 if (fMarker) fMarker->Paint(option);
163 }
164 void SetMarkerColor(Color_t colour)
165 {
166 if (fMarker) fMarker->SetLineColor(colour);
167 }
168private:
169 TMarker3DBox* fMarker;
170};
171
88cb7938 172
4347b38f 173//____________________________________________________________________
925e6570 174ClassImp(AliFMD)
1a1fdef7 175#if 0
176 ; // This is to keep Emacs from indenting the next line
177#endif
7e54281f 178
4347b38f 179//____________________________________________________________________
180AliFMD::AliFMD()
90da4514 181 : AliDetector(),
182 fSDigits(0),
afddaa11 183 fNsdigits(0),
1a1fdef7 184 fDetailed(kTRUE),
54e415a8 185 fBad(0)
fe4da5cc 186{
187 //
188 // Default constructor for class AliFMD
189 //
1a1fdef7 190 AliDebug(10, "\tDefault CTOR");
4ac75127 191 fHits = 0;
192 fDigits = 0;
193 fIshunt = 0;
194 fUseOld = kFALSE;
54e415a8 195 fUseAssembly = kTRUE;
196 fBad = new TClonesArray("AliFMDHit");
fe4da5cc 197}
dc8af42e 198
56b1929b 199//____________________________________________________________________
200AliFMD::AliFMD(const AliFMD& other)
201 : AliDetector(other),
56b1929b 202 fSDigits(other.fSDigits),
203 fNsdigits(other.fNsdigits),
1a1fdef7 204 fDetailed(other.fDetailed),
54e415a8 205 fBad(other.fBad)
56b1929b 206{
207 // Copy constructor
4ac75127 208 fUseOld = other.fUseOld;
4ac75127 209 fUseAssembly = other.fUseAssembly;
56b1929b 210}
211
4347b38f 212//____________________________________________________________________
1a1fdef7 213AliFMD::AliFMD(const char *name, const char *title)
4347b38f 214 : AliDetector (name, title),
afddaa11 215 fSDigits(0),
216 fNsdigits(0),
1a1fdef7 217 fDetailed(kTRUE),
54e415a8 218 fBad(0)
fe4da5cc 219{
220 //
221 // Standard constructor for Forward Multiplicity Detector
222 //
1a1fdef7 223 AliDebug(10, "\tStandard CTOR");
4ac75127 224 fUseOld = kFALSE;
4ac75127 225 fUseAssembly = kFALSE;
54e415a8 226 fBad = new TClonesArray("AliFMDHit");
54240c8d 227
fe4da5cc 228 // Initialise Hit array
4347b38f 229 HitsArray();
230 gAlice->GetMCApp()->AddHitList(fHits);
d1280e40 231
4347b38f 232 // (S)Digits for the detectors disk
233 DigitsArray();
234 SDigitsArray();
235
236 // CHC: What is this?
dc8af42e 237 fIshunt = 0;
4347b38f 238 SetMarkerColor(kRed);
239 SetLineColor(kYellow);
fe4da5cc 240}
d28dcc0d 241
4347b38f 242//____________________________________________________________________
dc8af42e 243AliFMD::~AliFMD ()
d28dcc0d 244{
4347b38f 245 // Destructor for base class AliFMD
246 if (fHits) {
247 fHits->Delete();
248 delete fHits;
249 fHits = 0;
250 }
251 if (fDigits) {
252 fDigits->Delete();
253 delete fDigits;
254 fDigits = 0;
255 }
256 if (fSDigits) {
257 fSDigits->Delete();
258 delete fSDigits;
259 fSDigits = 0;
260 }
54e415a8 261 if (fBad) {
262 fBad->Delete();
263 delete fBad;
264 fBad = 0;
265 }
4347b38f 266}
267
56b1929b 268//____________________________________________________________________
269AliFMD&
270AliFMD::operator=(const AliFMD& other)
271{
088f8e79 272 // Assignment operator
56b1929b 273 AliDetector::operator=(other);
56b1929b 274 fSDigits = other.fSDigits;
275 fNsdigits = other.fNsdigits;
1a1fdef7 276 fDetailed = other.fDetailed;
54e415a8 277 fBad = other.fBad;
56b1929b 278 return *this;
279}
280
4347b38f 281//====================================================================
282//
283// GEometry ANd Traking
284//
285//____________________________________________________________________
286void
287AliFMD::CreateGeometry()
288{
4347b38f 289 //
37c4363a 290 // Create the geometry of Forward Multiplicity Detector. The actual
291 // construction of the geometry is delegated to the class AliFMDRing
292 // and AliFMDSubDetector and the relevant derived classes.
293 //
294 // The flow of this member function is:
295 //
296 // FOR rings fInner and fOuter DO
297 // AliFMDRing::Init();
298 // END FOR
299 //
300 // Set up hybrud card support (leg) volume shapes
301 //
302 // FOR rings fInner and fOuter DO
303 // AliFMDRing::SetupGeometry();
304 // END FOR
305 //
306 // FOR subdetectors fFMD1, fFMD2, and fFMD3 DO
307 // AliFMDSubDetector::SetupGeomtry();
308 // END FOR
309 //
310 // FOR subdetectors fFMD1, fFMD2, and fFMD3 DO
311 // AliFMDSubDetector::Geomtry();
312 // END FOR
1a1fdef7 313 //
54e415a8 314 AliFMDGeometry* fmd = AliFMDGeometry::Instance();
54e415a8 315 fmd->SetDetailed(fDetailed);
316 fmd->UseAssembly(fUseAssembly);
317 fmd->Build();
4347b38f 318}
319
320//____________________________________________________________________
321void AliFMD::CreateMaterials()
322{
54e415a8 323 // Define the materials and tracking mediums needed by the FMD
324 // simulation. These mediums are made by sending the messages
325 // AliMaterial, AliMixture, and AliMedium to the passed AliModule
326 // object module. The defined mediums are
4347b38f 327 //
54e415a8 328 // FMD Si$ Silicon (active medium in sensors)
329 // FMD C$ Carbon fibre (support cone for FMD3 and vacuum pipe)
330 // FMD Al$ Aluminium (honeycomb support plates)
331 // FMD PCB$ Printed Circuit Board (FEE board with VA1_3)
332 // FMD Chip$ Electronics chips (currently not used)
333 // FMD Air$ Air (Air in the FMD)
334 // FMD Plastic$ Plastic (Support legs for the hybrid cards)
335 //
336 // Pointers to TGeoMedium objects are retrived from the TGeoManager
337 // singleton. These pointers are later used when setting up the
338 // geometry
339 AliDebug(10, "\tCreating materials");
340 // Get pointer to geometry singleton object.
341 AliFMDGeometry* geometry = AliFMDGeometry::Instance();
342 geometry->Init();
343#if 0
344 if (gGeoManager && gGeoManager->GetMedium("FMD Si$")) {
345 // We need to figure out the some stuff about the geometry
346 fmd->ExtractGeomInfo();
347 return;
348 }
349#endif
54e415a8 350 Int_t id;
351 Double_t a = 0;
352 Double_t z = 0;
353 Double_t density = 0;
354 Double_t radiationLength = 0;
355 Double_t absorbtionLength = 999;
356 Int_t fieldType = gAlice->Field()->Integ(); // Field type
357 Double_t maxField = gAlice->Field()->Max(); // Field max.
358 Double_t maxBending = 0; // Max Angle
359 Double_t maxStepSize = 0.001; // Max step size
360 Double_t maxEnergyLoss = 1; // Max Delta E
361 Double_t precision = 0.001; // Precision
362 Double_t minStepSize = 0.001; // Minimum step size
363
364 // Silicon
365 a = 28.0855;
366 z = 14.;
367 density = geometry->GetSiDensity();
368 radiationLength = 9.36;
369 maxBending = 1;
370 maxStepSize = .001;
371 precision = .001;
372 minStepSize = .001;
373 id = kSiId;
374 AliMaterial(id, "Si$", a, z, density, radiationLength, absorbtionLength);
375 AliMedium(kSiId, "Si$", id,1,fieldType,maxField,maxBending,
376 maxStepSize,maxEnergyLoss,precision,minStepSize);
377
378
379 // Carbon
380 a = 12.011;
381 z = 6.;
382 density = 2.265;
383 radiationLength = 18.8;
384 maxBending = 10;
385 maxStepSize = .01;
386 precision = .003;
387 minStepSize = .003;
388 id = kCarbonId;
389 AliMaterial(id, "Carbon$", a, z, density, radiationLength, absorbtionLength);
390 AliMedium(kCarbonId, "Carbon$", id,0,fieldType,maxField,maxBending,
391 maxStepSize,maxEnergyLoss,precision,minStepSize);
392
393 // Aluminum
394 a = 26.981539;
395 z = 13.;
396 density = 2.7;
397 radiationLength = 8.9;
398 id = kAlId;
399 AliMaterial(id, "Aluminum$",a,z, density, radiationLength, absorbtionLength);
400 AliMedium(kAlId, "Aluminum$", id, 0, fieldType, maxField, maxBending,
401 maxStepSize, maxEnergyLoss, precision, minStepSize);
402
403
404 // Copper
405 a = 63.546;
406 z = 29;
407 density = 8.96;
408 radiationLength = 1.43;
409 id = kCopperId;
410 AliMaterial(id, "Copper$",
411 a, z, density, radiationLength, absorbtionLength);
412 AliMedium(kCopperId, "Copper$", id, 0, fieldType, maxField, maxBending,
413 maxStepSize, maxEnergyLoss, precision, minStepSize);
414
415
416 // Silicon chip
417 {
418 Float_t as[] = { 12.0107, 14.0067, 15.9994,
419 1.00794, 28.0855, 107.8682 };
420 Float_t zs[] = { 6., 7., 8.,
421 1., 14., 47. };
422 Float_t ws[] = { 0.039730642, 0.001396798, 0.01169634,
423 0.004367771, 0.844665, 0.09814344903 };
424 density = 2.36436;
425 maxBending = 10;
426 maxStepSize = .01;
427 precision = .003;
428 minStepSize = .003;
429 id = kSiChipId;
430 AliMixture(id, "Si Chip$", as, zs, density, 6, ws);
431 AliMedium(kSiChipId, "Si Chip$", id, 0, fieldType, maxField, maxBending,
432 maxStepSize, maxEnergyLoss, precision, minStepSize);
433 }
434
435 // Kaption
436 {
437 Float_t as[] = { 1.00794, 12.0107, 14.010, 15.9994};
438 Float_t zs[] = { 1., 6., 7., 8.};
439 Float_t ws[] = { 0.026362, 0.69113, 0.07327, 0.209235};
440 density = 1.42;
441 maxBending = 1;
442 maxStepSize = .001;
443 precision = .001;
444 minStepSize = .001;
445 id = kKaptonId;
446 AliMixture(id, "Kaption$", as, zs, density, 4, ws);
447 AliMedium(kKaptonId, "Kaption$", id,0,fieldType,maxField,maxBending,
448 maxStepSize,maxEnergyLoss,precision,minStepSize);
449 }
450
451 // Air
452 {
453 Float_t as[] = { 12.0107, 14.0067, 15.9994, 39.948 };
454 Float_t zs[] = { 6., 7., 8., 18. };
455 Float_t ws[] = { 0.000124, 0.755267, 0.231781, 0.012827 };
456 density = .00120479;
457 maxBending = 1;
458 maxStepSize = .001;
459 precision = .001;
460 minStepSize = .001;
461 id = kAirId;
462 AliMixture(id, "Air$", as, zs, density, 4, ws);
463 AliMedium(kAirId, "Air$", id,0,fieldType,maxField,maxBending,
464 maxStepSize,maxEnergyLoss,precision,minStepSize);
465 }
466
467 // PCB
468 {
469 Float_t zs[] = { 14., 20., 13., 12.,
470 5., 22., 11., 19.,
471 26., 9., 8., 6.,
472 7., 1.};
473 Float_t as[] = { 28.0855, 40.078, 26.981538, 24.305,
474 10.811, 47.867, 22.98977, 39.0983,
475 55.845, 18.9984, 15.9994, 12.0107,
476 14.0067, 1.00794};
477 Float_t ws[] = { 0.15144894, 0.08147477, 0.04128158, 0.00904554,
478 0.01397570, 0.00287685, 0.00445114, 0.00498089,
479 0.00209828, 0.00420000, 0.36043788, 0.27529426,
480 0.01415852, 0.03427566};
481 density = 1.8;
482 maxBending = 1;
483 maxStepSize = .001;
484 precision = .001;
485 minStepSize = .001;
486 id = kPcbId;
487 AliMixture(id, "PCB$", as, zs, density, 14, ws);
488 AliMedium(kPcbId, "PCB$", id,0,fieldType,maxField,maxBending,
489 maxStepSize,maxEnergyLoss,precision,minStepSize);
490 }
491
492 // Plastic
493 {
494 Float_t as[] = { 1.01, 12.01 };
495 Float_t zs[] = { 1., 6. };
496 Float_t ws[] = { 1., 1. };
497 density = 1.03;
498 maxBending = 10;
499 maxStepSize = .01;
500 precision = .003;
501 minStepSize = .003;
502 id = kPlasticId;
503 AliMixture(id, "Plastic$", as, zs, density, -2, ws);
504 AliMedium(kPlasticId, "Plastic$", id,0,fieldType,maxField,maxBending,
505 maxStepSize,maxEnergyLoss,precision,minStepSize);
506 }
d28dcc0d 507}
dc8af42e 508
4347b38f 509//____________________________________________________________________
510void
511AliFMD::Init()
bf000c32 512{
513 AliDebug(1, "Initialising FMD detector object");
514 AliFMDGeometry* fmd = AliFMDGeometry::Instance();
515 fmd->InitTransformations();
516}
dc8af42e 517
54240c8d 518//____________________________________________________________________
519void
520AliFMD::FinishEvent()
521{
bf000c32 522 if (AliLog::GetDebugLevel("FMD", "AliFMD") < 10) return;
54e415a8 523 if (fBad && fBad->GetEntries() > 0) {
524 AliWarning((Form("EndEvent", "got %d 'bad' hits", fBad->GetEntries())));
525 TIter next(fBad);
526 AliFMDHit* hit;
bf000c32 527 while ((hit = static_cast<AliFMDHit*>(next()))) hit->Print("D");
54e415a8 528 fBad->Clear();
529 }
54240c8d 530}
531
532
4347b38f 533//====================================================================
534//
535// Graphics and event display
536//
537//____________________________________________________________________
538void
539AliFMD::BuildGeometry()
b9a2d5e4 540{
4347b38f 541 //
542 // Build simple ROOT TNode geometry for event display
543 //
544 // Build a simplified geometry of the FMD used for event display
545 //
37c4363a 546 // The actual building of the TNodes is done by
547 // AliFMDSubDetector::SimpleGeometry.
824466d5 548 AliDebug(10, "\tCreating a simplified geometry");
b9a2d5e4 549
1a1fdef7 550 AliFMDGeometry* fmd = AliFMDGeometry::Instance();
551
552 static TXTRU* innerShape = 0;
553 static TXTRU* outerShape = 0;
554 static TObjArray* innerRot = 0;
555 static TObjArray* outerRot = 0;
556
557 if (!innerShape || !outerShape) {
558 // Make the shapes for the modules
559 for (Int_t i = 0; i < 2; i++) {
560 AliFMDRing* r = 0;
561 switch (i) {
562 case 0: r = fmd->GetRing('I'); break;
563 case 1: r = fmd->GetRing('O'); break;
564 }
565 if (!r) {
566 AliError(Form("no ring found for i=%d", i));
567 return;
568 }
569 Double_t siThick = r->GetSiThickness();
570 const Int_t nv = r->GetNVerticies();
571 Double_t theta = r->GetTheta();
572 Int_t nmod = r->GetNModules();
573
574 TXTRU* shape = new TXTRU(r->GetName(), r->GetTitle(), "void", nv, 2);
575 for (Int_t j = 0; j < nv; j++) {
576 TVector2* vv = r->GetVertex(nv - 1 - j);
577 shape->DefineVertex(j, vv->X(), vv->Y());
578 }
579 shape->DefineSection(0, -siThick / 2, 1, 0, 0);
580 shape->DefineSection(1, +siThick / 2, 1, 0, 0);
581 shape->SetLineColor(GetLineColor());
582
583 TObjArray* rots = new TObjArray(nmod);
584 for (Int_t j = 0; j < nmod; j++) {
585 Double_t th = (j + .5) * theta * 2;
586 TString name(Form("FMD_ring_%c_rot_%02d", r->GetId(), j));
587 TString title(Form("FMD Ring %c Rotation # %d", r->GetId(), j));
588 TRotMatrix* rot = new TRotMatrix(name.Data(), title.Data(),
589 90, th, 90, fmod(90+th,360), 0, 0);
590 rots->AddAt(rot, j);
591 }
592
593 switch (r->GetId()) {
594 case 'i':
595 case 'I': innerShape = shape; innerRot = rots; break;
596 case 'o':
597 case 'O': outerShape = shape; outerRot = rots; break;
598 }
599 }
600 }
601
4347b38f 602 TNode* top = gAlice->GetGeometry()->GetNode("alice");
603
1a1fdef7 604 for (Int_t i = 1; i <= 3; i++) {
605 AliFMDDetector* det = fmd->GetDetector(i);
606 if (!det) {
607 Warning("BuildGeometry", "FMD%d seems to be disabled", i);
608 continue;
609 }
610 Double_t w = 0;
611 Double_t rh = det->GetRing('I')->GetHighR();
612 Char_t id = 'I';
613 if (det->GetRing('O')) {
614 w = TMath::Abs(det->GetRingZ('O') - det->GetRingZ('I'));
615 id = (TMath::Abs(det->GetRingZ('O'))
616 > TMath::Abs(det->GetRingZ('I')) ? 'O' : 'I');
617 rh = det->GetRing('O')->GetHighR();
618 }
619 w += (det->GetRing(id)->GetModuleSpacing() +
620 det->GetRing(id)->GetSiThickness());
621 TShape* shape = new TTUBE(det->GetName(), det->GetTitle(), "void",
622 det->GetRing('I')->GetLowR(), rh, w / 2);
623 Double_t z = (det->GetRingZ('I') - w / 2);
624 if (z > 0) z += det->GetRing(id)->GetModuleSpacing();
625 top->cd();
626 TNode* node = new TNode(det->GetName(), det->GetTitle(), shape,
627 0, 0, z, 0);
628 fNodes->Add(node);
629
630 for (Int_t j = 0; j < 2; j++) {
631 AliFMDRing* r = 0;
632 TShape* rshape = 0;
633 TObjArray* rots = 0;
634 switch (j) {
635 case 0:
636 r = det->GetRing('I'); rshape = innerShape; rots = innerRot; break;
637 case 1:
638 r = det->GetRing('O'); rshape = outerShape; rots = outerRot; break;
639 }
640 if (!r) continue;
641
642 Double_t siThick = r->GetSiThickness();
643 Int_t nmod = r->GetNModules();
644 Double_t modspace = r->GetModuleSpacing();
645 Double_t rz = - (z - det->GetRingZ(r->GetId()));
646
647 for (Int_t k = 0; k < nmod; k++) {
648 node->cd();
649 Double_t offz = (k % 2 == 1 ? modspace : 0);
650 TRotMatrix* rot = static_cast<TRotMatrix*>(rots->At(k));
651 TString name(Form("%s%c_module_%02d", det->GetName(), r->GetId(),k));
652 TString title(Form("%s%c Module %d", det->GetName(), r->GetId(),k));
653 TNode* mnod = new TNode(name.Data(), title.Data(), rshape,
654 0, 0, rz - siThick / 2
655 + TMath::Sign(offz,z), rot);
656 mnod->SetLineColor(GetLineColor());
657 fNodes->Add(mnod);
658 } // for (Int_t k = 0 ; ...)
659 } // for (Int_t j = 0 ; ...)
660 } // for (Int_t i = 1 ; ...)
37c55dc0 661}
88cb7938 662
bf000c32 663//____________________________________________________________________
664void
665AliFMD::LoadPoints(Int_t /* track */)
666{
667 //
668 // Store x, y, z of all hits in memory
669 //
670 if (!fHits) {
671 AliError(Form("fHits == 0. Name is %s",GetName()));
672 return;
673 }
674 Int_t nHits = fHits->GetEntriesFast();
675 if (nHits == 0) {
676 return;
677 }
678 Int_t tracks = gAlice->GetMCApp()->GetNtrack();
679 if (fPoints == 0) fPoints = new TObjArray(2 * tracks);
680
681 // Get geometry
682 AliFMDGeometry* geom = AliFMDGeometry::Instance();
683 geom->Init();
684 geom->InitTransformations();
685
686 // Now make markers for each hit
687 // AliInfo(Form("Drawing %d hits (have %d points) for track %d",
688 // nHits, fPoints->GetEntriesFast(), track));
689 for (Int_t ihit = 0; ihit < nHits; ihit++) {
690 AliFMDHit* hit = static_cast<AliFMDHit*>(fHits->At(ihit));
691 if (!hit) continue;
692 Double_t edep = hit->Edep();
693 Double_t m = hit->M();
694 Double_t poverm = (m == 0 ? 0 : hit->P());
695 Double_t absQ = TMath::Abs(hit->Q());
696 Bool_t bad = kFALSE;
697 // This `if' is to debug abnormal energy depositions. We trigger on
698 // p/m approx larger than or equal to a MIP, and a large edep - more
699 // than 1 keV - a MIP is 100 eV.
700 if (edep > absQ * absQ && poverm > 1) bad = kTRUE;
701
702 AliFMDPoints* p1 = new AliFMDPoints(hit, GetMarkerColor());
703 // AliPoints* p1 = new AliPoints();
704 // p1->SetMarkerColor(GetMarkerColor());
705 // p1->SetMarkerSize(GetMarkerSize());
706 // p1->SetPoint(0, hit->X(), hit->Y(), hit->Z());
707 p1->SetDetector(this);
708 p1->SetParticle(hit->GetTrack());
709 fPoints->AddAt(p1, hit->GetTrack());
710 if (bad) {
711 p1->SetMarkerColor(4);
712 // p1->SetMarkerSize(2 * GetMarkerSize());
713 }
714
715 Double_t x, y, z;
716 geom->Detector2XYZ(hit->Detector(), hit->Ring(), hit->Sector(),
717 hit->Strip(), x, y, z);
718 AliFMDPoints* p = new AliFMDPoints(hit, 3);
719 // AliPoints* p = new AliPoints();
720 // p->SetMarkerColor(3);
721 // p->SetMarkerSize(GetMarkerSize());
722 // p->SetPoint(0, x, y, z);
723 p->SetDetector(this);
724 p->SetParticle(hit->GetTrack());
725 p->SetXYZ(x, y, z);
726 p->SetMarkerColor(3);
727 fPoints->AddAt(p, tracks+hit->GetTrack());
728 if (bad) {
729 p->SetMarkerColor(5);
730 // p->SetMarkerSize(2 * GetMarkerSize());
731 }
732 // AliInfo(Form("Adding point at %d", tracks+hit->GetTrack()));
733 }
734}
735
4347b38f 736//____________________________________________________________________
737void
738AliFMD::DrawDetector()
fe4da5cc 739{
740 //
37c4363a 741 // Draw a shaded view of the Forward multiplicity detector
fe4da5cc 742 //
4347b38f 743 // DebugGuard guard("AliFMD::DrawDetector");
824466d5 744 AliDebug(10, "\tDraw detector");
4347b38f 745
1a1fdef7 746#if 0
4347b38f 747 //Set ALIC mother transparent
748 gMC->Gsatt("ALIC","SEEN",0);
4347b38f 749 //
750 gMC->Gdopt("hide", "on");
751 gMC->Gdopt("shad", "on");
752 gMC->Gsatt("*", "fill", 7);
753 gMC->SetClipBox(".");
754 gMC->SetClipBox("*", 0, 1000, -1000, 1000, -1000, 1000);
755 gMC->DefaultRange();
756 gMC->Gdraw("alic", 40, 30, 0, 12, 12, .055, .055);
757 gMC->Gdhead(1111, "Forward Multiplicity Detector");
758 gMC->Gdman(16, 10, "MAN");
759 gMC->Gdopt("hide", "off");
1a1fdef7 760#endif
fe4da5cc 761}
dc8af42e 762
4347b38f 763//____________________________________________________________________
17323043 764Int_t
4347b38f 765AliFMD::DistanceToPrimitive(Int_t, Int_t)
fe4da5cc 766{
767 //
768 // Calculate the distance from the mouse to the FMD on the screen
769 // Dummy routine
770 //
771 return 9999;
772}
dc8af42e 773
4347b38f 774//====================================================================
775//
776// Hit and Digit managment
777//
778//____________________________________________________________________
779void
780AliFMD::MakeBranch(Option_t * option)
781{
782 // Create Tree branches for the FMD.
37c4363a 783 //
784 // Options:
785 //
786 // H Make a branch of TClonesArray of AliFMDHit's
787 // D Make a branch of TClonesArray of AliFMDDigit's
788 // S Make a branch of TClonesArray of AliFMDSDigit's
789 //
4347b38f 790 const Int_t kBufferSize = 16000;
791 TString branchname(GetName());
792 TString opt(option);
793
794 if (opt.Contains("H", TString::kIgnoreCase)) {
795 HitsArray();
796 AliDetector::MakeBranch(option);
797 }
798 if (opt.Contains("D", TString::kIgnoreCase)) {
799 DigitsArray();
800 MakeBranchInTree(fLoader->TreeD(), branchname.Data(),
801 &fDigits, kBufferSize, 0);
802 }
803 if (opt.Contains("S", TString::kIgnoreCase)) {
804 SDigitsArray();
805 MakeBranchInTree(fLoader->TreeS(), branchname.Data(),
806 &fSDigits, kBufferSize, 0);
807 }
808}
809
810//____________________________________________________________________
811void
812AliFMD::SetTreeAddress()
813{
afddaa11 814 // Set branch address for the Hits, Digits, and SDigits Tree.
4347b38f 815 if (fLoader->TreeH()) HitsArray();
816 AliDetector::SetTreeAddress();
817
818 TTree *treeD = fLoader->TreeD();
819 if (treeD) {
820 DigitsArray();
821 TBranch* branch = treeD->GetBranch ("FMD");
822 if (branch) branch->SetAddress(&fDigits);
823 }
824
825 TTree *treeS = fLoader->TreeS();
826 if (treeS) {
827 SDigitsArray();
828 TBranch* branch = treeS->GetBranch ("FMD");
829 if (branch) branch->SetAddress(&fSDigits);
830 }
831}
832
833
834
835//____________________________________________________________________
836void
837AliFMD::SetHitsAddressBranch(TBranch *b)
b9a2d5e4 838{
37c4363a 839 // Set the TClonesArray to read hits into.
4347b38f 840 b->SetAddress(&fHits);
b9a2d5e4 841}
842
4347b38f 843//____________________________________________________________________
844void
845AliFMD::AddHit(Int_t track, Int_t *vol, Float_t *hits)
846{
847 // Add a hit to the hits tree
848 //
849 // The information of the two arrays are decoded as
850 //
851 // Parameters
852 // track Track #
853 // ivol[0] [UShort_t ] Detector #
854 // ivol[1] [Char_t ] Ring ID
855 // ivol[2] [UShort_t ] Sector #
856 // ivol[3] [UShort_t ] Strip #
857 // hits[0] [Float_t ] Track's X-coordinate at hit
858 // hits[1] [Float_t ] Track's Y-coordinate at hit
859 // hits[3] [Float_t ] Track's Z-coordinate at hit
860 // hits[4] [Float_t ] X-component of track's momentum
861 // hits[5] [Float_t ] Y-component of track's momentum
862 // hits[6] [Float_t ] Z-component of track's momentum
863 // hits[7] [Float_t ] Energy deposited by track
864 // hits[8] [Int_t ] Track's particle Id #
37c4363a 865 // hits[9] [Float_t ] Time when the track hit
866 //
867 //
69b696b9 868 AddHitByFields(track,
869 UShort_t(vol[0]), // Detector #
870 Char_t(vol[1]), // Ring ID
871 UShort_t(vol[2]), // Sector #
872 UShort_t(vol[3]), // Strip #
873 hits[0], // X
874 hits[1], // Y
875 hits[2], // Z
876 hits[3], // Px
877 hits[4], // Py
878 hits[5], // Pz
879 hits[6], // Energy loss
880 Int_t(hits[7]), // PDG
881 hits[8]); // Time
4347b38f 882}
883
884//____________________________________________________________________
54240c8d 885AliFMDHit*
69b696b9 886AliFMD::AddHitByFields(Int_t track,
887 UShort_t detector,
888 Char_t ring,
889 UShort_t sector,
890 UShort_t strip,
891 Float_t x,
892 Float_t y,
893 Float_t z,
894 Float_t px,
895 Float_t py,
896 Float_t pz,
897 Float_t edep,
898 Int_t pdg,
088f8e79 899 Float_t t,
900 Float_t l,
901 Bool_t stop)
b9a2d5e4 902{
dc8af42e 903 //
4347b38f 904 // Add a hit to the list
dc8af42e 905 //
4347b38f 906 // Parameters:
907 //
908 // track Track #
909 // detector Detector # (1, 2, or 3)
910 // ring Ring ID ('I' or 'O')
911 // sector Sector # (For inner/outer rings: 0-19/0-39)
912 // strip Strip # (For inner/outer rings: 0-511/0-255)
913 // x Track's X-coordinate at hit
914 // y Track's Y-coordinate at hit
915 // z Track's Z-coordinate at hit
916 // px X-component of track's momentum
917 // py Y-component of track's momentum
918 // pz Z-component of track's momentum
919 // edep Energy deposited by track
920 // pdg Track's particle Id #
921 // t Time when the track hit
088f8e79 922 // l Track length through the material.
923 // stop Whether track was stopped or disappeared
4347b38f 924 //
925 TClonesArray& a = *(HitsArray());
926 // Search through the list of already registered hits, and see if we
927 // find a hit with the same parameters. If we do, then don't create
928 // a new hit, but rather update the energy deposited in the hit.
929 // This is done, so that a FLUKA based simulation will get the
930 // number of hits right, not just the enerrgy deposition.
ac4c3fbb 931 AliFMDHit* hit = 0;
4347b38f 932 for (Int_t i = 0; i < fNhits; i++) {
933 if (!a.At(i)) continue;
ac4c3fbb 934 hit = static_cast<AliFMDHit*>(a.At(i));
4347b38f 935 if (hit->Detector() == detector
936 && hit->Ring() == ring
937 && hit->Sector() == sector
938 && hit->Strip() == strip
939 && hit->Track() == track) {
8f6ee336 940 AliDebug(1, Form("already had a hit in FMD%d%c[%2d,%3d] for track # %d,"
941 " adding energy (%f) to that hit (%f) -> %f",
942 detector, ring, sector, strip, track, edep, hit->Edep(),
943 hit->Edep() + edep));
4347b38f 944 hit->SetEdep(hit->Edep() + edep);
54240c8d 945 return hit;
4347b38f 946 }
947 }
948 // If hit wasn't already registered, do so know.
ac4c3fbb 949 hit = new (a[fNhits]) AliFMDHit(fIshunt, track, detector, ring, sector,
088f8e79 950 strip, x, y, z, px, py, pz, edep, pdg, t,
951 l, stop);
4347b38f 952 fNhits++;
54240c8d 953 return hit;
b9a2d5e4 954}
fe4da5cc 955
4347b38f 956//____________________________________________________________________
957void
69b696b9 958AliFMD::AddDigit(Int_t* digits, Int_t*)
fe4da5cc 959{
4347b38f 960 // Add a digit to the Digit tree
961 //
962 // Paramters
fe4da5cc 963 //
4347b38f 964 // digits[0] [UShort_t] Detector #
965 // digits[1] [Char_t] Ring ID
966 // digits[2] [UShort_t] Sector #
967 // digits[3] [UShort_t] Strip #
968 // digits[4] [UShort_t] ADC Count
969 // digits[5] [Short_t] ADC Count, -1 if not used
970 // digits[6] [Short_t] ADC Count, -1 if not used
971 //
69b696b9 972 AddDigitByFields(UShort_t(digits[0]), // Detector #
973 Char_t(digits[1]), // Ring ID
974 UShort_t(digits[2]), // Sector #
975 UShort_t(digits[3]), // Strip #
976 UShort_t(digits[4]), // ADC Count1
977 Short_t(digits[5]), // ADC Count2
978 Short_t(digits[6])); // ADC Count3
4347b38f 979}
980
981//____________________________________________________________________
982void
69b696b9 983AliFMD::AddDigitByFields(UShort_t detector,
984 Char_t ring,
985 UShort_t sector,
986 UShort_t strip,
987 UShort_t count1,
988 Short_t count2,
989 Short_t count3)
4347b38f 990{
991 // add a real digit - as coming from data
992 //
993 // Parameters
fe4da5cc 994 //
4347b38f 995 // detector Detector # (1, 2, or 3)
996 // ring Ring ID ('I' or 'O')
997 // sector Sector # (For inner/outer rings: 0-19/0-39)
998 // strip Strip # (For inner/outer rings: 0-511/0-255)
999 // count1 ADC count (a 10-bit word)
1000 // count2 ADC count (a 10-bit word), or -1 if not used
1001 // count3 ADC count (a 10-bit word), or -1 if not used
1002 TClonesArray& a = *(DigitsArray());
1003
1004 new (a[fNdigits++])
1005 AliFMDDigit(detector, ring, sector, strip, count1, count2, count3);
1006}
1007
1008//____________________________________________________________________
1009void
1010AliFMD::AddSDigit(Int_t* digits)
1011{
1012 // Add a digit to the SDigit tree
1013 //
1014 // Paramters
b9a2d5e4 1015 //
4347b38f 1016 // digits[0] [UShort_t] Detector #
1017 // digits[1] [Char_t] Ring ID
1018 // digits[2] [UShort_t] Sector #
1019 // digits[3] [UShort_t] Strip #
1020 // digits[4] [Float_t] Total energy deposited
1021 // digits[5] [UShort_t] ADC Count
1022 // digits[6] [Short_t] ADC Count, -1 if not used
1023 // digits[7] [Short_t] ADC Count, -1 if not used
1024 //
69b696b9 1025 AddSDigitByFields(UShort_t(digits[0]), // Detector #
1026 Char_t(digits[1]), // Ring ID
1027 UShort_t(digits[2]), // Sector #
1028 UShort_t(digits[3]), // Strip #
1029 Float_t(digits[4]), // Edep
1030 UShort_t(digits[5]), // ADC Count1
1031 Short_t(digits[6]), // ADC Count2
1032 Short_t(digits[7])); // ADC Count3
4347b38f 1033}
1034
1035//____________________________________________________________________
1036void
69b696b9 1037AliFMD::AddSDigitByFields(UShort_t detector,
1038 Char_t ring,
1039 UShort_t sector,
1040 UShort_t strip,
1041 Float_t edep,
1042 UShort_t count1,
1043 Short_t count2,
1044 Short_t count3)
4347b38f 1045{
1046 // add a summable digit
1047 //
1048 // Parameters
b9a2d5e4 1049 //
4347b38f 1050 // detector Detector # (1, 2, or 3)
1051 // ring Ring ID ('I' or 'O')
1052 // sector Sector # (For inner/outer rings: 0-19/0-39)
1053 // strip Strip # (For inner/outer rings: 0-511/0-255)
1054 // edep Total energy deposited
1055 // count1 ADC count (a 10-bit word)
1056 // count2 ADC count (a 10-bit word), or -1 if not used
1057 // count3 ADC count (a 10-bit word), or -1 if not used
37c4363a 1058 //
4347b38f 1059 TClonesArray& a = *(SDigitsArray());
1060
1061 new (a[fNsdigits++])
1062 AliFMDSDigit(detector, ring, sector, strip, edep, count1, count2, count3);
fe4da5cc 1063}
4347b38f 1064
1065//____________________________________________________________________
1066void
1067AliFMD::ResetSDigits()
d28dcc0d 1068{
4347b38f 1069 //
1070 // Reset number of digits and the digits array for this detector
1071 //
1072 fNsdigits = 0;
1073 if (fSDigits) fSDigits->Clear();
1074}
1075
1076
1077//____________________________________________________________________
1078TClonesArray*
1079AliFMD::HitsArray()
1080{
1081 // Initialize hit array if not already, and return pointer to it.
1082 if (!fHits) {
1083 fHits = new TClonesArray("AliFMDHit", 1000);
1084 fNhits = 0;
1085 }
1086 return fHits;
1087}
1088
1089//____________________________________________________________________
1090TClonesArray*
1091AliFMD::DigitsArray()
1092{
1093 // Initialize digit array if not already, and return pointer to it.
1094 if (!fDigits) {
1095 fDigits = new TClonesArray("AliFMDDigit", 1000);
1096 fNdigits = 0;
1097 }
1098 return fDigits;
1099}
1100
1101//____________________________________________________________________
1102TClonesArray*
1103AliFMD::SDigitsArray()
1104{
1105 // Initialize digit array if not already, and return pointer to it.
1106 if (!fSDigits) {
1107 fSDigits = new TClonesArray("AliFMDSDigit", 1000);
1108 fNsdigits = 0;
1109 }
1110 return fSDigits;
1111}
1112
1113//====================================================================
1114//
1115// Digitization
1116//
1117//____________________________________________________________________
1118void
1119AliFMD::Hits2Digits()
1120{
37c4363a 1121 // Create AliFMDDigit's from AliFMDHit's. This is done by making a
1122 // AliFMDDigitizer, and executing that code.
1123 //
a3537838 1124 Warning("Hits2Digits", "Try not to use this method.\n"
1125 "Instead, use AliSimulator");
4347b38f 1126 AliRunDigitizer* manager = new AliRunDigitizer(1, 1);
1127 manager->SetInputStream(0, "galice.root");
1128 manager->SetOutputFile("H2Dfile");
dc8af42e 1129
4347b38f 1130 /* AliDigitizer* dig =*/ CreateDigitizer(manager);
1131 manager->Exec("");
99d864b7 1132 delete manager;
4347b38f 1133}
1134
1135//____________________________________________________________________
1136void
1137AliFMD::Hits2SDigits()
1138{
37c4363a 1139 // Create AliFMDSDigit's from AliFMDHit's. This is done by creating
1140 // an AliFMDSDigitizer object, and executing it.
1141 //
56b1929b 1142 AliFMDSDigitizer* digitizer = new AliFMDSDigitizer("galice.root");
56b1929b 1143 digitizer->Exec("");
99d864b7 1144 delete digitizer;
4347b38f 1145}
1146
dc8af42e 1147
4347b38f 1148//____________________________________________________________________
1149AliDigitizer*
1150AliFMD::CreateDigitizer(AliRunDigitizer* manager) const
1151{
1152 // Create a digitizer object
56b1929b 1153 AliFMDDigitizer* digitizer = new AliFMDDigitizer(manager);
56b1929b 1154 return digitizer;
4347b38f 1155}
b9a2d5e4 1156
4347b38f 1157//====================================================================
1158//
1159// Raw data simulation
1160//
1161//__________________________________________________________________
1162void
1163AliFMD::Digits2Raw()
1164{
37c4363a 1165 // Turn digits into raw data.
1166 //
e802be3e 1167 // This uses the class AliFMDRawWriter to do the job. Please refer
1168 // to that class for more information.
1169 AliFMDRawWriter writer(this);
1170 writer.Exec();
b9a2d5e4 1171}
1172
4347b38f 1173
1174//====================================================================
1175//
1176// Utility
1177//
1178//__________________________________________________________________
1179void
1180AliFMD::Browse(TBrowser* b)
1181{
37c4363a 1182 // Browse this object.
1183 //
824466d5 1184 AliDebug(30, "\tBrowsing the FMD");
4347b38f 1185 AliDetector::Browse(b);
1a1fdef7 1186 b->Add(AliFMDGeometry::Instance());
4347b38f 1187}
1188
4347b38f 1189//___________________________________________________________________
1190//
1191// EOF
1192//