1 |
#include "PamVMCAcDig.h" |
2 |
#include <TF1.h> |
3 |
#include <TMath.h> |
4 |
|
5 |
using TMath::Power; |
6 |
using TMath::Sqrt; |
7 |
|
8 |
ClassImp(PamVMCAcDig) |
9 |
|
10 |
void PamVMCAcDig::DigitizeAC(Int_t EventNo){ |
11 |
|
12 |
// cout<<"Digitizing AC... "<<endl; |
13 |
|
14 |
fDEBUG = kTRUE; |
15 |
|
16 |
for (Int_t k= 0;k<5;k++) fSumEcat[k]=fSumEcas[k]=fSumEcard[k]=0.; |
17 |
//Zeroing arrays holds energy releases in AC |
18 |
|
19 |
UShort_t DataAC[128]; |
20 |
for(Int_t i=0; i<128; i++) DataAC[i]=0; |
21 |
|
22 |
|
23 |
// created: J. Conrad, KTH |
24 |
// modified: S. Orsi, INFN Roma2 |
25 |
// DataAC[0-63]: main AC board |
26 |
// DataAC[64-127]: extra AC board (identical to main board, for now) |
27 |
|
28 |
DataAC[0] = 0xACAC; |
29 |
DataAC[64]= 0xACAC; |
30 |
DataAC[1] = 0xAC11; |
31 |
DataAC[65] = 0xAC22; |
32 |
|
33 |
// the third word is a status word |
34 |
//(dummy: "no errors are present in the AC boards") |
35 |
DataAC[2] = 0xFFFF; //FFEF? |
36 |
DataAC[66] = 0xFFFF; |
37 |
|
38 |
const UInt_t nReg = 6; |
39 |
|
40 |
// FPGA Registers (dummy) |
41 |
for (UInt_t i=0; i<=nReg; i++){ |
42 |
DataAC[i+4] = 0xFFFF; |
43 |
DataAC[i+68] = 0xFFFF; |
44 |
} |
45 |
|
46 |
// the last word is a CRC |
47 |
// Dummy for the time being, but it might need |
48 |
// to be calculated in the end |
49 |
DataAC[63] = 0xABCD; |
50 |
DataAC[127] = 0xABCD; |
51 |
|
52 |
// shift registers (moved to the end of the routine) |
53 |
|
54 |
Int_t evntLSB=(UShort_t)EventNo; |
55 |
Int_t evntMSB=EventNo >> 16; |
56 |
|
57 |
// singles counters are dummy |
58 |
for (UInt_t i=0; i<=15; i++){ |
59 |
DataAC[i+26] = evntLSB; |
60 |
DataAC[i+90] = evntLSB; |
61 |
}; |
62 |
|
63 |
for (UInt_t i=0; i<=7; i++){ |
64 |
DataAC[i+42] = evntLSB; |
65 |
DataAC[i+106] = evntLSB; |
66 |
}; |
67 |
|
68 |
|
69 |
// increments for every trigger might be needed at some point. |
70 |
// dummy for now |
71 |
DataAC[50] = 0x0000; |
72 |
DataAC[114] = 0x0000; |
73 |
|
74 |
// dummy FPGA clock (increment by 1 at each event) |
75 |
if (EventNo<=0xFFFF) { |
76 |
DataAC[51] = 0x0000; |
77 |
DataAC[52] = EventNo; |
78 |
DataAC[115] = 0x0000; |
79 |
DataAC[116] = EventNo; |
80 |
} else { |
81 |
DataAC[51] = evntMSB; |
82 |
DataAC[52] = evntLSB; |
83 |
DataAC[115] = DataAC[51]; |
84 |
DataAC[116] = DataAC[52]; |
85 |
} |
86 |
|
87 |
// dummy temperatures |
88 |
DataAC[53] = 0x0000; |
89 |
DataAC[54] = 0x0000; |
90 |
DataAC[117] = 0x0000; |
91 |
DataAC[118] = 0x0000; |
92 |
|
93 |
|
94 |
// dummy DAC thresholds |
95 |
for (UInt_t i=0; i<=7; i++){ |
96 |
DataAC[i+55] = 0x1A13; |
97 |
DataAC[i+119] = 0x1A13; |
98 |
} |
99 |
|
100 |
FillErel(); |
101 |
|
102 |
// In this simpliefied approach we will assume that once |
103 |
// a particle releases > 0.5 mip in one of the 12 AC detectors it |
104 |
// will fire. We will furthermore assume that both cards read out |
105 |
// identical data. |
106 |
|
107 |
// If you develop your digitization algorithm, you should start by |
108 |
// identifying the information present in level2 (post-darth-vader) |
109 |
// data. |
110 |
|
111 |
// channel mapping Hit Map |
112 |
// 1 CARD4 0 LSB |
113 |
// 2 CAT2 0 |
114 |
// 3 CAS1 0 |
115 |
// 4 NC 0 |
116 |
// 5 CARD2 0 |
117 |
// 6 CAT4 1 |
118 |
// 7 CAS4 0 |
119 |
// 8 NC 0 |
120 |
// 9 CARD3 0 |
121 |
// 10 CAT3 0 |
122 |
// 11 CAS3 0 |
123 |
// 12 NC 0 |
124 |
// 13 CARD1 0 |
125 |
// 14 CAT1 0 |
126 |
// 15 CAS2 0 |
127 |
// 16 NC 0 MSB |
128 |
|
129 |
// In the first version only the hit-map is filled, not the SR. |
130 |
|
131 |
// Threshold: 0.8 MeV. |
132 |
|
133 |
const Float_t thr = 8e-4; //(GeV) |
134 |
|
135 |
//Important Note: In simulation model we have |
136 |
//CAT as solid plasic plate. So, I set values: |
137 |
|
138 |
fSumEcat[1]=fSumEcat[2]=fSumEcat[3]=fSumEcat[0]; |
139 |
|
140 |
DataAC[3] = 0x0000; |
141 |
|
142 |
if (fSumEcas[0] > thr) DataAC[3] = 0x0004; |
143 |
if (fSumEcas[1] > thr) DataAC[3] += 0x4000; |
144 |
if (fSumEcas[2] > thr) DataAC[3] += 0x0400; |
145 |
if (fSumEcas[3] > thr) DataAC[3] += 0x0040; |
146 |
|
147 |
if (fSumEcat[0] > thr) DataAC[3] += 0x2000; //We have solid CAT scintillator |
148 |
if (fSumEcat[1] > thr) DataAC[3] += 0x0002; //See note above |
149 |
if (fSumEcat[2] > thr) DataAC[3] += 0x0200; // |
150 |
if (fSumEcat[3] > thr) DataAC[3] += 0x0020; // |
151 |
|
152 |
if (fSumEcard[0] > thr) DataAC[3] += 0x1000; //C1D1(1) |
153 |
if (fSumEcard[1] > thr) DataAC[3] += 0x0010; //C1D1(2) |
154 |
if (fSumEcard[2] > thr) DataAC[3] += 0x0100; //C2D1(1) |
155 |
if (fSumEcard[3] > thr) DataAC[3] += 0x0001; //C2D1(2) |
156 |
|
157 |
DataAC[67] = DataAC[3]; |
158 |
|
159 |
// shift registers |
160 |
// the central bin is equal to the hitmap, all |
161 |
// other bins in the shift register are 0 |
162 |
for (UInt_t i=0; i<=15; i++){ |
163 |
DataAC[i+11] = 0x0000; |
164 |
DataAC[i+75] = 0x0000; |
165 |
} |
166 |
DataAC[18] = DataAC[3]; |
167 |
DataAC[82] = DataAC[3]; |
168 |
|
169 |
//++++++ WRITE EVERYTHING TO DIGITIZER'S BUFFER +++// |
170 |
fData.clear(); //clearing data buffer |
171 |
|
172 |
for(Int_t i= 0; i<128; i++) fData.push_back(DataAC[i]); |
173 |
|
174 |
|
175 |
if (fDEBUG){ |
176 |
cout<<"====== AC hit info ======"<<endl; |
177 |
cout<<"CAT: Erel="<<fSumEcat[0]*1.e6<<" (keV)"<<endl |
178 |
<<"CARD1: Erel="<<fSumEcard[0]*1.e6<<" (keV)"<<endl |
179 |
<<"CARD2: Erel="<<fSumEcard[1]*1.e6<<" (keV)"<<endl |
180 |
<<"CARD3: Erel="<<fSumEcard[2]*1.e6<<" (keV)"<<endl |
181 |
<<"CARD4: Erel="<<fSumEcard[3]*1.e6<<" (keV)"<<endl |
182 |
<<"CAS1: Erel="<<fSumEcas[0]*1.e6<<" (keV)"<<endl |
183 |
<<"CAS2: Erel="<<fSumEcas[1]*1.e6<<" (keV)"<<endl |
184 |
<<"CAS3: Erel="<<fSumEcas[2]*1.e6<<" (keV)"<<endl |
185 |
<<"CAS4: Erel="<<fSumEcas[3]*1.e6<<" (keV)"<<endl; |
186 |
cout<<"========================="<<endl; |
187 |
|
188 |
} |
189 |
} |
190 |
|
191 |
void PamVMCAcDig::FillErel(){ |
192 |
/* |
193 |
Detector KEY Number of paddles |
194 |
|
195 |
CAT TOP1 1 (solid volume with id=1) |
196 |
CAS SID1 4 (1-4) |
197 |
CARD C1D1 & C2D1 2 & 2 (1-2) |
198 |
*/ |
199 |
TClonesArray* hc=0; |
200 |
const char* keyac[4] = {"TOP1","SID1","C1D1","C2D1"}; |
201 |
for(Int_t i=0; i<4; i++){ |
202 |
hc = (TClonesArray*)fhitscolmap.GetValue(keyac[i]); |
203 |
if(hc) AddErel(hc, i); |
204 |
hc = 0; |
205 |
} |
206 |
} |
207 |
|
208 |
void PamVMCAcDig::AddErel(TClonesArray* HitColl, Int_t detcode){ |
209 |
|
210 |
|
211 |
// energy dependence on position (see file AcFitOutputDistancePmt.C by S.Orsi) |
212 |
// based on J.Lundquist's calculations (PhD thesis, page 94) |
213 |
// function: [0]+[1]*atan([2]/(x+1)), where the 3 parameters are: |
214 |
// 8.25470e-01 +- 1.79489e-02 |
215 |
// 6.41609e-01 +- 2.65846e-02 |
216 |
// 9.81177e+00 +- 1.21284e+00 |
217 |
// hp: 1 minimum ionising particle at 35cm from the PMT releases 1mip |
218 |
|
219 |
// TF1 *attenAC = new TF1("fAttAC",".825+.64*atan(9.8/x)",0.,45.); |
220 |
|
221 |
const Float_t posCasPmt[4][3]={{28.308, -17.168, 63.644},// 1 - CAS CPU: x,y,z |
222 |
{18.893, 24.913, 63.644},// 2 - CAS DCDC |
223 |
{-24.307, 17.162, 63.644},// 3 - CAS VME |
224 |
{-17.765, -28.300, 63.644}};// 4 - CAS IPM |
225 |
|
226 |
Float_t dx,dy,dz,dAC; // distance from PMT |
227 |
Int_t hitsNo=HitColl->GetEntriesFast(); |
228 |
PamVMCDetectorHit * hit = 0; |
229 |
|
230 |
if (hitsNo>50) cout<<"WARNING: PamVMCAcDig::AddErel... " |
231 |
<<"Number of hits in AC is out of range!!!"<<endl; |
232 |
|
233 |
switch(detcode){ |
234 |
case 0: //CAT |
235 |
for(Int_t k=0; k<hitsNo; k++){ |
236 |
hit = (PamVMCDetectorHit*)HitColl->At(k); |
237 |
fSumEcat[(hit->GetPOS())-1] += hit->GetEREL(); |
238 |
} |
239 |
break; |
240 |
|
241 |
case 1: //CAS |
242 |
for(Int_t k=0; k<hitsNo; k++){ |
243 |
hit = (PamVMCDetectorHit*)HitColl->At(k); |
244 |
dx = (hit->GetXIN()+hit->GetXOUT())/2.-posCasPmt[hit->GetPOS()-1][0]; |
245 |
dy = (hit->GetYIN()+hit->GetYOUT())/2.-posCasPmt[hit->GetPOS()-1][1]; |
246 |
dz = (hit->GetZIN()+hit->GetZOUT())/2.-posCasPmt[hit->GetPOS()-1][2]; |
247 |
dAC = Sqrt(dx*dx + dy*dy + dz*dz); |
248 |
//fSumEcas[(hit->GetPOS())-1] += (hit->GetEREL())*attenAC->Eval(dAC); |
249 |
if ((hit->GetPOS()==3)) fSumEcas[3] += (hit->GetEREL())*fattenAC->Eval(dAC); |
250 |
if ((hit->GetPOS()==4)) fSumEcas[1] += (hit->GetEREL())*fattenAC->Eval(dAC); |
251 |
if ((hit->GetPOS()==2)) fSumEcas[0] += (hit->GetEREL())*fattenAC->Eval(dAC); |
252 |
if ((hit->GetPOS()==1)) fSumEcas[2] += (hit->GetEREL())*fattenAC->Eval(dAC); |
253 |
} |
254 |
break; |
255 |
|
256 |
case 2: //C1D1 |
257 |
for(Int_t k=0; k<hitsNo; k++){ |
258 |
hit = (PamVMCDetectorHit*)HitColl->At(k); |
259 |
if ((hit->GetPOS()==1)) fSumEcard[3] += hit->GetEREL(); |
260 |
if ((hit->GetPOS()==2)) fSumEcard[0] += hit->GetEREL(); |
261 |
//fSumEcard[(hit->GetPOS())-1] += hit->GetEREL(); |
262 |
} |
263 |
break; |
264 |
case 3: //C2D1 |
265 |
for(Int_t k=0; k<hitsNo; k++){ |
266 |
hit = (PamVMCDetectorHit*)HitColl->At(k); |
267 |
if ((hit->GetPOS()==1)) fSumEcard[2] += hit->GetEREL(); |
268 |
if ((hit->GetPOS()==2)) fSumEcard[1] += hit->GetEREL(); |
269 |
//fSumEcard[(hit->GetPOS())+1] += hit->GetEREL(); |
270 |
} |
271 |
break; |
272 |
|
273 |
default: |
274 |
break; |
275 |
} |
276 |
|
277 |
|
278 |
|
279 |
|
280 |
} |