]>
Commit | Line | Data |
---|---|---|
37c4363a | 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 | /* $Id$ */ | |
17 | ||
18 | //____________________________________________________________________ | |
19 | // | |
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. | |
24 | // | |
37c4363a | 25 | // This class contains the detailed version of the FMD - that is, hits |
26 | // are produced during simulation. | |
27 | // | |
37c4363a | 28 | // See also the class AliFMD for a more detailed explanation of the |
29 | // various componets. | |
1a1fdef7 | 30 | // |
56b1929b | 31 | #include <TVirtualMC.h> // ROOT_TVirtualMC |
32 | #include <AliRun.h> // ALIRUN_H | |
33 | #include <AliMC.h> // ALIMC_H | |
34 | #include <AliLog.h> // ALILOG_H | |
e802be3e | 35 | #include "AliFMDv1.h" // ALIFMDV1_H |
54e415a8 | 36 | #ifndef USE_PRE_MOVE |
37 | #include "AliFMDGeometryBuilder.h" | |
38 | #include "AliFMDGeometry.h" | |
39 | #include "AliFMDDetector.h" | |
40 | #include "AliFMDRing.h" | |
41 | #include <TParticlePDG.h> | |
42 | #include <TDatabasePDG.h> | |
43 | #include "AliFMDHit.h" | |
44 | #else | |
1a1fdef7 | 45 | #include "AliFMDSimulator.h" // ALIFMDSIMULATOR_H |
46 | #include "AliFMDG3Simulator.h" // ALIFMDG3SIMULATOR_H | |
47 | #include "AliFMDGeoSimulator.h" // ALIFMDGEOSIMULATOR_H | |
54e415a8 | 48 | #include "AliFMDG3OldSimulator.h" // ALIFMDG3OLDSIMULATOR_H |
49 | #include "AliFMDGeoOldSimulator.h" // ALIFMDGEOOLDSIMULATOR_H | |
50 | #endif | |
37c4363a | 51 | |
52 | //____________________________________________________________________ | |
925e6570 | 53 | ClassImp(AliFMDv1) |
1a1fdef7 | 54 | #if 0 |
55 | ; // This is here to keep Emacs for indenting the next line | |
56 | #endif | |
37c4363a | 57 | |
58 | ||
54e415a8 | 59 | #ifndef USE_PRE_MOVE |
60 | //____________________________________________________________________ | |
61 | Bool_t | |
62 | AliFMDv1::VMC2FMD(TLorentzVector& v, UShort_t& detector, | |
63 | Char_t& ring, UShort_t& sector, UShort_t& strip) const | |
64 | { | |
65 | TVirtualMC* mc = TVirtualMC::GetMC(); | |
66 | AliFMDGeometry* fmd = AliFMDGeometry::Instance(); | |
67 | ||
68 | // Get track position | |
69 | mc->TrackPosition(v); | |
70 | Int_t moduleno; mc->CurrentVolOffID(fmd->GetModuleOff(), moduleno); | |
71 | Int_t iring; mc->CurrentVolOffID(fmd->GetRingOff(), iring); | |
72 | ring = Char_t(iring); | |
73 | Int_t det; mc->CurrentVolOffID(fmd->GetDetectorOff(), det); | |
74 | detector = det; | |
75 | ||
76 | ||
77 | // Get the ring geometry | |
78 | //Int_t nsec = fmd->GetDetector(detector)->GetRing(ring)->GetNSectors(); | |
79 | Int_t nstr = fmd->GetDetector(detector)->GetRing(ring)->GetNStrips(); | |
80 | Double_t lowr = fmd->GetDetector(detector)->GetRing(ring)->GetMinR(); | |
81 | Double_t theta = fmd->GetDetector(detector)->GetRing(ring)->GetTheta(); | |
82 | Double_t pitch = fmd->GetDetector(detector)->GetRing(ring)->GetPitch(); | |
83 | ||
84 | // Figure out the strip number | |
85 | Double_t r = TMath::Sqrt(v.X() * v.X() + v.Y() * v.Y()); | |
86 | Int_t str = Int_t((r - lowr) / pitch); | |
87 | if (str < 0 || str >= nstr) return kFALSE; | |
88 | strip = str; | |
89 | ||
90 | // Figure out the sector number | |
91 | Double_t phi = TMath::ATan2(v.Y(), v.X()) * 180. / TMath::Pi(); | |
92 | if (phi < 0) phi = 360. + phi; | |
93 | Double_t t = phi - 2 * moduleno * theta; | |
94 | sector = 2 * moduleno; | |
95 | if (t < 0 || t > 2 * theta) return kFALSE; | |
96 | else if (t > theta) sector += 1; | |
97 | ||
98 | AliDebug(40, Form("<1> Inside an active FMD volume FMD%d%c[%2d,%3d] %s", | |
99 | detector, ring, sector, strip, mc->CurrentVolPath())); | |
100 | return kTRUE; | |
101 | } | |
102 | ||
103 | //____________________________________________________________________ | |
104 | Bool_t | |
105 | AliFMDv1::VMC2FMD(Int_t copy, TLorentzVector& v, | |
106 | UShort_t& detector, Char_t& ring, | |
107 | UShort_t& sector, UShort_t& strip) const | |
108 | { | |
109 | TVirtualMC* mc = TVirtualMC::GetMC(); | |
110 | AliFMDGeometry* fmd = AliFMDGeometry::Instance(); | |
111 | ||
112 | strip = copy - 1; | |
113 | Int_t sectordiv; mc->CurrentVolOffID(fmd->GetSectorOff(), sectordiv); | |
114 | if (fmd->GetModuleOff() >= 0) { | |
115 | Int_t module; mc->CurrentVolOffID(fmd->GetModuleOff(), module); | |
116 | sector = 2 * module + sectordiv; | |
117 | } | |
118 | else | |
119 | sector = sectordiv; | |
120 | Int_t iring; mc->CurrentVolOffID(fmd->GetRingOff(), iring); | |
121 | ring = Char_t(iring); | |
122 | Int_t det; mc->CurrentVolOffID(fmd->GetDetectorOff(), det); | |
123 | detector = det; | |
124 | ||
125 | //Double_t rz = fmd->GetDetector(detector)->GetRingZ(ring); | |
088f8e79 | 126 | AliFMDDetector* gdet = fmd->GetDetector(detector); |
127 | AliFMDRing* gring = gdet->GetRing(ring); | |
128 | if (!gring) | |
129 | AliFatal(Form("Ring %c not found (%s)", ring, mc->CurrentVolPath())); | |
130 | Int_t n = gring->GetNSectors(); | |
54e415a8 | 131 | #if 0 |
132 | if (rz < 0) { | |
133 | Int_t s = ((n - sector + n / 2) % n) + 1; | |
134 | AliDebug(1, Form("Recalculating sector to %d (=%d-%d+%d/2%%%d+1 z=%f)", | |
135 | s, n, sector, n, n, rz)); | |
136 | sector = s; | |
137 | } | |
138 | #endif | |
139 | if (sector < 1 || sector > n) { | |
8f6ee336 | 140 | AliWarning(Form("sector # %d out of range (0-%d)", sector-1, n-1)); |
54e415a8 | 141 | return kFALSE; |
142 | } | |
143 | sector--; | |
144 | // Get track position | |
145 | mc->TrackPosition(v); | |
146 | AliDebug(15, Form("<2> Inside an active FMD volume FMD%d%c[%2d,%3d] %s", | |
147 | detector, ring, sector, strip, mc->CurrentVolPath())); | |
148 | ||
149 | return kTRUE; | |
150 | } | |
151 | #endif | |
152 | ||
37c4363a | 153 | //____________________________________________________________________ |
154 | void | |
155 | AliFMDv1::StepManager() | |
156 | { | |
54e415a8 | 157 | // Member function that is executed each time a hit is made in the |
158 | // FMD. None-charged particles are ignored. Dead tracks are | |
159 | // ignored. | |
160 | // | |
161 | // The procedure is as follows: | |
162 | // | |
163 | // - IF NOT track is alive THEN RETURN ENDIF | |
164 | // - IF NOT particle is charged THEN RETURN ENDIF | |
165 | // - IF NOT volume name is "STRI" or "STRO" THEN RETURN ENDIF | |
166 | // - Get strip number (volume copy # minus 1) | |
167 | // - Get phi division number (mother volume copy #) | |
168 | // - Get module number (grand-mother volume copy #) | |
169 | // - section # = 2 * module # + phi division # - 1 | |
170 | // - Get ring Id from volume name | |
171 | // - Get detector # from grand-grand-grand-mother volume name | |
172 | // - Get pointer to sub-detector object. | |
173 | // - Get track position | |
174 | // - IF track is entering volume AND track is inside real shape THEN | |
175 | // - Reset energy deposited | |
176 | // - Get track momentum | |
177 | // - Get particle ID # | |
178 | /// - ENDIF | |
179 | // - IF track is inside volume AND inside real shape THEN | |
180 | /// - Update energy deposited | |
181 | // - ENDIF | |
182 | // - IF track is inside real shape AND (track is leaving volume, | |
183 | // or it died, or it is stopped THEN | |
184 | // - Create a hit | |
185 | // - ENDIF | |
186 | // | |
187 | #ifndef USE_PRE_MOVE | |
188 | TVirtualMC* mc = TVirtualMC::GetMC(); | |
189 | if (!mc->IsTrackAlive()) return; | |
190 | Double_t absQ = TMath::Abs(mc->TrackCharge()); | |
191 | if (absQ <= 0) return; | |
192 | ||
193 | Int_t copy; | |
194 | Int_t vol = mc->CurrentVolID(copy); | |
195 | AliFMDGeometry* fmd = AliFMDGeometry::Instance(); | |
196 | if (!fmd->IsActive(vol)) { | |
197 | AliDebug(50, Form("Not an FMD volume %d '%s'",vol,mc->CurrentVolName())); | |
198 | return; | |
199 | } | |
200 | TLorentzVector v; | |
201 | UShort_t detector; | |
202 | Char_t ring; | |
203 | UShort_t sector; | |
204 | UShort_t strip; | |
205 | ||
206 | if (fmd->IsDetailed()) { | |
207 | if (!VMC2FMD(copy, v, detector, ring, sector, strip)) return; | |
208 | } else { | |
209 | if (!VMC2FMD(v, detector, ring, sector, strip)) return; | |
210 | } | |
211 | TLorentzVector p; | |
212 | mc->TrackMomentum(p); | |
213 | Int_t trackno = gAlice->GetMCApp()->GetCurrentTrackNumber(); | |
214 | Int_t pdg = mc->TrackPid(); | |
215 | Double_t mass = mc->TrackMass(); | |
216 | Double_t edep = mc->Edep() * 1000; // keV | |
217 | Double_t poverm = (mass == 0 ? 0 : p.P() / mass); | |
218 | Bool_t isBad = kFALSE; | |
219 | ||
220 | // This `if' is to debug abnormal energy depositions. We trigger on | |
221 | // p/m approx larger than or equal to a MIP, and a large edep - more | |
222 | // than 1 keV - a MIP is 100 eV. | |
223 | if (edep > absQ * absQ && poverm > 1) { | |
224 | isBad = kTRUE; | |
225 | TArrayI procs; | |
226 | mc->StepProcesses(procs); | |
227 | TString processes; | |
228 | for (Int_t ip = 0; ip < procs.fN; ip++) { | |
229 | if (ip != 0) processes.Append(","); | |
230 | processes.Append(TMCProcessName[procs.fArray[ip]]); | |
231 | } | |
232 | TDatabasePDG* pdgDB = TDatabasePDG::Instance(); | |
233 | TParticlePDG* particleType = pdgDB->GetParticle(pdg); | |
234 | TString pname(particleType ? particleType->GetName() : "???"); | |
235 | TString what; | |
236 | if (mc->IsTrackEntering()) what.Append("entering "); | |
237 | if (mc->IsTrackExiting()) what.Append("exiting "); | |
238 | if (mc->IsTrackInside()) what.Append("inside "); | |
239 | if (mc->IsTrackDisappeared()) what.Append("disappeared "); | |
240 | if (mc->IsTrackStop()) what.Append("stopped "); | |
241 | if (mc->IsNewTrack()) what.Append("new "); | |
242 | if (mc->IsTrackAlive()) what.Append("alive "); | |
243 | if (mc->IsTrackOut()) what.Append("out "); | |
244 | ||
245 | Int_t mother = gAlice->GetMCApp()->GetPrimary(trackno); | |
8f6ee336 | 246 | AliWarning(Form("Track # %5d deposits a lot of energy\n" |
088f8e79 | 247 | " Volume: %s\n" |
248 | " Momentum: (%7.4f,%7.4f,%7.4f)\n" | |
249 | " PDG: %d (%s)\n" | |
250 | " Edep: %-14.7f keV (mother %d)\n" | |
251 | " p/m: %-7.4f/%-7.4f = %-14.7f\n" | |
252 | " Processes: %s\n" | |
253 | " What: %s\n", | |
254 | trackno, mc->CurrentVolPath(), p.X(), p.Y(), p.Z(), | |
255 | pdg, pname.Data(), edep, mother, p.P(), mass, | |
256 | poverm, processes.Data(), what.Data())); | |
54e415a8 | 257 | } |
258 | ||
259 | // Check that the track is actually within the active area | |
260 | Bool_t entering = mc->IsTrackEntering(); | |
261 | Bool_t inside = mc->IsTrackInside(); | |
262 | Bool_t out = (mc->IsTrackExiting()|| mc->IsTrackDisappeared()|| | |
263 | mc->IsTrackStop()); | |
264 | // Reset the energy deposition for this track, and update some of | |
265 | // our parameters. | |
266 | if (entering) { | |
267 | AliDebug(15, Form("Track # %8d entering active FMD volume %s: " | |
268 | "Edep=%f (%f,%f,%f)", trackno, mc->CurrentVolPath(), | |
269 | edep, v.X(), v.Y(), v.Z())); | |
270 | fCurrentP = p; | |
271 | fCurrentV = v; | |
272 | fCurrentDeltaE = edep; | |
273 | fCurrentPdg = pdg; // mc->IdFromPDG(pdg); | |
274 | } | |
275 | // If the track is inside, then update the energy deposition | |
276 | if (inside && fCurrentDeltaE >= 0) { | |
277 | fCurrentDeltaE += edep; | |
278 | AliDebug(15, Form("Track # %8d inside active FMD volume %s: Edep=%f, " | |
279 | "Accumulated Edep=%f (%f,%f,%f)", trackno, | |
280 | mc->CurrentVolPath(), edep, fCurrentDeltaE, | |
281 | v.X(), v.Y(), v.Z())); | |
282 | } | |
283 | // The track exits the volume, or it disappeared in the volume, or | |
284 | // the track is stopped because it no longer fulfills the cuts | |
285 | // defined, then we create a hit. | |
286 | if (out) { | |
287 | if (fCurrentDeltaE >= 0) { | |
288 | fCurrentDeltaE += edep; | |
289 | AliDebug(15, Form("Track # %8d exiting active FMD volume %s: Edep=%g, " | |
290 | "Accumulated Edep=%g (%f,%f,%f)", trackno, | |
291 | mc->CurrentVolPath(), edep, fCurrentDeltaE, | |
292 | v.X(), v.Y(), v.Z())); | |
088f8e79 | 293 | TVector3 cur(v.Vect()); |
294 | cur -= fCurrentV.Vect(); | |
295 | Double_t len = cur.Mag(); | |
54e415a8 | 296 | AliFMDHit* h = |
297 | AddHitByFields(trackno, detector, ring, sector, strip, | |
298 | fCurrentV.X(), fCurrentV.Y(), fCurrentV.Z(), | |
299 | fCurrentP.X(), fCurrentP.Y(), fCurrentP.Z(), | |
088f8e79 | 300 | fCurrentDeltaE, fCurrentPdg, fCurrentV.T(), |
301 | len, mc->IsTrackDisappeared()||mc->IsTrackStop()); | |
54e415a8 | 302 | // Add a copy |
303 | if (isBad && fBad) { | |
304 | new ((*fBad)[fBad->GetEntries()]) AliFMDHit(*h); | |
305 | } | |
306 | } | |
307 | fCurrentDeltaE = -1; | |
308 | } | |
309 | #else | |
37c4363a | 310 | // Called for every step in the Forward Multiplicity Detector |
311 | // | |
1a1fdef7 | 312 | // The message is deligated to AliFMDSimulator::Exec |
37c4363a | 313 | // |
1a1fdef7 | 314 | if (!fSimulator) { |
315 | AliFatal("No simulator object made"); | |
316 | return; | |
37c4363a | 317 | } |
1a1fdef7 | 318 | fSimulator->Exec(""); |
54e415a8 | 319 | #endif |
37c4363a | 320 | } |
321 | //___________________________________________________________________ | |
322 | // | |
323 | // EOF | |
324 | // |