00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #include <stdlib.h>
00014 #include <stdio.h>
00015 #include <math.h>
00016
00017 #include <hddm_s.h>
00018 #include <geant3.h>
00019 #include <bintree.h>
00020
00021 #include "calibDB.h"
00022 extern s_HDDM_t* thisInputEvent;
00023 extern double asic_response(double t);
00024 extern double Ei(double x);
00025
00026 typedef struct{
00027 int writeenohits;
00028 int showersincol;
00029 int driftclusters;
00030 }controlparams_t;
00031
00032 extern controlparams_t controlparams_;
00033
00034
00035 const float wire_dead_zone_radius[4]={3.0,3.0,3.9,3.9};
00036 const float strip_dead_zone_radius[4]={1.3,1.3,1.3,1.3};
00037
00038 #define CATHODE_ROT_ANGLE 1.309 // 75 degrees
00039
00040
00041 static float DRIFT_SPEED =.0055;
00042 static float ACTIVE_AREA_OUTER_RADIUS =48.5;
00043 static float ANODE_CATHODE_SPACING =0.5;
00044 static float TWO_HIT_RESOL =25.;
00045 static int WIRES_PER_PLANE =96;
00046 static float WIRE_SPACING =1.0;
00047 static float U_OF_WIRE_ZERO =0;
00048 static float STRIPS_PER_PLANE =192;
00049 static float STRIP_SPACING =0.5;
00050 static float U_OF_STRIP_ZERO =0;
00051 static float STRIP_GAP =0.1;
00052 static int MAX_HITS =100;
00053 static float K2 =1.15;
00054 static float STRIP_NODES = 3;
00055 static float THRESH_KEV =1. ;
00056 static float THRESH_ANODE = 1.;
00057 static float THRESH_STRIPS =5. ;
00058 static float ELECTRON_CHARGE =1.6022e-4;
00059 static float DIFFUSION_COEFF = 1.1e-6;
00060 static float FDC_TIME_WINDOW = 1000.0;
00061 static float GAS_GAIN = 8e4;
00062
00063
00064 #if 0
00065 static float wire_dx_offset[2304];
00066 static float wire_dz_offset[2304];
00067 #endif
00068
00069 binTree_t* forwardDCTree = 0;
00070 static int stripCount = 0;
00071 static int wireCount = 0;
00072 static int pointCount = 0;
00073 static int initializedx=0;
00074
00075 void gpoiss_(float*,int*,const int*);
00076 void rnorml_(float*,int*);
00077
00078 typedef int (*compfn)(const void*, const void*);
00079
00080
00081 int fdc_anode_cluster_sort(const void *a,const void *b){
00082 const s_FdcAnodeTruthHit_t *ca=a;
00083 const s_FdcAnodeTruthHit_t *cb=b;
00084 if (ca->t<cb->t) return -1;
00085 else if (ca->t>cb->t) return 1;
00086 else return 0;
00087 }
00088 int fdc_cathode_cluster_sort(const void *a,const void *b){
00089 const s_FdcCathodeTruthHit_t *ca=a;
00090 const s_FdcCathodeTruthHit_t *cb=b;
00091 if (ca->t<cb->t) return -1;
00092 else if (ca->t>cb->t) return 1;
00093 else return 0;
00094 }
00095
00096
00097
00098
00099 void locate(float *xx,int n,float x,int *j){
00100 int ju,jm,jl;
00101 int ascnd;
00102
00103 jl=-1;
00104 ju=n;
00105 ascnd=(xx[n-1]>=xx[0]);
00106 while(ju-jl>1){
00107 jm=(ju+jl)>>1;
00108 if (x>=xx[jm]==ascnd)
00109 jl=jm;
00110 else
00111 ju=jm;
00112 }
00113 if (x==xx[0]) *j=0;
00114 else if (x==xx[n-1]) *j=n-2;
00115 else *j=jl;
00116 }
00117
00118
00119
00120 void polint(float *xa, float *ya,int n,float x, float *y,float *dy){
00121 int i,m,ns=0;
00122 float den,dif,dift,ho,hp,w;
00123
00124 float *c=(float *)calloc(n,sizeof(float));
00125 float *d=(float *)calloc(n,sizeof(float));
00126
00127 dif=fabs(x-xa[0]);
00128 for (i=0;i<n;i++){
00129 if ((dift=fabs(x-xa[i]))<dif){
00130 ns=i;
00131 dif=dift;
00132 }
00133 c[i]=ya[i];
00134 d[i]=ya[i];
00135 }
00136 *y=ya[ns--];
00137
00138 for (m=1;m<n;m++){
00139 for (i=1;i<=n-m;i++){
00140 ho=xa[i-1]-x;
00141 hp=xa[i+m-1]-x;
00142 w=c[i+1-1]-d[i-1];
00143 if ((den=ho-hp)==0.0) {
00144 free(c);
00145 free(d);
00146 return;
00147 }
00148
00149 den=w/den;
00150 d[i-1]=hp*den;
00151 c[i-1]=ho*den;
00152
00153 }
00154
00155 *y+=(*dy=(2*ns<(n-m) ?c[ns+1]:d[ns--]));
00156 }
00157 free(c);
00158 free(d);
00159 }
00160
00161
00162 double wire_signal(double t,s_FdcAnodeTruthHits_t* ahits){
00163 double t0=1.0;
00164 int m;
00165 double asic_gain=0.76;
00166 double func=0;
00167 for (m=0;m<ahits->mult;m++){
00168 if (t>ahits->in[m].t){
00169 double my_time=t-ahits->in[m].t;
00170 func+=asic_gain*ahits->in[m].dE*asic_response(my_time);
00171 }
00172 }
00173 return func;
00174 }
00175
00176
00177 double cathode_signal(double t,s_FdcCathodeTruthHits_t* chits){
00178 double t0=1.0;
00179 int m;
00180 double asic_gain=2.3;
00181 double func=0;
00182 for (m=0;m<chits->mult;m++){
00183 if (t>chits->in[m].t){
00184 double my_time=t-chits->in[m].t;
00185 func+=asic_gain*chits->in[m].q*asic_response(my_time);
00186 }
00187 }
00188 return func;
00189 }
00190
00191
00192 void AddFDCCathodeHits(int PackNo,float xwire,float avalanche_y,float tdrift,
00193 int n_p,int track,int ipart,int chamber,int module,
00194 int layer, int global_wire_number){
00195
00196 s_FdcCathodeTruthHits_t* chits;
00197
00198
00199 float q_anode;
00200 int n_t;
00201
00202 float n_s_per_p=1.89;
00203 if (controlparams_.driftclusters==0){
00204
00205
00206
00207
00208
00209 int n_s,one=1;
00210 float n_s_mean = ((float)n_p)*n_s_per_p;
00211 gpoiss_(&n_s_mean,&n_s,&one);
00212 n_t = n_s+n_p;
00213 q_anode=((float)n_t)*GAS_GAIN*ELECTRON_CHARGE;
00214 }
00215 else{
00216
00217
00218
00219
00220 int n_s;
00221 int one=1;
00222 gpoiss_(&n_s_per_p,&n_s,&one);
00223
00224 n_t=1+n_s;
00225 q_anode=GAS_GAIN*ELECTRON_CHARGE*((float)n_t);
00226 }
00227
00228
00229 int plane, node;
00230 for (plane=1; plane<4; plane+=2){
00231 float theta = (plane == 1)? -CATHODE_ROT_ANGLE : +CATHODE_ROT_ANGLE;
00232 float cathode_u = xwire*cos(theta)+avalanche_y*sin(theta);
00233 int strip1 = ceil((cathode_u-U_OF_STRIP_ZERO)/STRIP_SPACING +0.5);
00234 float cathode_u1 = (strip1-1)*STRIP_SPACING + U_OF_STRIP_ZERO;
00235 float delta = cathode_u-cathode_u1;
00236 float half_gap=ANODE_CATHODE_SPACING;
00237
00238 #if 0
00239 half_gap+=(plane==1)?+wire_dz_offset[global_wire_number]:
00240 -wire_dz_offset[global_wire_number];
00241 #endif
00242
00243 for (node=-STRIP_NODES; node<=STRIP_NODES; node++){
00244
00245
00246
00247 float lambda1=(((float)node-0.5)*STRIP_SPACING+STRIP_GAP/2.
00248 -delta)/half_gap;
00249 float lambda2=(((float)node+0.5)*STRIP_SPACING-STRIP_GAP/2.
00250 -delta)/half_gap;
00251 float factor=0.25*M_PI*K2;
00252 float q = 0.25*q_anode*(tanh(factor*lambda2)-tanh(factor*lambda1));
00253
00254 int strip = strip1+node;
00255
00256
00257 float strip_outer_u=cathode_u1
00258 +(STRIP_SPACING+STRIP_GAP/2.)*(int)node;
00259 float cathode_v=-xwire*sin(theta)+avalanche_y*cos(theta);
00260 float check_radius=sqrt(strip_outer_u*strip_outer_u
00261 +cathode_v*cathode_v);
00262
00263 if ((strip > 0)
00264 && (check_radius>strip_dead_zone_radius[PackNo])
00265 && (strip <= STRIPS_PER_PLANE)){
00266 int mark = (chamber<<20) + (plane<<10) + strip;
00267 void** cathodeTwig = getTwig(&forwardDCTree, mark);
00268 if (*cathodeTwig == 0){
00269 s_ForwardDC_t* fdc = *cathodeTwig = make_s_ForwardDC();
00270 s_FdcChambers_t* chambers = make_s_FdcChambers(1);
00271 s_FdcCathodeStrips_t* strips = make_s_FdcCathodeStrips(1);
00272 strips->mult = 1;
00273 strips->in[0].plane = plane;
00274 strips->in[0].strip = strip;
00275 strips->in[0].fdcCathodeTruthHits = chits
00276 = make_s_FdcCathodeTruthHits(MAX_HITS);
00277 chambers->mult = 1;
00278 chambers->in[0].module = module;
00279 chambers->in[0].layer = layer;
00280 chambers->in[0].fdcCathodeStrips = strips;
00281 fdc->fdcChambers = chambers;
00282 stripCount++;
00283 }
00284 else{
00285 s_ForwardDC_t* fdc = *cathodeTwig;
00286 chits = fdc->fdcChambers->in[0].fdcCathodeStrips
00287 ->in[0].fdcCathodeTruthHits;
00288 }
00289
00290 int nhit;
00291 for (nhit = 0; nhit < chits->mult; nhit++){
00292
00293
00294
00295 if (fabs(chits->in[nhit].t - tdrift) <TWO_HIT_RESOL)
00296 {
00297 break;
00298 }
00299 }
00300 if (nhit < chits->mult)
00301 {
00302
00303 chits->in[nhit].q += q;
00304 if(chits->in[nhit].t>tdrift){
00305 chits->in[nhit].t = tdrift;
00306 chits->in[nhit].itrack = track;
00307 chits->in[nhit].ptype = ipart;
00308 }
00309 }
00310 else if (nhit < MAX_HITS){
00311 chits->in[nhit].t = tdrift;
00312 chits->in[nhit].q = q;
00313 chits->in[nhit].itrack = track;
00314 chits->in[nhit].ptype = ipart;
00315 chits->mult++;
00316 }
00317 else{
00318
00319
00320
00321
00322
00323
00324 }
00325
00326 }
00327 }
00328 }
00329 }
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340 int AddFDCAnodeHit(s_FdcAnodeTruthHits_t* ahits,int layer,int ipart,int track,
00341 float xwire,float xyz[3],float dE,float t,float *tdrift){
00342
00343
00344
00345 float rndno[2];
00346 int two=2;
00347
00348
00349
00350
00351
00352 {
00353 float rho,phi1;
00354 grndm_(rndno,&two);
00355 rho = sqrt(-2*log(rndno[0]));
00356 phi1 = rndno[1]*2*M_PI;
00357 rndno[0] = rho*cos(phi1);
00358 rndno[1] = rho*sin(phi1);
00359 }
00360
00361
00362 float x[3],B[3];
00363 transformCoord(xyz,"local",x,"global");
00364 gufld_db_(x,B);
00365
00366
00367
00368 float wire_dir[2];
00369 float wire_theta=1.0472*(float)((layer%3)-1);
00370 float phi=0.;;
00371 float Br=sqrt(B[0]*B[0]+B[1]*B[1]);
00372
00373 wire_dir[0]=sin(wire_theta);
00374 wire_dir[1]=cos(wire_theta);
00375 if (Br>0.) phi= acos((B[0]*wire_dir[0]+B[1]*wire_dir[1])/Br);
00376
00377
00378 float dx=xyz[0]-xwire;
00379 float dx2=dx*dx;
00380 float dx4=dx2*dx2;
00381 float dz2=xyz[2]*xyz[2];
00382 float dz4=dz2*dz2;
00383
00384
00385
00386
00387 xyz[1]+=( 0.1458*B[2]*(1.-0.048*Br) )*dx
00388 +( 0.1717+0.01227*B[2] )*(Br*cos(phi))*xyz[2]
00389 +( -0.000176 )*dx*dx2/(dz2+0.001);
00390
00391 xyz[1]+=(( 0.01 )*pow(dx2+dz2,0.125)+( 0.0061 )*dx2)*rndno[1];
00392
00393
00394
00395 if (sqrt(xyz[1]*xyz[1]+xwire*xwire)>ACTIVE_AREA_OUTER_RADIUS)
00396 return 0;
00397
00398
00399
00400 float tdrift_unsmeared=( 1086.0-106.7*B[2] )*dx2+( 1068.0 )*dz2
00401 +dx4*(( -2.675 )/(dz2+0.001)+( 2.4e4 )*dz2);
00402 float dt=(( 39.44 )*dx4/(0.5-dz2)+( 56.0 )*dz4/(0.5-dx2)
00403 +( 0.01566 )*dx4/(dz4+0.002)/(0.251-dx2))*rndno[1];
00404
00405 double dradius=sqrt(dx2+dz2);
00406 if (dradius-0.5>=0. && dt<0){
00407 dt=0.;
00408 }
00409
00410
00411 double v_max=0.08;
00412 double tmin=dradius/v_max;
00413 double tdrift_smeared=tdrift_unsmeared+dt;
00414 if (tdrift_smeared<tmin){
00415 tdrift_smeared=tmin;
00416 }
00417
00418
00419 *tdrift=t+tdrift_smeared;
00420
00421
00422 if (t>FDC_TIME_WINDOW) return 0;
00423
00424 int nhit;
00425
00426
00427 for (nhit = 0; nhit < ahits->mult; nhit++)
00428 {
00429 if (fabs(ahits->in[nhit].t - *tdrift) < TWO_HIT_RESOL)
00430 {
00431 break;
00432 }
00433 }
00434 if (nhit < ahits->mult)
00435 {
00436
00437 ahits->in[nhit].dE += dE;
00438 if(ahits->in[nhit].t>*tdrift){
00439 ahits->in[nhit].t = *tdrift;
00440 ahits->in[nhit].t_unsmeared=tdrift_unsmeared;
00441 ahits->in[nhit].d = sqrt(dx2+dz2);
00442
00443 ahits->in[nhit].itrack = track;
00444 ahits->in[nhit].ptype = ipart;
00445 }
00446
00447
00448
00449
00450
00451 }
00452 else if (nhit < MAX_HITS)
00453 {
00454 ahits->in[nhit].t = *tdrift;
00455 ahits->in[nhit].t_unsmeared=tdrift_unsmeared;
00456 ahits->in[nhit].dE = dE;
00457 ahits->in[nhit].d = sqrt(dx2+dz2);
00458 ahits->in[nhit].itrack = track;
00459 ahits->in[nhit].ptype = ipart;
00460 ahits->mult++;
00461 }
00462 else
00463 {
00464 fprintf(stderr,"HDGeant error in hitForwardDC: ");
00465 fprintf(stderr,"max hit count %d exceeded, truncating!\n",MAX_HITS);
00466 }
00467
00468 return 1;
00469 }
00470
00471
00472
00473 void hitForwardDC (float xin[4], float xout[4],
00474 float pin[5], float pout[5], float dEsum,
00475 int track, int stack, int history, int ipart)
00476 {
00477 float x[3], t;
00478 float dx[3], dr;
00479 float dEdx;
00480 float xlocal[3];
00481 float xinlocal[3];
00482 float xoutlocal[3];
00483 float dradius;
00484 float alpha,sinalpha,cosalpha;
00485 int i,j;
00486
00487 if (!initializedx){
00488 mystr_t strings[250];
00489 float values[250];
00490 int nvalues = 250;
00491
00492
00493 int status = GetConstants("FDC/fdc_parms", &nvalues,values,strings);
00494 if (!status) {
00495 int ncounter = 0;
00496 int i;
00497 for ( i=0;i<(int)nvalues;i++){
00498
00499 if (!strcmp(strings[i].str,"FDC_DRIFT_SPEED")) {
00500 DRIFT_SPEED = values[i];
00501 ncounter++;
00502 }
00503 if (!strcmp(strings[i].str,"FDC_ACTIVE_AREA_OUTER_RADIUS")) {
00504 ACTIVE_AREA_OUTER_RADIUS = values[i];
00505 ncounter++;
00506 }
00507 if (!strcmp(strings[i].str,"FDC_ANODE_CATHODE_SPACING")) {
00508 ANODE_CATHODE_SPACING = values[i];
00509 ncounter++;
00510 }
00511 if (!strcmp(strings[i].str,"FDC_TWO_HIT_RESOL")) {
00512 TWO_HIT_RESOL = values[i];
00513 ncounter++;
00514 }
00515 if (!strcmp(strings[i].str,"FDC_WIRES_PER_PLANE")) {
00516 WIRES_PER_PLANE = values[i];
00517 ncounter++;
00518 }
00519 if (!strcmp(strings[i].str,"FDC_WIRE_SPACING")) {
00520 WIRE_SPACING = values[i];
00521 ncounter++;
00522 }
00523 if (!strcmp(strings[i].str,"FDC_STRIPS_PER_PLANE")) {
00524 STRIPS_PER_PLANE = values[i];
00525 ncounter++;
00526 }
00527 if (!strcmp(strings[i].str,"FDC_STRIP_SPACING")) {
00528 STRIP_SPACING = values[i];
00529 ncounter++;
00530 }
00531 if (!strcmp(strings[i].str,"FDC_STRIP_GAP")) {
00532 STRIP_GAP = values[i];
00533 ncounter++;
00534 }
00535 if (!strcmp(strings[i].str,"FDC_MAX_HITS")) {
00536 MAX_HITS = values[i];
00537 ncounter++;
00538 }
00539 if (!strcmp(strings[i].str,"FDC_K2")) {
00540 K2 = values[i];
00541 ncounter++;
00542 }
00543 if (!strcmp(strings[i].str,"FDC_STRIP_NODES")) {
00544 STRIP_NODES = values[i];
00545 ncounter++;
00546 }
00547 if (!strcmp(strings[i].str,"FDC_THRESH_KEV")) {
00548 THRESH_KEV = values[i];
00549 ncounter++;
00550 }
00551 if (!strcmp(strings[i].str,"FDC_THRESH_STRIPS")) {
00552 THRESH_STRIPS = values[i];
00553 ncounter++;
00554 }
00555 if (!strcmp(strings[i].str,"FDC_ELECTRON_CHARGE")) {
00556 ELECTRON_CHARGE = values[i];
00557 ncounter++;
00558 }
00559 if (!strcmp(strings[i].str,"FDC_DIFFUSION_COEFF")) {
00560 DIFFUSION_COEFF = values[i];
00561 ncounter++;
00562 }
00563 }
00564 U_OF_WIRE_ZERO = (-((WIRES_PER_PLANE-1.)*WIRE_SPACING)/2);
00565 U_OF_STRIP_ZERO = (-((STRIPS_PER_PLANE-1.)*STRIP_SPACING)/2);
00566
00567 if (ncounter==16){
00568 printf("FDC: ALL parameters loaded from Data Base\n");
00569 } else if (ncounter<16){
00570 printf("FDC: NOT ALL necessary parameters found in Data Base %d out of 16\n",ncounter);
00571 } else {
00572 printf("FDC: SOME parameters found more than once in Data Base\n");
00573 }
00574 #if 0
00575 {
00576 int num_values=2304*2;
00577 float my_values[2304*2];
00578 mystr_t my_strings[2304*2];
00579 status=GetArrayConstants("FDC/fdc_wire_offsets",&num_values,
00580 my_values,my_strings);
00581 if (!status){
00582 int i;
00583 for (i=0;i<num_values;i+=2){
00584 int j=i/2;
00585 wire_dx_offset[j]=my_values[i];
00586 wire_dz_offset[j]=my_values[i+1];
00587 }
00588 }
00589 }
00590 #endif
00591 }
00592 initializedx = 1 ;
00593 }
00594
00595
00596 int layer = getlayer_wrapper_();
00597 if (layer==0){
00598 printf("hitFDC: FDC layer number evaluates to zero! THIS SHOULD NEVER HAPPEN! drop this particle.\n");
00599 return;
00600 }
00601
00602
00603
00604 int PackNo = getpackage_wrapper_()-1;
00605 if (PackNo==-1){
00606 printf("hitFDC: FDC package number evaluates to zero! THIS SHOULD NEVER HAPPEN! drop this particle.\n");
00607 return;
00608 }
00609 int glayer=6*PackNo+layer-1;
00610 int module = 2*(PackNo)+(layer-1)/3+1;
00611 int chamber = (module*10)+(layer-1)%3+1;
00612 int wire1,wire2;
00613 int wire,dwire;
00614
00615
00616 layer=(layer-1)%3+1;
00617
00618 transformCoord(xin,"global",xinlocal,"local");
00619
00620 wire1 = ceil((xinlocal[0] - U_OF_WIRE_ZERO)/WIRE_SPACING +0.5);
00621 transformCoord(xout,"global",xoutlocal,"local");
00622 wire2 = ceil((xoutlocal[0] - U_OF_WIRE_ZERO)/WIRE_SPACING +0.5);
00623
00624 if ((wire1>WIRES_PER_PLANE && wire2==WIRES_PER_PLANE) ||
00625 (wire2>WIRES_PER_PLANE && wire1==WIRES_PER_PLANE))
00626 wire1=wire2=WIRES_PER_PLANE;
00627 if ((wire1==0 && wire2 == 1) || (wire1==1 && wire2== 0)){
00628 wire1=wire2=1;
00629 }
00630
00631 if (wire1>WIRES_PER_PLANE&&wire2>WIRES_PER_PLANE) return;
00632 if (wire1==0 && wire2==0) return;
00633
00634 if (wire1>WIRES_PER_PLANE) wire1=wire2;
00635 else if (wire2>WIRES_PER_PLANE) wire2=wire1;
00636 if (wire1==0) wire1=wire2;
00637 else if (wire2==0) wire2=wire1;
00638
00639 dwire = (wire1 < wire2)? 1 : -1;
00640 alpha = atan2(xoutlocal[0]-xinlocal[0],xoutlocal[2]-xinlocal[2]);
00641 sinalpha=sin(alpha);
00642 cosalpha=cos(alpha);
00643 xlocal[0] = (xinlocal[0] + xoutlocal[0])/2;
00644 xlocal[1] = (xinlocal[1] + xoutlocal[1])/2;
00645 xlocal[2] = (xinlocal[2] + xoutlocal[2])/2;
00646
00647 wire = ceil((xlocal[0] - U_OF_WIRE_ZERO)/WIRE_SPACING +0.5);
00648 x[0] = (xin[0] + xout[0])/2;
00649 x[1] = (xin[1] + xout[1])/2;
00650 x[2] = (xin[2] + xout[2])/2;
00651 t = (xin[3] + xout[3])/2 * 1e9;
00652 dx[0] = xin[0] - xout[0];
00653 dx[1] = xin[1] - xout[1];
00654 dx[2] = xin[2] - xout[2];
00655 dr = sqrt(dx[0]*dx[0] + dx[1]*dx[1] + dx[2]*dx[2]);
00656 if (dr > 1e-3)
00657 {
00658 dEdx = dEsum/dr;
00659 }
00660 else
00661 {
00662 dEdx = 0;
00663 }
00664
00665
00666
00667
00668 if (sqrt(xlocal[0]*xlocal[0]+xlocal[1]*xlocal[1])
00669 < wire_dead_zone_radius[PackNo])
00670 {
00671 return;
00672 }
00673
00674
00675
00676 if (history == 0)
00677 {
00678 int mark = (1<<16) + (chamber<<20) + pointCount;
00679 void** twig = getTwig(&forwardDCTree, mark);
00680 if (*twig == 0)
00681 {
00682 s_ForwardDC_t* fdc = *twig = make_s_ForwardDC();
00683 s_FdcChambers_t* chambers = make_s_FdcChambers(1);
00684 s_FdcTruthPoints_t* points = make_s_FdcTruthPoints(1);
00685 float xwire = U_OF_WIRE_ZERO + (wire-1)*WIRE_SPACING;
00686 float u[2];
00687 u[0] = xinlocal[2];
00688 u[1] = xinlocal[0]-xwire;
00689 dradius = fabs(u[1]*cosalpha-u[0]*sinalpha);
00690 points->mult = 1;
00691 int a = thisInputEvent->physicsEvents->in[0].reactions->in[0].vertices->in[0].products->mult;
00692 points->in[0].primary = (stack <= a);
00693 points->in[0].track = track;
00694 points->in[0].x = x[0];
00695 points->in[0].y = x[1];
00696 points->in[0].z = x[2];
00697 points->in[0].t = t;
00698 points->in[0].px = pin[0]*pin[4];
00699 points->in[0].py = pin[1]*pin[4];
00700 points->in[0].pz = pin[2]*pin[4];
00701 points->in[0].E = pin[3];
00702 points->in[0].dradius = dradius;
00703 points->in[0].dEdx = dEdx;
00704 points->in[0].ptype = ipart;
00705 chambers->mult = 1;
00706 chambers->in[0].module = module;
00707 chambers->in[0].layer = layer;
00708 chambers->in[0].fdcTruthPoints = points;
00709 fdc->fdcChambers = chambers;
00710 pointCount++;
00711 }
00712 }
00713
00714
00715
00716 if (dEsum > 0)
00717 {
00718 float sign=1.;
00719
00720 for (wire=wire1; wire-dwire != wire2; wire+=dwire)
00721 {
00722 int valid_hit=1;
00723 float dE,dt;
00724 float u[2];
00725 float x0[3],x1[3];
00726 float avalanche_y;
00727 float xwire = U_OF_WIRE_ZERO + (wire-1)*WIRE_SPACING;
00728 int global_wire_number=96*glayer+wire-1;
00729
00730 #if 0
00731 xwire+=wire_dx_offset[global_wire_number];
00732 #endif
00733
00734 if (wire1==wire2){
00735 dE=dEsum;
00736 x0[0] = xinlocal[0];
00737 x0[1] = xinlocal[1];
00738 x0[2] = xinlocal[2];
00739 x1[0] = xoutlocal[0];
00740 x1[1] = xoutlocal[1];
00741 x1[2] = xoutlocal[2];
00742 }
00743 else{
00744 x0[0] = xwire-0.5*dwire*WIRE_SPACING;
00745 x0[1] = xinlocal[1] + (x0[0]-xinlocal[0]+1e-20)*
00746 (xoutlocal[1]-xinlocal[1])/(xoutlocal[0]-xinlocal[0]+1e-20);
00747 x0[2] = xinlocal[2] + (x0[0]-xinlocal[0]+1e-20)*
00748 (xoutlocal[2]-xinlocal[2])/(xoutlocal[0]-xinlocal[0]+1e-20);
00749 if (fabs(x0[2]-xoutlocal[2]) > fabs(xinlocal[2]-xoutlocal[2]))
00750 {
00751 x0[0] = xinlocal[0];
00752 x0[1] = xinlocal[1];
00753 x0[2] = xinlocal[2];
00754 }
00755 x1[0] = xwire+0.5*dwire*WIRE_SPACING;
00756 x1[1] = xinlocal[1] + (x1[0]-xinlocal[0]+1e-20)*
00757 (xoutlocal[1]-xinlocal[1])/(xoutlocal[0]-xinlocal[0]+1e-20);
00758 x1[2] = xinlocal[2] + (x1[0]-xinlocal[0]+1e-20)*
00759 (xoutlocal[2]-xinlocal[2])/(xoutlocal[0]-xinlocal[0]+1e-20);
00760 if (fabs(x1[2]-xinlocal[2]) > fabs(xoutlocal[2]-xinlocal[2]))
00761 {
00762 x1[0] = xoutlocal[0];
00763 x1[1] = xoutlocal[1];
00764 x1[2] = xoutlocal[2];
00765 }
00766 dE = dEsum*(x1[2]-x0[2])/(xoutlocal[2]-xinlocal[2]);
00767 }
00768
00769 if (dE > 0){
00770 s_FdcAnodeTruthHits_t* ahits;
00771
00772
00773 int mark = (chamber<<20) + (2<<10) + wire;
00774 void** twig = getTwig(&forwardDCTree, mark);
00775
00776 if (*twig == 0)
00777 {
00778 s_ForwardDC_t* fdc = *twig = make_s_ForwardDC();
00779 s_FdcChambers_t* chambers = make_s_FdcChambers(1);
00780 s_FdcAnodeWires_t* wires = make_s_FdcAnodeWires(1);
00781 wires->mult = 1;
00782 wires->in[0].wire = wire;
00783 wires->in[0].fdcAnodeTruthHits = ahits = make_s_FdcAnodeTruthHits(MAX_HITS);
00784 chambers->mult = 1;
00785 chambers->in[0].module = module;
00786 chambers->in[0].layer = layer;
00787 chambers->in[0].fdcAnodeWires = wires;
00788 fdc->fdcChambers = chambers;
00789 wireCount++;
00790 }
00791 else
00792 {
00793 s_ForwardDC_t* fdc = *twig;
00794 ahits = fdc->fdcChambers->in[0].fdcAnodeWires->in[0].fdcAnodeTruthHits;
00795 }
00796
00797
00798 float rndno[2];
00799 int two=2;
00800
00801
00802
00803
00804
00805
00806
00807 int one=1;
00808
00809 float n_s_per_p=1.89;
00810
00811 float w_eff=30.2e-9;
00812
00813 float n_p_mean = dE/w_eff/(1.+n_s_per_p);
00814 int n_p;
00815 gpoiss_(&n_p_mean,&n_p,&one);
00816
00817
00818 float tdrift=0;
00819
00820 if (controlparams_.driftclusters==0){
00821 float zrange=x1[2]-x0[2];
00822 float tany=(x1[1]-x0[1])/zrange;
00823 float tanx=(x1[0]-x0[0])/zrange;
00824 float dz=ANODE_CATHODE_SPACING-dradius*sign*sinalpha;
00825 #if 0
00826 dz+=wire_dz_offset[global_wire_number];
00827 #endif
00828 xlocal[0]=x0[0]+tanx*dz;
00829 if (fabs(xlocal[0]-xwire)>0.5){
00830 xlocal[0]=x1[0];
00831 xlocal[1]=x1[1];
00832 xlocal[2]=x1[2];
00833 }
00834 else{
00835 xlocal[1]=x0[1]+tany*dz;
00836 xlocal[2]=x0[2]+dz;
00837 }
00838
00839
00840
00841
00842 if (sqrt(xlocal[0]*xlocal[0]+xlocal[1]*xlocal[1])
00843 >=wire_dead_zone_radius[PackNo]){
00844 if (AddFDCAnodeHit(ahits,layer,ipart,track,xwire,xlocal,dE,t,
00845 &tdrift)){
00846 AddFDCCathodeHits(PackNo,xwire,xlocal[1],tdrift,n_p,track,ipart,
00847 chamber,module,layer,global_wire_number);
00848 }
00849
00850 }
00851 }
00852 else{
00853
00854 int n;
00855 for (n=0;n<n_p;n++){
00856
00857 float rndno[2];
00858 grndm_(rndno,&two);
00859 float dzrand=(x1[2]-x0[2])*rndno[0];
00860
00861 xlocal[0]=x0[0]+(x1[0]-x0[0])*rndno[0];
00862 xlocal[1]=x0[1]+(x1[1]-x0[1])*rndno[0];
00863 xlocal[2]=x0[2]+dzrand;
00864
00865
00866
00867 if (sqrt(xlocal[0]*xlocal[0]+xlocal[1]*xlocal[1])
00868 >=wire_dead_zone_radius[PackNo]){
00869 if (AddFDCAnodeHit(ahits,layer,ipart,track,xwire,xlocal,dE,t,
00870 &tdrift)){
00871 AddFDCCathodeHits(PackNo,xwire,xlocal[1],tdrift,n_p,track,ipart,
00872 chamber,module,layer,global_wire_number);
00873 }
00874 }
00875
00876 }
00877 }
00878 }
00879
00880 sign*=-1;
00881 }
00882 }
00883 }
00884
00885
00886
00887 void hitforwarddc_(float* xin, float* xout,
00888 float* pin, float* pout, float* dEsum,
00889 int* track, int* stack, int* history, int* ipart)
00890 {
00891 hitForwardDC(xin,xout,pin,pout,*dEsum,*track,*stack,*history,*ipart);
00892 }
00893
00894
00895
00896
00897 s_ForwardDC_t* pickForwardDC ()
00898 {
00899 s_ForwardDC_t* box;
00900 s_ForwardDC_t* item;
00901
00902 if ((stripCount == 0) && (wireCount == 0) && (pointCount == 0))
00903 {
00904 return HDDM_NULL;
00905 }
00906
00907 box = make_s_ForwardDC();
00908 box->fdcChambers = make_s_FdcChambers(32);
00909 box->fdcChambers->mult = 0;
00910 while (item = (s_ForwardDC_t*) pickTwig(&forwardDCTree))
00911 {
00912 s_FdcChambers_t* chambers = item->fdcChambers;
00913 int module = chambers->in[0].module;
00914 int layer = chambers->in[0].layer;
00915 int m = box->fdcChambers->mult;
00916
00917
00918 s_FdcAnodeWires_t* wires = chambers->in[0].fdcAnodeWires;
00919 int wire;
00920 s_FdcCathodeStrips_t* strips = chambers->in[0].fdcCathodeStrips;
00921 int strip;
00922 s_FdcTruthPoints_t* points = chambers->in[0].fdcTruthPoints;
00923 int point;
00924 int mok=0;
00925 for (wire=0; wire < wires->mult; wire++)
00926 {
00927 s_FdcAnodeTruthHits_t* ahits = wires->in[wire].fdcAnodeTruthHits;
00928
00929
00930 qsort(ahits->in,ahits->mult,sizeof(s_FdcAnodeTruthHit_t),
00931 (compfn)fdc_anode_cluster_sort);
00932
00933 int i,iok=0;
00934
00935 if (controlparams_.driftclusters==0){
00936 for (iok=i=0; i < ahits->mult; i++)
00937 {
00938 if (ahits->in[i].dE >= THRESH_KEV/1e6)
00939 {
00940 if (iok < i)
00941 {
00942 ahits->in[iok] = ahits->in[i];
00943 }
00944 ++iok;
00945 ++mok;
00946 }
00947 }
00948 }
00949 else{
00950
00951
00952
00953
00954
00955 int num_samples=(int)FDC_TIME_WINDOW;
00956 float *samples=(float *)malloc(num_samples*sizeof(float));
00957 for (i=0;i<num_samples;i++){
00958 samples[i]=wire_signal((float)i,ahits);
00959
00960 }
00961
00962 int returned_to_baseline=0;
00963 float q=0;
00964 for (i=0;i<num_samples;i++){
00965 if (samples[i]>=THRESH_ANODE){
00966 if (returned_to_baseline==0){
00967 ahits->in[iok].itrack = ahits->in[0].itrack;
00968 ahits->in[iok].ptype = ahits->in[0].ptype;
00969
00970
00971
00972 float t_array[4];
00973 int k;
00974 float my_t,my_terr;
00975 for (k=0;k<4;k++) t_array[k]=i-1+k;
00976 polint(&samples[i-1],t_array,4,THRESH_ANODE,&my_t,&my_terr);
00977 ahits->in[iok].t=my_t;
00978
00979 returned_to_baseline=1;
00980 iok++;
00981 mok++;
00982 }
00983 q+=samples[i];
00984 }
00985 if (returned_to_baseline
00986 && (samples[i]<THRESH_ANODE)){
00987 returned_to_baseline=0;
00988 }
00989 }
00990 free(samples);
00991 }
00992
00993 if (iok)
00994 {
00995 ahits->mult = iok;
00996 }
00997 else if (ahits != HDDM_NULL)
00998 {
00999 FREE(ahits);
01000 }
01001 }
01002 if ((wires != HDDM_NULL) && (mok == 0))
01003 {
01004 FREE(wires);
01005 wires = HDDM_NULL;
01006 }
01007
01008
01009 mok = 0;
01010 for (strip=0; strip < strips->mult; strip++)
01011 {
01012 s_FdcCathodeTruthHits_t* chits = strips->in[strip].fdcCathodeTruthHits;
01013
01014
01015 qsort(chits->in,chits->mult,sizeof(s_FdcCathodeTruthHit_t),
01016 (compfn)fdc_cathode_cluster_sort);
01017
01018 int i,iok=0;
01019
01020 if (controlparams_.driftclusters==0){
01021 for (iok=i=0; i < chits->mult; i++)
01022 {
01023 if (chits->in[i].q > 0.)
01024 {
01025 if (iok < i)
01026 {
01027 chits->in[iok] = chits->in[i];
01028 }
01029 ++iok;
01030 ++mok;
01031 }
01032 }
01033
01034 }
01035 else{
01036
01037
01038 int num_samples=(int)(FDC_TIME_WINDOW);
01039 float *samples=(float *)malloc(num_samples*sizeof(float));
01040 for (i=0;i<num_samples;i++){
01041 samples[i]=cathode_signal((float)i,chits);
01042
01043 }
01044
01045 int threshold_toggle=0;
01046 int istart=0;
01047 float q=0;
01048 int FADC_BIN_SIZE=1;
01049 for (i=0;i<num_samples;i+=FADC_BIN_SIZE){
01050 if (samples[i]>=THRESH_STRIPS){
01051 if (threshold_toggle==0){
01052 chits->in[iok].itrack = chits->in[0].itrack;
01053 chits->in[iok].ptype = chits->in[0].ptype;
01054 chits->in[iok].t=(float) i;
01055
01056 istart=i-1;
01057 threshold_toggle=1;
01058
01059
01060 }
01061 }
01062 if (threshold_toggle &&
01063 (samples[i]<THRESH_STRIPS)){
01064 int j;
01065
01066 for (j=istart+1;j<i-1;j++){
01067 if (samples[j]>samples[j-1] && samples[j]>samples[j+1]){
01068 chits->in[iok].q=samples[j];
01069 break;
01070 }
01071 }
01072 threshold_toggle=0;
01073 iok++;
01074 mok++;
01075
01076 }
01077 }
01078 i=num_samples-1;
01079 if (samples[i]>=THRESH_STRIPS&&threshold_toggle){
01080 int j;
01081 for (j=istart+1;j<i-1;j++){
01082 if (samples[j]>samples[j-1] && samples[j]>samples[j+1]){
01083 chits->in[iok].q=samples[j];
01084 break;
01085 }
01086 }
01087 }
01088
01089 free(samples);
01090 }
01091
01092 if (iok)
01093 {
01094 chits->mult = iok;
01095
01096 }
01097 else if (chits != HDDM_NULL)
01098 {
01099 FREE(chits);
01100 }
01101
01102 }
01103 if ((strips != HDDM_NULL) && (mok == 0))
01104 {
01105 FREE(strips);
01106 strips = HDDM_NULL;
01107 }
01108
01109 if ((wires != HDDM_NULL) ||
01110 (strips != HDDM_NULL) ||
01111 (points != HDDM_NULL))
01112 {
01113 if ((m == 0) || (module > box->fdcChambers->in[m-1].module)
01114 || (layer > box->fdcChambers->in[m-1].layer))
01115 {
01116 box->fdcChambers->in[m] = chambers->in[0];
01117
01118 box->fdcChambers->in[m].fdcCathodeStrips =
01119 make_s_FdcCathodeStrips(stripCount);
01120 box->fdcChambers->in[m].fdcAnodeWires =
01121 make_s_FdcAnodeWires(wireCount);
01122 box->fdcChambers->in[m].fdcTruthPoints =
01123 make_s_FdcTruthPoints(pointCount);
01124 box->fdcChambers->mult++;
01125 }
01126 else
01127 {
01128 m--;
01129 }
01130 for (strip=0; strip < strips->mult; ++strip)
01131 {
01132 int mm = box->fdcChambers->in[m].fdcCathodeStrips->mult++;
01133 box->fdcChambers->in[m].fdcCathodeStrips->in[mm] = strips->in[strip];
01134 }
01135 if (strips != HDDM_NULL)
01136 {
01137 FREE(strips);
01138 }
01139 for (wire=0; wire < wires->mult; ++wire)
01140 {
01141 int mm = box->fdcChambers->in[m].fdcAnodeWires->mult++;
01142 box->fdcChambers->in[m].fdcAnodeWires->in[mm] = wires->in[wire];
01143 }
01144 if (wires != HDDM_NULL)
01145 {
01146 FREE(wires);
01147 }
01148 for (point=0; point < points->mult; ++point)
01149 {
01150 int mm = box->fdcChambers->in[m].fdcTruthPoints->mult++;
01151 box->fdcChambers->in[m].fdcTruthPoints->in[mm] = points->in[point];
01152 }
01153 if (points != HDDM_NULL)
01154 {
01155 FREE(points);
01156 }
01157 }
01158 FREE(chambers);
01159 FREE(item);
01160 }
01161
01162 stripCount = wireCount = pointCount = 0;
01163
01164 if ((box->fdcChambers != HDDM_NULL) &&
01165 (box->fdcChambers->mult == 0))
01166 {
01167 FREE(box->fdcChambers);
01168 box->fdcChambers = HDDM_NULL;
01169 }
01170 if (box->fdcChambers->mult == 0)
01171 {
01172 FREE(box);
01173 box = HDDM_NULL;
01174 }
01175 return box;
01176 }