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