Line data Source code
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 : // **************************************************************************
15 :
16 : //====================================================================================================================================================
17 : //
18 : // Main class of the ALICE Muon Forward Tracker
19 : //
20 : // Contact author: antonio.uras@cern.ch
21 : //
22 : //====================================================================================================================================================
23 :
24 : #include "AliLog.h"
25 : #include "AliCodeTimer.h"
26 : #include "TFile.h"
27 : #include "TGeoManager.h"
28 : #include "TGeoVolume.h"
29 : #include "TGeoMatrix.h"
30 : #include "TVirtualMC.h"
31 : #include "TClonesArray.h"
32 : #include "TGeoGlobalMagField.h"
33 : #include "AliRun.h"
34 : #include "AliLoader.h"
35 : #include "AliDetector.h"
36 : #include "AliMC.h"
37 : #include "AliMagF.h"
38 : #include "AliMFT.h"
39 : #include "AliMFTHit.h"
40 : #include "AliMFTDigit.h"
41 : #include "AliMFTCluster.h"
42 : #include "AliTrackReference.h"
43 : #include "AliMFTSegmentation.h"
44 : #include "AliMFTDigitizer.h"
45 : #include "AliMFTPlane.h"
46 : #include "AliMFTConstants.h"
47 : #include "TString.h"
48 : #include "TObjArray.h"
49 : #include "AliMFTGeometry.h"
50 :
51 12 : ClassImp(AliMFT)
52 :
53 : //====================================================================================================================================================
54 :
55 : AliMFT::AliMFT():
56 0 : AliDetector(),
57 0 : fVersion(1),
58 0 : fNPlanes(0),
59 0 : fSDigitsPerPlane(0),
60 0 : fDigitsPerPlane(0),
61 0 : fRecPointsPerPlane(0),
62 0 : fSideDigits(0),
63 0 : fSegmentation(0),
64 0 : fNameGeomFile(0),
65 0 : fChargeDispersion(25.e-4),
66 0 : fSingleStepForChargeDispersion(0),
67 0 : fNStepForChargeDispersion(4),
68 0 : fDensitySupportOverSi(0.036),
69 0 : fFileNameForUnderyingEvent(0),
70 0 : fFileNameForPileUpEvents(0),
71 0 : fNPileUpEvents(0),
72 0 : fUnderlyingEventID(-1)
73 0 : {
74 :
75 : // default constructor
76 :
77 0 : for (Int_t iPileUp=0; iPileUp<AliMFTConstants::fNMaxPileUpEvents; iPileUp++) fPileUpEventsIDs[iPileUp] = -1;
78 :
79 :
80 0 : }
81 :
82 : //====================================================================================================================================================
83 :
84 : AliMFT::AliMFT(const Char_t *name, const Char_t *title):
85 0 : AliDetector(name, title),
86 0 : fVersion(1),
87 0 : fNPlanes(0),
88 0 : fSDigitsPerPlane(0),
89 0 : fDigitsPerPlane(0),
90 0 : fRecPointsPerPlane(0),
91 0 : fSideDigits(0),
92 0 : fSegmentation(0),
93 0 : fNameGeomFile(0),
94 0 : fChargeDispersion(25.e-4),
95 0 : fSingleStepForChargeDispersion(0),
96 0 : fNStepForChargeDispersion(4),
97 0 : fDensitySupportOverSi(0.036),
98 0 : fFileNameForUnderyingEvent(0),
99 0 : fFileNameForPileUpEvents(0),
100 0 : fNPileUpEvents(0),
101 0 : fUnderlyingEventID(-1)
102 0 : {
103 :
104 0 : for (Int_t iPileUp=0; iPileUp<AliMFTConstants::fNMaxPileUpEvents; iPileUp++) fPileUpEventsIDs[iPileUp] = -1;
105 :
106 0 : fNameGeomFile = "AliMFTGeometry.root";
107 :
108 0 : SetGeometry();
109 :
110 0 : Init();
111 :
112 0 : }
113 :
114 : //====================================================================================================================================================
115 :
116 : AliMFT::AliMFT(const Char_t *name, const Char_t *title, Char_t *nameGeomFile):
117 0 : AliDetector(name, title),
118 0 : fVersion(1),
119 0 : fNPlanes(0),
120 0 : fSDigitsPerPlane(0),
121 0 : fDigitsPerPlane(0),
122 0 : fRecPointsPerPlane(0),
123 0 : fSideDigits(0),
124 0 : fSegmentation(0),
125 0 : fNameGeomFile(0),
126 0 : fChargeDispersion(25.e-4),
127 0 : fSingleStepForChargeDispersion(0),
128 0 : fNStepForChargeDispersion(4),
129 0 : fDensitySupportOverSi(0.036),
130 0 : fFileNameForUnderyingEvent(0),
131 0 : fFileNameForPileUpEvents(0),
132 0 : fNPileUpEvents(0),
133 0 : fUnderlyingEventID(-1)
134 0 : {
135 :
136 0 : for (Int_t iPileUp=0; iPileUp<AliMFTConstants::fNMaxPileUpEvents; iPileUp++) fPileUpEventsIDs[iPileUp] = -1;
137 :
138 0 : fNameGeomFile = nameGeomFile;
139 :
140 0 : SetGeometry();
141 :
142 0 : Init();
143 :
144 0 : }
145 :
146 : //====================================================================================================================================================
147 :
148 0 : AliMFT::~AliMFT() {
149 :
150 0 : if (fSDigitsPerPlane) { fSDigitsPerPlane->Delete(); delete fSDigitsPerPlane; }
151 0 : if (fDigitsPerPlane) { fDigitsPerPlane->Delete(); delete fDigitsPerPlane; }
152 0 : if (fRecPointsPerPlane) { fRecPointsPerPlane->Delete(); delete fRecPointsPerPlane; }
153 :
154 0 : }
155 :
156 : //====================================================================================================================================================
157 :
158 : void AliMFT::CreateMaterials() {
159 :
160 : /// \todo Check all materials Remove the one unneeded
161 :
162 :
163 : // Definition of MFT materials - to be updated to the most recent values
164 :
165 0 : AliDebug(1,"Start MFT materials");
166 :
167 :
168 : // data from PDG booklet 2002 density [gr/cm^3] rad len [cm] abs len [cm]
169 0 : Float_t aSi = 28.085 , zSi = 14. , dSi = 2.329 , radSi = 21.82/dSi , absSi = 108.4/dSi ; // Silicon
170 : Float_t aCarb = 12.01 , zCarb = 6. , dCarb = 2.265 , radCarb = 18.8 , absCarb = 49.9 ; // Carbon
171 : Float_t aAlu = 26.98 , zAlu = 13. , dAlu = 2.70 , radAlu = 8.897 , absAlu = 39.70 ; // Aluminum
172 0 : Float_t aBe = 9.012182 , zBe = 4. , dBe = 1.85 , radBe = 65.19/dBe , absBe = 77.8/dBe ; // Beryllium
173 : Float_t aCu = 63.546 , zCu = 29. , dCu = 8.96 , radCu = 1.436 , absCu = 15.32 ; // Copper
174 :
175 : // Air mixture
176 : const Int_t nAir = 4;
177 0 : Float_t aAir[nAir] = {12, 14, 16, 36} , zAir[nAir] = {6, 7, 8, 18} , wAir[nAir]={0.000124, 0.755267, 0.231781, 0.012827} , dAir=0.00120479, dAirVacuum=0.00120479e-4;
178 :
179 : // Water mixture
180 : const Int_t nWater = 2;
181 0 : Float_t aWater[nWater] = {1.00794, 15.9994} , zWater[nWater] = {1, 8} , wWater[nWater] = {0.111894, 0.888106} , dWater=1.;
182 :
183 : // SiO2 mixture
184 : const Int_t nSiO2 = 2;
185 0 : Float_t aSiO2[nSiO2] = {15.9994, 28.0855} , zSiO2[nSiO2] = {8., 14.} , wSiO2[nSiO2] = {0.532565, 0.467435} , dSiO2 = 2.20;
186 :
187 : // Inox mixture
188 : const Int_t nInox = 9;
189 0 : Float_t aInox[nInox] = {12.0107, 54.9380, 28.0855, 30.9738, 32.0660, 58.6928, 51.9961, 95.9400, 55.8450} ;
190 0 : Float_t zInox[nInox] = { 6, 25, 14, 15, 16, 28, 24, 42, 26 } ;
191 0 : Float_t wInox[nInox] = {0.0003, 0.02, 0.01, 0.00045, 0.0003, 0.12, 0.17, 0.025, 0.65395} ;
192 : Float_t dInox = 8.03;
193 :
194 : // Kapton polyimide film (from SPD AliITSv11.cxx) and http://physics.nist.gov/cgi-bin/Star/compos.pl?matno=179
195 0 : Float_t aKapton[4]={1.00794,12.0107, 14.010,15.9994};
196 0 : Float_t zKapton[4]={1.,6.,7.,8.};
197 0 : Float_t wKapton[4]={0.026362,0.69113,0.07327,0.209235};
198 : Float_t dKapton = 1.42;
199 :
200 : //--- EPOXY --- C18 H19 O3 from ITS AliITSv11.cxx
201 0 : Float_t aEpoxy[3] = {15.9994, 1.00794, 12.0107} ;
202 0 : Float_t zEpoxy[3] = { 8., 1., 6.} ;
203 0 : Float_t wEpoxy[3] = { 3., 19., 18.} ;
204 : Float_t dEpoxy = 1.8 ;
205 :
206 : //--- CARBON FIBER CM55J --- from ITS AliITSv11.cxx
207 0 : Float_t aCM55J[4]={12.0107,14.0067,15.9994,1.00794};
208 0 : Float_t zCM55J[4]={6.,7.,8.,1.};
209 0 : Float_t wCM55J[4]={0.908508078,0.010387573,0.055957585,0.025146765};
210 : Float_t dCM55J = 1.8; // 1.63 from AliITSv11Geometry.cxx !?
211 :
212 : // Rohacell mixture
213 : const Int_t nRohacell = 3;
214 0 : Float_t aRohacell[nRohacell] = {1.00794, 12.0107, 15.9994};
215 0 : Float_t zRohacell[nRohacell] = {1., 6., 8.};
216 0 : Float_t wRohacell[nRohacell] = {0.0858, 0.5964, 0.3178};
217 : Float_t dRohacell = 0.075;
218 :
219 : // Polyimide pipe mixture
220 : const Int_t nPolyimide = 4;
221 0 : Float_t aPolyimide[nPolyimide] = {1.00794, 12.0107, 14.0067, 15.9994};
222 0 : Float_t zPolyimide[nPolyimide] = {1, 6, 7, 8};
223 0 : Float_t wPolyimide[nPolyimide] = {0.00942, 0.56089, 0.13082, 0.29887};
224 : Float_t dPolyimide = 1.4;
225 :
226 : // PEEK mixture (Polyether Ether Ketone)
227 : const Int_t nPEEK = 3;
228 0 : Float_t aPEEK[nPEEK] = {1.00794, 12.0107, 15.9994} ;
229 0 : Float_t zPEEK[nPEEK] = {1, 6, 8} ;
230 0 : Float_t wPEEK[nPEEK] = {0.06713, 0.40001, 0.53285} ;
231 : Float_t dPEEK = 1.32;
232 :
233 : // (Printed Circuit Board), material type FR4
234 : const Int_t nFR4 = 5;
235 0 : Float_t aFR4[nFR4] = {1.00794, 12.0107, 15.9994, 28.0855, 79.904} ;
236 0 : Float_t zFR4[nFR4] = {1, 6, 8, 14, 35} ;
237 0 : Float_t wFR4[nFR4] = {0.0684428, 0.278042,0.405633, 0.180774, 0.0671091} ;
238 : Float_t dFR4 = 1.7; //Density FR4= 1.7 Cu=8.96
239 :
240 :
241 : Int_t matId = 0; // tmp material id number
242 : Int_t unsens = 0, sens=1; // sensitive or unsensitive medium
243 : Int_t itgfld = 3; // type of field intergration 0 no field -1 user in guswim 1 Runge Kutta 2 helix 3 const field along z
244 : Float_t maxfld = 5.; // max field value
245 :
246 : Float_t tmaxfd = -10.0; // max deflection angle due to magnetic field in one step
247 : Float_t stemax = 0.001; // max step allowed [cm]
248 : Float_t deemax = -0.2; // maximum fractional energy loss in one step 0<deemax<=1
249 : Float_t epsil = 0.001; // tracking precision [cm]
250 : Float_t stmin = -0.001; // minimum step due to continuous processes [cm] (negative value: choose it automatically)
251 :
252 : Float_t tmaxfdSi = 0.1; // max deflection angle due to magnetic field in one step
253 : Float_t stemaxSi = 5.0e-4; // maximum step allowed [cm]
254 : Float_t deemaxSi = 0.1; // maximum fractional energy loss in one step 0<deemax<=1
255 : Float_t epsilSi = 0.5e-4; // tracking precision [cm]
256 : Float_t stminSi = -0.001; // minimum step due to continuous processes [cm] (negative value: choose it automatically)
257 :
258 0 : Int_t fieldType = ((AliMagF*)TGeoGlobalMagField::Instance()->GetField())->Integ(); // Field type
259 0 : Double_t maxField = ((AliMagF*)TGeoGlobalMagField::Instance()->GetField())->Max(); // Field max.
260 :
261 0 : AliMixture(kAir,"Air$", aAir, zAir, dAir, nAir, wAir);
262 0 : AliMedium(kAir, "Air$", kAir, unsens, fieldType, maxField, tmaxfd, stemax, deemax, epsil, stmin);
263 : //
264 : // Vacuum
265 0 : AliMixture(kVacuum, "Vacuum$", aAir, zAir, dAirVacuum, nAir, wAir);
266 0 : AliMedium(kVacuum, "Vacuum$", kVacuum, unsens, itgfld, maxfld, tmaxfd, stemax, deemax, epsil, stmin);
267 :
268 0 : AliMaterial(++matId, "Si$", aSi, zSi, dSi, radSi, absSi);
269 0 : AliMedium(kSi, "Si$", matId, sens, fieldType, maxField, tmaxfdSi, stemaxSi, deemaxSi, epsilSi, stminSi);
270 :
271 0 : AliMaterial(++matId, "Readout$", aSi, zSi, dSi, radSi, absSi);
272 0 : AliMedium(kReadout, "Readout$", matId, unsens, fieldType, maxField, tmaxfdSi, stemaxSi, deemaxSi, epsilSi, stminSi);
273 :
274 0 : AliMaterial(++matId, "Support$", aSi, zSi, dSi*fDensitySupportOverSi, radSi/fDensitySupportOverSi, absSi/fDensitySupportOverSi);
275 0 : AliMedium(kSupport, "Support$", matId, unsens, fieldType, maxField, tmaxfdSi, stemaxSi, deemaxSi, epsilSi, stminSi);
276 :
277 : Double_t maxBending = 0; // Max Angle
278 : Double_t maxStepSize = 0.001; // Max step size
279 : Double_t maxEnergyLoss = 1; // Max Delta E
280 : Double_t precision = 0.001; // Precision
281 : Double_t minStepSize = 0.001; // Minimum step size
282 : // Carbon
283 : aCarb = 12.011;
284 : zCarb = 6.;
285 : dCarb = 2.265;
286 : radCarb = 18.8;
287 : absCarb = 999;
288 : maxBending = 10;
289 : maxStepSize = .01;
290 : precision = .003;
291 : minStepSize = .003;
292 0 : AliMaterial(matId, "Carbon$", aCarb, zCarb, dCarb, radCarb, absCarb);
293 0 : AliMedium(kCarbon, "Carbon$", matId,0,fieldType,maxField,maxBending,
294 : maxStepSize,maxEnergyLoss,precision,minStepSize);
295 :
296 : // AliMaterial(++matId, "Carbon$", aCarb, zCarb, dCarb, radCarb, absCarb );
297 : // AliMedium(kCarbon, "Carbon$", matId, unsens, fieldType, maxField, tmaxfd, stemax, deemax, epsil, stmin);
298 :
299 0 : AliMaterial(++matId, "Be$", aBe, zBe, dBe, radBe, absBe );
300 0 : AliMedium(kBe, "Be$", matId, unsens, fieldType, maxField, tmaxfd, stemax, deemax, epsil, stmin);
301 :
302 0 : AliMaterial(++matId, "Alu$", aAlu, zAlu, dAlu, radAlu, absAlu);
303 0 : AliMedium(kAlu, "Alu$", matId, unsens, fieldType, maxField, tmaxfd, stemax, deemax, epsil, stmin);
304 :
305 :
306 0 : AliMixture(++matId, "Water$", aWater, zWater, dWater, nWater, wWater);
307 0 : AliMedium(kWater, "Water$", matId, unsens, itgfld, maxfld, tmaxfd, stemax, deemax, epsil, stmin);
308 :
309 0 : AliMixture(++matId, "SiO2$", aSiO2, zSiO2, dSiO2, nSiO2, wSiO2);
310 0 : AliMedium(kSiO2, "SiO2$", matId, unsens, itgfld, maxfld, tmaxfd, stemax, deemax, epsil, stmin);
311 :
312 0 : AliMixture(++matId, "Inox$", aInox, zInox, dInox, nInox, wInox);
313 0 : AliMedium(kInox, "Inox$", matId, unsens, itgfld, maxfld, tmaxfd, stemax, deemax, epsil, stmin);
314 :
315 0 : AliMixture(++matId, "Kapton$", aKapton, zKapton, dKapton, 4, wKapton);
316 0 : AliMedium(kKapton,"Kapton$", matId, unsens, itgfld, maxfld, tmaxfd, stemax, deemax, epsil, stmin);
317 :
318 0 : AliMixture(++matId, "Epoxy$", aEpoxy, zEpoxy, dEpoxy, -3, wEpoxy);
319 0 : AliMedium(kEpoxy,"Epoxy$", matId, unsens, itgfld, maxfld, tmaxfd, stemax, deemax, epsil, stmin);
320 :
321 0 : AliMixture(++matId,"C (M55J)$",aCM55J,zCM55J,dCM55J,4,wCM55J);
322 0 : AliMedium(kCarbonEpoxy,"CarbonFiber$", matId, unsens, itgfld, maxfld, tmaxfd, stemax, deemax, epsil, stmin);
323 :
324 0 : AliMixture(++matId, "Rohacell", aRohacell, zRohacell, dRohacell, nRohacell, wRohacell);
325 0 : AliMedium(kRohacell, "Rohacell", matId, unsens, itgfld, maxfld, tmaxfd, stemax, deemax, epsil, stmin);
326 :
327 0 : AliMixture(++matId, "Polyimide", aPolyimide, zPolyimide, dPolyimide, nPolyimide, wPolyimide);
328 0 : AliMedium(kPolyimide, "Polyimide", matId, unsens, itgfld, maxfld, tmaxfd, stemax, deemax, epsil, stmin);
329 :
330 0 : AliMixture(++matId, "PEEK$", aPEEK, zPEEK, dPEEK, nPEEK, wPEEK);
331 0 : AliMedium(kPEEK, "PEEK$", matId, unsens, itgfld, maxfld, tmaxfd, stemax, deemax, epsil, stmin);
332 :
333 0 : AliMixture(++matId, "FR4$", aFR4, zFR4, dFR4, nFR4, wFR4);
334 0 : AliMedium(kFR4, "FR4$", matId, unsens, itgfld, maxfld, tmaxfd, stemax, deemax, epsil, stmin);
335 :
336 0 : AliMaterial(++matId, "Cu$", aCu, zCu, dCu, radCu, absCu);
337 0 : AliMedium(kCu, "Cu$", matId, unsens, itgfld, maxfld, tmaxfd, stemax, deemax, epsil, stmin);
338 :
339 0 : AliDebug(1,"End MFT materials");
340 :
341 0 : }
342 :
343 : //====================================================================================================================================================
344 :
345 : void AliMFT::CreateGeometry() {
346 :
347 : // Creates detailed geometry simulation (currently GEANT volumes tree)
348 :
349 0 : if(!TVirtualMC::GetMC()->IsRootGeometrySupported()) return;
350 :
351 0 : AliMFTGeometry* mftGeom = AliMFTGeometry::Instance();
352 :
353 0 : mftGeom->Build();
354 :
355 0 : if (fNStepForChargeDispersion) fSingleStepForChargeDispersion = fChargeDispersion/Double_t(fNStepForChargeDispersion);
356 :
357 0 : }
358 :
359 : //====================================================================================================================================================
360 :
361 : void AliMFT::AddAlignableVolumes() {
362 :
363 : // Create entries for alignable volumes associating the symbolic volume
364 : // name with the corresponding volume path. Needs to be syncronized with
365 : // eventual changes in the geometry.
366 :
367 0 : TString sysName = "MFT";
368 0 : TString volPath = "/ALIC_1/MFT_0";
369 :
370 0 : if (!gGeoManager->SetAlignableEntry(sysName.Data(),volPath.Data())) {
371 0 : AliFatal(Form("Alignable entry %s not created. Volume path %s not valid", sysName.Data(), volPath.Data()));
372 : }
373 :
374 0 : }
375 :
376 : //====================================================================================================================================================
377 :
378 : void AliMFT::StepManager() {
379 :
380 : // If MFT is not active do nothing
381 0 : if (!(this->IsActive())) return;
382 :
383 0 : AliMFTGeometry *mftGeo = AliMFTGeometry::Instance();
384 0 : AliMFTSegmentation * seg = mftGeo->GetSegmentation();
385 0 : if (!seg) AliFatal("No segmentation available");
386 :
387 0 : TVirtualMC* mc = TVirtualMC::GetMC();
388 :
389 0 : Double_t absQ = TMath::Abs(mc->TrackCharge());
390 0 : if (absQ <= 0) return;
391 :
392 0 : Int_t copy;
393 : // Check if hit is into a MFT sensor volume
394 0 : if(mc->CurrentVolID(copy) != mftGeo->GetSensorVolumeID() ) return;
395 : // Get The Sensor Unique ID
396 0 : int chipId=-1,ladderId=-1,diskId=-1,halfId=-1,level=0;
397 0 : mc->CurrentVolOffID(++level,chipId);
398 0 : mc->CurrentVolOffID(++level,ladderId);
399 0 : mc->CurrentVolOffID(++level,diskId);
400 0 : mc->CurrentVolOffID(++level,halfId);
401 0 : Int_t detElemID = mftGeo->GetObjectID(AliMFTGeometry::kSensorType,halfId,diskId,ladderId,chipId);
402 0 : AliDebug(1,Form("Found hit into half = %d; disk = %d; ladder = %d; chip = %d",halfId,diskId,ladderId,chipId));
403 :
404 0 : if (mc->IsTrackExiting()) {
405 0 : AddTrackReference(gAlice->GetMCApp()->GetCurrentTrackNumber(), AliTrackReference::kMFT);
406 0 : }
407 :
408 0 : static TLorentzVector position, momentum;
409 0 : static AliMFTHit hit;
410 :
411 : Int_t status = 0;
412 :
413 : // Track status
414 0 : if (mc->IsTrackInside()) status += 0x1<<0;
415 0 : if (mc->IsTrackEntering()) status += 0x1<<1;
416 0 : if (mc->IsTrackExiting()) status += 0x1<<2;
417 0 : if (mc->IsTrackOut()) status += 0x1<<3;
418 0 : if (mc->IsTrackDisappeared()) status += 0x1<<4;
419 0 : if (mc->IsTrackStop()) status += 0x1<<5;
420 0 : if (mc->IsTrackAlive()) status += 0x1<<6;
421 :
422 : // ---------- Fill hit structure
423 :
424 0 : hit.SetDetElemID(detElemID);
425 0 : hit.SetPlane(diskId);
426 0 : hit.SetTrack(gAlice->GetMCApp()->GetCurrentTrackNumber());
427 :
428 0 : mc->TrackPosition(position);
429 0 : mc->TrackMomentum(momentum);
430 :
431 0 : AliDebug(1, Form(" %s Hit #%06d (x=%f, y=%f, z=%f) belongs to track %02d",
432 : mc->CurrentVolName(), fNhits, position.X(), position.Y(), position.Z(), gAlice->GetMCApp()->GetCurrentTrackNumber()));
433 :
434 0 : hit.SetPosition(position);
435 0 : hit.SetTOF(mc->TrackTime());
436 0 : hit.SetMomentum(momentum);
437 0 : hit.SetStatus(status);
438 0 : hit.SetEloss(mc->Edep());
439 : // hit.SetShunt(GetIshunt());
440 : // if (mc->IsTrackEntering()) {
441 : // hit.SetStartPosition(position);
442 : // hit.SetStartTime(mc->TrackTime());
443 : // hit.SetStartStatus(status);
444 : // return; // don't save entering hit.
445 : // }
446 :
447 : // Fill hit structure with this new hit.
448 0 : new ((*fHits)[fNhits++]) AliMFTHit(hit);
449 :
450 : // Save old position... for next hit.
451 : // hit.SetStartPosition(position);
452 : // hit.SetStartTime(mc->TrackTime());
453 : // hit.SetStartStatus(status);
454 :
455 : return;
456 :
457 0 : }
458 :
459 :
460 : //====================================================================================================================================================
461 :
462 : void AliMFT::Hits2SDigits(){
463 :
464 : // Interface method invoked from AliSimulation to create a list of sdigits corresponding to list of hits. Every hit generates one sdigit.
465 0 : AliCodeTimerAuto("",0);
466 :
467 0 : AliDebug(1, "Start Hits2SDigits.");
468 :
469 0 : AliMFTGeometry *mftGeo = AliMFTGeometry::Instance();
470 0 : AliMFTSegmentation * seg = mftGeo->GetSegmentation();
471 0 : if (!seg) AliFatal("No segmentation available");
472 :
473 0 : if (!fLoader->TreeH()) fLoader->LoadHits();
474 :
475 0 : if (!fLoader->TreeS()) {
476 :
477 0 : for (Int_t iEvt=0;iEvt<fLoader->GetRunLoader()->GetNumberOfEvents(); iEvt++) {
478 :
479 0 : fLoader->GetRunLoader()->GetEvent(iEvt);
480 0 : fLoader->MakeTree("S");
481 0 : MakeBranch("S");
482 0 : SetTreeAddress();
483 :
484 0 : AliDebug(1, Form("Event %03d: fLoader->TreeH()->GetEntries() = %2d", iEvt, Int_t(fLoader->TreeH()->GetEntries())));
485 :
486 0 : for (Int_t iTrack=0; iTrack<fLoader->TreeH()->GetEntries(); iTrack++) {
487 0 : fLoader->TreeH()->GetEntry(iTrack);
488 0 : Hits2SDigitsLocal(Hits(), GetSDigitsList(), iTrack); // convert these hits to a list of sdigits
489 : }
490 :
491 0 : fLoader->TreeS()->Fill();
492 0 : fLoader->WriteSDigits("OVERWRITE");
493 0 : ResetSDigits();
494 :
495 : }
496 0 : }
497 :
498 0 : fLoader->UnloadHits();
499 0 : fLoader->UnloadSDigits();
500 :
501 0 : AliDebug(1,"Stop Hits2SDigits.");
502 :
503 0 : }
504 :
505 : //====================================================================================================================================================
506 :
507 : void AliMFT::Hits2SDigitsLocal(TClonesArray *hits, const TObjArray *pSDig, Int_t track) {
508 :
509 : // Add sdigits of these hits to the list
510 :
511 0 : AliDebug(1, "Entering Hits2SDigitsLocal");
512 :
513 0 : TClonesArray *pSDigList[AliMFTConstants::kNDisks];
514 0 : for (Int_t iPlane=0; iPlane<AliMFTConstants::kNDisks; iPlane++) pSDigList[iPlane] = NULL;
515 0 : for (Int_t iPlane=0; iPlane<AliMFTConstants::kNDisks; iPlane++) {
516 0 : pSDigList[iPlane] = (TClonesArray*) (*pSDig)[iPlane];
517 0 : AliDebug(1,Form("Entries of pSDigList %3d; plane: %02d,",pSDigList[iPlane]->GetEntries(),iPlane));
518 0 : if (!track && pSDigList[iPlane]->GetEntries()!=0) AliErrorClass("Some of sdigits lists is not empty");
519 : }
520 :
521 0 : for (Int_t iHit=0; iHit<hits->GetEntries(); iHit++) {
522 :
523 0 : AliMFTHit *hit = (AliMFTHit*) hits->At(iHit);
524 :
525 : // AliDebug(1,Form("\n--- New hit x,y,z %f %f %f ",hit->X(), hit->Y(), hit->Z()));
526 :
527 : // Creating "main digit"
528 :
529 0 : AliMFTDigit *mainSDigit = new AliMFTDigit();
530 0 : mainSDigit->SetEloss(hit->GetEloss());
531 0 : mainSDigit->SetDetElemID(hit->GetDetElemID());
532 0 : mainSDigit->SetPlane(hit->GetPlane());
533 0 : mainSDigit->AddMCLabel(hit->GetTrack());
534 0 : Int_t xPixel = -1;
535 0 : Int_t yPixel = -1;
536 0 : AliMFTGeometry * mftGeom = AliMFTGeometry::Instance();
537 :
538 0 : AliDebug(2,Form("Hit at x,y,z = %f %f %f ",hit->X(), hit->Y(), hit->Z()));
539 0 : if(mftGeom->Hit2PixelID(hit->X(), hit->Y(), hit->Z(), mainSDigit->GetDetElemID(), xPixel, yPixel)){
540 0 : mainSDigit->SetPixID(xPixel, yPixel, 0);
541 0 : mainSDigit->SetPixWidth(AliMFTConstants::kXPixelPitch, AliMFTConstants::kYPixelPitch,AliMFTConstants::kSensorThickness);
542 0 : Double_t xCenter, yCenter, zCenter;
543 0 : mftGeom->GetPixelCenter( xPixel, yPixel, mainSDigit->GetDetElemID(), xCenter, yCenter, zCenter );
544 0 : mainSDigit->SetPixCenter(xCenter, yCenter, zCenter );
545 0 : new ((*fSideDigits)[fSideDigits->GetEntries()]) AliMFTDigit(*mainSDigit);
546 0 : AliDebug(2, Form("Created new sdigit (%f, %f, %f) from hit (%f, %f, %f)",
547 : mainSDigit->GetPixelCenterX(), mainSDigit->GetPixelCenterY(), mainSDigit->GetPixelCenterZ(), hit->X(), hit->Y(), hit->Z()));
548 0 : } else
549 0 : AliDebug(1,Form("Hit outside active area : hit x,y,z = %f ; %f ; %f --> Pixel %d ; %d ",hit->X(), hit->Y(), hit->Z(),xPixel,yPixel));
550 :
551 :
552 :
553 :
554 : // creating "side digits" to simulate the effect of charge dispersion
555 :
556 0 : Double_t pi4 = TMath::Pi()/4.;
557 0 : for (Int_t iStep=0; iStep<fNStepForChargeDispersion; iStep++) {
558 0 : Double_t shift = (iStep+1) * fSingleStepForChargeDispersion;
559 0 : for (Int_t iAngle=0; iAngle<8; iAngle++) {
560 0 : Double_t shiftX = shift*TMath::Cos(iAngle*pi4);
561 0 : Double_t shiftY = shift*TMath::Sin(iAngle*pi4);
562 0 : if (mftGeom->Hit2PixelID(hit->X()+shiftX, hit->Y()+shiftY, hit->Z(), mainSDigit->GetDetElemID(), xPixel, yPixel) ){
563 : Bool_t digitExists = kFALSE;
564 0 : for (Int_t iSideDigit=0; iSideDigit<fSideDigits->GetEntries(); iSideDigit++) {
565 0 : if (xPixel==((AliMFTDigit*) fSideDigits->At(iSideDigit))->GetPixelX() &&
566 0 : yPixel==((AliMFTDigit*) fSideDigits->At(iSideDigit))->GetPixelY() &&
567 0 : mainSDigit->GetDetElemID() == ((AliMFTDigit*) fSideDigits->At(iSideDigit))->GetDetElemID()) {
568 : digitExists = kTRUE;
569 0 : break;
570 : }
571 : }
572 0 : if (!digitExists) {
573 0 : AliMFTDigit *sideSDigit = new AliMFTDigit();
574 0 : sideSDigit->SetEloss(0.);
575 0 : sideSDigit->SetDetElemID(hit->GetDetElemID());
576 0 : sideSDigit->SetPlane(hit->GetPlane());
577 0 : sideSDigit->AddMCLabel(hit->GetTrack());
578 0 : sideSDigit->SetPixID(xPixel, yPixel, 0);
579 0 : mainSDigit->SetPixWidth(AliMFTConstants::kXPixelPitch, AliMFTConstants::kYPixelPitch,AliMFTConstants::kSensorThickness);
580 0 : Double_t xCenter, yCenter, zCenter;
581 0 : mftGeom->GetPixelCenter( xPixel, yPixel, mainSDigit->GetDetElemID(), xCenter, yCenter, zCenter );
582 0 : mainSDigit->SetPixCenter(xCenter, yCenter, zCenter );
583 0 : new ((*fSideDigits)[fSideDigits->GetEntries()]) AliMFTDigit(*sideSDigit);
584 0 : }
585 0 : }
586 : }
587 : }
588 :
589 :
590 : // -------- checking which pixels switched on have their diode actually within the charge dispersion radius
591 :
592 0 : for (Int_t iSDigit=0; iSDigit<fSideDigits->GetEntries(); iSDigit++) {
593 0 : AliMFTDigit *mySDig = (AliMFTDigit*) (fSideDigits->At(iSDigit));
594 0 : Double_t distance = TMath::Sqrt(TMath::Power(mySDig->GetPixelCenterX()-hit->X(),2) + TMath::Power(mySDig->GetPixelCenterY()-hit->Y(),2));
595 0 : if (distance<fChargeDispersion) {
596 0 : AliDebug(1,Form("Created new side sdigit (%f, %f, %f) from hit (%f, %f, %f)",
597 : mySDig->GetPixelCenterX(), mySDig->GetPixelCenterY(), mySDig->GetPixelCenterZ(), hit->X(), hit->Y(), hit->Z()));
598 0 : new ((*pSDigList[mySDig->GetPlane()])[pSDigList[mySDig->GetPlane()]->GetEntries()]) AliMFTDigit(*mySDig);
599 : }
600 : }
601 :
602 0 : fSideDigits->Delete();
603 :
604 0 : }
605 :
606 0 : AliDebug(1,"Exiting Hits2SDigitsLocal");
607 :
608 0 : }
609 :
610 : //====================================================================================================================================================
611 :
612 : void AliMFT::MakeBranch(Option_t *option) {
613 :
614 : // Create Tree branches
615 0 : AliDebug(1, Form("Start with option= %s.",option));
616 :
617 : const Int_t kBufSize = 4000;
618 :
619 0 : const Char_t *cH = strstr(option,"H");
620 0 : const Char_t *cD = strstr(option,"D");
621 0 : const Char_t *cS = strstr(option,"S");
622 :
623 0 : if (cH && fLoader->TreeH()) {
624 0 : CreateHits();
625 0 : MakeBranchInTree(fLoader->TreeH(), "MFT", &fHits, kBufSize, 0);
626 0 : }
627 :
628 0 : if (cS && fLoader->TreeS()) {
629 0 : CreateSDigits();
630 0 : for(Int_t iPlane=0; iPlane<AliMFTConstants::kNDisks; iPlane++) MakeBranchInTree(fLoader->TreeS(),
631 0 : Form("Plane_%02d",iPlane),
632 0 : &((*fSDigitsPerPlane)[iPlane]),
633 : kBufSize, 0);
634 0 : }
635 :
636 0 : if (cD && fLoader->TreeD()) {
637 0 : CreateDigits();
638 0 : for(Int_t iPlane=0; iPlane<AliMFTConstants::kNDisks; iPlane++) MakeBranchInTree(fLoader->TreeD(),
639 0 : Form("Plane_%02d",iPlane),
640 0 : &((*fDigitsPerPlane)[iPlane]),
641 : kBufSize, 0);
642 0 : }
643 :
644 0 : AliDebug(1,"Stop.");
645 :
646 0 : }
647 :
648 : //====================================================================================================================================================
649 :
650 : void AliMFT::SetTreeAddress() {
651 :
652 :
653 : //Set branch address for the Hits and Digits Tree.
654 0 : AliDebug(1, "Start.");
655 :
656 0 : AliDebug(1, Form("AliMFT::SetTreeAddress Hits fLoader->TreeH() = %p\n", fLoader->TreeH()));
657 0 : if (fLoader->TreeH() && fLoader->TreeH()->GetBranch("MFT")) {
658 0 : CreateHits();
659 0 : fLoader->TreeH()->SetBranchAddress("MFT", &fHits);
660 0 : }
661 :
662 0 : AliDebug(1, Form("AliMFT::SetTreeAddress SDigits fLoader->TreeS() = %p\n", fLoader->TreeS()));
663 0 : if (fLoader->TreeS() && fLoader->TreeS()->GetBranch("Plane_00")) {
664 0 : CreateSDigits();
665 0 : for(Int_t iPlane=0; iPlane<AliMFTConstants::kNDisks; iPlane++) {
666 0 : fLoader->TreeS()->SetBranchAddress(Form("Plane_%02d",iPlane), &((*fSDigitsPerPlane)[iPlane]));
667 : }
668 0 : }
669 :
670 0 : AliDebug(1, Form("AliMFT::SetTreeAddress Digits fLoader->TreeD() = %p\n", fLoader->TreeD()));
671 0 : if (fLoader->TreeD() && fLoader->TreeD()->GetBranch("Plane_00")) {
672 0 : CreateDigits();
673 0 : for(Int_t iPlane=0; iPlane<AliMFTConstants::kNDisks; iPlane++) {
674 0 : fLoader->TreeD()->SetBranchAddress(Form("Plane_%02d",iPlane), &((*fDigitsPerPlane)[iPlane]));
675 : }
676 0 : }
677 :
678 0 : AliDebug(1, Form("AliMFT::SetTreeAddress RecPoints fLoader->TreeR() = %p\n", fLoader->TreeR()));
679 0 : if (fLoader->TreeR() && fLoader->TreeR()->GetBranch("Plane_00")) {
680 0 : CreateRecPoints();
681 0 : for(Int_t iPlane=0; iPlane<AliMFTConstants::kNDisks; iPlane++) {
682 0 : fLoader->TreeR()->SetBranchAddress(Form("Plane_%02d",iPlane), &((*fRecPointsPerPlane)[iPlane]));
683 : }
684 0 : }
685 :
686 0 : AliDebug(1,"Stop.");
687 :
688 0 : }
689 :
690 : //====================================================================================================================================================
691 :
692 : void AliMFT::SetGeometry() {
693 :
694 : // AliInfo("AliMFT::SetGeometry\n");
695 : //
696 : // fSegmentation = new AliMFTSegmentation(fNameGeomFile.Data());
697 : //
698 : // fNPlanes = fSegmentation->GetNPlanes();
699 :
700 0 : fNPlanes = AliMFTConstants::kNDisks;
701 :
702 0 : }
703 :
704 : //====================================================================================================================================================
705 :
706 : void AliMFT::CreateHits() {
707 :
708 : // create array of hits
709 :
710 0 : AliDebug(1, "AliMFT::CreateHits()");
711 :
712 0 : if (fHits) return;
713 0 : fHits = new TClonesArray("AliMFTHit");
714 :
715 0 : }
716 :
717 : //====================================================================================================================================================
718 :
719 : void AliMFT::CreateSDigits() {
720 :
721 : // create sdigits list
722 :
723 0 : AliDebug(1, "AliMFT::CreateSDigits()");
724 :
725 0 : if (fSDigitsPerPlane) return;
726 0 : fSDigitsPerPlane = new TObjArray(AliMFTConstants::kNDisks);
727 0 : for (Int_t iPlane=0; iPlane<AliMFTConstants::kNDisks; iPlane++) fSDigitsPerPlane->AddAt(new TClonesArray("AliMFTDigit"), iPlane);
728 :
729 0 : fSideDigits = new TClonesArray("AliMFTDigit");
730 :
731 0 : }
732 :
733 : //====================================================================================================================================================
734 :
735 : void AliMFT::CreateDigits() {
736 :
737 : // create digits list
738 :
739 0 : AliDebug(1, "AliMFT::CreateDigits()");
740 :
741 0 : if (fDigitsPerPlane) return;
742 0 : fDigitsPerPlane = new TObjArray(AliMFTConstants::kNDisks);
743 0 : for(Int_t iPlane=0; iPlane<AliMFTConstants::kNDisks; iPlane++) fDigitsPerPlane->AddAt(new TClonesArray("AliMFTDigit"), iPlane);
744 :
745 0 : }
746 :
747 : //====================================================================================================================================================
748 :
749 : void AliMFT::CreateRecPoints() {
750 :
751 : // create recPoints list
752 :
753 0 : AliDebug(1, "AliMFT::CreateRecPoints()");
754 :
755 0 : if (fRecPointsPerPlane) return;
756 0 : fRecPointsPerPlane = new TObjArray(AliMFTConstants::kNDisks);
757 0 : for(Int_t iPlane=0; iPlane<AliMFTConstants::kNDisks; iPlane++) fRecPointsPerPlane->AddAt(new TClonesArray("AliMFTCluster"), iPlane);
758 :
759 0 : }
760 :
761 : //====================================================================================================================================================
|