Bug Summary

File:programs/Simulation/HDGeant/hitFDC.c
Location:line 1063, column 9
Description:The right operand of '>' is a garbage value

Annotated Source Code

1/*
2 * hitFDC - registers hits for forward drift chambers
3 *
4 * This is a part of the hits package for the
5 * HDGeant simulation program for Hall D.
6 *
7 * version 1.0 -Richard Jones July 16, 2001
8 *
9 * changes: Wed Jun 20 13:19:56 EDT 2007 B. Zihlmann
10 * add ipart to the function hitForwardDC
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"
22extern s_HDDM_t* thisInputEvent;
23extern double asic_response(double t);
24extern double Ei(double x);
25
26typedef struct{
27 int writeenohits;
28 int showersincol;
29 int driftclusters;
30}controlparams_t;
31
32extern controlparams_t controlparams_;
33
34
35const float wire_dead_zone_radius[4]={3.0,3.0,3.9,3.9};
36const 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// Drift speed 2.2cm/us is appropriate for a 90/10 Argon/Methane mixture
41static float DRIFT_SPEED =.0055;
42static float ACTIVE_AREA_OUTER_RADIUS =48.5;
43static float ANODE_CATHODE_SPACING =0.5;
44static float TWO_HIT_RESOL =1.;
45static int WIRES_PER_PLANE =96;
46static float WIRE_SPACING =1.0;
47static float U_OF_WIRE_ZERO =0;//(-((WIRES_PER_PLANE-1.)*WIRE_SPACING)/2)
48static float STRIPS_PER_PLANE =192;
49static float STRIP_SPACING =0.5;
50static float U_OF_STRIP_ZERO =0;// (-((STRIPS_PER_PLANE-1.)*STRIP_SPACING)/2)
51static float STRIP_GAP =0.1;
52static int MAX_HITS =100;
53static float K2 =1.15;
54static float STRIP_NODES = 3;
55static float THRESH_KEV =1. ;
56static float THRESH_ANODE = 1.;
57static float THRESH_STRIPS =5. ; /* pC */
58static float ELECTRON_CHARGE =1.6022e-4; /* fC */
59static float DIFFUSION_COEFF = 1.1e-6; // cm^2/s --> 200 microns at 1 cm
60static float FDC_TIME_WINDOW = 1000.0; //time window for accepting FDC hits, ns
61static float GAS_GAIN = 8e4;
62
63
64#if 0
65static float wire_dx_offset[2304];
66static float wire_dz_offset[2304];
67#endif
68
69binTree_t* forwardDCTree = 0;
70static int stripCount = 0;
71static int wireCount = 0;
72static int pointCount = 0;
73static int initializedx=0;
74
75void gpoiss_(float*,int*,const int*); // avoid solaris compiler warnings
76void rnorml_(float*,int*);
77
78typedef int (*compfn)(const void*, const void*);
79
80// Sort functions for sorting clusters
81int 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}
88int 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// Locate a position in array xx given x
99void 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// Polynomial interpolation on a grid.
119// Adapted from Numerical Recipes in C (2nd Edition), pp. 121-122.
120void 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++){
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++){
139 for (i=1;i<=n-m;i++){
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;
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// Simulation of signal on a wire
158double wire_signal(double t,s_FdcAnodeTruthHits_t* ahits){
159 double t0=1.0; // ns; rough order of magnitude
160 int m;
161 double asic_gain=0.76; // mV/fC
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// Simulation of signal on a cathode strip (ASIC output)
173double cathode_signal(double t,s_FdcCathodeTruthHits_t* chits){
174 double t0=1.0; // ns; rough order of magnitude
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// Generate hits in two cathode planes flanking the wire plane
188void 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 // Anode charge
195 float q_anode;
196 int n_t;
197 // Average number of secondary ion pairs for 40/60 Ar/CO2 mixture
198 float n_s_per_p=1.89;
199 if (controlparams_.driftclusters==0){
200 /* Total number of ion pairs. On average for each primary ion
201 pair produced there are n_s secondary ion pairs produced. The
202 probability distribution is a compound poisson distribution
203 that requires generating two Poisson variables.
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 // Distribute the number of secondary ionizations for this primary
213 // ionization according to a Poisson distribution with mean n_s_over_p.
214 // For simplicity we assume these secondary electrons and the primary
215 // electron stay together as a cluster.
216 int n_s;
217 int one=1;
218 gpoiss_(&n_s_per_p,&n_s,&one);
219 // Anode charge in units of fC
220 n_t=1+n_s;
221 q_anode=GAS_GAIN*ELECTRON_CHARGE*((float)n_t);
222 }
223
224 /* Mock-up of cathode strip charge distribution */
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 /* Induce charge on the strips according to the Mathieson
241 function tuned to results from FDC prototype
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 /* Throw away hits on strips falling within a certain dead-zone
252 radius */
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 // To cut down on the number of output clusters, combine
289 // those that would be indistiguishable in time given the
290 // expected timing resolution
291 if (fabs(chits->in[nhit].t - tdrift) <TWO_HIT_RESOL)
292 {
293 break;
294 }
295 }
296 if (nhit < chits->mult) /* merge with former hit */
297 {
298 /* Use the time from the earlier hit but add the charge */
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){ /* create new hit */
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 // supress warning
315 /*
316 fprintf(stderr,"HDGeant error in hitForwardDC: ");
317 fprintf(stderr,"max hit count %d exceeded, truncating!\n",
318 MAX_HITS);
319 */
320 }
321
322 }
323 } // loop over cathode strips
324 } // loop over cathode views
325}
326
327
328
329
330
331
332
333
334
335// Add wire information
336int 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 // Generate 2 random numbers from a Gaussian distribution
340 //
341 float rndno[2];
342 int two=2;
343
344 // Only and always use the built-in Geant random generator,
345 // otherwise debugging is a problem because sequences are not
346 // reproducible from a given pair of random seeds. [rtj]
347
348 /* rnorml_(rndno,&two); */ {
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 // Get the magnetic field at this cluster position
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 // Find the angle between the wire direction and the direction of the
363 // magnetic field in the x-y plane
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 // useful combinations of dx and dz
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 // Next compute the avalanche position along wire.
381 // Correct avalanche position with deflection along wire due to
382 // Lorentz force.
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 // Add transverse diffusion
387 xyz[1]+=(( 0.01 )*pow(dx2+dz2,0.125)+( 0.0061 )*dx2)*rndno[1];
388
389 // Do not use this cluster if the Lorentz force would deflect
390 // the electrons outside the active region of the detector
391 if (sqrt(xyz[1]*xyz[1]+xwire*xwire)>ACTIVE_AREA_OUTER_RADIUS)
392 return 0;
393
394 // Model the drift time and longitudinal diffusion as a function of
395 // position of the cluster within the cell
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 // Only allow deviations to longer times if near the cell border
401 double dradius=sqrt(dx2+dz2);
402 if (dradius-0.5>=0. && dt<0){
403 dt=0.;
404 }
405
406 // Minimum drift time for docas near wire (very crude approximation)
407 double v_max=0.08; // guess for now based on Garfield, near wire
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 // Avalanche time
415 *tdrift=t+tdrift_smeared;
416
417 // Skip cluster if the time would go beyond readout window
418 if (t>FDC_TIME_WINDOW) return 0;
419
420 int nhit;
421
422 // Record the anode hit
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) /* merge with former hit */
431 {
432 /* use the time from the earlier hit but add the energy */
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 /*ahits->in[nhit].t =
444 (ahits->in[nhit].t * ahits->in[nhit].dE + tdrift * dE)
445 / (ahits->in[nhit].dE += dE);
446 */
447 }
448 else if (nhit < MAX_HITS) /* create new hit */
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/* register hits during tracking (from gustep) */
468
469void 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 // Get parameters related to the geometry and the signals
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 //printf("%d %s %f\n",i,strings[i].str,values[i]);
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 /* Get chamber information */
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 //int module = getmodule_();
598 //int chamber = (module*10)+layer;
599 //int PackNo = (chamber-11)/20;
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 // transform layer number into Richard's scheme
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 // Check that wire numbers are not out of range
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 // Make sure at least one wire number is valid
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 /* Make a fuzzy boundary around the forward dead region
662 * by killing any track segment whose midpoint is within the boundary */
663
664 if (sqrt(xlocal[0]*xlocal[0]+xlocal[1]*xlocal[1])
665 < wire_dead_zone_radius[PackNo])
666 {
667 return;
668 }
669
670 /* post the hit to the truth tree */
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 /* post the hit to the hits tree, mark cell as hit */
711
712 if (dEsum > 0)
713 {
714 float sign=1.; // for dealing with the y-position for tracks crossing two cells
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 // Create (or grab) an entry in the tree for the anode wire
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 // Find the number of primary ion pairs:
798 /* The total number of ion pairs depends on the energy deposition
799 and the effective average energy to produce a pair, w_eff.
800 On average for each primary ion pair produced there are n_s_per_p
801 secondary ion pairs produced.
802 */
803 int one=1;
804 // Average number of secondary ion pairs for 40/60 Ar/CO2 mixture
805 float n_s_per_p=1.89;
806 //Average energy needed to produce an ion pair for 50/50 mixture
807 float w_eff=30.2e-9; // GeV
808 // Average number of primary ion pairs
809 float n_p_mean = dE/w_eff/(1.+n_s_per_p);
810 int n_p; // number of primary ion pairs
811 gpoiss_(&n_p_mean,&n_p,&one);
812
813 // Drift time
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 /* If the cluster position is within the wire-deadened region of the
836 detector, skip this cluster
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 // Loop over the number of primary ion pairs
850 int n;
851 for (n=0;n<n_p;n++){
852 // Generate a cluster at a random position along the path with cell
853 float rndno[2];
854 grndm_(rndno,&two);
855 float dzrand=(x1[2]-x0[2])*rndno[0];
856 // Position of the cluster
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 /* If the cluster position is within the wire-deadened region of the
861 detector, skip this cluster
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 } // loop over primary ion pairs
873 }
874 } // Check for non-zero energy
875
876 sign*=-1; // for dealing with the y-position for tracks crossing two cells
877 } // loop over wires
878 } // Check that total energy deposition is not zero
879}
880
881/* entry points from fortran */
882
883void 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/* pick and package the hits for shipping */
892
893s_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))
1
Loop condition is true. Entering loop body
5
Loop condition is true. Entering loop body
9
Loop condition is true. Entering loop body
13
Loop condition is true. Entering loop body
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 /* compress out the hits below threshold */
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++)
2
Loop condition is false. Execution continues on line 998
6
Loop condition is false. Execution continues on line 998
10
Loop condition is false. Execution continues on line 998
14
Loop condition is false. Execution continues on line 998
922 {
923 s_FdcAnodeTruthHits_t* ahits = wires->in[wire].fdcAnodeTruthHits;
924
925 // Sort the clusters by time
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{ // Simulate clusters within the cell
946
947 // printf("-------------\n");
948
949
950 // Temporary histogram in 1 ns bins to store waveform data
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 //printf("%f %f\n",(float)i,samples[i]);
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 // Do an interpolation to find the time at which the threshold
967 // was crossed.
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 } // Simulation of clusters within cell
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++)
3
Loop condition is false. Execution continues on line 1099
7
Loop condition is false. Execution continues on line 1099
11
Loop condition is false. Execution continues on line 1099
15
Loop condition is true. Entering loop body
1007 {
1008 s_FdcCathodeTruthHits_t* chits = strips->in[strip].fdcCathodeTruthHits;
1009
1010 // Sort the clusters by time
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){
16
Taking false branch
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 // Temporary histogram in 1 ns bins to store waveform data
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++){
17
Loop condition is true. Entering loop body
18
Loop condition is true. Entering loop body
19
Loop condition is true. Entering loop body
20
Loop condition is false. Execution continues on line 1041
1037 samples[i]=cathode_signal((float)i,chits);
1038 //printf("t %f V %f\n",(float)i,samples[i]);
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){
21
Loop condition is true. Entering loop body
25
Loop condition is true. Entering loop body
28
Loop condition is true. Entering loop body
1046 if (samples[i]>=THRESH_STRIPS){
22
Taking true branch
26
Taking false branch
29
Taking false branch
1047 if (threshold_toggle==0){
23
Taking true branch
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 //chits->in[iok].q=samples[i];
1052 istart=i-1;
1053 threshold_toggle=1;
1054 //iok++;
1055 //mok++;
1056 }
1057 }
1058 if (threshold_toggle &&
24
Taking false branch
27
Taking false branch
30
Taking true branch
1059 (samples[i]<THRESH_STRIPS)){
1060 int j;
1061 // Find the first peak
1062 for (j=istart+1;j<i-1;j++){
31
Loop condition is true. Entering loop body
1063 if (samples[j]>samples[j-1] && samples[j]>samples[j+1]){
32
The right operand of '>' is a garbage value
1064 chits->in[iok].q=samples[j];
1065 break;
1066 }
1067 }
1068 threshold_toggle=0;
1069 iok++;
1070 mok++;
1071 //break;
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 }// Simulate clusters within cell
1087
1088 if (iok)
1089 {
1090 chits->mult = iok;
1091 //chits->mult=1;
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) ||
4
Taking false branch
8
Taking false branch
12
Taking false branch
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}