00001 #include "NueAna/ParticlePID/ParticleFinder/Chain.h"
00002 #include "MessageService/MsgService.h"
00003
00004 #include <math.h>
00005
00006 CVSID("$Id: Chain.cxx,v 1.2 2009/06/23 22:42:24 scavan Exp $");
00007
00008 ClassImp(Chain)
00009
00010
00011 int Chain::lastid = 0;
00012
00013 Chain::Chain()
00014 {
00015
00016 start_t=0.0;
00017 end_t=0.0;
00018 start_z=0.0;
00019 end_z=0.0;
00020 particletype=0;
00021 sum_e=0.0;
00022 weighted_t=0.0;
00023 entries=0;
00024 avg_slope=0.0;
00025 avg_offset=0.0;
00026 last_slope=0.0;
00027 front_slope=0.0;
00028 back_slope=0.0;
00029 front_offset=0.0;
00030 back_offset=0.0;
00031 parentChain=-1;
00032 myId=-1;
00033 level=0;
00034 muonfrac=0.0;
00035 interior_muonfrac=0.0;
00036 emlike=0.0;
00037 num_peaks=0;
00038 strict_decreasing=1;
00039 strict_increasing=1;
00040 lastpeake=0.0;
00041 lastpeakprob=0;
00042 sum_z=0.0;
00043 sum_t=0.0;
00044 sum_z_z=0.0;
00045 sum_z_t=0.0;
00046 muonlike=0;
00047 a=0.0;
00048 b=0.0;
00049
00050
00051
00052
00053 t.clear();
00054 z.clear();
00055 e.clear();
00056 cluster_id.clear();
00057 children.clear();
00058
00059 myId=lastid++;
00060
00061
00062 muon_threshold_max=2;
00063 muon_threshold_min=0.5;
00064 muon_min_hits=2;
00065
00066 available=1;
00067
00068 }
00069
00070 Chain::~Chain()
00071 {
00072 t.clear();
00073 z.clear();
00074 e.clear();
00075 cluster_id.clear();
00076 children.clear();
00077 }
00078
00079 void Chain::ResetCounter()
00080 {
00081 lastid=0;
00082 }
00083
00084
00085
00086 double Chain::interpolate(double test_z)
00087 {
00088 double int_t=0;
00089 if(z.size()<1)return 0;
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101 std::vector<double>z;
00102 std::vector<double>t;
00103 std::vector<double>e;
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115 z.push_back(this->z[0]);
00116 t.push_back(this->t[0]*this->e[0]);
00117 e.push_back(this->e[0]);
00118 int cnt=0;
00119 for(unsigned int i=1;i<this->z.size();i++)
00120 {
00121 if(fabs(this->z[i]-this->z[i-1])>0.001)
00122 {
00123 cnt++;
00124 z.push_back(this->z[i]);
00125 t.push_back(this->t[i]*this->e[i]);
00126 e.push_back(this->e[i]);
00127 }else{
00128 t[cnt]+=this->t[i]*this->e[i];
00129 e[cnt]+=this->e[i];
00130 }
00131 }
00132
00133 for(unsigned int i=0;i<z.size();i++)
00134 {
00135 t[i]/=e[i];
00136 }
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148 if(z.size()>2)
00149 {
00150
00151 if(test_z>=end_z)
00152 {
00153 int i=z.size()-1;
00154 if(i>1)
00155 int_t = interpolate(z[i],t[i],z[i-1],t[i-1],z[i-2],t[i-2],test_z);
00156 }else if(test_z<=start_z)
00157 {
00158 if(z.size()>2)
00159 int_t = interpolate(z[0],t[0],z[1],t[1],z[2],t[2],test_z);
00160 }else{
00161 int i=z.size()-1;
00162 if(i>1)
00163 int_t = interpolate(z[i],t[i],z[i-1],t[i-1],z[i-2],t[i-2],test_z);
00164 if(z.size()>2)
00165 int_t += interpolate(z[0],t[0],z[1],t[1],z[2],t[2],test_z);
00166
00167 int_t /=2;
00168 }
00169
00170 }else if(z.size()>1)
00171 {
00172 int end = z.size()-1;
00173 double dz = z[end]-z[end-1];
00174 double dt = t[end]-t[end-1];
00175 if(dz!=0)
00176 {
00177 double slope = dt/dz;
00178 int_t = (test_z-z[end-1])*slope+t[end-1];
00179 }
00180 }else if(z.size()==1)
00181 {
00182 int_t = t[0];
00183 }
00184
00185
00186
00187
00188 return int_t;
00189 }
00190
00191
00192 double Chain::interpolate(double z0, double t0, double z1, double t1, double z2, double t2, double z)
00193 {
00194 double int_t=0;
00195
00196
00197 double L0 = (z-z1)*(z-z2)/( (z0-z1)*(z0-z2));
00198 double L1 = (z-z0)*(z-z2)/( (z1-z0)*(z1-z2));
00199 double L2 = (z-z0)*(z-z1)/( (z2-z0)*(z2-z1));
00200
00201 int_t = t0*L0 + t1*L1 + t2*L2;
00202
00203
00204
00205 return int_t;
00206 }
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218 void Chain::Recalc()
00219 {
00220
00221 std::vector<double>mt=t;
00222 std::vector<double>mz=z;
00223 std::vector<double>me=e;
00224 std::vector<int>mc=cluster_id;
00225
00226 ClearHits();
00227
00228 for(unsigned int i=0;i<mt.size();i++)
00229 if(me[i]>0)insert(mt[i],mz[i],me[i],cluster_id[i]);
00230
00231
00232
00233 }
00234
00235
00236
00237
00238 void Chain::Reverse()
00239 {
00240
00241
00242
00243 std::vector<double>mt;
00244 for(unsigned int i=0;i<t.size();i++)mt.push_back(t[i]);
00245 std::vector<double>mz;
00246 for(unsigned int i=0;i<z.size();i++)mz.push_back(z[i]);
00247 std::vector<double>me;
00248 for(unsigned int i=0;i<e.size();i++)me.push_back(e[i]);
00249
00250 std::vector<int>mc;
00251 for(unsigned int i=0;i<cluster_id.size();i++)mc.push_back(cluster_id[i]);
00252
00253
00254
00255 ClearHits();
00256
00257
00258
00259 for(int i=mt.size()-1;i>-1;i--)
00260 add_to_back(mt[i],mz[i],me[i],cluster_id[i]);
00261
00262
00263
00264
00265 }
00266
00267
00268
00269 void Chain::ClearHits()
00270 {
00271 start_t=0.0;
00272 end_t=0.0;
00273 start_z=0.0;
00274 end_z=0.0;
00275 sum_e=0.0;
00276 weighted_t=0.0;
00277 entries=0;
00278 avg_slope=0.0;
00279 avg_offset=0.0;
00280 last_slope=0.0;
00281 front_slope=0.0;
00282 back_slope=0.0;
00283 muonfrac=0.0;
00284 interior_muonfrac=0.0;
00285 emlike=0.0;
00286 num_peaks=0;
00287 strict_decreasing=1;
00288 strict_increasing=1;
00289 lastpeake=0.0;
00290 lastpeakprob=0;
00291 sum_z=0.0;
00292 sum_t=0.0;
00293 sum_z_z=0.0;
00294 sum_z_t=0.0;
00295 muonlike=0;
00296 a=0.0;
00297 b=0.0;
00298
00299
00300 z.clear();
00301 e.clear();
00302 t.clear();
00303 cluster_id.clear();
00304
00305 }
00306
00307
00308 void Chain::PrintChain()
00309 {
00310
00311 if(!MsgService::Instance()->IsActive("Chain",Msg::kDebug))return;
00312
00313 printf("Chain %d \n",myId);
00314 printf("%d entries start_t %f start_z %f end_t %f end_z %f\n",entries,start_t,start_z,end_t,end_z);
00315 printf("sume %f avg_slope %f lastslope %f frontslope %f backslope %f\n",sum_e,avg_slope,last_slope,front_slope,back_slope);
00316 printf("muonfrac %f, intmf %f, emlike %f, peaks %d, sdec %d, sinc %d\n",muonfrac, interior_muonfrac, emlike, num_peaks,strict_decreasing, strict_increasing);
00317
00318 printf(" hits (t,z,e) : ");
00319 for(unsigned int i=0;i<t.size();i++)
00320 printf(" (%f, %f, %f - %d)", t[i],z[i],e[i],cluster_id[i]);
00321 printf("\n");
00322
00323
00324 }
00325
00326
00327 void Chain::updateMuonFrac(double , double , double ie)
00328 {
00329 if(ie < muon_threshold_max && ie > muon_threshold_min)
00330 {
00331
00332 if(entries>2)
00333 {
00334 int cntfirst=0;
00335 if ( e[0] < muon_threshold_max && e[0] > muon_threshold_min ) cntfirst=1;
00336 interior_muonfrac = (double)(muonlike - cntfirst) / (double)(entries-2);
00337 }
00338
00339 muonlike++;
00340 if (muon_min_hits <= entries ) muonfrac = (double)muonlike / (double)entries;
00341 }
00342
00343 }
00344
00345 void Chain::updateNumPeaks(double , double , double ie)
00346 {
00347 if(entries>1)
00348 if(ie < lastpeake && lastpeakprob)
00349 {
00350 num_peaks++;
00351 lastpeakprob = 0;
00352 }else if(ie > lastpeake)
00353 {
00354 lastpeakprob = 1;
00355 }
00356
00357
00358 if(entries>1)
00359 {
00360 if(ie <= lastpeake) strict_increasing=0;
00361 if(ie >= lastpeake) strict_decreasing=0;
00362 }
00363
00364
00365 lastpeake = ie;
00366
00367 }
00368
00369 void Chain::updateEMLike(double , double , double )
00370 {
00371
00372 emlike = num_peaks==1;
00373 }
00374
00375
00376 int Chain::good_slope()
00377 {
00378
00379
00380 int good=0;
00381
00382 if(t.size()>1)good=1;
00383
00384 return good;
00385 }
00386
00387
00388
00389 void Chain::insert(double it, double iz, double ie, int my_cluster_id)
00390 {
00391
00392 double lastt = 0.0;
00393 double lastz = 0.0;
00394 double laste = 0.0;
00395
00396 if(t.size()>0)
00397 {
00398 lastt=t.back();
00399 lastz=z.back();
00400 laste=e.back();
00401 }
00402
00403 int insert_idx=-1;
00404 for(unsigned int i=0;i<t.size();i++)
00405 {
00406 if(iz<z[i])
00407 {
00408 insert_idx=i;
00409 break;
00410 }
00411 }
00412
00413 if(t.size()==0)
00414 {
00415 start_t=it;
00416 start_z=iz;
00417 end_t=it;
00418 end_z=iz;
00419 }
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434 if(start_z>iz)
00435 {
00436 start_z=iz;
00437 start_t=it;
00438 }
00439
00440 if(end_z<iz)
00441 {
00442 end_z=iz;
00443 end_t=it;
00444 }
00445
00446 weighted_t*=sum_e;
00447 weighted_t +=it*ie;
00448
00449 sum_e+=ie;
00450
00451 weighted_t /=sum_e;
00452
00453 entries++;
00454 if(insert_idx>-1)
00455 {
00456 std::vector<double>::iterator itr_f=t.begin();
00457 itr_f+=insert_idx;
00458 t.insert(itr_f,it);
00459 itr_f=z.begin();
00460 itr_f+=insert_idx;
00461 z.insert(itr_f,iz);
00462 itr_f=e.begin();
00463 itr_f+=insert_idx;
00464 e.insert(itr_f,ie);
00465 std::vector<int>::iterator itr_i=cluster_id.begin();
00466 itr_i+=insert_idx;
00467 cluster_id.insert(itr_i,my_cluster_id);
00468 }else{
00469 t.push_back(it);
00470 z.push_back(iz);
00471 e.push_back(ie);
00472 cluster_id.push_back(my_cluster_id);
00473 }
00474
00475
00476 sum_z+=iz;
00477 sum_t+=it;
00478 sum_z_z+=iz*iz;
00479 sum_z_t+=iz*it;
00480
00481
00482 double n=(double)entries;
00483 if(n>1 && (n*sum_z_z-(sum_z)*(sum_z))!=0)
00484 {
00485 a=(sum_t*sum_z_z-sum_z*sum_z_t)/(n*sum_z_z-(sum_z)*(sum_z));
00486 b=(n*sum_z_t-sum_z*sum_t)/(n*sum_z_z-(sum_z)*(sum_z));
00487 }
00488
00489 avg_slope = b;
00490 avg_offset = a;
00491
00492 if(entries>1 && lastz-iz)last_slope =(lastt-it)/(lastz-iz);
00493
00494
00495 if(entries>1 && entries<=4)
00496 {
00497 front_slope=b;
00498 front_offset=a;
00499 back_slope=b;
00500 back_offset=a;
00501 }
00502 if(entries>4)
00503 {
00504
00505 int n=4;
00506 double sum_z_t=0;
00507 double sum_z=0;
00508 double sum_t=0;
00509 double sum_z_z=0;
00510
00511 for(unsigned int i=e.size()-1;i>e.size()-5;i--)
00512 {
00513 sum_z+=z[i];
00514 sum_t+=t[i];
00515 sum_z_t+=z[i]*t[i];
00516 sum_z_z+=z[i]*z[i];
00517 }
00518
00519
00520 if(fabs(n*sum_z_z-(sum_z)*(sum_z))>1e-10)
00521 {
00522 back_slope=(n*sum_z_t-sum_z*sum_t)/(n*sum_z_z-(sum_z)*(sum_z));
00523 back_offset=(sum_t*sum_z_z-sum_z*sum_z_t)/(n*sum_z_z-(sum_z)*(sum_z));
00524 }
00525
00526
00527 n=4;
00528 if(entries>12)n=entries/3;
00529 if(n>10)n=10;
00530 sum_z_t=0;
00531 sum_z=0;
00532 sum_t=0;
00533 sum_z_z=0;
00534
00535 for(int i=0;i<n;i++)
00536 {
00537 sum_z+=z[i];
00538 sum_t+=t[i];
00539 sum_z_t+=z[i]*t[i];
00540 sum_z_z+=z[i]*z[i];
00541 }
00542
00543 if(fabs(n*sum_z_z-(sum_z)*(sum_z))>1e-10)
00544 {
00545 front_slope=(n*sum_z_t-sum_z*sum_t)/(n*sum_z_z-(sum_z)*(sum_z));
00546 front_offset=(sum_t*sum_z_z-sum_z*sum_z_t)/(n*sum_z_z-(sum_z)*(sum_z));
00547 }
00548 }
00549
00550
00551 updateMuonFrac(it, iz, ie);
00552 updateNumPeaks(it, iz, ie);
00553 updateEMLike(it, iz, ie);
00554
00555 }
00556
00557
00558 void Chain::add_to_back(double it, double iz, double ie, int my_cluster_id)
00559 {
00560
00561 double lastt = 0.0;
00562 double lastz = 0.0;
00563 double laste = 0.0;
00564
00565 if(t.size()>0)
00566 {
00567 lastt=t.back();
00568 lastz=z.back();
00569 laste=e.back();
00570 }else{
00571 start_t=it;
00572 start_z=iz;
00573 }
00574
00575 weighted_t*=sum_e;
00576 weighted_t +=it*ie;
00577
00578 sum_e+=ie;
00579
00580 weighted_t /=sum_e;
00581
00582 entries++;
00583
00584 t.push_back(it);
00585 z.push_back(iz);
00586 e.push_back(ie);
00587 cluster_id.push_back(my_cluster_id);
00588
00589
00590
00591 sum_z+=iz;
00592 sum_t+=it;
00593 sum_z_z+=iz*iz;
00594 sum_z_t+=iz*it;
00595
00596 end_t=it;
00597 end_z=iz;
00598
00599
00600 double n=(double)entries;
00601 if(n>1 && fabs(n*sum_z_z-(sum_z)*(sum_z))>1e-10 )
00602 {
00603 a=(sum_t*sum_z_z-sum_z*sum_z_t)/(n*sum_z_z-(sum_z)*(sum_z));
00604 b=(n*sum_z_t-sum_z*sum_t)/(n*sum_z_z-(sum_z)*(sum_z));
00605 }
00606
00607 avg_slope = b;
00608 avg_offset = a;
00609
00610 if(entries>1 && lastz-iz)last_slope =(lastt-it)/(lastz-iz);
00611
00612
00613 if(entries>1 && entries<=4)
00614 {
00615 front_slope=b;
00616 front_offset=a;
00617 back_slope=b;
00618 back_offset=a;
00619 }
00620 if(entries>4)
00621 {
00622 int n=4;
00623 double sum_z_t=0;
00624 double sum_z=0;
00625 double sum_t=0;
00626 double sum_z_z=0;
00627
00628 for(unsigned int i=e.size()-1;i>e.size()-5;i--)
00629 {
00630 sum_z+=z[i];
00631 sum_t+=t[i];
00632 sum_z_t+=z[i]*t[i];
00633 sum_z_z+=z[i]*z[i];
00634 }
00635
00636 if(fabs(n*sum_z_z-(sum_z)*(sum_z))>1e-10)
00637 {
00638 back_slope=(n*sum_z_t-sum_z*sum_t)/(n*sum_z_z-(sum_z)*(sum_z));
00639 back_offset=(sum_t*sum_z_z-sum_z*sum_z_t)/(n*sum_z_z-(sum_z)*(sum_z));
00640 }
00641 }
00642
00643
00644 updateMuonFrac(it, iz, ie);
00645 updateNumPeaks(it, iz, ie);
00646 updateEMLike(it, iz, ie);
00647
00648 }