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 : /* $Id$ */
17 :
18 : //-----------------------------------------------------------------------------
19 : // Class AliMUONTriggerResponseV1
20 : // ------------------
21 : // Trigger chamber response
22 : // with cluster size activated
23 : //-----------------------------------------------------------------------------
24 :
25 : #include "AliMUONResponseTriggerV1.h"
26 : #include "AliMUON.h"
27 : #include "AliMUONDigit.h"
28 : #include "AliMUONGeometryTransformer.h"
29 : #include "AliMUONConstants.h"
30 :
31 : #include "AliCDBManager.h"
32 : #include "AliCDBPath.h"
33 : #include "AliCDBEntry.h"
34 :
35 : #include "AliMpPad.h"
36 : #include "AliMpSegmentation.h"
37 : #include "AliMpVSegmentation.h"
38 : #include "AliMpCathodType.h"
39 :
40 : #include "AliRun.h"
41 : #include "AliDCSValue.h"
42 : #include "AliLog.h"
43 :
44 : #include <TMath.h>
45 : #include <TRandom.h>
46 : #include <TMap.h>
47 : #include <iostream>
48 :
49 : /// \cond CLASSIMP
50 16 : ClassImp(AliMUONResponseTriggerV1)
51 : /// \endcond
52 :
53 : namespace
54 : {
55 : AliMUON* muon()
56 : {
57 64 : return static_cast<AliMUON*>(gAlice->GetModule("MUON"));
58 : }
59 :
60 : void Global2Local(Int_t detElemId, Double_t xg, Double_t yg, Double_t zg, Double_t& xl, Double_t& yl, Double_t& zl)
61 : {
62 : // ideally should be :
63 : // Double_t x,y,z;
64 : // AliMUONGeometry::Global2Local(detElemId,xg,yg,zg,x,y,z);
65 : // but while waiting for this geometry singleton, let's go through
66 : // AliMUON still.
67 :
68 64 : const AliMUONGeometryTransformer* transformer = muon()->GetGeometryTransformer();
69 32 : transformer->Global2Local(detElemId,xg,yg,zg,xl,yl,zl);
70 32 : }
71 :
72 : }
73 :
74 :
75 : //------------------------------------------------------------------
76 208 : AliMUONResponseTriggerV1::AliMUONResponseTriggerV1() : AliMUONResponseTrigger(), fGenerCluster(0), fHVvalues(), fBValues(), fWorkCondition(2)
77 260 : {
78 104 : }
79 :
80 : //------------------------------------------------------------------
81 16 : AliMUONResponseTriggerV1::AliMUONResponseTriggerV1(Int_t mode) : AliMUONResponseTrigger(), fGenerCluster(0), fHVvalues(), fBValues(), fWorkCondition(mode)
82 20 : {
83 : //mode: 1=streamer - 2=avalanche
84 4 : SetHV();
85 4 : SetBValues();
86 8 : }
87 :
88 : //------------------------------------------------------------------
89 : AliMUONResponseTriggerV1::~AliMUONResponseTriggerV1()
90 336 : {
91 168 : }
92 :
93 : //------------------------------------------------------------------
94 : Int_t AliMUONResponseTriggerV1::SetGenerCluster()
95 : {
96 : // Set the GenerCluster parameter and return 1
97 128 : fGenerCluster = gRandom->Rndm();
98 64 : return 1;
99 : }
100 :
101 : //------------------------------------------------------------------
102 : Float_t AliMUONResponseTriggerV1::FireStripProb(Float_t x4,Float_t theta,Int_t rpc,Int_t plane,Int_t cath) const
103 : {
104 : /// parametrisation of the probability that a strip neighbour of the main
105 : /// strip is fired
106 : /// WARNING : need to convert x4 from cm to mm
107 :
108 342 : Float_t hv = fHVvalues.At(18*plane+rpc);
109 : Float_t parA, parB, parC;
110 :
111 171 : if(fWorkCondition == 2) //avalanche
112 171 : parB = fBValues.At(72*cath+18*plane+rpc);
113 : else //streamer
114 : parB = 2.966;
115 :
116 :
117 171 : parA = 6.089 * hv - 52.70;
118 171 : parC = 8.3e-4 * hv - 0.5e-3;
119 :
120 171 : return (TMath::Cos(theta)*parA/(parA+TMath::Cos(theta)*TMath::Power(x4*10.,parB))+parC)/(TMath::Cos(theta)+parC);
121 : }
122 :
123 : //------------------------------------------------------------------
124 : void AliMUONResponseTriggerV1::DisIntegrate(const AliMUONHit& hit, TList& digits, Float_t /*timeDif*/)
125 : {
126 : /// Generate digits (on each cathode) from 1 hit, with cluster-size generation.
127 :
128 64 : digits.Clear();
129 :
130 32 : Float_t xhit = hit.X();
131 32 : Float_t yhit = hit.Y();
132 32 : Float_t zhit = hit.Z();
133 32 : Int_t detElemId = hit.DetElemId();
134 32 : Int_t plane = detElemId/100 - 11; //plane from 0 to 3
135 32 : Int_t rpc = detElemId%100; //rpc from 0 to 3
136 :
137 32 : Double_t x,y,z;
138 32 : Global2Local(detElemId,xhit,yhit,zhit,x,y,z);
139 :
140 32 : Float_t tof = hit.Age();
141 : Int_t twentyNano(100);
142 32 : if (tof<AliMUONConstants::TriggerTofLimit())
143 : {
144 : twentyNano=1;
145 32 : }
146 :
147 :
148 : Int_t nboard = 0;
149 :
150 192 : for(Int_t cath = AliMp::kCath0; cath <= AliMp::kCath1; ++cath)
151 : {
152 64 : const AliMpVSegmentation* seg = AliMpSegmentation::Instance()->GetMpSegmentation(detElemId,AliMp::GetCathodType(cath));
153 :
154 64 : AliMpPad pad = seg->PadByPosition(x,y,kFALSE);
155 64 : Int_t ix = pad.GetIx();
156 64 : Int_t iy = pad.GetIy();
157 :
158 320 : AliDebug(1,Form("xhit,yhit=%e,%e lx,ly,lz=%e,%e,%e ix,iy=%d,%d",xhit,yhit,x,y,z,ix,iy));
159 :
160 64 : if ( !pad.IsValid() )
161 : {
162 0 : AliWarning(Form("hit w/o strip %d-%d xhit,yhit=%e,%e local x,y,z ""%e,%e,%e ix,iy=%d,%d",detElemId,cath,xhit,yhit,x,y,z,ix,iy));
163 0 : continue;
164 : }
165 :
166 128 : if ( cath == AliMp::kCath0 ) nboard = pad.GetLocalBoardId(0);
167 :
168 192 : AliMUONDigit* d = new AliMUONDigit(detElemId,nboard,
169 64 : pad.GetLocalBoardChannel(0),
170 : cath);
171 :
172 64 : d->SetPadXY(ix,iy);
173 64 : d->SetCharge(twentyNano);
174 :
175 64 : digits.Add(d);
176 :
177 64 : SetGenerCluster(); // 1 randum number per cathode (to be checked)
178 :
179 64 : Int_t xList[30], yList[30];
180 64 : Neighbours(cath,ix,iy,xList,yList);
181 :
182 :
183 : Int_t qp = 0; // fired/no-fired strip = 1/0
184 3968 : for (Int_t i=0; i<30; i++) // loop on neighbors
185 : {
186 1920 : if (i==0 || i==15 || qp!=0) // built-up cluster // need to iterate in iy/ix for bending/non-bending plane
187 : {
188 576 : Int_t ixNeigh = (cath == 0) ? ix : xList[i];
189 576 : Int_t iyNeigh = (cath == 0) ? yList[i] : iy;
190 :
191 192 : AliMpPad padNeigh = seg->PadByIndices(ixNeigh,iyNeigh,kFALSE);
192 192 : if(padNeigh.IsValid()) // existing neighbourg
193 : {
194 171 : Int_t dix=-(ixNeigh-ix);
195 171 : Int_t diy=-(iyNeigh-iy);
196 171 : Float_t xlocalNeigh = padNeigh.GetPositionX();
197 171 : Float_t ylocalNeigh = padNeigh.GetPositionY();
198 171 : Float_t dpx = padNeigh.GetDimensionX();
199 171 : Float_t dpy = padNeigh.GetDimensionY();
200 171 : Float_t distX = TMath::Abs((Float_t)dix) * ((Float_t)dix * dpx + xlocalNeigh - x);
201 171 : Float_t distY = TMath::Abs((Float_t)diy) * ((Float_t)diy * dpy + ylocalNeigh - y);
202 171 : Float_t dist = TMath::Sqrt(distX*distX+distY*distY);
203 :
204 342 : if(fGenerCluster < FireStripProb(dist,0,rpc,plane,cath))
205 48 : qp = 1;
206 : else
207 : qp = 0;
208 :
209 171 : if(qp == 1)
210 : { // this digit is fired
211 192 : AliMUONDigit* dNeigh = new AliMUONDigit(detElemId,padNeigh.GetLocalBoardId(0),padNeigh.GetLocalBoardChannel(0),cath);
212 :
213 48 : dNeigh->SetPadXY(ixNeigh,iyNeigh);
214 48 : dNeigh->SetCharge(twentyNano);
215 48 : digits.Add(dNeigh);
216 48 : } // digit fired
217 171 : } // pad is valid
218 192 : } // built-up cluster
219 : } // loop on neighbors
220 128 : } // loop on cathode
221 32 : }
222 :
223 : //------------------------------------------------------------------
224 : void AliMUONResponseTriggerV1::SetHV()
225 : {
226 : //
227 : /// Set HV values from OCDB
228 : //
229 8 : fHVvalues.Set(72);
230 4 : TString side;
231 : Int_t newRPC=0,newPlane=0;
232 :
233 4 : AliCDBManager *manager = AliCDBManager::Instance();
234 4 : AliCDBPath path("MUON/Calib/TriggerDCS");
235 4 : AliCDBEntry *entry = manager->Get(path);
236 4 : if (entry == NULL) {
237 0 : AliWarning("No map found in MUON/Calib/TriggerDCS");
238 0 : return;
239 : }
240 12 : TMap *hvMap = dynamic_cast<TMap*>(entry->GetObject());
241 : TObjArray *objArr = 0x0;
242 :
243 : AliDCSValue *dcsValue = 0x0;
244 : UInt_t time1,time2,timebegin=0,timeend=0;
245 : Int_t nEntries;
246 : Float_t voltage = 0;
247 :
248 40 : for(Int_t iPlane=0; iPlane<4; iPlane++) //loop on MT
249 : {
250 608 : for(Int_t iRPC=0; iRPC<18; iRPC++) //loop on RPC
251 : {
252 288 : if(iRPC>=5 && iRPC<=13)
253 : {
254 144 : side = "OUTSIDE";
255 144 : newRPC = 14-iRPC;
256 144 : }
257 :
258 : else
259 : {
260 144 : side = "INSIDE";
261 :
262 144 : if(iRPC>=14)
263 64 : newRPC = iRPC-13;
264 : else
265 80 : newRPC = iRPC+5;
266 : }
267 :
268 576 : switch(iPlane)
269 : {
270 72 : case 0: newPlane = 11; break;
271 72 : case 1: newPlane = 12; break;
272 72 : case 2: newPlane = 21; break;
273 72 : case 3: newPlane = 22; break;
274 : }
275 :
276 1152 : objArr = (TObjArray*)hvMap->GetValue(Form("MTR_%s_MT%d_RPC%d_HV.vEff",side.Data(),newPlane,newRPC));
277 288 : nEntries = objArr->GetEntries();
278 :
279 1152 : for(Int_t i=0; i<nEntries-1; i++)
280 : {
281 576 : dcsValue = (AliDCSValue*)objArr->At(i+1);
282 288 : time2 = dcsValue->GetTimeStamp();
283 :
284 288 : if(i==nEntries-2)
285 288 : timeend = time2;
286 :
287 576 : dcsValue = (AliDCSValue*)objArr->At(i);
288 288 : time1 = dcsValue->GetTimeStamp();
289 :
290 288 : if(i==0)
291 288 : timebegin = time1;
292 :
293 576 : voltage += (dcsValue->GetFloat())*(time2-time1);
294 : }
295 :
296 288 : Double_t deltaTime = timeend - timebegin;
297 864 : Double_t meanVoltage = ( deltaTime == 0. ) ? 0. : voltage/deltaTime/1000.;
298 288 : fHVvalues.AddAt(meanVoltage,18*iPlane+iRPC); //voltage in kV, not in V
299 :
300 : voltage=0;
301 1440 : AliDebug(1,Form("HV value for MTR_%s_MT%d_RPC%d_HV.vEff = %g (kV)",side.Data(),newPlane,newRPC,meanVoltage));
302 : }
303 : }
304 8 : }
305 :
306 : //------------------------------------------------------------------
307 : void AliMUONResponseTriggerV1::SetBValues()
308 : {
309 : //
310 : /// Set B values for cluster size function
311 : //
312 :
313 8 : fBValues.Set(144);
314 :
315 4 : Float_t bValues[2][4][18] = {{{1.97,2.47,2.47,2.47,2.97,2.97,2.47,2.47,1.97,2.22,1.97,2.47,1.97,2.97,2.97,2.47,2.47,1.97}, //MT11BP
316 : {2.22,2.22,1.97,2.47,2.97,2.97,1.97,2.47,1.97,1.97,1.97,2.47,1.97,2.97,2.97,1.97,1.97,1.97}, //MT12BP
317 : {2.22,2.22,2.47,2.47,2.97,2.97,2.47,2.47,2.22,1.97,1.97,2.47,1.97,2.97,2.97,1.97,1.97,1.97}, //MT21BP
318 : {1.97,1.97,2.97,2.97,2.97,2.97,2.47,1.97,1.97,1.97,1.72,2.47,2.22,2.97,2.97,1.97,1.97,1.97}}, //MT22BP
319 : {{1.97,2.47,2.47,2.97,2.97,2.97,2.97,2.47,1.97,1.97,2.22,2.47,2.97,2.97,2.97,2.97,1.97,1.72}, //MT11NBP
320 : {2.47,1.97,2.22,2.97,2.97,2.97,2.47,2.97,1.97,1.97,1.97,2.97,2.97,2.97,2.97,2.97,1.97,1.97}, //MT12NBP
321 : {1.97,2.47,2.47,2.97,2.97,2.97,2.97,2.47,2.22,1.97,2.22,2.47,2.97,2.97,2.97,2.47,1.97,1.97}, //MT21NBP
322 : {1.72,1.97,2.97,2.97,2.97,2.97,2.97,1.97,1.72,2.22,1.97,2.47,2.97,2.47,2.97,1.97,1.97,1.97}}};//MT22NBP
323 :
324 24 : for(Int_t iCath=0; iCath<2; iCath++) //loop on side
325 : {
326 80 : for(Int_t iPlane=0; iPlane<4; iPlane++) //loop on MT
327 : {
328 1216 : for(Int_t iRPC=0; iRPC<18; iRPC++) //loop on RPC
329 : {
330 576 : fBValues.AddAt(bValues[iCath][iPlane][iRPC],72*iCath+18*iPlane+iRPC);
331 : }
332 : }
333 : }
334 4 : }
335 :
336 : //------------------------------------------------------------------
337 : void AliMUONResponseTriggerV1::Neighbours(const Int_t cath, const Int_t ix, const Int_t iy, Int_t Xlist[30], Int_t Ylist[30]) const
338 : {
339 : ///-----------------BENDING----------------------------------------- /n
340 : /// Returns list of 30 next neighbours for given X strip (ix, iy) /n
341 : /// neighbour number 4 in the list - /n
342 : /// neighbour number 3 in the list | /n
343 : /// neighbour number 2 in the list |_ Upper part /n
344 : /// neighbour number 1 in the list | /n
345 : /// neighbour number 0 in the list - /n
346 : /// X strip (ix, iy) /n
347 : /// neighbour number 5 in the list - /n
348 : /// neighbour number 6 in the list | _ Lower part /n
349 : /// neighbour number 7 in the list | /n
350 : /// neighbour number 8 in the list | /n
351 : /// neighbour number 9 in the list - /n
352 : /// /n
353 : ///-----------------NON-BENDING------------------------------------- /n
354 : /// Returns list of 30 next neighbours for given Y strip (ix, iy) /n
355 : /// neighbour number 9 8 7 6 5 (Y strip (ix, iy)) 0 1 2 3 4 in the list /n
356 : /// |_______| |_______| /n
357 : /// left right /n
358 :
359 4032 : for (Int_t i=0; i<30; i++)
360 : {
361 1920 : Xlist[i] = -1;
362 1920 : Ylist[i] = -1;
363 : }
364 :
365 64 : Int_t iList[30]={29,28,27,26,25,24,23,22,21,20,19,18,17,16,15,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14};
366 :
367 : // need to iterate in iy/ix for bending/non-bending plane
368 64 : Int_t iNeigh = (cath == 0) ? iy : ix;
369 :
370 : Int_t i=0;
371 4096 : for (Int_t j=iNeigh-15; j<=iNeigh+15; j++)
372 : {
373 1984 : if (j == iNeigh)
374 : continue;
375 :
376 : // need to iterate in iy/ix for bending/non-bending plane
377 1920 : Int_t ixNeigh = ( cath == 0 ) ? ix : j;
378 1920 : Int_t iyNeigh = ( cath == 0 ) ? j : iy;
379 :
380 : // cout << " " << cath << " " << ix << " " << iy
381 : // << " " << ixNeigh << " " << iyNeigh << "\n";
382 :
383 1920 : Xlist[iList[i]]=ixNeigh;
384 1920 : Ylist[iList[i]]=iyNeigh;
385 1920 : i++;
386 1920 : }
387 64 : }
|