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