-
Notifications
You must be signed in to change notification settings - Fork 3
/
o2r.cc
408 lines (306 loc) · 9.62 KB
/
o2r.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
// Daniel Pitzl (DESY) Aug 2014
// .out to .root
// o2r -c 205 run5.out
#include <stdlib.h> // atoi
#include <iostream> // cout
#include <iomanip> // setw
#include <string> // strings
#include <sstream> // stringstream
#include <fstream> // files
#include <vector>
#include <cmath>
#include <TFile.h>
#include <TH1D.h>
#include <TH2D.h>
#include <TProfile.h>
#include <TProfile2D.h>
#include <TRandom1.h>
using namespace std;
#include "pixelForReadout.h" //struct pixel, struct cluster
// globals:
bool haveGain = 0;
double p0[52][80];
double p1[52][80];
double p2[52][80];
double p3[52][80];
double p4[52][80];
double p5[52][80];
pixel pb[4160]; // global declaration: vector of pixels with hit
int fNHit; // global
//------------------------------------------------------------------------------
// inverse decorrelated Weibull PH -> large Vcal DAC
double PHtoVcal( double ph, int col, int row )
{
if( !haveGain )
return ph;
if( col < 0 )
return ph;
if( col > 51 )
return ph;
if( row < 0 )
return ph;
if( row > 79 )
return ph;
// phroc2ps decorrelated: ph = p4 - p3*exp(-t^p2), t = p0 + q/p1
double Ared = ph - p4[col][row]; // p4 is asymptotic maximum
if( Ared >= 0 ) {
Ared = -0.1; // avoid overflow
}
double a3 = p3[col][row]; // positive
// large Vcal = ( (-ln(-(A-p4)/p3))^1/p2 - p0 )*p1
double vc =
p1[col][row] * ( pow( -log( -Ared / a3 ), 1 / p2[col][row] ) - p0[col][row] );
if( vc > 999 )
cout << "overflow " << vc << " at"
<< setw( 3 ) << col
<< setw( 3 ) << row << ", Ared " << Ared << ", a3 " << a3 << endl;
//return vc * p5[col][row]; // small Vcal
return vc; // large Vcal
}
// ----------------------------------------------------------------------
vector<cluster> getClus()
{
// returns clusters with local coordinates
// decodePixels should have been called before to fill pixel buffer pb
// simple clusterization
// cluster search radius fCluCut ( allows fCluCut-1 empty pixels)
const int fCluCut = 1; // clustering: 1 = no gap (15.7.2012)
vector<cluster> v;
if( fNHit == 0 ) return v;
int* gone = new int[fNHit];
for( int i = 0; i < fNHit; ++i )
gone[i] = 0;
int seed = 0;
while( seed < fNHit ) {
// start a new cluster
cluster c;
c.vpix.push_back( pb[seed] );
gone[seed] = 1;
// let it grow as much as possible:
int growing;
do{
growing = 0;
for( int i = 0; i < fNHit; ++i ) {
if( !gone[i] ){ // unused pixel
for( unsigned int p = 0; p < c.vpix.size(); p++ ) { // vpix in cluster so far
int dr = c.vpix.at(p).row - pb[i].row;
int dc = c.vpix.at(p).col - pb[i].col;
if( ( dr>=-fCluCut) && (dr<=fCluCut)
&& (dc>=-fCluCut) && (dc<=fCluCut) ) {
c.vpix.push_back(pb[i]);
gone[i] = 1;
growing = 1;
break; // important!
}
} // loop over vpix
} // not gone
} // loop over all pix
}
while( growing );
// added all I could. determine position and append it to the list of clusters:
c.sumA = 0;
c.charge = 0;
c.size = 0;
c.col = 0;
c.row = 0;
//c.xy[0] = 0;
//c.xy[1] = 0;
double sumQ = 0;
for( vector<pixel>::iterator p = c.vpix.begin(); p != c.vpix.end(); p++ ) {
c.sumA += p->ana; // Aout
double Qpix = p->anaVcal; // calibrated [ke]
if( Qpix < 0 ) Qpix = 1; // DP 1.7.2012
c.charge += Qpix;
//if( Qpix > 20 ) Qpix = 20; // DP 25.8.2013, cut tail. tiny improv
sumQ += Qpix;
c.col += (*p).col*Qpix;
c.row += (*p).row*Qpix;
//c.xy[0] += (*p).xy[0]*Qpix;
//c.xy[1] += (*p).xy[1]*Qpix;
}
c.size = c.vpix.size();
//cout << "(cluster with " << c.vpix.size() << " pixels)" << endl;
if( ! c.charge == 0 ) {
c.col /= sumQ;
c.row /= sumQ;
//c.col /= c.charge;
//c.row /= c.charge;
//c.xy[0] /= c.charge;
//c.xy[1] /= c.charge;
}
else {
c.col = (*c.vpix.begin()).col;
c.row = (*c.vpix.begin()).row;
//c.xy[0] = (*c.vpix.begin()).xy[0];
//c.xy[1] = (*c.vpix.begin()).xy[1];
cout << "GetClus: cluster with zero charge" << endl;
}
v.push_back(c); // add cluster to vector
// look for a new seed = used pixel:
while( (++seed < fNHit) && gone[seed] );
} // while over seeds
// nothing left, return clusters
delete gone;
return v;
}
//------------------------------------------------------------------------------
int main( int argc, char* argv[] )
{
cout << "main " << argv[0] << " called with " << argc << " arguments" << endl;
if( argc == 1 ) {
cout << "give file name" << endl;
return 1;
}
// file name = last argument:
string evFileName( argv[argc-1] );
cout << "try to open " << evFileName;
ifstream evFile( argv[argc-1] );
if( !evFile ) {
cout << " : failed " << endl;
return 2;
}
cout << " : succeed " << endl;
// further arguments:
int chip = 205;
for( int i = 1; i < argc; i++ ) {
if( !strcmp( argv[i], "-c" ) )
chip = atoi( argv[++i] );
} // argc
// gain:
string gainFileName;
if( chip == 205 )
gainFileName = "/home/pitzl/psi/dtb/tst303/c205-gaincal-trim36.dat"; // 6.8.2014
double ke = 0.350; // large Vcal -> ke
if( gainFileName.length( ) > 0 ) {
ifstream gainFile( gainFileName.c_str() );
if( gainFile ) {
haveGain = 1;
cout << "gain: " << gainFileName << endl;
char ih[99];
int icol;
int irow;
while( gainFile >> ih ) {
gainFile >> icol;
gainFile >> irow;
gainFile >> p0[icol][irow];
gainFile >> p1[icol][irow];
gainFile >> p2[icol][irow];
gainFile >> p3[icol][irow];
gainFile >> p4[icol][irow];
gainFile >> p5[icol][irow];
}
} // gainFile open
} // gainFileName
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// (re-)create root file:
TFile* histoFile = new TFile( "run.root", "RECREATE" );
// book histos:
TH1D hnpx( "npx", "pixel per event;pixels;events", 51, -0.5, 50.5 );
TH1D hcol( "px_col", "pixel col;column;pixels", 52, -0.5, 51.5 );
TH1D hrow( "px_row", "pixel row;row;pixels", 80, -0.5, 79.5 );
TH2D hmap( "px_map", "pixel map;column;row;pixels",
52, -0.5, 51.5, 80, -0.5, 79.5 );
TH1D hq( "px_charge", "pixel charge;pixel charge [ke];pixels",
100, 0, 20 );
TH1D hncl( "ncl", "cluster per event;cluster;events", 21, -0.5, 20.5 );
TH1D hsiz( "cl_size", "cluster size;pixels/cluster;cluster",
31, -0.5, 30.5 );
TH1D hchg( "cl_charge", "cluster charge;cluster charge [ke];clusters",
200, 0, 100 );
TH1D hchg1( "cl_charge1", "cluster charge Loch;cluster charge [ke];clusters",
200, 0, 100 );
TH1D hchg2( "cl_charge2", "cluster charge Blende;cluster charge [ke];clusters",
200, 0, 100 );
TProfile2D
sizevsxy( "cl_size_map",
"pixels/cluster;cluster col;cluster row;<pixels/cluster>",
52, -0.5, 51.5, 80, -0.5, 79.5, 0, 99 );
TProfile2D
chrgvsxy( "cl_chrg_map",
"cluster charge;cluster col;cluster row;<cluster charge> [ke]",
52, -0.5, 51.5, 80, -0.5, 79.5, 0, 999 );
TH2D
lowmap( "low_chrg_map",
"small cluster charge;cluster col;cluster row",
52, -0.5, 51.5, 80, -0.5, 79.5 );
TProfile
sizevsdd( "cl_size_scan",
"pixels/cluster;center distance [mm];cluster row;<pixels/cluster>",
50, 0, 6, 0, 99 );
TProfile
chrgvsdd( "cl_chrg_scan",
"cluster charge;center distance [mm];cluster row;<cluster charge> [ke]",
50, 0, 6, 0, 999 );
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// event loop:
bool ldb = 0;
int nev = 0;
int mpx = 0;
int iev = 0;
int col = 0;
int row = 0;
int adc = 0;
// Read file by lines
string sl;
while( evFile.good() && ! evFile.eof() ) {
getline( evFile, sl ); // read one line into string
istringstream is( sl ); // tokenize string
is >> iev;
++nev;
int npx = 0;
do {
is >> col;
is >> row;
is >> adc;
double q = PHtoVcal( adc, col, row ) * ke; // [ke]
hcol.Fill( col );
hrow.Fill( row );
hmap.Fill( col, row );
hq.Fill( q );
// fill pixel block for clustering:
pb[npx].col = col;
pb[npx].row = row;
pb[npx].ana = adc;
pb[npx].anaVcal = q;
++npx;
++mpx;
}
while( ! is.eof() );
hnpx.Fill( npx );
fNHit = npx; // for cluster search
vector<cluster> clust = getClus();
hncl.Fill( clust.size() );
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// look at clusters:
for( vector<cluster>::iterator c = clust.begin(); c != clust.end(); c++ ) {
hsiz.Fill( c->size );
hchg.Fill( c->charge );
sizevsxy.Fill( c->col, c->row, c->size );
chrgvsxy.Fill( c->col, c->row, c->charge );
if( c->charge < 15 )
lowmap.Fill( c->col, c->row );
// Lochblende:
double dx = 0.15 * (c->col - 26); // [mm]
double dy = 0.10 * (c->row - 43); // [mm]
double dd = sqrt( dx*dx + dy*dy );
sizevsdd.Fill( dd, c->size );
chrgvsdd.Fill( dd, c->charge );
if( dd < 1.5 ) {
hchg1.Fill( c->charge );
}
else
hchg2.Fill( c->charge );
// pix in clus:
} // clusters
if( ldb ) cout << endl << "event " << nev << endl;
if( !(nev%1000) ) cout << "event " << nev << endl;
} // while events
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
cout << "eof" << endl;
cout << "events " << nev
<< ", pixel " << mpx
<< endl;
histoFile->Write();
histoFile->Close();
return 0;
}