1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | #include <stdlib.h> |
14 | #include <stdio.h> |
15 | #include <math.h> |
16 | |
17 | #include <hddm_s.h> |
18 | #include <geant3.h> |
19 | #include <bintree.h> |
20 | |
21 | #include "calibDB.h" |
22 | extern s_HDDM_t* thisInputEvent; |
23 | extern double asic_response(double t); |
24 | extern double Ei(double x); |
25 | |
26 | typedef struct{ |
27 | int writeenohits; |
28 | int showersincol; |
29 | int driftclusters; |
30 | }controlparams_t; |
31 | |
32 | extern controlparams_t controlparams_; |
33 | |
34 | |
35 | const float wire_dead_zone_radius[4]={3.0,3.0,3.9,3.9}; |
36 | const float strip_dead_zone_radius[4]={1.3,1.3,1.3,1.3}; |
37 | |
38 | #define CATHODE_ROT_ANGLE1.309 1.309 // 75 degrees |
39 | |
40 | |
41 | static float DRIFT_SPEED =.0055; |
42 | static float ACTIVE_AREA_OUTER_RADIUS =48.5; |
43 | static float ANODE_CATHODE_SPACING =0.5; |
44 | static float TWO_HIT_RESOL =1.; |
45 | static int WIRES_PER_PLANE =96; |
46 | static float WIRE_SPACING =1.0; |
47 | static float U_OF_WIRE_ZERO =0; |
48 | static float STRIPS_PER_PLANE =192; |
49 | static float STRIP_SPACING =0.5; |
50 | static float U_OF_STRIP_ZERO =0; |
51 | static float STRIP_GAP =0.1; |
52 | static int MAX_HITS =100; |
53 | static float K2 =1.15; |
54 | static float STRIP_NODES = 3; |
55 | static float THRESH_KEV =1. ; |
56 | static float THRESH_ANODE = 1.; |
57 | static float THRESH_STRIPS =5. ; |
58 | static float ELECTRON_CHARGE =1.6022e-4; |
59 | static float DIFFUSION_COEFF = 1.1e-6; |
60 | static float FDC_TIME_WINDOW = 1000.0; |
61 | static float GAS_GAIN = 8e4; |
62 | |
63 | |
64 | #if 0 |
65 | static float wire_dx_offset[2304]; |
66 | static float wire_dz_offset[2304]; |
67 | #endif |
68 | |
69 | binTree_t* forwardDCTree = 0; |
70 | static int stripCount = 0; |
71 | static int wireCount = 0; |
72 | static int pointCount = 0; |
73 | static int initializedx=0; |
74 | |
75 | void gpoiss_(float*,int*,const int*); |
76 | void rnorml_(float*,int*); |
77 | |
78 | typedef int (*compfn)(const void*, const void*); |
79 | |
80 | |
81 | int fdc_anode_cluster_sort(const void *a,const void *b){ |
82 | const s_FdcAnodeTruthHit_t *ca=a; |
83 | const s_FdcAnodeTruthHit_t *cb=b; |
84 | if (ca->t<cb->t) return -1; |
85 | else if (ca->t>cb->t) return 1; |
86 | else return 0; |
87 | } |
88 | int fdc_cathode_cluster_sort(const void *a,const void *b){ |
89 | const s_FdcCathodeTruthHit_t *ca=a; |
90 | const s_FdcCathodeTruthHit_t *cb=b; |
91 | if (ca->t<cb->t) return -1; |
92 | else if (ca->t>cb->t) return 1; |
93 | else return 0; |
94 | } |
95 | |
96 | |
97 | |
98 | |
99 | void locate(float *xx,int n,float x,int *j){ |
100 | int ju,jm,jl; |
101 | int ascnd; |
102 | |
103 | jl=-1; |
104 | ju=n; |
105 | ascnd=(xx[n-1]>=xx[0]); |
106 | while(ju-jl>1){ |
107 | jm=(ju+jl)>>1; |
108 | if (x>=xx[jm]==ascnd) |
109 | jl=jm; |
110 | else |
111 | ju=jm; |
112 | } |
113 | if (x==xx[0]) *j=0; |
114 | else if (x==xx[n-1]) *j=n-2; |
115 | else *j=jl; |
116 | } |
117 | |
118 | |
119 | |
120 | void polint(float *xa, float *ya,int n,float x, float *y,float *dy){ |
121 | int i,m,ns=0; |
122 | float den,dif,dift,ho,hp,w; |
123 | |
124 | float *c=(float *)calloc(n,sizeof(float)); |
125 | float *d=(float *)calloc(n,sizeof(float)); |
| |
126 | |
127 | dif=fabs(x-xa[0]); |
128 | for (i=0;i<n;i++){ |
| 2 | | Loop condition is true. Entering loop body | |
|
| 4 | | Loop condition is true. Entering loop body | |
|
| 6 | | Loop condition is false. Execution continues on line 136 | |
|
129 | if ((dift=fabs(x-xa[i]))<dif){ |
| |
| |
130 | ns=i; |
131 | dif=dift; |
132 | } |
133 | c[i]=ya[i]; |
134 | d[i]=ya[i]; |
135 | } |
136 | *y=ya[ns--]; |
137 | |
138 | for (m=1;m<n;m++){ |
| 7 | | Loop condition is true. Entering loop body | |
|
139 | for (i=1;i<=n-m;i++){ |
| 8 | | Loop condition is true. Entering loop body | |
|
140 | ho=xa[i-1]-x; |
141 | hp=xa[i+m-1]-x; |
142 | w=c[i+1-1]-d[i-1]; |
143 | if ((den=ho-hp)==0.0) return; |
| |
| 10 | | Memory is never released; potential leak of memory pointed to by 'd' |
|
144 | |
145 | den=w/den; |
146 | d[i-1]=hp*den; |
147 | c[i-1]=ho*den; |
148 | |
149 | } |
150 | |
151 | *y+=(*dy=(2*ns<(n-m) ?c[ns+1]:d[ns--])); |
152 | } |
153 | free(c); |
154 | free(d); |
155 | } |
156 | |
157 | |
158 | double wire_signal(double t,s_FdcAnodeTruthHits_t* ahits){ |
159 | double t0=1.0; |
160 | int m; |
161 | double asic_gain=0.76; |
162 | double func=0; |
163 | for (m=0;m<ahits->mult;m++){ |
164 | if (t>ahits->in[m].t){ |
165 | double my_time=t-ahits->in[m].t; |
166 | func+=asic_gain*ahits->in[m].dE*asic_response(my_time); |
167 | } |
168 | } |
169 | return func; |
170 | } |
171 | |
172 | |
173 | double cathode_signal(double t,s_FdcCathodeTruthHits_t* chits){ |
174 | double t0=1.0; |
175 | int m; |
176 | double asic_gain=2.3; |
177 | double func=0; |
178 | for (m=0;m<chits->mult;m++){ |
179 | if (t>chits->in[m].t){ |
180 | double my_time=t-chits->in[m].t; |
181 | func+=asic_gain*chits->in[m].q*asic_response(my_time); |
182 | } |
183 | } |
184 | return func; |
185 | } |
186 | |
187 | |
188 | void AddFDCCathodeHits(int PackNo,float xwire,float avalanche_y,float tdrift, |
189 | int n_p,int track,int ipart,int chamber,int module, |
190 | int layer, int global_wire_number){ |
191 | |
192 | s_FdcCathodeTruthHits_t* chits; |
193 | |
194 | |
195 | float q_anode; |
196 | int n_t; |
197 | |
198 | float n_s_per_p=1.89; |
199 | if (controlparams_.driftclusters==0){ |
200 | |
201 | |
202 | |
203 | |
204 | |
205 | int n_s,one=1; |
206 | float n_s_mean = ((float)n_p)*n_s_per_p; |
207 | gpoiss_(&n_s_mean,&n_s,&one); |
208 | n_t = n_s+n_p; |
209 | q_anode=((float)n_t)*GAS_GAIN*ELECTRON_CHARGE; |
210 | } |
211 | else{ |
212 | |
213 | |
214 | |
215 | |
216 | int n_s; |
217 | int one=1; |
218 | gpoiss_(&n_s_per_p,&n_s,&one); |
219 | |
220 | n_t=1+n_s; |
221 | q_anode=GAS_GAIN*ELECTRON_CHARGE*((float)n_t); |
222 | } |
223 | |
224 | |
225 | int plane, node; |
226 | for (plane=1; plane<4; plane+=2){ |
227 | float theta = (plane == 1)? -CATHODE_ROT_ANGLE1.309 : +CATHODE_ROT_ANGLE1.309; |
228 | float cathode_u = xwire*cos(theta)+avalanche_y*sin(theta); |
229 | int strip1 = ceil((cathode_u-U_OF_STRIP_ZERO)/STRIP_SPACING +0.5); |
230 | float cathode_u1 = (strip1-1)*STRIP_SPACING + U_OF_STRIP_ZERO; |
231 | float delta = cathode_u-cathode_u1; |
232 | float half_gap=ANODE_CATHODE_SPACING; |
233 | |
234 | #if 0 |
235 | half_gap+=(plane==1)?+wire_dz_offset[global_wire_number]: |
236 | -wire_dz_offset[global_wire_number]; |
237 | #endif |
238 | |
239 | for (node=-STRIP_NODES; node<=STRIP_NODES; node++){ |
240 | |
241 | |
242 | |
243 | float lambda1=(((float)node-0.5)*STRIP_SPACING+STRIP_GAP/2. |
244 | -delta)/half_gap; |
245 | float lambda2=(((float)node+0.5)*STRIP_SPACING-STRIP_GAP/2. |
246 | -delta)/half_gap; |
247 | float factor=0.25*M_PI3.14159265358979323846*K2; |
248 | float q = 0.25*q_anode*(tanh(factor*lambda2)-tanh(factor*lambda1)); |
249 | |
250 | int strip = strip1+node; |
251 | |
252 | |
253 | float strip_outer_u=cathode_u1 |
254 | +(STRIP_SPACING+STRIP_GAP/2.)*(int)node; |
255 | float cathode_v=-xwire*sin(theta)+avalanche_y*cos(theta); |
256 | float check_radius=sqrt(strip_outer_u*strip_outer_u |
257 | +cathode_v*cathode_v); |
258 | |
259 | if ((strip > 0) |
260 | && (check_radius>strip_dead_zone_radius[PackNo]) |
261 | && (strip <= STRIPS_PER_PLANE)){ |
262 | int mark = (chamber<<20) + (plane<<10) + strip; |
263 | void** cathodeTwig = getTwig(&forwardDCTree, mark); |
264 | if (*cathodeTwig == 0){ |
265 | s_ForwardDC_t* fdc = *cathodeTwig = make_s_ForwardDC(); |
266 | s_FdcChambers_t* chambers = make_s_FdcChambers(1); |
267 | s_FdcCathodeStrips_t* strips = make_s_FdcCathodeStrips(1); |
268 | strips->mult = 1; |
269 | strips->in[0].plane = plane; |
270 | strips->in[0].strip = strip; |
271 | strips->in[0].fdcCathodeTruthHits = chits |
272 | = make_s_FdcCathodeTruthHits(MAX_HITS); |
273 | chambers->mult = 1; |
274 | chambers->in[0].module = module; |
275 | chambers->in[0].layer = layer; |
276 | chambers->in[0].fdcCathodeStrips = strips; |
277 | fdc->fdcChambers = chambers; |
278 | stripCount++; |
279 | } |
280 | else{ |
281 | s_ForwardDC_t* fdc = *cathodeTwig; |
282 | chits = fdc->fdcChambers->in[0].fdcCathodeStrips |
283 | ->in[0].fdcCathodeTruthHits; |
284 | } |
285 | |
286 | int nhit; |
287 | for (nhit = 0; nhit < chits->mult; nhit++){ |
288 | |
289 | |
290 | |
291 | if (fabs(chits->in[nhit].t - tdrift) <TWO_HIT_RESOL) |
292 | { |
293 | break; |
294 | } |
295 | } |
296 | if (nhit < chits->mult) |
297 | { |
298 | |
299 | chits->in[nhit].q += q; |
300 | if(chits->in[nhit].t>tdrift){ |
301 | chits->in[nhit].t = tdrift; |
302 | chits->in[nhit].itrack = track; |
303 | chits->in[nhit].ptype = ipart; |
304 | } |
305 | } |
306 | else if (nhit < MAX_HITS){ |
307 | chits->in[nhit].t = tdrift; |
308 | chits->in[nhit].q = q; |
309 | chits->in[nhit].itrack = track; |
310 | chits->in[nhit].ptype = ipart; |
311 | chits->mult++; |
312 | } |
313 | else{ |
314 | |
315 | |
316 | |
317 | |
318 | |
319 | |
320 | } |
321 | |
322 | } |
323 | } |
324 | } |
325 | } |
326 | |
327 | |
328 | |
329 | |
330 | |
331 | |
332 | |
333 | |
334 | |
335 | |
336 | int AddFDCAnodeHit(s_FdcAnodeTruthHits_t* ahits,int layer,int ipart,int track, |
337 | float xwire,float xyz[3],float dE,float t,float *tdrift){ |
338 | |
339 | |
340 | |
341 | float rndno[2]; |
342 | int two=2; |
343 | |
344 | |
345 | |
346 | |
347 | |
348 | { |
349 | float rho,phi1; |
350 | grndm_(rndno,&two); |
351 | rho = sqrt(-2*log(rndno[0])); |
352 | phi1 = rndno[1]*2*M_PI3.14159265358979323846; |
353 | rndno[0] = rho*cos(phi1); |
354 | rndno[1] = rho*sin(phi1); |
355 | } |
356 | |
357 | |
358 | float x[3],B[3]; |
359 | transformCoord(xyz,"local",x,"global")transformcoord_(xyz,"local",x,"global",strlen("local"),strlen ("global")); |
360 | gufld2_(x,B); |
361 | |
362 | |
363 | |
364 | float wire_dir[2]; |
365 | float wire_theta=1.0472*(float)((layer%3)-1); |
366 | float phi=0.;; |
367 | float Br=sqrt(B[0]*B[0]+B[1]*B[1]); |
368 | |
369 | wire_dir[0]=sin(wire_theta); |
370 | wire_dir[1]=cos(wire_theta); |
371 | if (Br>0.) phi= acos((B[0]*wire_dir[0]+B[1]*wire_dir[1])/Br); |
372 | |
373 | |
374 | float dx=xyz[0]-xwire; |
375 | float dx2=dx*dx; |
376 | float dx4=dx2*dx2; |
377 | float dz2=xyz[2]*xyz[2]; |
378 | float dz4=dz2*dz2; |
379 | |
380 | |
381 | |
382 | |
383 | xyz[1]+=( 0.1458*B[2]*(1.-0.048*Br) )*dx |
384 | +( 0.1717+0.01227*B[2] )*(Br*cos(phi))*xyz[2] |
385 | +( -0.000176 )*dx*dx2/(dz2+0.001); |
386 | |
387 | xyz[1]+=(( 0.01 )*pow(dx2+dz2,0.125)+( 0.0061 )*dx2)*rndno[1]; |
388 | |
389 | |
390 | |
391 | if (sqrt(xyz[1]*xyz[1]+xwire*xwire)>ACTIVE_AREA_OUTER_RADIUS) |
392 | return 0; |
393 | |
394 | |
395 | |
396 | float tdrift_unsmeared=( 1086.0-106.7*B[2] )*dx2+( 1068.0 )*dz2 |
397 | +dx4*(( -2.675 )/(dz2+0.001)+( 2.4e4 )*dz2); |
398 | float dt=(( 39.44 )*dx4/(0.5-dz2)+( 56.0 )*dz4/(0.5-dx2) |
399 | +( 0.01566 )*dx4/(dz4+0.002)/(0.251-dx2))*rndno[1]; |
400 | |
401 | double dradius=sqrt(dx2+dz2); |
402 | if (dradius-0.5>=0. && dt<0){ |
403 | dt=0.; |
404 | } |
405 | |
406 | |
407 | double v_max=0.08; |
408 | double tmin=dradius/v_max; |
409 | double tdrift_smeared=tdrift_unsmeared+dt; |
410 | if (tdrift_smeared<tmin){ |
411 | tdrift_smeared=tmin; |
412 | } |
413 | |
414 | |
415 | *tdrift=t+tdrift_smeared; |
416 | |
417 | |
418 | if (t>FDC_TIME_WINDOW) return 0; |
419 | |
420 | int nhit; |
421 | |
422 | |
423 | for (nhit = 0; nhit < ahits->mult; nhit++) |
424 | { |
425 | if (fabs(ahits->in[nhit].t - *tdrift) < TWO_HIT_RESOL) |
426 | { |
427 | break; |
428 | } |
429 | } |
430 | if (nhit < ahits->mult) |
431 | { |
432 | |
433 | ahits->in[nhit].dE += dE; |
434 | if(ahits->in[nhit].t>*tdrift){ |
435 | ahits->in[nhit].t = *tdrift; |
436 | ahits->in[nhit].t_unsmeared=tdrift_unsmeared; |
437 | ahits->in[nhit].d = sqrt(dx2+dz2); |
438 | |
439 | ahits->in[nhit].itrack = track; |
440 | ahits->in[nhit].ptype = ipart; |
441 | } |
442 | |
443 | |
444 | |
445 | |
446 | |
447 | } |
448 | else if (nhit < MAX_HITS) |
449 | { |
450 | ahits->in[nhit].t = *tdrift; |
451 | ahits->in[nhit].t_unsmeared=tdrift_unsmeared; |
452 | ahits->in[nhit].dE = dE; |
453 | ahits->in[nhit].d = sqrt(dx2+dz2); |
454 | ahits->in[nhit].itrack = track; |
455 | ahits->in[nhit].ptype = ipart; |
456 | ahits->mult++; |
457 | } |
458 | else |
459 | { |
460 | fprintf(stderrstderr,"HDGeant error in hitForwardDC: "); |
461 | fprintf(stderrstderr,"max hit count %d exceeded, truncating!\n",MAX_HITS); |
462 | } |
463 | |
464 | return 1; |
465 | } |
466 | |
467 | |
468 | |
469 | void hitForwardDC (float xin[4], float xout[4], |
470 | float pin[5], float pout[5], float dEsum, |
471 | int track, int stack, int history, int ipart) |
472 | { |
473 | float x[3], t; |
474 | float dx[3], dr; |
475 | float dEdx; |
476 | float xlocal[3]; |
477 | float xinlocal[3]; |
478 | float xoutlocal[3]; |
479 | float dradius; |
480 | float alpha,sinalpha,cosalpha; |
481 | int i,j; |
482 | |
483 | if (!initializedx){ |
484 | mystr_t strings[250]; |
485 | float values[250]; |
486 | int nvalues = 250; |
487 | |
488 | |
489 | int status = GetConstants("FDC/fdc_parms", &nvalues,values,strings); |
490 | if (!status) { |
491 | int ncounter = 0; |
492 | int i; |
493 | for ( i=0;i<(int)nvalues;i++){ |
494 | |
495 | if (!strcmp(strings[i].str,"FDC_DRIFT_SPEED")) { |
496 | DRIFT_SPEED = values[i]; |
497 | ncounter++; |
498 | } |
499 | if (!strcmp(strings[i].str,"FDC_ACTIVE_AREA_OUTER_RADIUS")) { |
500 | ACTIVE_AREA_OUTER_RADIUS = values[i]; |
501 | ncounter++; |
502 | } |
503 | if (!strcmp(strings[i].str,"FDC_ANODE_CATHODE_SPACING")) { |
504 | ANODE_CATHODE_SPACING = values[i]; |
505 | ncounter++; |
506 | } |
507 | if (!strcmp(strings[i].str,"FDC_TWO_HIT_RESOL")) { |
508 | TWO_HIT_RESOL = values[i]; |
509 | ncounter++; |
510 | } |
511 | if (!strcmp(strings[i].str,"FDC_WIRES_PER_PLANE")) { |
512 | WIRES_PER_PLANE = values[i]; |
513 | ncounter++; |
514 | } |
515 | if (!strcmp(strings[i].str,"FDC_WIRE_SPACING")) { |
516 | WIRE_SPACING = values[i]; |
517 | ncounter++; |
518 | } |
519 | if (!strcmp(strings[i].str,"FDC_STRIPS_PER_PLANE")) { |
520 | STRIPS_PER_PLANE = values[i]; |
521 | ncounter++; |
522 | } |
523 | if (!strcmp(strings[i].str,"FDC_STRIP_SPACING")) { |
524 | STRIP_SPACING = values[i]; |
525 | ncounter++; |
526 | } |
527 | if (!strcmp(strings[i].str,"FDC_STRIP_GAP")) { |
528 | STRIP_GAP = values[i]; |
529 | ncounter++; |
530 | } |
531 | if (!strcmp(strings[i].str,"FDC_MAX_HITS")) { |
532 | MAX_HITS = values[i]; |
533 | ncounter++; |
534 | } |
535 | if (!strcmp(strings[i].str,"FDC_K2")) { |
536 | K2 = values[i]; |
537 | ncounter++; |
538 | } |
539 | if (!strcmp(strings[i].str,"FDC_STRIP_NODES")) { |
540 | STRIP_NODES = values[i]; |
541 | ncounter++; |
542 | } |
543 | if (!strcmp(strings[i].str,"FDC_THRESH_KEV")) { |
544 | THRESH_KEV = values[i]; |
545 | ncounter++; |
546 | } |
547 | if (!strcmp(strings[i].str,"FDC_THRESH_STRIPS")) { |
548 | THRESH_STRIPS = values[i]; |
549 | ncounter++; |
550 | } |
551 | if (!strcmp(strings[i].str,"FDC_ELECTRON_CHARGE")) { |
552 | ELECTRON_CHARGE = values[i]; |
553 | ncounter++; |
554 | } |
555 | if (!strcmp(strings[i].str,"FDC_DIFFUSION_COEFF")) { |
556 | DIFFUSION_COEFF = values[i]; |
557 | ncounter++; |
558 | } |
559 | } |
560 | U_OF_WIRE_ZERO = (-((WIRES_PER_PLANE-1.)*WIRE_SPACING)/2); |
561 | U_OF_STRIP_ZERO = (-((STRIPS_PER_PLANE-1.)*STRIP_SPACING)/2); |
562 | |
563 | if (ncounter==16){ |
564 | printf("FDC: ALL parameters loaded from Data Base\n"); |
565 | } else if (ncounter<16){ |
566 | printf("FDC: NOT ALL necessary parameters found in Data Base %d out of 16\n",ncounter); |
567 | } else { |
568 | printf("FDC: SOME parameters found more than once in Data Base\n"); |
569 | } |
570 | #if 0 |
571 | { |
572 | int num_values=2304*2; |
573 | float my_values[2304*2]; |
574 | mystr_t my_strings[2304*2]; |
575 | status=GetArrayConstants("FDC/fdc_wire_offsets",&num_values, |
576 | my_values,my_strings); |
577 | if (!status){ |
578 | int i; |
579 | for (i=0;i<num_values;i+=2){ |
580 | int j=i/2; |
581 | wire_dx_offset[j]=my_values[i]; |
582 | wire_dz_offset[j]=my_values[i+1]; |
583 | } |
584 | } |
585 | } |
586 | #endif |
587 | } |
588 | initializedx = 1 ; |
589 | } |
590 | |
591 | |
592 | int layer = getlayer_(); |
593 | if (layer==0){ |
594 | printf("hitFDC: FDC layer number evaluates to zero! THIS SHOULD NEVER HAPPEN! drop this particle.\n"); |
595 | return; |
596 | } |
597 | |
598 | |
599 | |
600 | int PackNo = getpackage_()-1; |
601 | if (PackNo==-1){ |
602 | printf("hitFDC: FDC package number evaluates to zero! THIS SHOULD NEVER HAPPEN! drop this particle.\n"); |
603 | return; |
604 | } |
605 | int glayer=6*PackNo+layer-1; |
606 | int module = 2*(PackNo)+(layer-1)/3+1; |
607 | int chamber = (module*10)+(layer-1)%3+1; |
608 | int wire1,wire2; |
609 | int wire,dwire; |
610 | |
611 | |
612 | layer=(layer-1)%3+1; |
613 | |
614 | transformCoord(xin,"global",xinlocal,"local")transformcoord_(xin,"global",xinlocal,"local",strlen("global" ),strlen("local")); |
615 | |
616 | wire1 = ceil((xinlocal[0] - U_OF_WIRE_ZERO)/WIRE_SPACING +0.5); |
617 | transformCoord(xout,"global",xoutlocal,"local")transformcoord_(xout,"global",xoutlocal,"local",strlen("global" ),strlen("local")); |
618 | wire2 = ceil((xoutlocal[0] - U_OF_WIRE_ZERO)/WIRE_SPACING +0.5); |
619 | |
620 | if ((wire1>WIRES_PER_PLANE && wire2==WIRES_PER_PLANE) || |
621 | (wire2>WIRES_PER_PLANE && wire1==WIRES_PER_PLANE)) |
622 | wire1=wire2=WIRES_PER_PLANE; |
623 | if ((wire1==0 && wire2 == 1) || (wire1==1 && wire2== 0)){ |
624 | wire1=wire2=1; |
625 | } |
626 | |
627 | if (wire1>WIRES_PER_PLANE&&wire2>WIRES_PER_PLANE) return; |
628 | if (wire1==0 && wire2==0) return; |
629 | |
630 | if (wire1>WIRES_PER_PLANE) wire1=wire2; |
631 | else if (wire2>WIRES_PER_PLANE) wire2=wire1; |
632 | if (wire1==0) wire1=wire2; |
633 | else if (wire2==0) wire2=wire1; |
634 | |
635 | dwire = (wire1 < wire2)? 1 : -1; |
636 | alpha = atan2(xoutlocal[0]-xinlocal[0],xoutlocal[2]-xinlocal[2]); |
637 | sinalpha=sin(alpha); |
638 | cosalpha=cos(alpha); |
639 | xlocal[0] = (xinlocal[0] + xoutlocal[0])/2; |
640 | xlocal[1] = (xinlocal[1] + xoutlocal[1])/2; |
641 | xlocal[2] = (xinlocal[2] + xoutlocal[2])/2; |
642 | |
643 | wire = ceil((xlocal[0] - U_OF_WIRE_ZERO)/WIRE_SPACING +0.5); |
644 | x[0] = (xin[0] + xout[0])/2; |
645 | x[1] = (xin[1] + xout[1])/2; |
646 | x[2] = (xin[2] + xout[2])/2; |
647 | t = (xin[3] + xout[3])/2 * 1e9; |
648 | dx[0] = xin[0] - xout[0]; |
649 | dx[1] = xin[1] - xout[1]; |
650 | dx[2] = xin[2] - xout[2]; |
651 | dr = sqrt(dx[0]*dx[0] + dx[1]*dx[1] + dx[2]*dx[2]); |
652 | if (dr > 1e-3) |
653 | { |
654 | dEdx = dEsum/dr; |
655 | } |
656 | else |
657 | { |
658 | dEdx = 0; |
659 | } |
660 | |
661 | |
662 | |
663 | |
664 | if (sqrt(xlocal[0]*xlocal[0]+xlocal[1]*xlocal[1]) |
665 | < wire_dead_zone_radius[PackNo]) |
666 | { |
667 | return; |
668 | } |
669 | |
670 | |
671 | |
672 | if (history == 0) |
673 | { |
674 | int mark = (1<<16) + (chamber<<20) + pointCount; |
675 | void** twig = getTwig(&forwardDCTree, mark); |
676 | if (*twig == 0) |
677 | { |
678 | s_ForwardDC_t* fdc = *twig = make_s_ForwardDC(); |
679 | s_FdcChambers_t* chambers = make_s_FdcChambers(1); |
680 | s_FdcTruthPoints_t* points = make_s_FdcTruthPoints(1); |
681 | float xwire = U_OF_WIRE_ZERO + (wire-1)*WIRE_SPACING; |
682 | float u[2]; |
683 | u[0] = xinlocal[2]; |
684 | u[1] = xinlocal[0]-xwire; |
685 | dradius = fabs(u[1]*cosalpha-u[0]*sinalpha); |
686 | points->mult = 1; |
687 | int a = thisInputEvent->physicsEvents->in[0].reactions->in[0].vertices->in[0].products->mult; |
688 | points->in[0].primary = (stack <= a); |
689 | points->in[0].track = track; |
690 | points->in[0].x = x[0]; |
691 | points->in[0].y = x[1]; |
692 | points->in[0].z = x[2]; |
693 | points->in[0].t = t; |
694 | points->in[0].px = pin[0]*pin[4]; |
695 | points->in[0].py = pin[1]*pin[4]; |
696 | points->in[0].pz = pin[2]*pin[4]; |
697 | points->in[0].E = pin[3]; |
698 | points->in[0].dradius = dradius; |
699 | points->in[0].dEdx = dEdx; |
700 | points->in[0].ptype = ipart; |
701 | chambers->mult = 1; |
702 | chambers->in[0].module = module; |
703 | chambers->in[0].layer = layer; |
704 | chambers->in[0].fdcTruthPoints = points; |
705 | fdc->fdcChambers = chambers; |
706 | pointCount++; |
707 | } |
708 | } |
709 | |
710 | |
711 | |
712 | if (dEsum > 0) |
713 | { |
714 | float sign=1.; |
715 | |
716 | for (wire=wire1; wire-dwire != wire2; wire+=dwire) |
717 | { |
718 | int valid_hit=1; |
719 | float dE,dt; |
720 | float u[2]; |
721 | float x0[3],x1[3]; |
722 | float avalanche_y; |
723 | float xwire = U_OF_WIRE_ZERO + (wire-1)*WIRE_SPACING; |
724 | int global_wire_number=96*glayer+wire-1; |
725 | |
726 | #if 0 |
727 | xwire+=wire_dx_offset[global_wire_number]; |
728 | #endif |
729 | |
730 | if (wire1==wire2){ |
731 | dE=dEsum; |
732 | x0[0] = xinlocal[0]; |
733 | x0[1] = xinlocal[1]; |
734 | x0[2] = xinlocal[2]; |
735 | x1[0] = xoutlocal[0]; |
736 | x1[1] = xoutlocal[1]; |
737 | x1[2] = xoutlocal[2]; |
738 | } |
739 | else{ |
740 | x0[0] = xwire-0.5*dwire*WIRE_SPACING; |
741 | x0[1] = xinlocal[1] + (x0[0]-xinlocal[0]+1e-20)* |
742 | (xoutlocal[1]-xinlocal[1])/(xoutlocal[0]-xinlocal[0]+1e-20); |
743 | x0[2] = xinlocal[2] + (x0[0]-xinlocal[0]+1e-20)* |
744 | (xoutlocal[2]-xinlocal[2])/(xoutlocal[0]-xinlocal[0]+1e-20); |
745 | if (fabs(x0[2]-xoutlocal[2]) > fabs(xinlocal[2]-xoutlocal[2])) |
746 | { |
747 | x0[0] = xinlocal[0]; |
748 | x0[1] = xinlocal[1]; |
749 | x0[2] = xinlocal[2]; |
750 | } |
751 | x1[0] = xwire+0.5*dwire*WIRE_SPACING; |
752 | x1[1] = xinlocal[1] + (x1[0]-xinlocal[0]+1e-20)* |
753 | (xoutlocal[1]-xinlocal[1])/(xoutlocal[0]-xinlocal[0]+1e-20); |
754 | x1[2] = xinlocal[2] + (x1[0]-xinlocal[0]+1e-20)* |
755 | (xoutlocal[2]-xinlocal[2])/(xoutlocal[0]-xinlocal[0]+1e-20); |
756 | if (fabs(x1[2]-xinlocal[2]) > fabs(xoutlocal[2]-xinlocal[2])) |
757 | { |
758 | x1[0] = xoutlocal[0]; |
759 | x1[1] = xoutlocal[1]; |
760 | x1[2] = xoutlocal[2]; |
761 | } |
762 | dE = dEsum*(x1[2]-x0[2])/(xoutlocal[2]-xinlocal[2]); |
763 | } |
764 | |
765 | if (dE > 0){ |
766 | s_FdcAnodeTruthHits_t* ahits; |
767 | |
768 | |
769 | int mark = (chamber<<20) + (2<<10) + wire; |
770 | void** twig = getTwig(&forwardDCTree, mark); |
771 | |
772 | if (*twig == 0) |
773 | { |
774 | s_ForwardDC_t* fdc = *twig = make_s_ForwardDC(); |
775 | s_FdcChambers_t* chambers = make_s_FdcChambers(1); |
776 | s_FdcAnodeWires_t* wires = make_s_FdcAnodeWires(1); |
777 | wires->mult = 1; |
778 | wires->in[0].wire = wire; |
779 | wires->in[0].fdcAnodeTruthHits = ahits = make_s_FdcAnodeTruthHits(MAX_HITS); |
780 | chambers->mult = 1; |
781 | chambers->in[0].module = module; |
782 | chambers->in[0].layer = layer; |
783 | chambers->in[0].fdcAnodeWires = wires; |
784 | fdc->fdcChambers = chambers; |
785 | wireCount++; |
786 | } |
787 | else |
788 | { |
789 | s_ForwardDC_t* fdc = *twig; |
790 | ahits = fdc->fdcChambers->in[0].fdcAnodeWires->in[0].fdcAnodeTruthHits; |
791 | } |
792 | |
793 | |
794 | float rndno[2]; |
795 | int two=2; |
796 | |
797 | |
798 | |
799 | |
800 | |
801 | |
802 | |
803 | int one=1; |
804 | |
805 | float n_s_per_p=1.89; |
806 | |
807 | float w_eff=30.2e-9; |
808 | |
809 | float n_p_mean = dE/w_eff/(1.+n_s_per_p); |
810 | int n_p; |
811 | gpoiss_(&n_p_mean,&n_p,&one); |
812 | |
813 | |
814 | float tdrift=0; |
815 | |
816 | if (controlparams_.driftclusters==0){ |
817 | float zrange=x1[2]-x0[2]; |
818 | float tany=(x1[1]-x0[1])/zrange; |
819 | float tanx=(x1[0]-x0[0])/zrange; |
820 | float dz=ANODE_CATHODE_SPACING-dradius*sign*sinalpha; |
821 | #if 0 |
822 | dz+=wire_dz_offset[global_wire_number]; |
823 | #endif |
824 | xlocal[0]=x0[0]+tanx*dz; |
825 | if (fabs(xlocal[0]-xwire)>0.5){ |
826 | xlocal[0]=x1[0]; |
827 | xlocal[1]=x1[1]; |
828 | xlocal[2]=x1[2]; |
829 | } |
830 | else{ |
831 | xlocal[1]=x0[1]+tany*dz; |
832 | xlocal[2]=x0[2]+dz; |
833 | } |
834 | |
835 | |
836 | |
837 | |
838 | if (sqrt(xlocal[0]*xlocal[0]+xlocal[1]*xlocal[1]) |
839 | >=wire_dead_zone_radius[PackNo]){ |
840 | if (AddFDCAnodeHit(ahits,layer,ipart,track,xwire,xlocal,dE,t, |
841 | &tdrift)){ |
842 | AddFDCCathodeHits(PackNo,xwire,xlocal[1],tdrift,n_p,track,ipart, |
843 | chamber,module,layer,global_wire_number); |
844 | } |
845 | |
846 | } |
847 | } |
848 | else{ |
849 | |
850 | int n; |
851 | for (n=0;n<n_p;n++){ |
852 | |
853 | float rndno[2]; |
854 | grndm_(rndno,&two); |
855 | float dzrand=(x1[2]-x0[2])*rndno[0]; |
856 | |
857 | xlocal[0]=x0[0]+(x1[0]-x0[0])*rndno[0]; |
858 | xlocal[1]=x0[1]+(x1[1]-x0[1])*rndno[0]; |
859 | xlocal[2]=x0[2]+dzrand; |
860 | |
861 | |
862 | |
863 | if (sqrt(xlocal[0]*xlocal[0]+xlocal[1]*xlocal[1]) |
864 | >=wire_dead_zone_radius[PackNo]){ |
865 | if (AddFDCAnodeHit(ahits,layer,ipart,track,xwire,xlocal,dE,t, |
866 | &tdrift)){ |
867 | AddFDCCathodeHits(PackNo,xwire,xlocal[1],tdrift,n_p,track,ipart, |
868 | chamber,module,layer,global_wire_number); |
869 | } |
870 | } |
871 | |
872 | } |
873 | } |
874 | } |
875 | |
876 | sign*=-1; |
877 | } |
878 | } |
879 | } |
880 | |
881 | |
882 | |
883 | void hitforwarddc_(float* xin, float* xout, |
884 | float* pin, float* pout, float* dEsum, |
885 | int* track, int* stack, int* history, int* ipart) |
886 | { |
887 | hitForwardDC(xin,xout,pin,pout,*dEsum,*track,*stack,*history,*ipart); |
888 | } |
889 | |
890 | |
891 | |
892 | |
893 | s_ForwardDC_t* pickForwardDC () |
894 | { |
895 | s_ForwardDC_t* box; |
896 | s_ForwardDC_t* item; |
897 | |
898 | if ((stripCount == 0) && (wireCount == 0) && (pointCount == 0)) |
899 | { |
900 | return HDDM_NULL(void*)&hddm_s_nullTarget; |
901 | } |
902 | |
903 | box = make_s_ForwardDC(); |
904 | box->fdcChambers = make_s_FdcChambers(32); |
905 | box->fdcChambers->mult = 0; |
906 | while (item = (s_ForwardDC_t*) pickTwig(&forwardDCTree)) |
907 | { |
908 | s_FdcChambers_t* chambers = item->fdcChambers; |
909 | int module = chambers->in[0].module; |
910 | int layer = chambers->in[0].layer; |
911 | int m = box->fdcChambers->mult; |
912 | |
913 | |
914 | s_FdcAnodeWires_t* wires = chambers->in[0].fdcAnodeWires; |
915 | int wire; |
916 | s_FdcCathodeStrips_t* strips = chambers->in[0].fdcCathodeStrips; |
917 | int strip; |
918 | s_FdcTruthPoints_t* points = chambers->in[0].fdcTruthPoints; |
919 | int point; |
920 | int mok=0; |
921 | for (wire=0; wire < wires->mult; wire++) |
922 | { |
923 | s_FdcAnodeTruthHits_t* ahits = wires->in[wire].fdcAnodeTruthHits; |
924 | |
925 | |
926 | qsort(ahits->in,ahits->mult,sizeof(s_FdcAnodeTruthHit_t), |
927 | (compfn)fdc_anode_cluster_sort); |
928 | |
929 | int i,iok=0; |
930 | |
931 | if (controlparams_.driftclusters==0){ |
932 | for (iok=i=0; i < ahits->mult; i++) |
933 | { |
934 | if (ahits->in[i].dE >= THRESH_KEV/1e6) |
935 | { |
936 | if (iok < i) |
937 | { |
938 | ahits->in[iok] = ahits->in[i]; |
939 | } |
940 | ++iok; |
941 | ++mok; |
942 | } |
943 | } |
944 | } |
945 | else{ |
946 | |
947 | |
948 | |
949 | |
950 | |
951 | int num_samples=(int)FDC_TIME_WINDOW; |
952 | float *samples=(float *)malloc(num_samples*sizeof(float)); |
953 | for (i=0;i<num_samples;i++){ |
954 | samples[i]=wire_signal((float)i,ahits); |
955 | |
956 | } |
957 | |
958 | int returned_to_baseline=0; |
959 | float q=0; |
960 | for (i=0;i<num_samples;i++){ |
961 | if (samples[i]>=THRESH_ANODE){ |
962 | if (returned_to_baseline==0){ |
963 | ahits->in[iok].itrack = ahits->in[0].itrack; |
964 | ahits->in[iok].ptype = ahits->in[0].ptype; |
965 | |
966 | |
967 | |
968 | float t_array[4]; |
969 | int k; |
970 | float my_t,my_terr; |
971 | for (k=0;k<4;k++) t_array[k]=i-1+k; |
972 | polint(&samples[i-1],t_array,4,THRESH_ANODE,&my_t,&my_terr); |
973 | ahits->in[iok].t=my_t; |
974 | |
975 | returned_to_baseline=1; |
976 | iok++; |
977 | mok++; |
978 | } |
979 | q+=samples[i]; |
980 | } |
981 | if (returned_to_baseline |
982 | && (samples[i]<THRESH_ANODE)){ |
983 | returned_to_baseline=0; |
984 | } |
985 | } |
986 | free(samples); |
987 | } |
988 | |
989 | if (iok) |
990 | { |
991 | ahits->mult = iok; |
992 | } |
993 | else if (ahits != HDDM_NULL(void*)&hddm_s_nullTarget) |
994 | { |
995 | FREE(ahits)free(ahits); |
996 | } |
997 | } |
998 | if ((wires != HDDM_NULL(void*)&hddm_s_nullTarget) && (mok == 0)) |
999 | { |
1000 | FREE(wires)free(wires); |
1001 | wires = HDDM_NULL(void*)&hddm_s_nullTarget; |
1002 | } |
1003 | |
1004 | |
1005 | mok = 0; |
1006 | for (strip=0; strip < strips->mult; strip++) |
1007 | { |
1008 | s_FdcCathodeTruthHits_t* chits = strips->in[strip].fdcCathodeTruthHits; |
1009 | |
1010 | |
1011 | qsort(chits->in,chits->mult,sizeof(s_FdcCathodeTruthHit_t), |
1012 | (compfn)fdc_cathode_cluster_sort); |
1013 | |
1014 | int i,iok=0; |
1015 | |
1016 | if (controlparams_.driftclusters==0){ |
1017 | for (iok=i=0; i < chits->mult; i++) |
1018 | { |
1019 | if (chits->in[i].q >= THRESH_STRIPS) |
1020 | { |
1021 | if (iok < i) |
1022 | { |
1023 | chits->in[iok] = chits->in[i]; |
1024 | } |
1025 | ++iok; |
1026 | ++mok; |
1027 | } |
1028 | } |
1029 | |
1030 | } |
1031 | else{ |
1032 | |
1033 | |
1034 | int num_samples=(int)(FDC_TIME_WINDOW); |
1035 | float *samples=(float *)malloc(num_samples*sizeof(float)); |
1036 | for (i=0;i<num_samples;i++){ |
1037 | samples[i]=cathode_signal((float)i,chits); |
1038 | |
1039 | } |
1040 | |
1041 | int threshold_toggle=0; |
1042 | int istart=0; |
1043 | float q=0; |
1044 | int FADC_BIN_SIZE=1; |
1045 | for (i=0;i<num_samples;i+=FADC_BIN_SIZE){ |
1046 | if (samples[i]>=THRESH_STRIPS){ |
1047 | if (threshold_toggle==0){ |
1048 | chits->in[iok].itrack = chits->in[0].itrack; |
1049 | chits->in[iok].ptype = chits->in[0].ptype; |
1050 | chits->in[iok].t=(float) i; |
1051 | |
1052 | istart=i-1; |
1053 | threshold_toggle=1; |
1054 | |
1055 | |
1056 | } |
1057 | } |
1058 | if (threshold_toggle && |
1059 | (samples[i]<THRESH_STRIPS)){ |
1060 | int j; |
1061 | |
1062 | for (j=istart+1;j<i-1;j++){ |
1063 | if (samples[j]>samples[j-1] && samples[j]>samples[j+1]){ |
1064 | chits->in[iok].q=samples[j]; |
1065 | break; |
1066 | } |
1067 | } |
1068 | threshold_toggle=0; |
1069 | iok++; |
1070 | mok++; |
1071 | |
1072 | } |
1073 | } |
1074 | i=num_samples-1; |
1075 | if (samples[i]>=THRESH_STRIPS&&threshold_toggle){ |
1076 | int j; |
1077 | for (j=istart+1;j<i-1;j++){ |
1078 | if (samples[j]>samples[j-1] && samples[j]>samples[j+1]){ |
1079 | chits->in[iok].q=samples[j]; |
1080 | break; |
1081 | } |
1082 | } |
1083 | } |
1084 | |
1085 | free(samples); |
1086 | } |
1087 | |
1088 | if (iok) |
1089 | { |
1090 | chits->mult = iok; |
1091 | |
1092 | } |
1093 | else if (chits != HDDM_NULL(void*)&hddm_s_nullTarget) |
1094 | { |
1095 | FREE(chits)free(chits); |
1096 | } |
1097 | |
1098 | } |
1099 | if ((strips != HDDM_NULL(void*)&hddm_s_nullTarget) && (mok == 0)) |
1100 | { |
1101 | FREE(strips)free(strips); |
1102 | strips = HDDM_NULL(void*)&hddm_s_nullTarget; |
1103 | } |
1104 | |
1105 | if ((wires != HDDM_NULL(void*)&hddm_s_nullTarget) || |
1106 | (strips != HDDM_NULL(void*)&hddm_s_nullTarget) || |
1107 | (points != HDDM_NULL(void*)&hddm_s_nullTarget)) |
1108 | { |
1109 | if ((m == 0) || (module > box->fdcChambers->in[m-1].module) |
1110 | || (layer > box->fdcChambers->in[m-1].layer)) |
1111 | { |
1112 | box->fdcChambers->in[m] = chambers->in[0]; |
1113 | |
1114 | box->fdcChambers->in[m].fdcCathodeStrips = |
1115 | make_s_FdcCathodeStrips(stripCount); |
1116 | box->fdcChambers->in[m].fdcAnodeWires = |
1117 | make_s_FdcAnodeWires(wireCount); |
1118 | box->fdcChambers->in[m].fdcTruthPoints = |
1119 | make_s_FdcTruthPoints(pointCount); |
1120 | box->fdcChambers->mult++; |
1121 | } |
1122 | else |
1123 | { |
1124 | m--; |
1125 | } |
1126 | for (strip=0; strip < strips->mult; ++strip) |
1127 | { |
1128 | int mm = box->fdcChambers->in[m].fdcCathodeStrips->mult++; |
1129 | box->fdcChambers->in[m].fdcCathodeStrips->in[mm] = strips->in[strip]; |
1130 | } |
1131 | if (strips != HDDM_NULL(void*)&hddm_s_nullTarget) |
1132 | { |
1133 | FREE(strips)free(strips); |
1134 | } |
1135 | for (wire=0; wire < wires->mult; ++wire) |
1136 | { |
1137 | int mm = box->fdcChambers->in[m].fdcAnodeWires->mult++; |
1138 | box->fdcChambers->in[m].fdcAnodeWires->in[mm] = wires->in[wire]; |
1139 | } |
1140 | if (wires != HDDM_NULL(void*)&hddm_s_nullTarget) |
1141 | { |
1142 | FREE(wires)free(wires); |
1143 | } |
1144 | for (point=0; point < points->mult; ++point) |
1145 | { |
1146 | int mm = box->fdcChambers->in[m].fdcTruthPoints->mult++; |
1147 | box->fdcChambers->in[m].fdcTruthPoints->in[mm] = points->in[point]; |
1148 | } |
1149 | if (points != HDDM_NULL(void*)&hddm_s_nullTarget) |
1150 | { |
1151 | FREE(points)free(points); |
1152 | } |
1153 | } |
1154 | FREE(chambers)free(chambers); |
1155 | FREE(item)free(item); |
1156 | } |
1157 | |
1158 | stripCount = wireCount = pointCount = 0; |
1159 | |
1160 | if ((box->fdcChambers != HDDM_NULL(void*)&hddm_s_nullTarget) && |
1161 | (box->fdcChambers->mult == 0)) |
1162 | { |
1163 | FREE(box->fdcChambers)free(box->fdcChambers); |
1164 | box->fdcChambers = HDDM_NULL(void*)&hddm_s_nullTarget; |
1165 | } |
1166 | if (box->fdcChambers->mult == 0) |
1167 | { |
1168 | FREE(box)free(box); |
1169 | box = HDDM_NULL(void*)&hddm_s_nullTarget; |
1170 | } |
1171 | return box; |
1172 | } |