Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

Finder.cxx

Go to the documentation of this file.
00001 #include "MessageService/MsgService.h"
00002 
00003 #include "NueAna/ParticlePID/ParticleFinder/Finder.h"
00004 //#include "NueAna/ParticlePID/ParticleFinder/EMFitter.h"
00005 #include "NueAna/ParticlePID/ParticleFinder/Particle3D.h"
00006 
00007 #include "NueAna/ParticlePID/ParticleFinder/ParticleType.h"
00008 #include "NueAna/ParticlePID/ParticleFinder/LongMuonFinder.h"
00009 #include "NueAna/ParticlePID/ParticleFinder/PrimaryShowerFinder.h"
00010 #include "Conventions/Detector.h"
00011 
00012 #include "TPolyLine.h"
00013 #include "TMarker.h"
00014 #include "TMath.h"
00015 #include <algorithm>
00016 
00017 #include <sstream>
00018 #include <math.h>
00019 #include "ShwFit.h"
00020 
00021 #include <limits>
00022 
00023 
00024 
00025 
00026 
00027 CVSID("$Id: Finder.cxx,v 1.9 2009/09/11 05:00:40 gmieg Exp $");
00028 
00029 
00030 
00031 
00032 
00033 
00034 
00035 Finder::Finder():  vtx_u(0.0), vtx_v(0.0), vtx_z(0.0)
00036 {
00037 
00038         sorter_map.clear();
00039         DoMRCC=0;
00040 
00041 
00042 
00043 
00044 
00045         
00046         //cluster_map.clear();
00047         meupergev=0;
00048 }
00049 
00050 Finder::~Finder()
00051 {
00052 
00053         sorter_map.clear();
00054         //cluster_map.clear();
00055 
00056 }
00057 
00058 void Finder::Reset()
00059 {
00060         sorter_map.clear(); 
00061 
00062 
00063         loc_map.clear(); 
00064         plane.clear(); 
00065         strip.clear(); 
00066         energy.clear(); 
00067         particles.clear(); 
00068         t.clear();
00069         z.clear(); 
00070         view.clear();  
00071         //cluster_map.clear();
00072 
00073         true_vtx_u=0.0;
00074         true_vtx_v=0.0;
00075         true_vtx_z=0.0;
00076 
00077 
00078         vtx_u=0.0;
00079         vtx_v=0.0;
00080         vtx_z=0.0;
00081         shareholder.Reset();
00082 }
00083 
00084 
00085 void Finder::AddStrip(int myplane, int mystrip, double myenergy, double st, double sz, int myview)
00086 {
00087         mypoh->event.nstrips++;
00088 
00089 
00090         mypoh->strips.AddStrip(myplane,mystrip,myenergy,st,sz,myview);
00091 
00092         plane.push_back(myplane); 
00093         strip.push_back(mystrip); 
00094         energy.push_back(myenergy); 
00095         t.push_back(st); 
00096         z.push_back(sz);
00097         view.push_back(myview);
00098 
00099         mypoh->event.large_minz = (mypoh->event.large_minz < sz) ? mypoh->event.large_minz : sz;
00100         mypoh->event.large_maxz = (mypoh->event.large_maxz > sz) ? mypoh->event.large_maxz : sz;
00101         if(myview==2)
00102         {
00103                 mypoh->event.large_minu = (mypoh->event.large_minu < st) ? mypoh->event.large_minu : st;
00104                 mypoh->event.large_maxu = (mypoh->event.large_maxu > st) ? mypoh->event.large_maxu : st;
00105         }else if(myview==3){
00106                 mypoh->event.large_minv = (mypoh->event.large_minv < st) ? mypoh->event.large_minv : st;
00107                 mypoh->event.large_maxv = (mypoh->event.large_maxv > st) ? mypoh->event.large_maxv : st;        
00108         }
00109 
00110 
00111         //printf("adding %f %f %d\n",st,sz,myview);
00112     sorter_map.insert(std::pair <double,int>(myenergy, (int)energy.size()-1))
00113 ;
00114         
00115     loc_map[myplane][mystrip]=plane.size()-1;
00116 
00117 
00118 
00119 
00120 }
00121 
00122 
00123 void Finder::ClearXTalk()
00124 {
00125         printf("DONT USE Finder::ClearXTalk()!\n");
00126         exit(1);
00127 
00128         double thresh = 3; //number of mips below which we don't care about looking for xtalk....
00129 
00130         for(unsigned int i=0;i<plane.size();i++)
00131         {
00132                 sorter_map.insert(std::pair <double,int>(energy[i],i));
00133                 loc_map[plane[i]][strip[i]]=i;
00134         }
00135         
00136 
00137         
00138         double reassignedxtalke=0.0;
00139         
00140         int foundxtalk=0;
00141         std::map<int, std::map<int, int> >::iterator p_iter;
00142         for(p_iter=loc_map.begin();p_iter!=loc_map.end(); p_iter++)
00143     {
00144         std::map<int, int>::iterator s_iter;
00145         for(s_iter=p_iter->second.begin();s_iter!=p_iter->second.end(); s_iter++)
00146         {
00147                         if (energy[s_iter->second]<thresh)continue;
00148                         
00149                         std::map<int, int>::iterator s_iter2;
00150                         for(s_iter2=p_iter->second.begin();s_iter2!=p_iter->second.end(); s_iter2++)
00151                 {
00152                                 if(s_iter==s_iter2)continue;
00153                                 int sp=abs(s_iter->first-s_iter2->first);
00154         //                      printf("sep %d view %d plane %d high %f low %f\n",sp,view[s_iter->second],plane[s_iter->second],energy[s_iter->second],energy[s_iter2->second]);
00155                                 
00156                                 if( sp>9 && sp<14)//sp == 13)
00157                                 {
00158                                         if(energy[s_iter2->second] < 0.3 * energy[s_iter->second]) //suspected crosstalk hit is < 30% of the high hit
00159                                         {
00160                                                 reassignedxtalke+=energy[s_iter2->second];
00161                                                 
00162                                                 energy[s_iter->second]+=energy[s_iter2->second];
00163                                                 energy[s_iter2->second]=0.0;
00164                                                 foundxtalk=1;
00165                                         }
00166                                 }
00167                         
00168                         }
00169                 }
00170         }
00171 
00172 
00173 //      if(reassignedxtalke>0)printf("XTALK FILTER --- %f reassigned!\n",reassignedxtalke);
00174 
00175 
00176         if(foundxtalk)
00177         {
00178                 std::vector<int>tplane;
00179                 std::vector<int>tstrip;
00180                 std::vector<int>tview;
00181                 std::vector<double>tt;
00182                 std::vector<double>tz;
00183                 std::vector<double>tenergy;
00184         
00185         
00186                 for(unsigned int i=0;i<energy.size();i++)
00187                 {
00188                         if(energy[i]>0.001)
00189                         {
00190                                 tplane.push_back(plane[i]); 
00191                                 tstrip.push_back(strip[i]); 
00192                                 tenergy.push_back(energy[i]); 
00193                                 tt.push_back(t[i]); 
00194                                 tz.push_back(z[i]);
00195                                 tview.push_back(view[i]);
00196                         }
00197                 }
00198                 
00199                 plane=tplane;
00200                 strip=tstrip;
00201                 view=tview;
00202                 t=tt;
00203                 z=tz;
00204                 energy=tenergy;
00205                 
00206         }
00207 
00208 
00209         sorter_map.clear();
00210         loc_map.clear();
00211 
00212 }
00213 
00214 
00215 
00216 void Finder::SetStatus(Chain *c, int status)
00217 {
00218 
00219         for(unsigned int i=0;i<c->cluster_id.size();i++)
00220         {
00221                 mypoh->clusterer.GetCluster(c->cluster_id[i])->SetStatus(status);
00222         //      printf("setting status cluster id %d to %d\n",c->cluster_id[i],status);
00223         }
00224 }
00225 
00226 
00227 void Finder::Process(ParticleObjectHolder & p)
00228 {
00229         if(!meupergev)
00230         {
00231                 cout <<"At Finder::Process... meupergev has not been set!\n";
00232                 exit(1);
00233         }
00234 
00235         
00236         mypoh=&p;
00237 
00238 //don't clear the xtalk here... use the XTalkFilter module!     
00239 //      if(p.GetHeader().GetVldContext().GetDetector()==Detector::kFar)ClearXTalk(); //only far has xtalk
00240         
00241 
00242 /*      
00243         for(unsigned int i=0;i<plane.size();i++)
00244         {
00245                 sorter_map.insert(std::pair <double,int>(energy[i],i));
00246                 loc_map[plane[i]][strip[i]]=i;
00247         
00248                 Managed::ClusterManager * clusterhelper = (view[i]==2) ? &mypoh->clusterer : (view[i]==3) ? &mypoh->clusterer : 0;
00249                 if(clusterhelper)clusterhelper->AddStrip(plane[i], strip[i], energy[i], t[i], z[i], view[i]);
00250 
00251         }
00252         
00253 */
00254 
00255         
00256 //mypoh->clusterer=clustermanager_u;
00257 mypoh->clusterer=clustermanager_v;
00258         
00259 //      mypoh->clusterer.MakeClusters();
00260 //      mypoh->clusterer.MakeClusters();
00261 
00262         mypoh->event.nclusters =  mypoh->clusterer.clusters.size();
00263 //      mypoh->event.nclusters += mypoh->clusterer.clusters.size();
00264         
00265 
00266         std::vector<Managed::ManagedCluster> clusters = mypoh->clusterer.clusters;
00267 /*      for(int i=0;i<clusters.size();i++)
00268         {
00269                 printf("clu id %d view %d z %f t %f e %f\n",clusters[i].id,clusters[i].view,clusters[i].z,clusters[i].t,clusters[i].e);
00270         
00271         
00272         }
00273 */
00274         //currently required for the display... should clean it up later!
00275         mypoh->clusterer.FillClusterMap(&mypoh->cluster_map);
00276         mypoh->clusterer.FillClusterMap(&mypoh->cluster_map);
00277         
00278 
00279         //look for long muons
00280         mypoh->clusterer.MakeClusters(0.02,0.05,0.01);
00281 
00282         LongMuonFinder lmf(mypoh->GetHeader().GetVldContext().GetDetector());
00283         int foundlongmuon = lmf.FindLongMuon(&mypoh->clusterer);
00284 
00285         int didMRCC=0;
00286 
00287         if(foundlongmuon )
00288         {
00289                         mypoh->eventquality.foundlongmuon=1;
00290                                 Particle3D *lp=lmf.GetParticle3D();
00291                                 
00292                                 if(lp)
00293                                 {
00294                                         std::vector<Particle3D*> pout1;
00295                                         pout1.push_back(lp);    
00296                 
00297                                         FinalizeParticles3D(pout1); //final computation of values, etc...
00298                         
00299                                         if(!DoMRCC)
00300                                         {
00301                                                 for(unsigned int i=0;i<pout1.size();i++)
00302                                                 {
00303                                                         mypoh->AddParticle3D(*(pout1[i]));
00304                                                 }
00305                                         }else{
00306                                                 MRCCInfo * mrccinfo = mypoh->GetMRCCInfo();
00307                                                 mrccinfo->removedmuon = *(pout1[0]); 
00308                                                 mrccinfo->stage=1;
00309                                                 didMRCC=1;
00310                                                 
00311                                         }               
00312                                 }
00313                                 
00314                                 //we need to store the chains to prevent further use...even if doing MRCC!
00315                                 
00316                                 int cu = mypoh->chu.NewChain();
00317                                 Chain * tempcu = mypoh->chu.GetChain(cu);
00318                                 *tempcu = *lmf.GetChain(2);
00319 
00320                                 int cv = mypoh->chv.NewChain();
00321                                 Chain * tempcv = mypoh->chv.GetChain(cv);
00322                                 *tempcv = *lmf.GetChain(3);
00323                                 
00324                                 if(DoMRCC)
00325                                 {
00326                                         SetStatus(tempcu,-10);
00327                                         SetStatus(tempcv,-10);
00328                                 }
00329                         
00330         }
00331 
00332 
00333         //cout <<"*********Currently have "<<mypoh->particles3d.size()<<" particles in POH\n";
00334         if(DoMRCC)foundlongmuon=0;//we don't want to use the muon vertex in the reco!
00335 
00336         if(lmf.FoundSingleViewLongMuon())
00337         {
00338                 mypoh->eventquality.single_view_long_muon=1;
00339                 //printf("!!!! Found a single good muon in only one view!\n");
00340         
00341         }
00342 
00343 
00344         //if we don't have a long muon, then this is probably either a NC or nue event
00345         //so lets look for a primary shower to get a fix on the event vertex
00346         mypoh->clusterer.MakeClusters(0.2,0.05,0.05);
00347 
00348 
00349         mypoh->clusterer.DumpClusters();
00350 
00351         int foundprimaryshower =0;
00352 
00353         PrimaryShowerFinder*psf = &mypoh->psf;  //mypoh has the psf for the display...
00354         psf->chu=&mypoh->chu;
00355         psf->chv=&mypoh->chv;
00356 
00357         //if foundlongmuon
00358         if(foundlongmuon)
00359         {
00360                 Particle3D *lp=lmf.GetParticle3D();
00361                 //printf("FOUND LONG MUON setting psf vertex %f %f %f\n",lp->start_u, lp->start_v, lp->start_z);
00362 
00363 
00364                 psf->SetVertex(lp->start_u, lp->start_v, lp->start_z);
00365         }
00366 
00367         foundprimaryshower = psf->FindPrimaryShower(&mypoh->clusterer);
00368 
00369 
00370         if(foundprimaryshower)
00371         {
00372                 mypoh->eventquality.foundprimaryshower=1;
00373         
00374                                 Particle3D *lp=psf->GetParticle3D();
00375                                 
00376                                 if(lp)
00377                                 {
00378                                         std::vector<Particle3D*> pout1;
00379                                         pout1.push_back(lp);    
00380                 
00381                                         FinalizeParticles3D(pout1); //final computation of values, etc...
00382 
00383                 
00384                                         if(!DoMRCC || (pout1.size()>0 && pout1[0]->particletype != Particle3D::muon) || didMRCC)
00385                                         {
00386                                                 for(unsigned int i=0;i<pout1.size();i++)
00387                                                 {
00388                                                         mypoh->AddParticle3D(*(pout1[i]));
00389                                                 }
00390                                         }else{
00391                                                 MRCCInfo * mrccinfo = mypoh->GetMRCCInfo();
00392                                                 mrccinfo->removedmuon = *(pout1[0]); 
00393                                                 mrccinfo->stage=2;
00394                                                 
00395                                         }               
00396 
00397                                 }
00398                 
00399                 //chains are being added in psf now...          
00400                 /*              
00401                                 int cu = mypoh->chu.NewChain();
00402                                 Chain * tempcu = mypoh->chu.GetChain(cu);
00403                                 *tempcu = *psf->GetChain(2);
00404 
00405                                 int cv = mypoh->chv.NewChain();
00406                                 Chain * tempcv = mypoh->chv.GetChain(cv);
00407                                 *tempcv = *psf->GetChain(3);
00408                 */              
00409                         
00410         }
00411 
00412 
00413         if(psf->FoundSingleViewPrimaryShower())
00414         {
00415                 mypoh->eventquality.single_view_primary_shower=1;
00416                 //printf("!!!! Found a single primary shower in only one view!\n");
00417         
00418         }
00419 
00420 
00421 
00422 
00423         //if foundprimaryshower
00424         if(foundprimaryshower)
00425         {
00426                 Particle3D *lp=psf->GetParticle3D();
00427                 vtx_u = lp->start_u;
00428                 vtx_v = lp->start_v;
00429                 vtx_z = lp->start_z;
00430         }       
00431         
00432         //if foundlongmuon
00433         if(foundlongmuon)
00434         {
00435                 Particle3D *lp=lmf.GetParticle3D();
00436                 
00437                 if(foundprimaryshower)
00438                 {
00439                         Particle3D *lpe=psf->GetParticle3D();
00440                         if(lpe->start_z > lp->start_z)
00441                         {
00442                                 vtx_u = lp->start_u;
00443                                 vtx_v = lp->start_v;
00444                                 vtx_z = lp->start_z;
00445                         }
00446                 }else{
00447                                 vtx_u = lp->start_u;
00448                                 vtx_v = lp->start_v;
00449                                 vtx_z = lp->start_z;            
00450                 
00451                 }
00452         }       
00453         
00454 
00455         //cout <<"*********Currently have "<<mypoh->particles3d.size()<<" particles in POH\n";
00456 
00457 //mypoh->clusterer.GetClusterSaver()->DumpClusters();
00458 
00459         //now look in clusters for tracks
00460         //remember to recluster!
00462 //      mypoh->clusterer.MakeClusters(0.2,0.05,0.05);
00463 
00464 
00465         MSG("Finder",Msg::kInfo) <<"----U----"<<endl;   
00466 
00467 
00468         
00469         ChainHelper * chu= &mypoh->chu;
00470         //Managed::ClusterManager  * clu = &mypoh->clusterer;
00471 /*      chu->max_z_gap=0.3;
00472         chu->max_slope=3;
00473         chu->SetDetector(mypoh->GetHeader().GetVldContext().GetDetector());
00474         MakeChains(clu,chu,2);
00475 */      
00476         MSG("Finder",Msg::kInfo) <<"----V----"<<endl;   
00477         
00478         ChainHelper * chv= &mypoh->chv;
00479         //Managed::ClusterManager  * clv = &mypoh->clusterer;
00480 /*      chv->max_z_gap=0.3;
00481         chv->max_slope=3;
00482         chv->SetDetector(mypoh->GetHeader().GetVldContext().GetDetector());
00483         MakeChains(clv,chv,3);
00484 */
00485 
00486  
00487         //first guess of vertex 
00488 //      FindVertex(chu,chv);
00489 //      MSG("Finder",Msg::kInfo) << "first guess - vertex at (u,v,z)  ("<< vtx_u <<", "<< vtx_v <<", "<< vtx_z <<")"<<endl;
00490 //      MSG("Finder",Msg::kInfo) << "first guess - true vertex at (u,v,z)  ("<<true_vtx_u <<", "<< true_vtx_v <<", "<< true_vtx_z <<")"<<endl;
00491 
00492         chu->print_finished();
00493         chv->print_finished();
00494 
00495 
00496 
00497         MergeChains(chu);
00498         MergeChains(chv);
00499 
00500         
00501 
00502 
00503         FindVertex(chu,chv);
00504         
00505         
00506         //if foundprimaryshower
00507         if(foundprimaryshower)
00508         {
00509                 Particle3D *lp=psf->GetParticle3D();
00510                 vtx_u = lp->start_u;
00511                 vtx_v = lp->start_v;
00512                 vtx_z = lp->start_z;
00513                 
00514         }       
00515         
00516         //if foundlongmuon
00517         if(foundlongmuon)
00518         {
00519                 Particle3D *lp=lmf.GetParticle3D();
00520                 
00521                 if(foundprimaryshower)
00522                 {
00523                         Particle3D *lpe=psf->GetParticle3D();
00524                         if(lpe->start_z > lp->start_z)
00525                         {
00526                                 vtx_u = lp->start_u;
00527                                 vtx_v = lp->start_v;
00528                                 vtx_z = lp->start_z;
00529                         }
00530                 }else{
00531                 
00532                         vtx_u = lp->start_u;
00533                         vtx_v = lp->start_v;
00534                         vtx_z = lp->start_z;            
00535                 }
00536         }       
00537                 
00538         
00539         MSG("Finder",Msg::kInfo) << "vertex at (u,v,z)  ("<< vtx_u <<", "<< vtx_v <<", "<< vtx_z <<")"<<endl;
00540         MSG("Finder",Msg::kInfo) << "true vertex at (u,v,z)  ("<<true_vtx_u <<", "<< true_vtx_v <<", "<< true_vtx_z <<")"<<endl;
00541 
00542 
00543 
00544 
00545 //      RemoveNonVertexPointingChains(chu,2);
00546 //      RemoveNonVertexPointingChains(chv,3);   
00547 
00548 
00549 
00550         chu->print_finished();
00551         chv->print_finished();
00552 
00553 //      mypoh->clusterer.GetClusterSaver()->DumpClusters();
00554 
00555         //cout <<"*********Currently have "<<mypoh->particles3d.size()<<" particles in POH\n";
00556         Weave(chu,chv);
00557         //cout <<"*********Currently have "<<mypoh->particles3d.size()<<" particles in POH\n";
00558 
00559 
00560         std::vector<Particle3D * > p3d;
00561 /*      for(int i=0;i<mypoh->particles3d1->GetEntries();i++)
00562                 p3d.push_back( (Particle3D * )mypoh->particles3d1->At(i) );
00563 */
00564 
00565         p3d.clear();
00566         for(unsigned int i=0;i<mypoh->particles3d.size();i++)
00567                 p3d.push_back(&mypoh->particles3d[i]);
00568         
00569         DumpParticle3D(p3d);
00570         //cout <<"*********Currently have "<<mypoh->particles3d.size()<<" particles in POH\n";
00571                                 
00572 /*      for (unsigned int i=0;i<p3d.size();i++)
00573         {
00574                 //ostringstream s;
00575         
00576                 Particle3D * p = p3d[i];
00577                 if (p==0)continue;
00578         
00579 //              printf("saving with parb %f\n",p->emfit_b);
00580         }
00581 */
00582 
00583 
00584         //and store event params now...
00585         mypoh->cluster_saver.recomputeBounds();
00586         mypoh->event.minu=mypoh->cluster_saver.minu;
00587         mypoh->event.maxu=mypoh->cluster_saver.maxu;
00588         mypoh->event.minv=mypoh->cluster_saver.minv;
00589         mypoh->event.maxv=mypoh->cluster_saver.maxv;
00590 
00591         mypoh->event.minz=mypoh->cluster_saver.minz;
00592         mypoh->event.maxz=mypoh->cluster_saver.maxz;
00593 
00594         //recalculate the number of strips and event energy
00595 
00596         std::map<std::pair<int,int>, double> stripmap =mypoh->cluster_saver.GetStripEnergy();
00597         std::map<std::pair<int,int>, double>::iterator it;
00598         
00599         int stripcount=0;
00600         double  stripe=0;
00601 
00602         for(it = stripmap.begin();it!=stripmap.end();it++)
00603         {
00604                 if(it->second<1e-6)continue;
00605                 stripcount++;
00606                 stripe+=it->second;
00607 //              printf("%d %d %f\n",it->first.first,it->first.second,it->second);
00608         }
00609 
00610         double olde = mypoh->event.visenergy;
00611         mypoh->event.nstrips=stripcount;
00612         mypoh->event.visenergy=stripe;
00613         mypoh->event.nclusters =  mypoh->cluster_saver.nClusters;
00614 
00615 
00616 //      printf("old e %f new e %f strips %d\n",olde,stripe,stripcount);
00617 
00618 
00619         if(stripe - olde > 1)
00620         {
00621                 MSG("Finder",Msg::kError) << "Event Energy MISMATCH! Strip SumE = "<<olde<<" new ClusterSaver Energy "<<stripe<<"\n";   
00622 
00623         }
00624 }
00625 
00626 
00627 //this will attempt to merge chains which point to eachother
00628 void Finder::MergeChains(ChainHelper *ch)
00629 {
00630 
00631         std::vector<std::pair<int,int> >match;
00632 
00633         //iter over head chains
00634         for(int i=0;i<(int)ch->finished.size();i++)
00635         {
00636                 if(ch->finished[i].parentChain>-1)continue; //make it a head chain
00637                 if(ch->finished[i].entries<2)continue;
00638                 
00639         
00640                 double bestdist=10000;
00641                 //double maxtdist=0.1;
00642                 int bestid=-1;
00643                 double bestzdist=10000;
00644                 
00645                 //iter over ends of chains
00646                 for(int j=0;j<(int)ch->finished.size();j++)
00647                 {
00648                         if(i==j)continue;
00649                         if(ch->finished[j].children.size()>0)continue; //make it and ending chain
00650                         if(ch->finished[j].entries<2)continue;
00651                         
00652                         Chain *e  = &ch->finished[j]; //end of one chain
00653                         Chain *b = &ch->finished[i];  //beginning of another chain
00654                         
00655                         if(b->start_z-e->end_z < 0.035*2)continue; // require at least 2 planes away...
00656                 //      if(e->start_z - b->start_z< 0.035*2)continue; // require at least 2 planes away...
00657                         
00658                         double d = e->end_t - (e->end_z * b->front_slope + b->front_offset);
00659                 
00660                 //      double d = maxtdist;
00661                         
00662                         //need to make sure that the chain to be attached is vertex pointing...
00663                         
00664 
00665 /*
00667                         double canslope=b->front_slope;
00668                         double canoffset=b->front_offset;
00669                         double vpslope=e->back_slope;
00670                         double vpoffset=e->back_offset;
00671                         
00672                         
00673                         double t = ( vpoffset * canslope - vpslope *canoffset ) / (canslope - vpslope);
00674                         double z = (canoffset - vpoffset) / (vpslope - canslope);                       
00675                         
00676                         
00677                         printf("vp %d a %f b %f  can %d a %f b %f ------ t %f z %f\n",e->myId,e->a, e->b,b->myId,b->a, b->b,t,z);
00678                         printf("D t %f z%f \n",t,z);
00679                                 
00680                         if( z > e->end_z && z < b->start_z) // its a possible match! --- see if its the closest match...
00681                         if( t > e->end_t && t < b->start_t ||  t < e->end_t && t > b->start_t) //make sure its not kinky
00682                         {
00683                         
00684                                 printf("found match at z %f   t %f\n",z,t);
00685                                 
00686                                 d = e->end_t - (e->end_z * b->front_slope + b->front_offset);
00687                         
00688                         }
00690 */              
00691                         
00692                         
00693 //                      if(d<maxtdist)
00694 //                      {
00695                                 double totdist = sqrt( d*d + (e->end_z-b->start_z)*(e->end_z-b->start_z));
00696                         
00697                                 double zdist  = fabs(e->end_z-b->start_z);
00698                                 if(totdist<bestdist || zdist < bestzdist)
00699                                 {
00700                                         int points=0;
00701                                         double canslope=b->front_slope;
00702                                         double canoffset=b->front_offset;
00703                                         double vpslope=e->back_slope;
00704                                         double vpoffset=e->back_offset;
00705                                         double t = 0;
00706                                         double z = 0;
00707 
00708                                         if(canslope-vpslope>1e-10)
00709                                         {
00710                                                 t = ( vpoffset * canslope - vpslope *canoffset ) / (canslope - vpslope);
00711                                                 z = (canoffset - vpoffset) / (vpslope - canslope);
00712                                         }else{
00713                                                 continue;
00714                                         }
00715 
00716                                 //      if( z > e->end_z && z < b->start_z) points=1;
00717                                         
00718                                         if(fabs(e->back_slope - b->front_slope)<0.5)points=1;
00719                                 
00720                         //              cout <<"back slope "<< e->back_slope<<" front slope "<<b->front_slope<<endl;    
00721                                         
00722                                         //between supermodules in far?
00723                                         double maxtotdist=0.5;
00724                                         if(mypoh->GetHeader().GetVldContext().GetDetector() == Detector::kFar && fabs(e->end_z - 14.6)<0.2 && fabs(b->start_z-16)<0.2)maxtotdist+=16-14.6;
00725                                 
00726                                         //in back of near (partially instrumented every fourth plane)?
00727                                         if(mypoh->GetHeader().GetVldContext().GetDetector() == Detector::kNear && e->end_z >6 && b->start_z>6)maxtotdist*=4.;
00728                                 
00729                                 
00730                                         //make sure that the connection would not be kinky
00731                                         if(points)
00732                                         {
00733                                                 if((e->end_z-b->start_z)==0)continue;// that would be kinky anyways...
00734                                                 double connecting_slope = (e->end_t-b->start_t) / (e->end_z-b->start_z);
00735                                                 
00736                                                 if(fabs(connecting_slope - b->front_slope)>=0.5)points=0;
00737                                                 if(fabs(e->back_slope - connecting_slope)>=0.5)points=0;                                        
00738                                         }
00739                                 
00740                                         
00741                                         
00742                                         if(!points /*&& totdist>maxtotdist*/)
00743                                         {
00744                                                 MSG("Finder",Msg::kDebug) << "failing on points "<<e->myId <<" to "<< b->myId<<" totdist "<< totdist<<" zdist "<<zdist <<" tdist "<<d <<" intersection at z t"<<z<<" "<<t<<"\n";
00745                                                 continue;
00746                                         }
00747                                         
00748                                         
00749                                         
00750                                         bestdist=totdist;
00751                                         bestid=e->myId;
00752                                         bestzdist=zdist;
00753                                         
00754                                         MSG("Finder",Msg::kDebug) << "found better match "<<e->myId <<" to "<< b->myId<<" totdist "<< totdist<<" zdist "<<zdist <<" tdist "<<d <<"\n";
00755                                         
00756                                 }
00757                         }       
00758                         
00759 //              }
00760                 
00761                 
00762                 if(bestid>-1)
00763                 {
00764                         match.push_back(std::pair<int,int>(bestid,ch->finished[i].myId));
00765                 
00766                         MSG("Finder",Msg::kDebug) <<"!!!matched "<<bestid<<" "<<ch->finished[i].myId<<"\n";
00767                 
00768                 }
00769         }
00770         
00771         
00772         for(int i=0;i<(int)match.size();i++)
00773         {
00774                 ch->AttachAsChild(ch->GetChain(match[i].first),ch->GetChain(match[i].second));
00775         
00776         }
00777 
00778 
00779 
00780 }
00781 
00782 
00783 
00784 
00785 
00786 //after finding a vertex, run this function to remove chains that either do not point to the vertex  
00787 // or do not point to another chain that points to the vertex...
00788 // if the chain points to another chain that points to the vertex, then connect them!
00789 //
00790 //  this will use the chains slope and offset... but if there are multiple chains, with the first few only having a few hits
00791 //  then a new slope and offset should be constructed....   (not for now)
00792 //
00793 void Finder::RemoveNonVertexPointingChains(ChainHelper *ch, int view)
00794 {
00795 
00796         double max_dt = 0.1; // max distance of chain pointing to vertex z from vertex in t
00797 
00798         double vt =0.0;
00799         if(view==2) vt=vtx_u;
00800         if(view==3) vt=vtx_v;
00801 
00802 
00803         std::vector<int> marked;
00804         std::vector<int> vtxpointing;
00805         std::vector<int> head;
00806 
00807 
00808 
00809         for(unsigned int i=0;i<ch->finished.size();i++)
00810         {       
00811                 ostringstream os;
00812                 
00813                 //here is where we can reverse chains if they point the wrong way
00814                 //chain begin should be closer to the vertex than the end....
00815                 
00816                 
00817                 
00818                 
00820 /*              
00821                 os << "Chain id " << ch->finished[i].myId << " entries: " << ch->finished[i].entries<< " extrap posvtx: " <<  ch->finished[i].avg_slope * vtx_z + ch->finished[i].avg_offset << " vtxt " << vt << "  diff " <<fabs(vt - (ch->finished[i].avg_slope * vtx_z + ch->finished[i].avg_offset) ) ;
00822         
00823                 if(ch->finished[i].entries>1)
00824                 if(ch->finished[i].parentChain<0 || (ch->finished[i].level==1 && ch->GetChain(ch->finished[i].parentChain)->entries==1) ) //only look at head chains...         
00825                 if(max_dt < fabs(vt - (ch->finished[i].avg_slope * vtx_z + ch->finished[i].avg_offset) ) )
00826                 {
00827                         //its too far away...
00828                         //throw it out
00829                         marked.push_back(ch->finished[i].myId);
00830                         
00831                         os << "not pointing to vertex ";
00832                         
00833                 }else{
00834                         vtxpointing.push_back(ch->finished[i].myId);
00835                 }
00836                 MSG("Finder",Msg::kInfo) << os.str() << endl; 
00837 */
00838 
00839 
00840                 int close_enough=0;
00841                 double diff = fabs(vt - (ch->finished[i].front_slope * vtx_z + ch->finished[i].front_offset) );
00842                 close_enough = max_dt > diff;
00843                 
00844 os << "Chain id " << ch->finished[i].myId << " entries: " << ch->finished[i].entries<< " extrap posvtx: " <<  ch->finished[i].front_slope * vtx_z + ch->finished[i].front_offset << " vtxt " << vt<<" diff "<<diff<<endl;
00845                                 
00846                 //using interpolation is probably just better for finding hits to attach...
00847                 diff = fabs(vt - ch->finished[i].interpolate(vtx_z) );
00848                 if(!close_enough)close_enough = max_dt > diff;
00849 
00850                 os << "Chain id " << ch->finished[i].myId << " entries: " << ch->finished[i].entries<< " extrap posvtx: " <<  ch->finished[i].interpolate(vtx_z)  << " vtxt " << vt<<" diff "<<diff<<endl;              
00851 
00852                 //using interpolation is probably just better for finding hits to attach...
00853                 diff = fabs(vt - (ch->finished[i].avg_slope * vtx_z + ch->finished[i].avg_offset) );
00854                 if(!close_enough)close_enough = max_dt > diff;
00855                 
00856                 
00857 
00858 
00859                 os << "Chain id " << ch->finished[i].myId << " entries: " << ch->finished[i].entries<< " extrap posvtx: " <<  (ch->finished[i].avg_slope * vtx_z + ch->finished[i].avg_offset)  << " vtxt " << vt <<" diff "<<diff;
00860         
00861                 if(ch->finished[i].entries>1)
00862                 if(ch->finished[i].parentChain<0 || (ch->finished[i].level==1 && ch->GetChain(ch->finished[i].parentChain)->entries==1) ) //only look at head chains...         
00863                 if(!close_enough)
00864                 {
00865                         //its too far away...
00866                         //throw it out
00867                         marked.push_back(ch->finished[i].myId);
00868                         
00869                         os << " not pointing to vertex ";
00870                         
00871                 }else{
00872                         vtxpointing.push_back(ch->finished[i].myId);
00873                 }
00874                 MSG("Finder",Msg::kInfo) << os.str() << endl;
00875 
00876 
00877         }
00878         
00879         
00880         std::vector<int> todel;
00881         
00882         for (unsigned int i=0;i<marked.size();i++)
00883         {
00884                 //see if the chain is pointing to a vertexpointing chain....  if so, attach it...
00885                 //see if the projections cross somewhere between the start of the vertexpointing chain and the start of the candidate chain
00886                 
00887                 Chain * can = ch->GetChain(marked[i]);
00888                 
00889                 if(can->entries<2)continue;
00890                 
00891                 
00892                 double bestdist = 100000;
00893                 int bestpid = -1;
00894                 double attachpoint=0;
00895                 
00896                 for(unsigned int j=0;j<vtxpointing.size();j++)
00897                 {
00898                         //printf("looking to see if it points to a good chain for attachment....\n");
00899                 
00900                         Chain *vp = ch->GetChain(vtxpointing[j]);
00901                         //printf("A\n");        
00902                         if(vp->entries<2)continue;
00903                 
00904                         //printf("B\n");        
00905                         if(fabs(vp->a - can->a) < 0.000001)continue;  //dont want a fpe
00906                         //printf("C\n");        
00907                         if(can->start_z < vp->start_z)continue;
00908                         
00909         //              double t = ( vp->b * can->a - vp->a * can->b ) / (can->a - vp->a);
00910         //              double z = (can->b - vp->b) / (vp->a - can->a);
00911         
00912                 
00913 //                      double t = ( vp->a * can->b - vp->b * can->a ) / (can->b - vp->b);
00914 //                      double z = (can->a - vp->a) / (vp->b - can->b);
00915                 
00916 
00917                         double canslope=can->front_slope;
00918                         double canoffset=can->front_offset;
00919                         double vpslope=vp->front_slope;
00920                         double vpoffset=vp->front_offset;
00921                         
00922                         
00923                         double t = ( vpoffset * canslope - vpslope *canoffset ) / (canslope - vpslope);
00924                         double z = (canoffset - vpoffset) / (vpslope - canslope);                       
00925                         
00926                         
00927                         //printf("vp a %f b %f  can a %f b %f ------ t %f z %f\n",vp->a, vp->b,can->a, can->b,t,z);
00928                         
00929                         
00930                         
00931                 //      z+=vp->start_z;
00932                         //printf("D t %f z%f \n",t,z);  
00933                         if( z > vp->start_z && z < can->start_z) // its a possible match! --- see if its the closest match...
00934                         {
00935                         
00936                                 //printf("found match at z %f   t %f\n",z,t);
00937                                 
00938                                 double bd = bestdist+1  ;
00939                         
00940                                 attachpoint =z;
00941                         
00942                                 if( z < vp->end_z) // attach to middle of chain...
00943                                 {
00944                                         //printf("!!!! need to attach to middle of chain!!!\n");
00945                                         bd = sqrt ( (can->start_z-z)*(can->start_z-z) + (can->start_t - t)*(can->start_t - t));
00946                                         bestpid = vp->myId;
00947                                         
00948                                 }else{
00949                                         //printf("attach to end of chain\n");
00950                                         bd = sqrt ( (vp->end_z-can->start_z)*(vp->end_z-can->start_z) + (vp->end_t - can->start_t)*(vp->end_t - can->start_t));
00951                                 }
00952                                 if(bd<bestdist)
00953                                 {
00954                                         bestdist=bd;
00955                                         bestpid = vp->myId;
00956                                 }
00957                         }
00958                 }
00959                 
00960                 
00961         
00962         
00963                 //if not, delete it
00964                 if(bestpid>-1)
00965                 {
00966                         if(attachpoint < ch->GetChain(bestpid)->end_z) //need to break apart vertex pointing chain
00967                         {
00968                                 Chain * np = ch->SplitAt(ch->GetChain(bestpid),attachpoint);  //returns the chain that now ends at attachpoint
00969                 
00970                                 ch->AttachAsChild(np,can);
00971                 //              can->parentChain = np->myId;
00972                 //              np->children.push_back(can->myId);
00973                         
00974                         }else{   //just attach to the end
00975                         
00976                                 ch->AttachAsChild(ch->GetChain(bestpid),can);
00977                 //              can->parentChain = bestpid;
00978                 //              ch->GetChain(bestpid)->children.push_back(can->myId);
00979                         }
00980                 }else{
00981                         todel.push_back(marked[i]);
00982                 }
00983         }
00984         
00985 
00986 
00987         
00988         
00989         for(unsigned int i=0;i<todel.size();i++)
00990                 ch->DeleteChain(todel[i]);
00991                 
00992         
00993         
00994         
00995         ostringstream os;
00996         os << "remaing chains: ";
00997         for(unsigned int i=0;i<ch->finished.size();i++)
00998         {
00999                 os << ch->finished[i].myId<< " ";
01000         }
01001         
01002         MSG("Finder",Msg::kInfo) << os.str() << endl; 
01003 }
01004 
01005 
01006 
01007 
01008 
01009 void Finder::FindMuons(ChainHelper *ch)
01010 {
01011 
01012 
01013 //travel over chain - if we have at least two muon like hits, make a new muon chain going out to last muon hit
01014         //this new chain starts at first hit in the chain, and is not part of the primary chain
01015         //all muon like hits have all energy moved to new chain
01016         //larger hits have some average muon energy removed!
01017         
01018         
01019 
01020         std::vector<int> path = ch->FindMaxPath();
01021         if(path.size()<1)return;
01022 
01023 
01024         std::vector< std::pair<int,int> > muonlike;
01025         std::vector<double> muonlikee;
01026         
01027         int lastconsec=0;
01028         
01029         double avgmuon=0;
01030         int amuon=0;
01031         
01032         for(int i=0;i<(int)path.size();i++)
01033         {
01034         
01035                 MSG("Finder",Msg::kDebug) <<"path chain "<<path[i]<<endl;
01036                 int head=(i>0)?1:0;
01037                 for(int j=head;j<ch->GetChain(path[i])->entries;j++)
01038                 {
01039                         double e = ch->GetChain(path[i])->e[j];
01040                         if(e<2 && e>0.5){
01041                                 if((i!=(int)path.size()-1 || j!=ch->GetChain(path[i])->entries-1) || amuon>0)  
01042                                 //don't add if the only muonlike hit is at the end of a long chain
01043                                 //it could be a low energy shower hit!
01044                                 {
01045                                         muonlike.push_back(std::make_pair(path[i],j));
01046                                         muonlikee.push_back(e);
01047                                         avgmuon+=e;
01048                                         amuon++;
01049                                         lastconsec++;
01050                                 }
01051                         
01052                         }else{
01053                         
01054                                 if(i==(int)path.size()-1 && j>0)
01055                                 if(e<6.0*ch->GetChain(path[i])->e[j-1])  //try not to take overlapping large hits
01056                                 {
01057                                         if(lastconsec>0)
01058                                         {
01059                                                 muonlike.push_back(std::make_pair(path[i],j));
01060                                                 muonlikee.push_back(e);
01061                                         }
01062                                 }else{
01063                                         lastconsec=0;
01064                                 }       
01065                         }
01066                 }
01067         }
01068         
01069         if(amuon==0)return; //no muon hits found!
01070         
01071         
01072         avgmuon/=amuon;
01073         
01074 //      double avgmuon;
01075 //      for(int i=0;i<muonlikee.size();i++)
01076 //              avgmuon+=muonlikee[i];
01077 //      avgmuon/=muonlikee.size();
01078         
01079         //subtract out found muon hits
01080 //      for(int i=0;i<muonlike.size();i++)
01081 //              ch->GetChain(muonlike[i].first)->e[muonlike[i].second]=0.0;
01082         
01083         
01084         //subtract out avgmuon from all hits greater than avgmuon
01085         //make new chain, with found levels, and avglevels for rest
01086         int cid = ch->NewChain();
01087         Chain * c = ch->GetChain(cid);
01088 
01089 
01090 
01091 //      Chain c;
01092 
01093         for(unsigned int i=0;i<path.size();i++)
01094         {
01095                 int head=i>0?1:0;
01096                 
01097                 Chain * d = ch->GetChain(path[i]);
01098                 
01099                 if(d==0)
01100                 {
01101                         MSG("Finder",Msg::kError) <<"Bad path chain used - chain id "<<path[i]<<endl;
01102                         continue;
01103                 
01104                 }
01105                 
01106                 for(int j=head;j<d->entries;j++)
01107                 {
01108         //              double e = 0;
01109 /*              
01110                         if(d->e[j]>avgmuon)
01111                         {       d->e[j]-=avgmuon;
01112                                 e=avgmuon;
01113                         }else{
01114                                 e=d->e[j];
01115                                 
01116                         
01117                         
01118                         
01119                 //      double e = d->e[j];
01120                         for(int k=0;k<muonlike.size();k++)
01121                         {
01122                                 if(muonlike[k].first==path[i] && muonlike[k].second==j)
01123                                 {
01124                                         e= e > muonlikee[k] ? muonlikee[k] : e;
01125                                 }
01126                         }
01127                                 d->e[j]-=e;
01128                         }
01129 */
01130 
01131                         
01132                         //if(d->e[j]>avgmuon)d->e[j]-=avgmuon;
01133                         //double e = d->e[j];
01134                         
01135                         int found =0;
01136                         double e=0;
01137                         for(unsigned int k=0;k<muonlike.size();k++)
01138                         {
01139                                 if(muonlike[k].first==path[i] && muonlike[k].second==j)
01140                                 {
01141                                         e= muonlikee[k];
01142                                         found=1;
01143                                         break;
01144                                 }
01145                         }
01146                         if(found) //we already taged it as muon like - so move the hit
01147                         {
01148                                 //e=d->e[j];
01149                                 d->e[j]=0;
01150                         }else{
01151                                 e=avgmuon;
01152                                 d->e[j]-=avgmuon;
01153                         }
01154 
01155 
01156                 
01157                         if(e>0)
01158                         {       c->add_to_back(d->t[j],d->z[j],e,-1);
01159                                 MSG("Finder",Msg::kDebug) <<"muon adding "<< path[i] <<", "<< j<<" energy "<<e <<endl;
01160                         }
01161                 }
01162                 
01163                 
01164                 d->Recalc(); //remove the hits that we set e to 0 from the chain 
01165         }
01166         
01167         
01168 //print out chain ids....
01169 
01170 //      int cid = ch->NewChain();
01171   //  Chain * e =ch->GetChain(cid);
01172   //  *e = c;
01173         
01174         
01175         //attach new chain to current head....
01176 // //   c.parentChain=ch->GetChain(path[0]).myId;
01177 
01178         //ch->AttachAsChild(ch->GetChain(path[0]),c);
01179         
01180         c->particletype=Particle3D::muon; //say that we think it is a muon
01181         
01182         //add new chain to finished
01183 //      Chain d = *c;
01184         ch->particles.push_back(*c);    
01185         delete c;       
01186 
01187 }
01188 
01189 
01190 
01191 void Finder::MakeChains(Managed::ClusterManager  *cl, ChainHelper * ch, int view)
01192 {
01193 
01194         if(mypoh->event.vtx_z>0)
01195         {
01196                 ch->vtx_z=mypoh->event.vtx_z;
01197                 ch->vtx_t=view==2?mypoh->event.vtx_u:mypoh->event.vtx_v;
01198                 
01199         }
01200 
01201 
01202      std::map<double, std::map<double, int> >::iterator p_iterr;
01203      std::map<double, int >::iterator s_iterr;
01204 
01205      double lastz=-1;
01206      for(p_iterr=cl->GetClusterMap(view)->begin();p_iterr!=cl->GetClusterMap(view)->end(); p_iterr++)
01207      {
01208         //for the first one...
01209                 if(lastz==-1)lastz=p_iterr->first;
01210                 
01211                 
01212                 if(fabs(p_iterr->first - lastz) > 0.01)
01213                 {
01214                         ch->process_plane();
01215                         lastz=p_iterr->first;
01216                         //printf("process plane\n");
01217                 }
01218       
01219 
01220          for(s_iterr=p_iterr->second.begin();s_iterr!=p_iterr->second.end(); s_iterr++)
01221          {
01222 
01223       
01224                 Managed::ManagedCluster * c = cl->GetCluster(s_iterr->second);
01225                 if(!c)
01226                 {
01227                         //printf("!!! bad cluster map! finder.cxx around 897\n");
01228                         continue;
01229                 }
01230                 //printf("t %f z %f e %f id %d\n",s_iterr->first, p_iterr->first, c->e,c->id);
01231                 ch->add_to_plane(s_iterr->first, p_iterr->first, c->e,c->id);   
01232              }
01233 // ch->process_plane();
01234         
01235      }
01236      
01237      ch->process_plane();
01238  
01239         ch->finish();
01240         ch->print_finished();
01241         ch->FindMaxPath();
01242 
01243 }
01244 
01245 
01246 void Finder::FindVertex(ChainHelper * cu, ChainHelper * cv)
01247 {
01248         std::vector<int> mpu = cu->FindMaxPath();
01249         std::vector<int> mpv = cv->FindMaxPath();
01250         
01251         if(mpu.size() <1 || mpv.size() <1)return;
01252         
01253         
01254         double cu_t = cu->GetChain(mpu[0])->start_t;
01255         double cu_z = cu->GetChain(mpu[0])->start_z;
01256 
01257         double cv_t = cv->GetChain(mpv[0])->start_t;
01258         double cv_z = cv->GetChain(mpv[0])->start_z;    
01259         
01260         
01262         //try iterating through, measuring dt between adjacent hits in chain.
01263         //go through until dt(0,1)-dt(1,2)<thresh
01264         
01265         
01266 /*      int forcedadvancedu=0;
01267         int forcedadvancedv=0;
01268 */
01269         
01270 
01271 MSG("Finder",Msg::kDebug)<< "cuz " << cu_z <<" cvz "<< cv_z <<endl;
01272         
01273         
01275 /*      
01276         if((forcedadvancedu && forcedadvancedv) || (!forcedadvancedu && !forcedadvancedv))
01277         {
01278         
01279                 if(cv_z<cu_z)
01280                         cu_z=cv_z;
01281                 else
01282                         cv_z=cu_z;
01283         }else{
01284                 if(forcedadvancedu)
01285                         cv_z=cu_z;
01286                 if(forcedadvancedv)
01287                         cu_z=cv_z;
01288         }
01289 */              
01290 
01291 
01292 
01293                 if(cv_z<cu_z)
01294                         cu_z=cv_z;
01295                 else
01296                         cv_z=cu_z;
01297                         
01298 
01299                 int chuid=0;
01300                 
01301         //      if(cu->GetChain(mpu[0]).start_z<cu_z)
01302                 for(unsigned int i=0;i<mpu.size();i++)
01303                 {
01304                         if ( ( cu->GetChain(mpu[i])->start_z <= cu_z && cu->GetChain(mpu[i])->end_z >= cu_z )
01305                                  || (cu->GetChain(mpu[i])->start_z >= cu_z && cu->GetChain(mpu[i])->end_z <= cu_z))
01306                         {
01307                                 chuid=i;
01308                                 
01309                         }
01310                 }
01311                 
01312                 if(cu->GetChain(mpu[0])->entries<2 && mpu.size()>1)chuid=1;
01313                 
01314                 
01315                 int chvid=0;
01316                 
01317         //      if(cv->GetChain(mpv[0]).start_z<cv_z)
01318                 for(unsigned int i=0;i<mpv.size();i++)
01319                 {
01320                         if ( ( cv->GetChain(mpv[i])->start_z <= cv_z && cv->GetChain(mpv[i])->end_z >= cv_z )
01321                                  || (cv->GetChain(mpv[i])->start_z >= cv_z && cv->GetChain(mpv[i])->end_z <= cv_z))
01322                         {
01323                                 chvid=i;
01324                                 
01325                         }
01326                 }
01327         
01328                 if(cv->GetChain(mpv[0])->entries<2 && mpv.size()>1)chvid=1;
01329                 //printf("chain has %d entries, path has %d entries\n",cv->GetChain(mpv[0])->entries,mpv.size());
01330 
01331                 /*
01332                 printf("uchain\n");
01333                 for(unsigned int i=0;i<mpu.size();i++)printf("%d\n",mpu[i]);
01334                 printf("vchain\n");
01335                 for(unsigned int i=0;i<mpv.size();i++)printf("%d\n",mpv[i]);
01336         */      
01337                 
01338                         Chain * uuu = cu->GetChain(mpu[chuid]);
01339                         Chain * vvv =  cv->GetChain(mpv[chvid]);
01340                 
01341                 
01342                 
01343                         cu_z = uuu->start_z;
01344                         cv_z = vvv->start_z;
01345                 
01346                         if(cv_z<cu_z)
01347                         {
01348                                 cu_z=cv_z;
01349                         }
01350                         else
01351                         {
01352                                 cv_z=cu_z;
01353 
01354                         }
01355                 
01356                 
01357                         double tmpuz=0;
01358                         double tmpvz=0;
01359                         
01360                 //      double slopeu = cu->GetChain(mpu[chuid])->avg_slope;
01361                 //      double bzu = cu->GetChain(mpu[chuid])->start_z;
01362                 //      double btu = cu->GetChain(mpu[chuid])->start_t;
01363                         //double bt = cu->GetChain(mpu[chuid])->weighted_t;
01364                         
01365                                         //see if there is a big energy difference between the first 2 hits... if so, we probably want the 2nd hit
01366                                         if(uuu->entries>1 && uuu->e[0] < uuu->e[1]*0.2 )
01367                                         {
01368                                                 //bz = uuu->z[1];
01369                                                 //bt = uuu->t[1];
01370                                                 tmpuz=uuu->z[1];
01371                                                 cu_z=uuu->z[1];
01372                                         }
01373                                         else if(uuu->entries>2 && uuu->e[1] < uuu->e[2]*0.2 )
01374                                         {
01375                                                 //bz = uuu->z[2];
01376                                                 //bt = uuu->t[2];
01377                                                 tmpuz=uuu->z[2];
01378                                                 cu_z=uuu->z[1];
01379                                         }
01380                         
01381                         
01382 
01383 
01384         
01385         
01386                         
01387 //                      double slopev = cv->GetChain(mpv[chvid])->avg_slope;
01388 //                      double bzv = cv->GetChain(mpv[chvid])->start_z;
01389 //                      double btv = cv->GetChain(mpv[chvid])->start_t;
01390 
01391                         //double slopev = cv->GetChain(mpv[chvid])->front_slope;
01392                         //double offsetv = cv->GetChain(mpv[chvid])->front_offset;
01393                         //double slopeu = cu->GetChain(mpu[chuid])->front_slope;
01394                         //double offsetu = cu->GetChain(mpu[chuid])->front_offset;
01395 
01396                                                 
01397                                         if(vvv->entries>1 && vvv->e[0] < vvv->e[1]*0.2 )
01398                                         {
01399                                                 //bz = vvv->z[1];
01400                                                 //bt = vvv->t[1];
01401                                                 tmpvz=vvv->z[1];
01402                                                 cv_z=vvv->z[1];
01403                                         }
01404                                         else if(vvv->entries>2 && vvv->e[1] < vvv->e[2]*0.2 )
01405                                         {
01406                                         //      bz = vvv->z[2];
01407                                         //      bt = vvv->t[2];
01408                                                 tmpvz=vvv->z[2];
01409                                                 cv_z=vvv->z[2];
01410                                         }
01411 
01412                         //bt = cv->GetChain(mpv[chvid])->weighted_t;
01413                         
01414                 
01416 
01417                 
01418         vtx_z=cu_z<cv_z?cu_z:cv_z;
01419         
01420 //      if(tmpuz>0 && tmpvz == 0){ vtx_z=tmpuz; cu_z = vtx_z; }
01421 //      if(tmpvz>0 && tmpuz == 0){ vtx_z=tmpvz; cv_z = vtx_z;}
01422 //      if(tmpuz>0 && tmpvz > 0){ vtx_z=tmpuz<tmpvz ? tmpuz:tmpvz;  cu_z=vtx_z; cv_z=vtx_z; }           
01423                 
01424         //vtx_z-= 0.04;         
01425         
01426         
01427                 
01428                         //if we have a hit at the right z spot, use that t, otherwise extrapolate
01429                         if(fabs(vtx_z-uuu->z[0])<0.01)
01430                         {
01431                                 cu_t = uuu->t[0];
01432                         }else{
01433                                 
01434                                 double oldcut=cu_t;                     
01435                         //      cu_t = slopeu*(-bzu+cu_z) + btu;
01437                 
01438                         cu_t = uuu->interpolate(vtx_z);
01439                 
01440                         
01441                                 MSG("Finder",Msg::kDebug) << "using chain "<< mpu[chuid]<<" "<<cu->GetChain(mpu[chuid])->myId <<" for slope, moving ut from "<< oldcut <<" to "<< cu_t <<endl;
01442                         }
01443         
01444 
01445                         if(fabs(vtx_z-vvv->z[0])<0.01)
01446                         {
01447                                 cv_t = vvv->t[0];
01448                         }else{
01449                                                 
01450                                 double oldcut=cv_t;
01451                                 //cv_t = slopev*(-bzv+cv_z) + btv;              
01452 
01453                                 //cv_t = slopev * vtx_z + offsetv;
01454 
01455                         cv_t = vvv->interpolate(vtx_z);
01456 
01457 
01458                                 MSG("Finder",Msg::kDebug) << "using chain "<< mpv[chvid]<<" "<<cv->GetChain(mpv[chvid])->myId <<" for slope, moving ut from "<< oldcut <<" to "<< cv_t <<endl;
01459                         }
01460         
01461         
01462 
01463         
01464         //we should see if there is a chain path that passes close to this vertex
01465         //that is, if the found vertex is between the beginning and end of this chain, the chain should be split at the vertex, have the front part reversed
01466         //and the vertex should be adjusted to fall on this chain
01467         
01468         for(int q=0;q<2;q++)
01469         {
01470         
01471         ChainHelper * ch = q==0? cu:cv;
01472         
01473         for(unsigned int i=0;i<ch->finished.size();i++)
01474         {
01475                 if(ch->finished[i].start_z > vtx_z) continue;
01476                 std::vector<foundpath> paths = ch->FindPaths(ch->GetChain(ch->finished[i].myId));
01477                 
01478                 //find the chain where we would need to split....
01479                 for(unsigned int p =0;p<paths.size();p++)
01480                 {
01481         
01482                         //make sure the path is sufficiently far from the split point
01483                         if(! ( paths[p].start_z < vtx_z - 0.04 && paths[p].end_z > vtx_z + 0.04) )break;
01484         
01485                         int getp=-1;
01486                         for(unsigned int j=0;j<paths[p].path.size();j++)
01487                         {
01488                                 getp = paths[p].path[j];
01489                                 if(ch->GetChain(getp)->start_z < vtx_z -0.03 && ch->GetChain(getp)->end_z >= vtx_z+0.03)break;
01490                                 getp=-1;
01491                         }
01492                         if(getp<0)continue;
01493 
01494                 
01495         //              cout <<"WANT TO SPLIT "<<getp << " AT " <<vtx_z<<endl;
01496                 
01497                         Chain * m = ch->GetChain(getp);
01498                         //if its close to the vertex, ajust vertex position
01499                         
01500                         int pt_bef=-1;
01501                         int pt_aft=-1;
01502                         for(int j=1;j<m->entries;j++)
01503                         {
01504                                 if(m->z[j-1]<=vtx_z && m->z[j]>=vtx_z)
01505                                 {
01506                                         pt_bef=j-1;
01507                                         pt_aft=j;
01508                                         break;
01509                                 }
01510                         }
01511                 
01512 //                      cout<<"recalculating t from idx "<<pt_bef<<" "<<pt_aft<<endl;
01513                 
01514                         if(pt_bef>-1 && pt_aft>-1)
01515                         {
01516                                 double dt = m->t[pt_aft]-m->t[pt_bef];
01517                                 double dz = m->z[pt_aft]-m->z[pt_bef];
01518                         
01519                 //              cout << "dt "<<dt <<" dz "<<dz<<endl;
01520                         
01521                                 double vt=0;
01522                                 if(dt<0.0001)vt=m->t[pt_aft];
01523                                 
01524                                 else vt = (vtx_z-m->z[pt_bef]) * dt/dz + m->t[pt_bef];
01525                                 
01526                                 double oldt = q==0?cu_t:cv_t;
01527                                 
01528                 //              cout <<"old t "<<oldt << " new t "<<vt<<endl;
01529                                 
01530                                 if(fabs(oldt-vt)<0.05)
01531                                 {
01532                                         if(q==0)cu_t=vt;
01533                                         if(q==1)cv_t=vt;
01534                                 }
01535                         }
01536                 
01537                         
01538                         
01539                         Chain * d = ch->SplitAt(m,vtx_z);
01540                         
01541                         if(d->children.size()<1)continue; //unable to split the chain...
01542                         
01543                         //d->parentChain=-1;
01544                         d->level=0;
01545                         for(unsigned int chi =0;chi<d->children.size();chi++)
01546                         {
01547                                 Chain * cld = ch->GetChain(d->children[chi]);
01548                                 if(cld){
01549                                         cld->parentChain=-1;
01550                                 }
01551                         }
01552                         
01553                         Chain*p = ch->GetChain(d->parentChain);
01554                         if(p){
01555                                         for(unsigned int i=0;i<p->children.size();i++)
01556                                         {
01557                                         if(p->children[i]==d->myId)
01558                                         {
01559                                                 p->children.erase(p->children.begin()+i);
01560                         
01561                         //                      cout<<"\t reversal causing removing of child reference from parent "<<d->parentChain<<endl;
01562                         
01563                                                 break;  
01564                                         }
01565                                         }       
01566                         }
01567                         d->parentChain=-1;
01568                         
01569                         d->children.clear();
01570                         d->Reverse();
01571                         
01572                 }
01573         
01574         }
01575         
01576         
01577         }
01578         
01579 
01580         
01581 //      vtx_z-= 0.04;//0.025;  //event is usually before first hit.... make it better later, based on if this looks like a proton (indicating event forward of strip), or if this is a low hit strip(indicating hit well inside steel)
01582         
01583         vtx_u=cu_t;
01584         vtx_v=cv_t;
01585 
01586 }
01587 
01588 
01589 
01590 
01591 void Finder::FindIsolatedHits()
01592 {
01593 
01594         printf("dont use Finder::FindIsolatedHits()\n");
01595         exit(1);
01596 
01597         double minthreshold = 0.5;  //peak must be at least this big
01598         double peakfraction = 0.85;  //fraction of energy in peak in this single strip
01599 
01600         //iterate until all isolated peaks are exhaused....
01601 
01602 
01603       
01604 
01605         for(std::multimap<double,int>::reverse_iterator iter = sorter_map.rbegin(); iter!=sorter_map.rend();iter++)
01606         {
01607 
01608         //for now, just look for max
01609 
01610         int maxi=-1;
01611         double maxe=0;
01612 
01613         int p=0;
01614         int c=0;
01615 
01616         double st=0;
01617         double sz=0;
01618 
01619 
01620 
01621         double locale=iter->first;
01622 
01623         maxi = iter->second;
01624         int i = maxi;
01625                         maxe=energy[i];
01626                         p=plane[i];
01627                         c=strip[i];
01628                         st=t[i];
01629                         sz=z[i];
01630         MSG("Finder",Msg::kDebug) <<"isolated hit peak at plane, cell " << p << " "<< c << " with energy " << maxe <<endl;
01631 
01632 
01633 
01634         if(maxe<minthreshold)break; //since iteration is in e order, all further entries will also be below threshold
01635 
01636 
01637 
01638 
01639         for(unsigned int i=0;i<plane.size();i++)
01640         {
01641 //              if(plane[i]==p && abs(strip[i]-c)==1)locale+=energy[i];
01642 //              if(strip[i]==c && abs(plane[i]-p)==1)locale+=energy[i];
01643 
01644                 if(plane[i]==p && abs(strip[i]-c)==1)locale+=energy[i];
01645 
01646 
01647         }
01648 
01649 
01650 
01651         MSG("Finder",Msg::kDebug) << "peak "<< maxe/locale << " "<< maxe << " "<< p << " "<< sz << " " << sz/(1.0*p) <<endl;
01652         if(maxe/locale>peakfraction) //add particle
01653         {
01654                 Particle ptemp;
01655                 ptemp.begPlane=p;
01656                 ptemp.endPlane=p;
01657                 ptemp.begStrip=c;
01658                 ptemp.endStrip=c;
01659                 ptemp.stripEnergy=maxe - (locale-maxe) /4;  //assign the energy above the local average
01660                 ptemp.type=2112; //2112 neut 2212 prot
01661                 ptemp.endz=sz;
01662                 ptemp.begz=sz;
01663                 ptemp.endt=st;
01664                 ptemp.begt=st;
01665 
01666                 ptemp.plane.push_back(p);
01667                 ptemp.strip.push_back(c);
01668                 ptemp.energy.push_back(ptemp.stripEnergy);
01669                 
01670 
01671 
01672                 MSG("Finder",Msg::kDebug) <<"p at "<< p <<" "<< c <<" "<< st <<" "<< sz<<endl;
01673 
01674                 particles.push_back(ptemp);
01675 
01676         
01677                 //adjust the energy in the peak map, removing the value assigned to this hit, and replacing it with remaining value
01678 //              sorter_map.erase((--iter).base());
01679 //              sorter_map.insert(std::pair <double,int>((locale-maxe) /4, (int)energy.size()));        
01680 
01681 
01682 
01683 
01684 
01685         }else{continue;}
01686 
01687                 
01688         }
01689 
01690 
01691 }
01692 
01693 
01694 
01695 std::vector<std::pair<int,int> > Finder::matchViews(std::vector<foundpath> pu, std::vector<foundpath> pv)
01696 {
01697         std::vector<std::pair<int,int> >matches;
01698         
01699 //      cout <<"views sizes "<<pu.size()<<" "<<pv.size()<<endl;
01700         for(unsigned int i=0;i<pu.size();i++)
01701         {
01702 
01703                 std::vector<std::pair<int,int> >zmatches;
01704 
01705 MSG("Finder",Msg::kDebug) <<"--- "<<i<<endl;
01706 
01707                 //if(pu[i].entries<2)continue;
01708         
01709                 std::vector<double> zoverlap;   
01710         
01711                 for(unsigned int j=0;j<pv.size();j++)
01712                 {
01713 
01714 MSG("Finder",Msg::kDebug) <<"----- "<<j<<endl;
01715 
01716                 //      if(pv[j].entries<2)continue;
01717                 
01718                         if((pu[i].entries==1 && pv[j].entries>2 )|| (pu[i].entries>2 && pv[j].entries==1 ))
01719                         {
01720                         
01721                                 zoverlap.push_back(0.0);
01722                                 continue; //don't match single hit with path longer than 2
01723                         }
01724                         
01725                         
01726         MSG("Finder",Msg::kDebug)<< "looking at "<<i << "  "<<j<<endl;
01727         MSG("Finder",Msg::kDebug) << " pu ent " << pu[i].entries << " pv ent " << pv[j].entries<<endl;
01728                 
01729                 
01730                         double o=0.0;
01731                         if(pu[i].start_z>pv[j].end_z || pu[i].end_z < pv[j].start_z) //no overlap!
01732                         {
01733                                 zoverlap.push_back(o);
01734                                 
01735                         MSG("Finder",Msg::kDebug) << "no overlap " << pu[i].start_z << " to " << pu[i].end_z << " vs " << pv[j].start_z << " to "<< pv[j].end_z <<endl;
01736                                 
01737                         //      continue;
01738                         }else{
01739                         
01740                         double start = pu[i].start_z < pv[j].start_z ? pv[j].start_z : pu[i].start_z;
01741                         double end = pu[i].end_z< pv[j].end_z ? pu[i].end_z : pv[j].end_z;
01742                         
01743                         o = fabs(end-start);
01744                         
01745                         double sm1= fabs(pu[i].end_z - pu[i].start_z);
01746                         double sm2= fabs(pv[j].end_z - pv[j].start_z);
01747                         double sm=0;
01748                         sm = sm1 > 0 ? sm1 : sm;
01749                         sm = sm2 > 0 && (sm2 < sm || sm ==0)? sm2 : sm;
01750                         
01751                         sm = sm1>sm2?sm1:sm2;
01752                         
01753                 MSG("Finder",Msg::kDebug)<< "sm1 "<<sm1<<" sm2 "<<sm2<<" pl " << o << " sm " << sm <<endl;
01754                         
01755                         if(sm<0.00001)continue;
01756                         
01757                         if(o==0) //special case --- we already made sure that there was overlap ... so this happens when one of the views has 1 hit, so its pathlength is 0
01758                         o=sm=1;
01759                         
01760                         zoverlap.push_back(o / sm);  // recording fraction of overlap over smaller path
01761                         
01762         MSG("Finder",Msg::kDebug)<< "overlap : " << o/sm<< " smallest path length "<<sm <<endl;
01763                         }
01764                 }
01765 
01766 
01767                 //find the best
01768                 double bestz=0.0;
01769                 for(unsigned int j=0;j<zoverlap.size();j++)
01770                         bestz = bestz > zoverlap[j]  ? bestz : zoverlap[j] > 0.999 ? bestz : zoverlap[j]; //if its a complete overlap, we don't want to compare against it...
01771                 
01772                         //require minimum overlap of 50%
01773                         if(bestz < 0.4 && bestz!=0.0) continue;
01774                 
01775                 
01776                 //find all matches within 30% of best
01777                 for(unsigned int j=0;j<zoverlap.size();j++)
01778                 {
01779                         if((bestz - zoverlap[j]) < 0.3 * bestz || zoverlap[j] > 0.999)
01780                         {
01781                                 zmatches.push_back(std::pair<int,int>(i,j));
01782                                 MSG("Finder",Msg::kDebug)<< "\tkeeping "<<i<<" "<<j<<endl;
01783                         }
01784                 }
01785                 
01786                 if(zmatches.size()==0)continue;
01787                 
01788 /*              if(zmatches.size()>1) //we need to pick a single match, so now look at energy and pick the closest!
01789                 {
01790                         double beste = 100000.0; // distance in energy from ith pu
01791                         int besteidx=-1;
01792                         for(unsigned int j=0;j<zmatches.size();j++)
01793                         {
01794                                 double de =  fabs(pu[zmatches[j].first].energy - pv[zmatches[j].second].energy);
01795                                 if(beste > de)
01796                                 {
01797                                         beste = de;
01798                                         besteidx=j;
01799                                 }
01800                         
01801                         }
01802                         
01803                         if(besteidx>-1)
01804                         matches.push_back(zmatches[besteidx]);
01805                         
01806                 }else{
01807                         matches.push_back(zmatches[0]);
01808                 }               
01809 */
01810 
01811 
01812 
01813                 if(zmatches.size()>1) //we need to pick a single match, so now look at energy / # entries and pick the closest!
01814                 {
01815                         int closest=100000;
01816                         int cidx=-1;
01817                         for(unsigned int j=0;j<zmatches.size();j++)
01818                         {
01819                         //      int d = fabs(pu[zmatches[j].first].energy / pu[zmatches[j].first].entries - pv[zmatches[j].first].energy / pv[zmatches[j].second].entries);
01820                                 
01821                         //      d=d/fabs(pu[zmatches[j].first].entries - pv[zmatches[j].second].entries);
01822                                 
01823                                 
01824                                 int d = (int)(TMath::Abs(pu[zmatches[j].first].entries - pv[zmatches[j].second].entries));
01825 
01826                                 if(d<closest)
01827                                 {
01828                                         closest=d;
01829                                         cidx=j;
01830                                 }
01831                         
01832                         }
01833                         
01834                         if(cidx>-1)
01835                         {
01836                                 matches.push_back(zmatches[cidx]);
01837                                 continue;                               
01838                         }
01839 
01840 
01841                 }
01842 
01843 
01844 
01845         
01846 
01847 
01848 
01849                 if(zmatches.size()>1)
01850                         MSG("Finder",Msg::kWarning) << "Degeneracy not resolved in making 3d particle tracks!"<<endl;
01851 
01852                 for(unsigned int j=0;j<zmatches.size();j++)
01853                         matches.push_back(zmatches[j]);
01854 
01855         }
01856 
01857 
01858         return matches;
01859 }
01860 
01861 
01862 void Finder::Weave(ChainHelper * chu, ChainHelper * chv)
01863 {
01864         std::vector<foundpath> pu = GetPaths(chu);
01865         std::vector<foundpath> pv = GetPaths(chv);
01866 
01867         if(pu.size()<1 || pv.size()<1)return;
01868 
01869         
01870         DumpPaths(pu);
01871         DumpPaths(pv);
01872 
01874         //we should clean each found path vector to remove paths which differ only by the last chain
01875         //as happens when a muon brems
01876         
01877         for(int i=0;i<2;i++){
01878         
01879         std::vector<foundpath>::iterator it1;
01880         std::vector<foundpath>::iterator it2;   
01881         std::vector<foundpath> paths=i==0?pu:pv;
01882         if(paths.size()<2)continue;
01883         
01884         double minzlength=1.0; //distance in m before we can delete...
01885         
01886         it1 =paths.begin();
01887         while(it1!=paths.end())
01888         //for(it1 =paths.begin();it1!=paths.end();it1++)
01889         {
01890                 if(it1->path.size()<2)
01891                 {
01892                         it1++;
01893                         continue;
01894                 }
01895                 int diddel=0;
01896                 
01897                 it2=it1;
01898                 it2++;
01899                 while(it2!=paths.end())
01900                 //for(it2 =it1;it2!=paths.end();it2++)
01901                 {
01902                         diddel=0;
01903                         if(it2->path.size()<2)
01904                         {
01905                                 it2++;
01906                                 continue;
01907                         }
01908 
01909                         
01910                         //MSG("Finder",Msg::kDebug)<<"paths start / end /it1 /it2 "<<&(paths.begin())<<" "<<&(paths.end())<<" "<<&it1<<" "<<&it2<<endl;
01911                         
01912         
01913                         
01914                         //MSG("Finder",Msg::kDebug)<<"Comparing with sizes "<<it1->path.size()<<" "<<it2->path.size()<<endl;
01915                         
01916                         int close=1;
01917                         
01918                 //      int larger=it1->path.size()>it2->path.size()?0:1;
01919                         int larger=it1->end_z-it1->start_z > it2->end_z-it2->start_z ? 0:1;
01920                 
01921                 
01922                         std::vector<int> maxpi = larger==0?it1->path:it2->path;
01923                         std::vector<int> maxpj = larger==1?it1->path:it2->path; 
01924                         
01925                         for(unsigned int k=0;k<maxpj.size()-1;k++)
01926                         {
01927                         MSG("Finder",Msg::kDebug)<<"chains "<<maxpi[k]<<" "<<maxpj[k]<<endl;
01928                                 if(maxpi[k]!=maxpj[k])
01929                                 {
01930                                         close=0;
01931                                         break;
01932                                 }
01933                         }
01934                         
01935                         //delete the smaller one?
01936                         std::vector<foundpath>::iterator itsmall=larger==0?it2:it1;
01937                         double dist = itsmall->end_z-itsmall->start_z;
01938                         if(close && dist > minzlength)
01939                         {
01940                         /*MSG("Finder",Msg::kError)*/
01941                         /*cout<<"removing close chain (";
01942                         for(unsigned int q=0;q<it1->path.size();q++)cout <<it1->path[q]<<" ";
01943                         cout<<") (";
01944                         for(unsigned int q=0;q<it2->path.size();q++)cout <<it2->path[q]<<" ";
01945                         cout<<") \n";                   
01946                         */
01947 
01948                                 int both=it1==it2?1:0;
01949                                 if(larger==1)
01950                                 {
01951                                         it1=paths.erase(it1);
01952                                         if(both)it2=it1;
01953                                 }
01954                                 if(larger==0)
01955                                 {
01956                                         it2=paths.erase(it2);
01957                                         if(both)it2=it1;
01958                                 }
01959                                 
01960                                 //something doesnt work right....!
01961                                 //do this sucky hack
01962                                 diddel=1;
01963                                 
01964                                                 //MSG("Finder",Msg::kError)<<"current pointers start / end /it1 /it2 "<<&(paths.begin())<<" "<<&(paths.end())<<" "<<&it1<<" "<<&it2<<endl;
01965                         }
01966                         
01967                         if(diddel)
01968                         {
01969                                 it1=paths.begin();
01970                                 it2=it1;
01971                         }
01972                         it2++;
01973                         
01974                 }       
01975                 it1++;
01976                 
01977         }
01978                 if(i==0)pu=paths;
01979                 if(i==1)pv=paths;
01980         }//loop over views
01982 
01983         if(pu.size()<1 || pv.size()<1)
01984         {
01985                 MSG("Finder",Msg::kError)<<"Removal of similar paths results in empty view!\n"; 
01986                 return;
01987         }
01988 
01989 
01990         //cout <<"*********Currently have "<<mypoh->particles3d.size()<<" particles in POH\n";
01991 
01992         DumpPaths(pu);
01993         DumpPaths(pv);
01994         
01995         
01996         //now try to find best matches!
01997         std::vector<std::pair<int,int> >matches = matchViews(pu,pv);    
01998         for(unsigned int i=0;i<matches.size();i++)
01999         {
02000                 MSG("Finder",Msg::kDebug) << "found pair " << matches[i].first << " " <<matches[i].second<<endl;
02001         }
02002 
02003         //and check the other view first as well!
02004         std::vector<std::pair<int,int> >matcheso = matchViews(pv,pu);
02005         for(unsigned int i=0;i<matcheso.size();i++)
02006         {
02007                 MSG("Finder",Msg::kDebug) << "found pair " << matcheso[i].second << " " <<matcheso[i].first<<endl;
02008         }
02009         for(unsigned int i=0;i<matcheso.size();i++)
02010         {
02011                 int found =0;
02012                 std::pair<int,int> tmp = make_pair(matcheso[i].second, matcheso[i].first); //need to flip the pair
02013                 for(unsigned int j=0;j<matches.size();j++)
02014                 {
02015                         
02016                         if(matches[j]==tmp)
02017                         {
02018                                 found=1;
02019                                 break;
02020                         }
02021                 }
02022                 if(!found)matches.push_back(tmp);
02023         
02024         }
02025         
02026 
02027         
02028 //      printf("!!1 matches size %d\n",matches.size());
02029         
02030         
02031         if(matches.size()<1)return;
02032         
02033         ostringstream os;
02034         os << "Candidate matches on z overlap : ";
02035         for(unsigned int i=0;i<matches.size();i++)
02036         {
02037                 os << matches[i].first <<"-"<<matches[i].second<<" ";
02038         }
02039         MSG("Finder",Msg::kDebug) << os.str()<<endl;    
02040 
02041 
02042 
02043         //when getting rid of a match... make sure its the best match!  (as we can share a chain in one view!)
02044         //need to see if all matches are "fair"
02045         std::vector<std::pair<int,int> >matchestmp;
02046         std::vector<int>multu;
02047         std::vector<int>multv;
02048         for(unsigned int i=0;i<matches.size();i++)
02049         {
02050                 int mult0=0;
02051                 int mult1=0;
02052                 for(unsigned int j=0;j<matches.size();j++)
02053                 {
02054                         if(i==j)continue;
02055                         if(matches[i].first==matches[j].first)mult0++;
02056                         if(matches[i].second==matches[j].second)mult1++;
02057                 }
02058                 if(! ( mult0>0 && mult1>0 )) // no degeneracy
02059                 {
02060                         matchestmp.push_back(matches[i]);
02061                         multu.push_back(mult0);
02062                         multv.push_back(mult1);
02063                 }else if( mult0>0 && mult1>0 ) //degeneracy, but see if we really want it
02064                 {
02065                         //see if the reason why both of these are degenerate is because they are really long
02066                         //for example, this can happen to a long muon in a DIS CC
02067                         //we want each of these to be the longest out of all matches using each of these paths
02068                         int pass=1;
02069                         
02070                         for(unsigned int k=0;k<matches.size();k++)
02071                         {
02072                                 if(matches[i].second!=matches[k].second)continue;
02073                                 if(pu[matches[i].first].end_z-pu[matches[i].first].start_z < pu[matches[k].first].end_z-pu[matches[k].first].start_z)
02074                                 {
02075                                         pass=0;
02076                                         break;
02077                                 }
02078                         }
02079                         for(unsigned int k=0;k<matches.size();k++)
02080                         {
02081                                 if(matches[i].first!=matches[k].first)continue;
02082                                 if(pv[matches[i].second].end_z-pv[matches[i].second].start_z < pv[matches[k].second].end_z-pv[matches[k].second].start_z)
02083                                 {
02084                                         pass=0;
02085                                         break;
02086                                 }
02087                         }
02088                 
02089                         if(pass)
02090                         {
02091                                 matchestmp.push_back(matches[i]);
02092                                 multu.push_back(mult0);
02093                                 multv.push_back(mult1);
02094                         }
02095                 }
02096                 
02097                 MSG("Finder",Msg::kDebug) << "pair " << matches[i].first <<" " << matches[i].second << " matches " <<mult0 <<" "<< mult1<<"\n";
02098         }
02099         matches=matchestmp;
02100 
02101         //cout <<"*********Currently have "<<mypoh->particles3d.size()<<" particles in POH\n";
02102         
02103         //we now have matches...
02104         //for each, construct a 3d path view
02105         
02106         
02107         std::vector<Particle3D> p3v;
02108         for(unsigned int i=0;i<matches.size();i++)
02109         {
02110                 MSG("Finder",Msg::kDebug) << "Making 3d particle with paths "<<matches[i].first<<" "<<matches[i].second<<"\n";
02111         
02112                 Particle3D p3 = Make3DParticle(pu[matches[i].first].path, pv[matches[i].second].path, chu, chv,multu[i],multv[i]) ;
02113                 
02114                 //we also need to save the clusters....
02115                 
02116                 for(unsigned int j=0;j<p3.view.size();j++)
02117                 {
02118                         Managed::ClusterManager * cluster_manager = &mypoh->clusterer;//p3.view[j]==2?&clustermanager_u:&clustermanager_v;
02119                         if(p3.chainhit[j]>-1)
02120                         {
02121                                 ChainHelper *ch = p3.view[j]==2?chu:chv;
02122                                 int oldid = ch->GetChain(p3.chain[j])->cluster_id[p3.chainhit[j]];
02123                                 int newid = cluster_manager->SaveCluster(oldid,p3.e[j],3);
02124                                 
02125                                 Managed::ManagedCluster * cluster = cluster_manager->GetCluster(newid);
02126                                 if(cluster)
02127                                 {
02128                                         //printf("SSSS saved %d  with e %f new id %d with e %f \n",oldid,p3.e[j],newid,cluster->e);
02129                                 
02130                                         p3.e[j]=cluster->e;
02131                                 
02132                                         p3.chainhit[j]=newid;
02133                                         
02134                                         ch->ChangeHitId(oldid,newid);
02135                         
02136                                 }else{
02137                                         //printf("NNNN cluster %d doesn't exist! removing e %f from particle \n",oldid,p3.e[j]);
02138                                         p3.e[j]=0;
02139                                         p3.chainhit[j]=-1;
02140                                 
02141                                         
02142                                 }
02143                         }
02144                         
02145                                 
02146                 
02147                 }
02148                 
02149                 if(p3.entries && p3.sum_e>1e-5)
02150                 {
02151                         //printf("adding p3d with e %f\n",p3.sum_e);
02152                         p3v.push_back(p3);
02153                 }
02154         }
02155 
02156         
02157 //printf("!!2 p3 size %d \n",p3v.size());
02158 
02159         
02160         
02161         
02162         
02163         
02164         
02165 
02166         std::vector<Particle3D* > p3d;  
02167         for(unsigned int i=0;i<p3v.size();i++)
02168                 p3d.push_back(&p3v[i]); 
02169         
02170 //      p3d=SetShared(p3d);     
02171 
02172 //      shareholder.Reset();
02173 //      shareholder.BulkInsert(p3d);
02174 
02175         /*
02176         DumpParticle3D(p3d);
02177 
02178 
02179         std::vector<Particle3D*> pout;
02180         std::vector<Particle3D*> toshare;
02181         for(unsigned int i=0;i<p3d.size();i++)
02182         {
02183                 //cout<<"on particle3d "<<i<<endl;
02184         
02185                 std::vector<Particle3D* > po = ProcessParticle3D1(p3d[i]);
02186                 for(unsigned int j=0;j<po.size();j++)
02187                 {
02188                         //if(po[j]->hasShared()<1)
02189                                 pout.push_back(po[j]);  
02190                         //else toshare.push_back(po[j]);
02191                 }
02192         
02193         }
02194         */
02195         
02196 /*      
02197         cout <<"PROCESSING COMPLETE\n";
02198         cout <<"not shared\n";
02199                 DumpParticle3D(pout);
02200         cout <<"has shared\n";
02201 
02202                 DumpParticle3D(toshare);
02203                 
02204         cout << "UNSHARING ENERGY\n";
02205 */      
02206         
02207 
02208 /*
02209 
02210         int its=5; //max iterations to try to remove shared hits!
02211         while(toshare.size()>0 && its>0)
02212         {
02213                 std::vector<Particle3D*> tmp;
02214                 
02215                 //some code to process them, returning a vector....
02216                 
02217                 for(unsigned int i=0;i<toshare.size();i++)
02218                         tmp.push_back(toshare[i]);
02219                 toshare.clear();
02220                 
02221                 RemoveSharedHits(tmp);
02222                 
02223                 for(unsigned int i=0;i<tmp.size();i++)
02224                 {
02225                         if(tmp[i]->hasShared())
02226                                 toshare.push_back(tmp[i]);
02227                         else pout.push_back(tmp[i]);
02228                 
02229                 }
02230                 
02231                 its--;
02232         }
02233         
02234         if(toshare.size()>0)
02235         MSG("Finder",Msg::kWarning)<<"particles lost .... could not uniquely assign shared energy !"<<endl;
02236         
02237         */
02238 
02239 
02240 /*
02241         std::vector<Particle3D*> pout;
02242         for(unsigned int i=0;i<p3d.size();i++)
02243         {
02244                 std::vector<Particle3D* > po = ProcessParticle3D(p3d[i]);       //returned vector may not have shared hits....
02245                 
02246                 std::vector<Particle3D*> forsharing;
02247                 
02248                 for(unsigned int j=0;j<po.size();j++)
02249                         pout.push_back(po[j]);
02250                 
02251                 for(unsigned int j=0;j<pout.size();j++)
02252                         forsharing.push_back(pout[j]);
02253                 
02254                 for(unsigned int j=i+1;j<p3v.size();j++)
02255                         forsharing.push_back(p3d[j]);
02256 
02257                         
02258                 forsharing=SetShared(forsharing); //to reset if a hit is shared....
02259                 
02260                 
02261         }
02262         
02263         
02264         
02265 */      
02266 /*
02267         cout <<"CLEANING\n";
02268         for(unsigned int i=0;i<pout.size();i++)pout[i]->Clean(); //remove 0 energy hits...
02269         DumpParticle3D(pout);
02270 */      
02271 
02272 
02273 
02274         //we need to recalculate values after sharing hits
02275         //but don't try to find more unique muons
02276         //we just want to make sure that the type hasn't changed!
02277         std::vector<Particle3D*> pout1;
02278         for(unsigned int i=0;i<p3d.size();i++)
02279         {
02280                 std::vector<Particle3D* > po = ProcessParticle3D1(p3d[i],0);
02281                 for(unsigned int j=0;j<po.size();j++)
02282                 {
02283                         pout1.push_back(po[j]); 
02284                 }
02285         
02286         }
02287         
02288         //printf("weave found %d\n",pout1.size());
02289 
02290 //      pout1=p3d;
02291         //look for straglers (large hit, not associated with any chain.... condider these to be neutrons...)
02292         FindNeutrons(pout1);    
02293         //printf("weave found %d\n",pout1.size());
02294         
02295 
02296         FinalizeParticles3D(pout1); //final computation of values, etc...
02297         //printf("weave found %d\n",pout1.size());
02298 
02299 
02300         for(unsigned int i=0;i<pout1.size();i++)
02301         {
02302                 if(pout1[i]->sum_e>0.01)
02303                         mypoh->AddParticle3D(*(pout1[i]));
02304         }
02305         
02306         //printf("weave found %d\n",pout1.size());
02307 
02308                 
02309         DumpParticle3D(pout1);  
02310 
02311                 
02312         //RecordLostHits(pout1);        
02313                 
02314 //              printf("!!3 pout size %d\n",pout.size());
02315                 
02316                 
02317 //              printf("poh entries %d\n", mypoh->particles3d1->GetEntries());
02318                                 
02319 
02320 //      for(unsigned int i=0;i<p3d.size();i++)
02321 //              mypoh->AddParticle3D(*(p3d[i]));        
02322 
02323 
02324 
02325         //do a check to see if the total particle energy is less than the total event energy...
02326         double parte=0;
02327         for(unsigned int i=0;i<p3d.size();i++) parte+=p3d[i]->sum_e;
02328         
02329         if(parte-mypoh->event.visenergy>.001)printf("!!!!!!!!!!!!!!!!!!\n********************\nenergy mismatch!!!! particle sum %f   energy total %f\n!!!!!!!!!!!!!!!!!!\n********************\n",parte,mypoh->event.visenergy);
02330         
02331         
02332 
02333         
02334 }
02335 
02336 
02337 
02338 
02339 void Finder::FindNeutrons(std::vector<Particle3D*> & pout)
02340 {
02341         std::vector<Particle3D*> pout1=pout;
02342         //mark all clusters as unused
02343         Managed::ClusterManager  *clhu = &mypoh->clusterer;
02344         Managed::ClusterManager  *clhv = &mypoh->clusterer;
02345 
02346 /*
02347         ChainHelper *cht = &mypoh->chu;
02348         for(int i=0;i<cht->finished.size();i++)
02349         {
02350                 printf("chain %d \n",cht->finished[i].myId);
02351                 for(int j=0;j<cht->finished[i].cluster_id.size();j++)
02352                         printf("%d ",cht->finished[i].cluster_id[j]);
02353                 printf("\n");
02354         
02355         }
02356 
02357 
02358         cht =& mypoh->chv;
02359         for(int i=0;i<cht->finished.size();i++)
02360         {
02361                 printf("chain %d \n",cht->finished[i].myId);
02362                 for(int j=0;j<cht->finished[i].cluster_id.size();j++)
02363                         printf("%d ",cht->finished[i].cluster_id[j]);
02364                 printf("\n");
02365         
02366         }
02367 */              
02368 
02369 
02370 //cant do this check here.. because other particles might already be in poh and are not in pout 
02371         for(unsigned int i=0;i<clhu->clusters.size();i++)clhu->clusters[i].inuse=0;
02372         for(unsigned int i=0;i<clhv->clusters.size();i++)clhv->clusters[i].inuse=0;
02373         
02374         //go through existing partcle3d's marking used clusters as used
02375 
02376         for(unsigned int i=0;i<mypoh->particles3d.size();i++)pout1.push_back(&(mypoh->particles3d[i]));
02377 
02378         for(unsigned int i=0;i<pout1.size();i++)
02379         {
02380                 for(int j=0;j<pout1[i]->entries;j++)
02381                 {
02382                         ChainHelper *ch = pout1[i]->view[j]==2? &mypoh->chu : pout1[i]->view[j]==3?& mypoh->chv:0;
02383                         if(!ch)continue;
02384                         
02385                         //printf("c %d ch %d\n",pout1[i]->chain[j],pout1[i]->chainhit[j]);
02386                         
02387                         Chain * c = ch->GetChain(pout1[i]->chain[j]);
02388                         if(!c)
02389                         {
02390                                 //cout<<"chain information lost\n";
02391                                 continue;
02392                         }
02393                         
02394                         if(pout1[i]->chainhit[j]<0)continue;  //not available
02395                         
02396                         int id = c->cluster_id[pout1[i]->chainhit[j]];
02397                         
02398                         //cout <<"chain/hit "<<pout1[i]->chain[j] << " " <<pout1[i]->chainhit[j]<<endl;
02399                         
02400                         Managed::ClusterManager  * clh = pout1[i]->view[j]==2? clhu : pout1[i]->view[j]==3? clhv:0;
02401                         if(!clh)continue;
02402                         
02403                         Managed::ManagedCluster *cluster=clh->GetCluster(id);
02404                         if(cluster)cluster->inuse=1;
02405                         //cout<<"in use\n";
02406                 
02407                 }
02408         
02409         }
02410 
02411 /*
02412 
02413         for(unsigned int i=0;i<mypoh->particles3d.size();i++)pout1.push_back(&(mypoh->particles3d[i]));
02414 
02415         for(unsigned int i=0;i<pout1.size();i++)
02416         {
02417                 for(unsigned int j=0;j<pout1[i]->entries;j++)
02418                 {
02419                         ChainHelper *ch = pout1[i]->view[j]==2? &mypoh->chu : pout1[i]->view[j]==3?& mypoh->chv:0;
02420                         if(!ch)continue;
02421                         
02422                         printf("c %d ch %d\n",pout1[i]->chain[j],pout1[i]->chainhit[j]);
02423                         
02424                         Chain * c = ch->GetChain(pout1[i]->chain[j]);
02425                         if(!c)
02426                         {
02427                                 //cout<<"chain information lost\n";
02428                                 continue;
02429                         }
02430                         
02431                         if(pout1[i]->chainhit[j]<0)continue;  //not available
02432                         
02433                         int id = c->cluster_id[pout1[i]->chainhit[j]];
02434                         
02435                         cout <<"chain/hit "<<pout1[i]->chain[j] << " " <<pout1[i]->chainhit[j]<<endl;
02436                         
02437                         Managed::ClusterManager  * clh = pout1[i]->view[j]==2? clhu : pout1[i]->view[j]==3? clhv:0;
02438                         if(!clh)continue;
02439                         
02440                         Managed::ManagedCluster *cluster=clh->GetCluster(id);
02441                         if(cluster)cluster->inuse=1;
02442                         cout<<"in use\n";
02443                 
02444                 }
02445         
02446         }
02447 
02448 
02449 */
02450 
02451         //find unused clusters with energy > some thresh
02452         //make these into particles...
02453 /*      
02454         cout << "//////////////////////////////////////////////\nunused clutsers"<<endl;
02455         cout <<"U\n";
02456         
02457         for(unsigned int i=0;i<clhu->clusters.size();i++)
02458         {
02459                 Managed::ManagedCluster *c = & clhu->clusters[i];
02460                 if(c->inuse)continue;
02461                 cout << "Cluster "<<c->id << " z " << c->z << " t " << c->t << " E " << c->e<<endl;
02462         }
02463         cout <<"V\n";
02464         for(unsigned int i=0;i<clhv->clusters.size();i++)
02465         {
02466                 Managed::ManagedCluster *c = & clhv->clusters[i];
02467                 if(c->inuse)continue;
02468                 cout << "Cluster "<<c->id << " z " << c->z << " t " << c->t << " E " << c->e<<endl;
02469         }
02470         
02471         cout << "//////////////////////////////////////////////\n";
02472 
02473 */
02474 /*
02475         //for now just make 2d neutrons... (don't match views..)
02476         
02477         double neut_thresh=3.0;
02478         
02479         for(int q=0;q<2;q++)
02480         {
02481                 Managed::ClusterManager * ch = q==0?clhu:clhv;
02482                 for(unsigned int i=0;i<ch->clusters.size();i++)
02483                 {
02484                         Managed::ManagedCluster *c = & ch->clusters[i];
02485                         if(c->inuse)continue;
02486                         if(c->e<neut_thresh)continue;
02487                         
02488                                 Particle3D * pnew = new Particle3D();
02489                                 pnew->particletype=Particle3D::neutron;
02490                                 double u = q==0? c->t : 0.0;
02491                                 double v = q==1? c->t : 0.0;
02492                                 pnew->add_to_back(u, v, c->z, c->e, -1,-1, q==0?2:3, 0);
02493                                 pout.push_back(pnew);                   
02494                 }
02495         
02496         }
02497 */
02498         //for now just make 2d neutrons... (don't match views..)
02499         
02500         double neut_thresh=3.0;
02501         
02502         for(int q=0;q<2;q++)
02503         {
02504                 //Managed::ClusterManager * ch = q==0?clhu:clhv;
02505                 
02506                 std::vector<int> chidx = clhu->GetViewIndex(q==0?2:3);
02507                 std::vector<int> chidx_other = clhu->GetViewIndex(q==1?2:3);
02508                 
02509                 for(unsigned int i=0;i<chidx.size();i++)
02510                 {
02511                         Managed::ManagedCluster *c = & clhu->clusters[chidx[i]];
02512                         if(c->inuse)continue;
02513                         if(c->e<neut_thresh)continue;
02514                         
02515                         
02516                         //Managed::ClusterManager * ch_other = q==1?clhu:clhv;
02517                         std::vector<int>other_view;
02518                         for(unsigned int j=0;j<chidx_other.size();j++)
02519                         {
02520                                 Managed::ManagedCluster *cother = & clhu->clusters[chidx_other[j]];
02521                                 if(TMath::Abs(cother->z - c->z)<0.06 && !cother->inuse)
02522                                         other_view.push_back(j);
02523                         }       
02524                                 
02525                         if(other_view.size()==0)
02526                         {       
02527                                 Particle3D * pnew = new Particle3D();
02528                                 pnew->particletype=Particle3D::neutron;
02529                                 double u = q==0? c->t : vtx_u;
02530                                 double v = q==1? c->t : vtx_v;
02531                                 pnew->add_to_back(u, v, c->z, c->e, -1,-1, q==0?2:3, 0);
02532                                 pout.push_back(pnew);   
02533                                 c->inuse=1;             
02534                         }else{
02535                                 //don't interpolate....
02536                                 
02537                                 Managed::ManagedCluster *cother0 = & clhu->clusters[chidx_other[other_view[0]]];
02538                                 
02539                                 double o_t = cother0->t;
02540                                 if(other_view.size()==2) 
02541                                 {
02542                                         Managed::ManagedCluster *cother1 = & clhu->clusters[chidx_other[other_view[1]]];
02543 
02544                                         o_t += cother1->t;
02545                                         o_t /=2.0;
02546                                 }
02547                                 
02548                                 
02549                                 double u = q==0? c->t : o_t;
02550                                 double v = q==1? c->t : o_t;                            
02551                         
02552                         
02553                                 Particle3D * pnew = new Particle3D();
02554                                 pnew->particletype=Particle3D::neutron;
02555                                 pnew->add_to_back(u, v, c->z, c->e, -1,-1, q==0?2:3, 0);
02556                                 c->inuse=1;
02557                                 pnew->add_to_back(u, v, cother0->z, cother0->e, -1,-1, q==1?2:3, 0);
02558                                 cother0->inuse=1;                               
02559                                 if(other_view.size()==2)
02560                                 {
02561                                         Managed::ManagedCluster *cother1 = & clhu->clusters[chidx_other[other_view[1]]];
02562                                         pnew->add_to_back(u, v, cother1->z, cother1->e, -1,-1, q==1?2:3, 0);
02563                                         cother1->inuse=1;
02564                                 }
02565                                 
02566                                 pout.push_back(pnew);   
02567                         }
02568         
02569         
02570                 }
02571         
02572         }
02573 
02574 
02575 }
02576 
02577 
02578 
02581 void Finder::RecordLostHits(std::vector<Particle3D*> p3d)
02582 {
02583         for(int i=0;i<2;i++)
02584         {
02585                 Managed::ClusterManager * ch = i==0? &mypoh->clusterer : &mypoh->clusterer;
02586                 
02587                 for(unsigned int j=0;j<ch->clusters.size();j++)ch->clusters[j].inuse=0;
02588         }
02589         
02590         for(unsigned int i=0;i<p3d.size();i++)
02591         {
02592                 Particle3D * p = p3d[i];
02593                 for(unsigned int j=0;j<p->chain.size();j++)
02594                 {
02595                         Managed::ClusterManager * clh = p->view[j]==2 ? &mypoh->clusterer :  &mypoh->clusterer ;
02596                         ChainHelper * ch = p->view[j]==2 ? &mypoh->chu :  &mypoh->chv ;
02597                         Chain * chain = ch->GetChain(p->chain[j]);
02598                         if(p->chainhit[j]>-1)
02599                                 clh->GetCluster(chain->cluster_id[p->chainhit[j]])->inuse=1;
02600                 }
02601         }
02602         
02603         for(int i=0;i<2;i++)
02604         {
02605                 Managed::ClusterManager * ch = i==0? &mypoh->clusterer : &mypoh->clusterer;
02606                 
02607                 for(unsigned int j=0;j<ch->clusters.size();j++)
02608                 {
02609                         if(ch->clusters[j].inuse)continue;
02610                         for(unsigned int k=0;k<ch->clusters[j].hite.size();k++)
02611                         {
02612                                 mypoh->event.unused_e +=ch->clusters[j].hite[k];
02613                                 mypoh->event.unused_strips++;
02614                         
02615                         }
02616                 }
02617         }
02618 
02619         mypoh->event.unused_e_avg =0;
02620         if(mypoh->event.unused_strips>0)        
02621                 mypoh->event.unused_e_avg = mypoh->event.unused_e / mypoh->event.unused_strips;
02622         
02623         for(int i=0;i<2;i++)
02624         {
02625                 Managed::ClusterManager * ch = i==0? &mypoh->clusterer : &mypoh->clusterer;
02626                 
02627                 for(unsigned int j=0;j<ch->clusters.size();j++)
02628                 {
02629                         if(ch->clusters[j].inuse)continue;
02630                         for(unsigned int k=0;k<ch->clusters[j].hite.size();k++)
02631                         {
02632                                 mypoh->event.unused_e_rms += (ch->clusters[j].hite[k] - mypoh->event.unused_e_avg)*(ch->clusters[j].hite[k] - mypoh->event.unused_e_avg);
02633                         
02634                         }
02635                 }
02636         }
02637         
02638         mypoh->event.unused_e_rms=sqrt(mypoh->event.unused_e_rms);
02639         if(mypoh->event.unused_e_avg>0)mypoh->event.unused_e_rms/=mypoh->event.unused_e_avg;
02640         
02641 }
02642 
02643 
02644 
02650 void Finder::FinalizeParticles3D(std::vector<Particle3D*>pout)
02651 {
02652         for(unsigned int i=0;i<pout.size();i++)
02653         {
02654                 Particle3D * p = pout[i];
02655                 if(!p)continue;
02656         
02657                 p->Clean();
02658         
02659                 
02660                 if(p->entries>0)
02661                 {               
02662                         double sum_z=0;
02663                         double sum_z_z=0;
02664                         double sum_u=0;
02665                         double sum_z_u=0;
02666                         double sum_v=0;
02667                         double sum_z_v=0;
02668                                 
02669 
02670                         double n = 5 <p->entries? 5:p->entries;
02671                         if(n<1)continue;
02672                         for(int j=0;j<n;j++)
02673                         {
02674                 
02675                                 sum_z+=p->z[j];
02676                                 sum_z_z+=p->z[j]*p->z[j];
02677                                 sum_u+=p->u[j];
02678                                 sum_z_u+=p->z[j]*p->u[j];
02679                                 sum_v+=p->v[j];
02680                                 sum_z_v+=p->z[j]*p->v[j];
02681         
02682                         }
02683                 
02684                         if(n==1)//add the vertex as a point...
02685                         {
02686                         
02687                                 sum_z+=vtx_z;
02688                                 sum_z_z+=vtx_z*vtx_z;
02689                                 sum_u+=vtx_u;
02690                                 sum_z_u+=vtx_z*vtx_u;
02691                                 sum_v+=vtx_v;
02692                                 sum_z_v+=vtx_z*vtx_v;
02693                                 n++;
02694                         }
02695                 
02696                         double denom = (n*sum_z_z-(sum_z)*(sum_z)) < 1e-10 ? 0 :  (n*sum_z_z-(sum_z)*(sum_z));
02697                         double au=0;
02698                         double bu=0;
02699                         double av=0;
02700                         double bv=0;
02701                                 
02702                         if(denom==0)            
02703                         {
02704                           au=std::numeric_limits<double>::infinity();
02705                           bu=std::numeric_limits<double>::infinity();
02706                           av=std::numeric_limits<double>::infinity();
02707                           bv=std::numeric_limits<double>::infinity();
02708 
02709 
02710 
02711                         }else{
02712                                 au=(sum_u*sum_z_z-sum_z*sum_z_u)/denom;
02713                                 bu=(n*sum_z_u-sum_z*sum_u)/denom;
02714                                 av=(sum_v*sum_z_z-sum_z*sum_z_v)/denom;
02715                                 bv=(n*sum_z_v-sum_z*sum_v)/denom;
02716                         }
02717 
02718 
02719 
02720 
02721 
02722                 //      avg_slope = b;
02723                 //      avg_offset = a;
02724                 
02725                         double theta = TMath::ATan2(bv,bu);
02726                         double phi = TMath::ATan(bu*bu+bv*bv);
02727                 
02728                 
02729                         p->theta=theta;
02730                         p->phi=phi;
02731                 
02732                 }
02733                 
02734                 
02735                 //for now... if everything else is muon energy like...
02736                 p->calibrated_energy = p->sum_e * (1.46676) / 0.0241;
02737                 
02738                 
02739                 //attempt em fit!
02740                 if(p->particletype!=Particle3D::muon && p->entries>2 && p->emfit_a==0 /*already done?*/)
02741                 {
02742                 
02743                         ShwFit f;
02744                         
02745                         double startz=0;
02746                         
02747                         startz=p->z[0];
02748                         
02749                         for(int i=0;i<p->entries;i++)
02750                         {
02751                                 //double planewidth=0.035;
02752                                 
02753                 //              f.Insert(p->e[i],(int)((p->z[i]-startz)/planewidth));
02754                         
02755                 //              cout <<"inserting "<<p->e[i]<<" at plane "<<(int)((p->z[i]-startz)/planewidth)<<endl;
02756                 
02757                 //for now, do the simple thing and assume each hit is in the next plane...
02758                         
02759                                 //                      f.Insert(p->e[i],i+1);
02760                         
02761                         
02762                                 f.Insert3d(p->e[i],p->u[i],p->v[i],p->z[i]);
02763                         
02764                                 //cout <<"inserting "<<p->e[i]<<" at plane "<<i+1<<endl;
02765                 
02766                         
02767                         }
02768                         
02769                         //f.Fit();
02770                         
02771                         f.Fit3d();
02772                         
02773                         MSG("Finder",Msg::kDebug) <<"EM FIT! " << f.par_a << " " << f.par_b << " +- "<<f.par_b_err<<" "<<f.par_e0<<endl;
02774                 
02775                         p->emfit_a=f.par_a;
02776                         p->emfit_b=f.par_b;
02777                         p->emfit_e0=f.par_e0;
02778                         p->emfit_a_err=f.par_a_err;
02779                         p->emfit_b_err=f.par_b_err;
02780                         p->emfit_e0_err=f.par_e0_err;
02781                         p->emfit_prob=f.prob;
02782                         p->calibrated_energy=f.par_e0;
02783                         p->emfit_chisq=f.chisq;
02784                         p->emfit_ndf=f.ndf;
02785                         
02786 
02787                         p->pred_e_a=f.pred_e_a; 
02788                         p->pred_g_a=f.pred_g_a;
02789                         p->pred_b=f.pred_b;
02790                         p->pred_e0=f.pred_e0;
02791                         p->pred_e_chisq=f.pred_e_chisq;
02792                         p->pred_e_ndf=f.pred_e_ndf;
02793                         p->pred_g_chisq=f.pred_g_chisq;
02794                         p->pred_g_ndf=f.pred_g_ndf;                             
02795                                                 
02796                         p->pre_over=f.pre_over;         
02797                         p->pre_under=f.pre_under;               
02798                         p->post_over=f.post_over;               
02799                         p->post_under=f.post_under;     
02800                         
02801                         p->pp_chisq=f.pp_chisq;
02802                         p->pp_ndf=f.pp_ndf;
02803                         p->pp_igood=f.pp_igood;
02804                         p->pp_p=f.pp_p;
02805                         
02806                         p->cmp_chisq = f.cmp_chisq;
02807                         p->cmp_ndf = f.cmp_ndf;
02808                         p->peakdiff = f.peakdiff;
02809         
02810 //      if(p)           printf("finder-- %f %d %f\n",p->cmp_chisq,p->cmp_ndf, p->peakdiff);             
02811                 
02812                 //      if(f.par_b<0.31 || f.par_b > 0.69) //not too emlike!
02813                 //              if(p->particletype==Particle3D::electron)p->particletype=Particle3D::other;
02814                 //      if(f.par_b>0.31 && f.par_b < 0.69) //force it to be emlike if not already
02815                 //              p->particletype=Particle3D::electron;
02816                                 
02817                 //      if(p->particletype==Particle3D::electron && f.par_e0/25/60. < 0.8) p->particletype=Particle3D::other; //<0.8gev elec is hard to find... so thats probably not it!
02818                 /*
02819                         if(TMath::Prob(p->emfit_chisq,p->emfit_chisq/p->emfit_chisq_ndf)>0.8)
02820                         {
02821                                 p->particletype=Particle3D::electron;
02822                         }
02823                         else
02824                         {
02825                                 p->particletype=Particle3D::other;
02826                         }
02827                 */
02828                 
02829                 
02830                 //      if(f.prob>0.9)  //good fit
02831                         if(f.conv && 
02832                         f.par_b - f.par_b_err*2.0 < 0.6 && f.par_b + f.par_b_err*2.0 > 0.4 //2.0 sigma from correct b value     range
02833                         && f.par_b_err < f.par_b //< 0.4
02834                         && f.par_e0/60./meupergev>0.25) //at least 0.25 gev cal e  to trust it!
02835                         {
02836                                 p->particletype=Particle3D::electron;           
02837                         }
02838                         else
02839                         {
02840                                 p->particletype=Particle3D::other;
02841                                 
02842                 //              f.Fit3dx2();
02843                         }
02844                 
02845                 }
02846         
02847                 
02848                 //proton filter
02849                 for(unsigned int i=0;i<p->types.size();i++)
02850                 {
02851                         if(p->types[i].type==ParticleType::prot)
02852                         {
02853                                 //if 80% of the particle's energy is in the last two hits....
02854                                 
02855                                 if(p->sum_e<0.001)continue;
02856                                 
02857                                 if(p->entries<3)continue;
02858                                 
02859                                 double efrac =( p->e[p->entries-1] + p->e[p->entries-2] ) / p->sum_e;
02860                                 
02861                                 if(efrac > 0.6)
02862                                 {
02863                                         p->particletype=Particle3D::proton;
02864                                         
02865                                         p->calibrated_energy=p->sum_e*60.;
02866                                         break;
02867                                 }
02868                         }
02869                 
02870                 }
02871         
02872         
02873         }
02874 }
02875 
02876 
02877 
02878 
02879 std::vector<Particle3D> Finder::shareEnergy(std::vector<Particle3D> p3v)
02880 {
02881 
02882         //now iterate over found particles
02883         //and try to divide up shared energy!
02884         
02885         
02886         std::multimap< std::pair<int, std::pair<int,int> >, Particle3D* > pmap;
02887         for(int i=0;i<(int)p3v.size();i++)
02888         for(int j=0;j<p3v[i].entries;j++)
02889         {
02890                 pmap.insert(make_pair( make_pair( p3v[i].view[j],  make_pair(p3v[i].chain[j],p3v[i].chainhit[j])),&(p3v[i])) );
02891         
02892                 
02893         }
02894         
02895         
02896         std::pair<int,int>last;
02897         int lastcount=0;
02898         int lastview=0; 
02899         std::vector<Particle3D*> shared3ds;
02900         std::multimap< std::pair<int, std::pair<int,int> >, Particle3D* >::reverse_iterator it1;
02901         for(it1=pmap.rbegin();it1!=pmap.rend();it1++)
02902         {
02903                 if(lastcount==0)
02904                 {
02905                         last=it1->first.second;
02906                         lastcount=1;
02907                         lastview=it1->first.first;
02908                         shared3ds.clear();
02909                         shared3ds.push_back(it1->second);
02910                         continue;       
02911                 }
02912                 
02913                 if(lastcount==1 && ( last!=it1->first.second || lastview!=it1->first.first))
02914                 {
02915                         last=it1->first.second;
02916                         lastview=it1->first.first;
02917                         shared3ds.clear();
02918                         shared3ds.push_back(it1->second);
02919                         continue;
02920                 }
02921                 
02922                 if(last==it1->first.second && lastview==it1->first.first)
02923                 {
02924                         lastcount++;
02925                         shared3ds.push_back(it1->second);
02926                         continue;
02927                 }else{
02928                         //do what we need to do with all of the last ones...
02929                         
02930                         //find all with this key...
02931                         
02932                         //then run a function over the list of the effected particle3d's noting the chain and chain id
02933                         //this function will look for adjacent hits in each of the particle3ds and attempt to extrapolate
02934                         //energy will be divided up evenly
02935                         //start at the back (highest z) and work down... as most shared hits should be closer to the vertex
02936                         
02937                         for(unsigned int i=0;i<shared3ds.size();i++)
02938                         {
02939                                 shared3ds[i]->SetShared(last.first, last.second);
02940                         }
02941                         
02942                         ShareHit(lastview,last.first,last.second,shared3ds);
02943                         
02944                         
02945                         
02946                         
02947                         //printf("cmp %d %d shared %d times\n",last.first, last.second,lastcount);
02948                         
02949                         
02950                         
02951                         //then start with the new one..
02952                         lastcount=1;
02953                         last=it1->first.second;
02954                         lastview=it1->first.first;
02955                         shared3ds.clear();
02956                         shared3ds.push_back(it1->second);
02957                 }
02958                 
02959                 
02960         }
02961         
02962         if(lastcount>1)
02963         {
02964                 for(unsigned int i=0;i<shared3ds.size();i++)
02965                 {
02966                         shared3ds[i]->SetShared(last.first, last.second);
02967                 }
02968                 ShareHit(lastview,last.first,last.second,shared3ds);
02969                 //printf("cmp %d %d shared %d times\n",last.first, last.second,lastcount);
02970         }
02971 
02972         return p3v;
02973 
02974 }
02975 
02976 
02977 std::vector<Particle3D*> Finder::SetShared(std::vector<Particle3D*> p3v)
02978 {
02979 
02980         //now iterate over found particles
02981         //and try to divide up shared energy!
02982         
02983         
02984         std::multimap< std::pair<int, std::pair<int,int> >, Particle3D* > pmap;
02985         for(int i=0;i<(int)p3v.size();i++)
02986         for(int j=0;j<p3v[i]->entries;j++)
02987         {
02988                 pmap.insert(make_pair( make_pair( p3v[i]->view[j],  make_pair(p3v[i]->chain[j],p3v[i]->chainhit[j])),p3v[i]) );
02989                 p3v[i]->UnsetShared(p3v[i]->chain[j],p3v[i]->chainhit[j]);
02990                 
02991         }
02992         
02993         
02994         std::pair<int,int>last;
02995         int lastcount=0;
02996         int lastview=0; 
02997         std::vector<Particle3D*> shared3ds;
02998         std::multimap< std::pair<int, std::pair<int,int> >, Particle3D* >::reverse_iterator it1;
02999         for(it1=pmap.rbegin();it1!=pmap.rend();it1++)
03000         {
03001         
03002                 if(it1->second->ShareLocked(it1->first.second.first, it1->first.second.second)>0)continue;
03003         
03004                 if(lastcount==0)
03005                 {
03006                         last=it1->first.second;
03007                         lastcount=1;
03008                         lastview=it1->first.first;
03009                         shared3ds.clear();
03010                         shared3ds.push_back(it1->second);
03011                         continue;       
03012                 }
03013                 
03014                 if(lastcount==1 && ( last!=it1->first.second || lastview!=it1->first.first))
03015                 {
03016                         last=it1->first.second;
03017                         lastview=it1->first.first;
03018                         shared3ds.clear();
03019                         shared3ds.push_back(it1->second);
03020                         continue;
03021                 }
03022                 
03023                 if(last==it1->first.second && lastview==it1->first.first )
03024                 {
03025                         lastcount++;
03026                         shared3ds.push_back(it1->second);
03027                         continue;
03028                 }else{
03029                         //do what we need to do with all of the last ones...
03030                         
03031                         //find all with this key...
03032                         
03033                         //then run a function over the list of the effected particle3d's noting the chain and chain id
03034                         //this function will look for adjacent hits in each of the particle3ds and attempt to extrapolate
03035                         //energy will be divided up evenly
03036                         //start at the back (highest z) and work down... as most shared hits should be closer to the vertex
03037                         
03038                         for(unsigned int i=0;i<shared3ds.size();i++)
03039                         {
03040                                 shared3ds[i]->SetShared(last.first, last.second);
03041                         }
03042                         
03043                         //printf("cmp %d %d shared %d times\n",last.first, last.second,lastcount);
03044                         
03045                         
03046                         
03047                         //then start with the new one..
03048                         lastcount=1;
03049                         last=it1->first.second;
03050                         lastview=it1->first.first;
03051                         shared3ds.clear();
03052                         shared3ds.push_back(it1->second);
03053                 }
03054                 
03055                 
03056         }
03057         
03058         if(lastcount>1)
03059         {
03060                 for(unsigned int i=0;i<shared3ds.size();i++)
03061                 {
03062                         shared3ds[i]->SetShared(last.first, last.second);
03063                 }
03064                 //printf("cmp %d %d shared %d times\n",last.first, last.second,lastcount);
03065         }
03066 
03067         return p3v;
03068 
03069 }
03070 
03071 
03072 void Finder::ShareHit(int view, int chain, int chainhit, std::vector<Particle3D*> shared)
03073 {
03074 
03075         //for now, divide the energy based on the average of the next/previous energies
03076         //in a chain as a fraction of the total n/p energy in all of the shared chains....
03077         
03078         
03079         std::vector<double> es;
03080         for(unsigned int i=0;i<shared.size();i++)
03081         {
03082                 int inview = view == 2 ? 3 :2; //look in the opposite view
03083                 
03084                 double n = shared[i]->GetNextEnergy(chain,chainhit,inview);
03085                 double p = shared[i]->GetPreviousEnergy(chain,chainhit,inview);
03086                 //if either is 0 then we are the end of the chain, so count the non zero one twice
03087                 if(n==0 && p >0)n=p;
03088                 if(p==0 && n>0)p=n;
03089                 
03090                 //printf("e %f\n",n+p);
03091                 
03092                 es.push_back(n+p);
03093         }
03094         
03095         double total=0;;
03096         double totaln=0;
03097         for(unsigned int i=0;i<es.size();i++)
03098         {
03099                 totaln++;
03100                 total+=es[i];
03101         }
03102         
03103         ChainHelper * ch = view == 2 ? &mypoh->chu : &mypoh->chv;
03104         
03105         Chain *c =ch->GetChain(chain);
03106         double energy = c->e[chainhit];
03107         
03108         //printf("Sharing %f\n",energy);
03109         
03110         if(total==0)return; //shared hits with no energy!
03111         for(unsigned int i=0;i<es.size();i++)
03112         {
03113                 shared[i]->SetEnergy(chain,chainhit,view,energy*es[i]/total);
03114         }
03115         
03116 
03117 }
03118 
03119 
03120 
03121 
03122 std::vector<foundpath> Finder::GetPaths(ChainHelper*ch)
03123 {
03124 
03125 
03126         std::vector<foundpath> p;
03127         for(unsigned int i=0;i<ch->finished.size();i++)
03128         {
03129                 if(ch->finished[i].parentChain<0 )
03130                 {
03131                         std::vector<foundpath> t = ch->FindPaths(&ch->finished[i]);
03132                         //printf("head chain %d has %d paths\n",ch->finished[i].myId, t.size());
03133                         
03134                         for(unsigned int j=0;j<t.size();j++)
03135                         p.push_back(t[j]);
03136         
03137                 }
03138          }
03139          return p;
03140 }
03141 
03142 void Finder::DumpPaths(std::vector<foundpath> a)
03143 {
03144 
03145         ostringstream os;
03146         os << "Dumping Paths\n";
03147         for(unsigned int i=0;i<a.size();i++)
03148         {
03149                 os << "Path "<<i<<" :  ";
03150                 os << " start t,z "<<a[i].start_t<<", "<<a[i].start_z;
03151                 os << " end t,z "<<a[i].end_t<<", "<<a[i].end_z;
03152                 os << " entries " <<a[i].entries << " energy " << a[i].energy << " muonlike " << a[i].muonlike;
03153                 os << "\n\t Chain Path : ";
03154                 for(unsigned int j=0;j<a[i].path.size();j++)
03155                         os<<a[i].path[j]<<" ";
03156                 os <<"\n\n";
03157         }
03158         
03159         MSG("Finder",Msg::kDebug) << os.str();  
03160 
03161 }
03162         struct point
03163         {
03164                 int view;
03165                 double z;
03166                 double t;
03167                 double e;
03168                 int chain;
03169                 int chainhit;
03170                 double rms_t;
03171         };
03172         
03173         bool pointgreater(point p1, point p2){return p1.z < p2.z;}
03174         
03175 
03176 Particle3D Finder::Make3DParticle(std::vector<int>upath, std::vector<int>vpath, ChainHelper * chu, ChainHelper * chv,int multu=0, int multv=0)
03177 {
03178         Particle3D p;
03179 
03180 
03181         
03182         std::vector<point> points;
03183         
03184         double start =0;
03185         double end  =1000;
03186         
03187         double endu=0;
03188         double endv=0;
03189                 
03190         
03191         
03192         
03193         int type=0;
03194         
03195         
03196         for(unsigned int i=0;i<upath.size();i++)
03197         {
03198                 Chain *c = chu->GetChain(upath[i]);
03199                 //cout <<"using chain "<<upath[i]<<"\n";
03200                                 
03201                 if(c->particletype)
03202                         type = c->particletype;
03203                 
03204                 for(int j=0;j<c->entries;j++)
03205                 {
03206                         if(c->parentChain==-1 && j==0)
03207                                 start = start < c->z[j]? c->z[j] : start;
03208                         if(i == upath.size()-1 && j == c->entries-1)
03209                         {
03210                                 end = end < c->z[j] ? end : c->z[j];
03211                         }
03212                         endu=endu<c->z[j]?c->z[j]:endu;
03213 
03214                         //don't double count children head hits
03215                         if(c->parentChain>-1 && j==0)
03216                         {
03217                                 if(i==0)continue;
03218                                 Chain *cpast = chu->GetChain(upath[i-1]);
03219                                 if(cpast->cluster_id[cpast->entries-1] == c->cluster_id[0])
03220                                         continue; 
03221                         }
03222                         Managed::ManagedCluster * clu = mypoh->clusterer.GetCluster(c->cluster_id[j]);  
03223                         if(!clu)continue;               
03224                 
03225                         
03226                         point a;
03227                         a.z=c->z[j];
03228                         a.t=c->t[j];
03229                         if(c->available && clu->id>0)
03230                                 a.e=clu->e;
03231                         else a.e=0;
03232                         a.chain=c->myId;
03233                         if(c->available && clu->id>0)
03234                                 a.chainhit=j;
03235                         else
03236                                 a.chainhit=-1;
03237                         a.view=2;
03238                         
03239 
03240                         if(clu)
03241                         {
03242                                 a.rms_t=clu->rms_t;
03243                                 points.push_back(a);
03244                         }
03245                         
03246                         
03247                 //      printf("adding pt u %f %f %f\n",a.z,a.t,a.e);
03248                         
03249                 }
03250         
03251         }
03252         for(int i=0;i<(int)vpath.size();i++)
03253         {
03254                 Chain *c = chv->GetChain(vpath[i]);
03255                 
03256                 //cout <<"using chain "<<vpath[i]<<"\n";
03257                 
03258                 if(c->particletype)
03259                         type = c->particletype;
03260                 for(int j=0;j<c->entries;j++)
03261                 {
03262                         if(c->parentChain==-1 && j==0)
03263                                 start = start < c->z[j]? c->z[j] : start;
03264                         if(i == (int)vpath.size()-1 && j == c->entries-1)
03265                         {
03266                                 end = end < c->z[j] ? end : c->z[j];
03267                         }
03268                         endv=endv<c->z[j]?c->z[j]:endv;
03269                         
03270                         //don't double count children head hits
03271                         if(c->parentChain>-1 && j==0)
03272                         {
03273                                 if(i==0)continue;
03274                                 Chain *cpast = chv->GetChain(vpath[i-1]);
03275                                 if(cpast->cluster_id[cpast->entries-1] == c->cluster_id[0])
03276                                         continue; 
03277                         }
03278 
03279                         Managed::ManagedCluster * clu = mypoh->clusterer.GetCluster(c->cluster_id[j]);  
03280                         if(!clu)continue;               
03281                         
03282 
03283                         point a;
03284                         a.z=c->z[j];
03285                         a.t=c->t[j];
03286                         if(c->available && clu->id>0)
03287                                 a.e=clu->e;
03288                         else
03289                                 a.e=0;
03290                         a.chain=c->myId;
03291                         if(c->available && clu->id>0)
03292                                 a.chainhit=j;
03293                         else
03294                                 a.chainhit=-1;
03295                         a.view=3;
03296                         
03297 
03298                         if(clu){
03299                                 a.rms_t=clu->rms_t;
03300                                 points.push_back(a);
03301                         }
03302 
03303                 //      printf("adding pt v %f %f %f\n",a.z,a.t,a.e);
03304 
03305                 }
03306         
03307         }
03308         
03309         //we don't want the particle to extrapolate too far....
03310         double stopend = endu<endv?endu:endv;
03311         //but if that chain path is only used once, then we want to go all the way to the end!
03312         if(!multu && multv)stopend = stopend<endu?endu:stopend;
03313         if(!multv && multu)stopend = stopend<endv?endv:stopend;
03314         if(!multv && !multu)stopend = endu<endv?endv:endu;
03315                 
03316         std::sort(points.begin(), points.end(),pointgreater);
03317 
03318 /*
03319 double largest_z=0;
03320 double largest_idx=0;
03321         for(unsigned int i=0;i<points.size();i++)
03322         {
03323                 if(points[i].z>largest_z)
03324                 {
03325                         largest_z=points[i].z;
03326                         largest_idx=i;
03327                 }
03328         }
03329 */      
03331 
03332         
03333         for(unsigned int i=0;i<points.size();i++)
03334         {
03335 //              if( start - points[i].z > 0.045 )continue;
03336 //              if( points[i].z - end > 0.045)continue; //within 1 planes, we want the end of the chain
03337         
03338 
03339         
03340         
03341         
03342         //are we at the end of usuable points?
03343         int done=0;
03344         for(unsigned int j=i;j<points.size();j++)
03345         {
03346                 if(points[j].e>0)break;
03347         
03348                 if(j==points.size()-1)done=1;
03349         }
03350         if(done)break;
03351         
03352                 if(points[i].z>stopend)continue;
03353         
03354                 int myview = points[i].view;
03355                 int lower=-1;
03356                 int upper=-1;
03357                 for(int j=i-1;j>-1;j--)
03358                 {
03359                         if(points[j].view!=myview)
03360                         {
03361                                 lower=j;
03362                                 break;
03363                         }
03364                 }
03365                 for(unsigned int j=i+1;j<points.size();j++)
03366                 {
03367                         if(points[j].view!=myview)
03368                         {
03369                                 upper=j;
03370                                 break;
03371                         }
03372                 }       
03373                 
03374                 
03375                 
03376                 double u = points[i].view==2 ? points[i].t : 0;
03377                 double v = points[i].view==3 ? points[i].t : 0;
03378                 double e = points[i].e;
03379                 double z = points[i].z;
03380                 int view = points[i].view;
03381                 
03382                 double rms_t = points[i].rms_t;
03383                 
03384 
03385                 
03386                 if(lower>-1 && upper > -1 )// good we can extrapolate!
03387                 {
03388                         double s = (points[upper].t - points[lower].t) /  ( points[upper].z - points[lower].z);
03389                         
03390                         double t = s * (points[i].z-points[lower].z) + points[lower].t;
03391                         
03392                         u = myview == 2 ? u : t;
03393                         v = myview == 3 ? v : t;
03394                         
03395 
03396                 }else if(lower>-1 && upper < 0)  //just user the closest other view t value
03397                 {
03398                         
03399                 //      printf("looking for lower value\n");
03400                         //do we have another lower value?
03401                         int lower2=-1;
03402                         for(int j=lower-1;j>-1;j--)
03403                         {
03404                                 if(points[j].view!=myview && fabs(points[lower].z-points[j].z)>0.04)
03405                                 {
03406                                         lower2=j;
03407                 //                      printf("second lower found\n");
03408                                         break;
03409                                 }
03410                         }
03411                         
03412                         
03413                         if(lower2>-1 && fabs( points[lower].z - points[lower2].z) >0)
03414                         {
03415                                 double s = (points[lower].t - points[lower2].t) /  ( points[lower].z - points[lower2].z);
03416                         
03417                                 double off = points[lower].t - points[lower].z*s;
03418                         
03419                                 double t = s * points[i].z + off;
03420                                 u = myview == 2 ? u : t;
03421                                 v = myview == 3 ? v : t;
03422                 //              printf("extrap  tz tz   %f %f    %f %f to %f\n",points[lower].t,points[lower].z,points[lower2].t,points[lower2].z,points[i].z);
03423                         }else{
03424                                 u = myview == 2 ? u : points[lower].t;
03425                                 v = myview == 3 ? v : points[lower].t;
03426         //                      printf("using closer point\n");
03427                         }
03428         //              printf("uv %f %f\n",u,v);
03429                         
03430                 }
03431                 else if(upper>-1 && lower < 0)   //just user the closest other view t value
03432                 {
03433                 
03434 
03435                 
03436                         //do we have another upper value?
03437                         int upper2=-1;
03438                         for(unsigned int j=upper+1;j<points.size();j++)
03439                         {
03440                                 if(points[j].view!=myview && fabs(points[upper].z-points[j].z)>0.04)
03441                                 {
03442                                         upper2=j;
03443                                         break;
03444                                 }
03445                         }
03446                         
03447                         if(upper2>-1 && fabs( points[upper2].z - points[upper].z)>0)
03448                         {
03449                                 double s = (points[upper2].t - points[upper].t) /  ( points[upper2].z - points[upper].z);
03450                                 double off = points[upper].t - points[upper].z*s;
03451                         
03452                                 double t = s * points[i].z + off;
03453                                 u = myview == 2 ? u : t;
03454                                 v = myview == 3 ? v : t;
03455                                                                 
03456                 //              printf("ext next hit with t %f z %f  t %f z %f for ext\n",points[upper].t,points[upper].z,points[upper2].t,points[upper2].z);
03457                         
03458                         }else{
03459                                 u = myview == 2 ? u : points[upper].t;
03460                                 v = myview == 3 ? v : points[upper].t;
03461 
03462                         }
03463 
03464 
03465 
03466                         //lets use the vertex!
03467 
03468 /*
03469                         if(points[upper].view != points[i].view)
03470                                 upper=upper2;
03471                                 
03472                         if(points[upper].view == points[i].view)
03473                         {
03474 */                              double vz =vtx_z;
03475                                 double vt = 0;
03476                                 vt = points[upper].view == 2 ? vtx_u : vt;
03477                                 vt = points[upper].view == 3 ? vtx_v : vt;
03478                         
03479                                 double t =vt;
03480                                 
03481                                 //if the point at z is not the same as z vtx, we need to extrapolate 
03482                                 if(fabs ( points[upper].z - vz)>0.001)
03483                                 {                       
03484                         
03485                                         double s = (points[upper].t - vt) /  ( points[upper].z - vz);
03486                                         t = s * (points[i].z-vz) + vt;                  
03487                         
03488                                 }
03489                                 
03490                         //      printf("---view %d u %f v %f t %f\n",myview,u,v,t);
03491                         //      printf("---vtx z %f t%f upper z %f t %f\n",vz,vt,points[upper].z,points[upper].t);
03492                         
03493 
03494                                 u = myview == 2 ? u : t;
03495                                 v = myview == 3 ? v : t;
03496 //                      }       
03497                                 
03498 
03499                 }
03500                 else if(upper==-1 && lower==-1) //we have an empty view!!!
03501                 {
03502 
03503                         u = myview == 2 ? u : 0;
03504                         v = myview == 3 ? v : 0;
03505                 }
03506                 
03507                 p.add_to_back(u,v,z,e,points[i].chain,points[i].chainhit,view,rms_t);
03508                 
03509                 //printf("adding %f %f %f --- %f\n",u,v,z,e);
03510         }
03511         
03512         
03513         if(type)
03514                 p.particletype=(Particle3D::EParticle3DType)type;
03515         
03516         p.finalize();
03517         
03518         return p;
03519 }
03520 
03521 
03522 
03523 
03524 
03525 
03526 void Finder::DumpParticle3D(std::vector<Particle3D*> p3d)
03527 {
03528         ostringstream s;
03529         
03530         s << "Dump of Particle3D's "<<endl;
03531         s << "Number of Particle3D : "<<p3d.size()<< endl<<endl;
03532                 
03533                 
03534         for (unsigned int i=0;i<p3d.size();i++)
03535         {
03536                 //ostringstream s;
03537         
03538                 Particle3D * p = p3d[i];
03539                 if (p==0)continue;
03540         
03541         
03542 
03543         
03544                 s << "\n---Particle3d " << i << "---\nstart, stop (u,v,z) (" << p->start_u << ", "<< p->start_v << ", " << p->start_z <<") (" <<p->end_u<<", "<< p->end_v << ", " << p->end_z <<")"<<endl;
03545                 s << "entries "<< p->entries << " muonlike " << p->muonfrac <<endl;
03546                 
03547                 
03548 
03549                 
03550                 s<<"types: ";
03551                 for(unsigned int j=0;j<p->types.size();j++)
03552                 {
03553                         switch( p->types[j].type)
03554                         {
03555                                 case    ParticleType::em:
03556                                         s<<"em ";
03557                                         break;
03558                                 case ParticleType::emshort:
03559                                         s<<"emshort  ";
03560                                         break;                          
03561                                 case ParticleType::muon:
03562                                         s<<"muon ";
03563                                         break;
03564                                 case ParticleType::prot:
03565                                         s<<"prot ";
03566                                         break;          
03567                                 case ParticleType::pi0:
03568                                         s<<"pi0 ";
03569                                         break;
03570                                 case ParticleType::uniquemuon:
03571                                         s<<"uniquemuon ";
03572                                         break;  
03573                         
03574                         }
03575                                 
03576                 }
03577                 s<<endl;
03578                 
03579                 s<<"particletype : "<<p->particletype<<endl;
03580                 
03581                 
03582                 s<<"par a " << p->emfit_a << " par b "<< p->emfit_b << " par e0 "<< p->emfit_e0 << " cale "<<p->calibrated_energy<<" chisq " << p->emfit_chisq<<" ndf " << p->emfit_ndf<<endl;
03583                 s<<"emprob " << p->emfit_prob <<" avg rms_t "<<p->avg_rms_t<<endl;
03584                 s<<"vise "<<p->sum_e<<endl;
03585                                 
03586                 s << "points (u,v,z,e - chain, chainhit, chainview - shared - rms_t - view) : ";
03587                 for(int j=0;j<p->entries;j++)
03588                         s << "(" << p->u[j]<<", "<<p->v[j]<<", "<<p->z[j]<<", "<<p->e[j]<<" - " << p->chain[j] <<", "<<p->chainhit[j]<<", "<<p->view[j]<<" - "<<p->shared[j]<<" - "<< p->rms_t[j]<< " - " << p->view[j]<<") ";
03589         
03590         /*
03591         s << "points (e - shared) : ";
03592                 for(int j=0;j<p->entries;j++)
03593                         s << "(" <<p->e[j]<<" - "<<p->shared[j]<<") ";
03594         
03595         */
03596         
03597         
03598 
03599                         
03600                         
03601 
03602                         
03603                         
03604                 s<<endl<<endl;
03605         
03606                         //check to see if it is a good particle........
03607                 for(unsigned int q=0;q<p->u.size();q++)
03608                 {
03609                         if(p->e[q]<0)MSG("Finder",Msg::kDebug) <<"BAD E "<<p->e[q]<<" at "<<q<<"\n";
03610                         if(p->z[q]<0||p->z[q]>30 ||isnan(p->z[q]))MSG("Finder",Msg::kDebug) <<"BAD Z "<<p->z[q]<<" at "<<q<<"\n";
03611                         
03612                         if(p->u[q]<-10||p->u[q]>10 ||isnan(p->u[q]))MSG("Finder",Msg::kDebug) <<"BAD U "<<p->u[q]<<" at "<<q<<"\n";
03613                         if(p->v[q]<-10||p->v[q]>10 ||isnan(p->v[q]))MSG("Finder",Msg::kDebug) <<"BAD U "<<p->v[q]<<" at "<<q<<"\n";
03614                 }
03615 
03616         
03617                 
03618                 
03619         }
03620         
03621         s << "\n!!! shareholder has "<<shareholder.GetTotRemaining() << " hits still shared!\n";
03622 
03623 
03624         MSG("Finder",Msg::kDebug) <<s.str();
03625 
03626         
03627 
03628 }
03629 
03630 /*
03631 enum particletype
03632 {
03633         em,
03634         emshort,
03635         muon,
03636         prot,
03637         pi0,
03638         uniquemuon
03639 
03640 
03641 };
03642 */
03643 
03644 /*
03645 struct ptype
03646 {
03647         particletype type;
03648         int start;
03649         int stop;
03650 };
03651 */
03652 
03653 
03654 std::vector<Particle3D*> Finder::ProcessParticle3D(Particle3D * p3d)
03655 {
03656 
03657         std::vector<Particle3D*> pout;
03658 
03659         ostringstream s;
03660         s<<"\nparticle types:\n";
03661 
03662         //std::vector<ptype> types;
03663 
03664         //for the muon checks
03665         double lowm=0.2;
03666         double highm=3;
03667         int minm=2;
03668 
03669 
03670         //em check
03671         int lastemend=-1;
03672         int lastemlow=-1;
03673         if(p3d->entries>3)
03674         for(int i=0;i<p3d->entries-2;i++)
03675         {
03676                 double p0 = p3d->e[i];
03677                 double p1 = p3d->e[i+1];
03678                 double p2 = p3d->e[i+2];
03679                 if(p0<p1 && p1>p2 && p1 > highm) 
03680                 {
03681 
03682                         int low=i;
03683                         int high=i+2;
03684 
03685                         
03686                         for(int h=i-1;h>-1;h--)
03687                         {
03688                                 if(p3d->e[h]<p3d->e[h+1])
03689                                 {
03690                                         low=h;
03691                                 }else{
03692                                         break;
03693                                 }
03694                         }
03695                         for(int h=i+3;h<p3d->entries;h++)
03696                         {
03697                                 if(p3d->e[h]<p3d->e[h-1])
03698                                 {
03699                                         high=h;
03700                                 }else{
03701                                         break;
03702                                 }
03703                         }
03704                         if(low==lastemend)
03705                         {
03706 
03707                                 s<<"pi0 like - found consecutive em like from "<<lastemlow<<" to "<<high<<endl;
03708                                 ParticleType a;
03709                                 a.type = ParticleType::pi0;
03710                                 a.start=lastemlow;
03711                                 a.stop=high;
03712                                 p3d->types.push_back(a);
03713                         }
03714                         s<<"em like from "<< low << " to " <<high<<endl;
03715                         i=high; //start after this found em like structure
03716                         lastemend=high;
03717                         lastemlow=low;
03718                         ParticleType a;
03719                         a.type = ParticleType::em;
03720                         a.start=low;
03721                         a.stop=high;
03722                         p3d->types.push_back(a);        
03723                 }               
03724         }
03725         
03726         //shortem check
03727         if(p3d->entries>3)
03728         {
03729                 double p0 = p3d->e[0];
03730                 double p1 = p3d->e[1];
03731                 double p2 = p3d->e[2];  
03732                 if(p0>p1 && p1>p2 && p0 > highm)
03733                 {
03734 
03735                         s<<"shortem like"<<endl;
03736                         
03737                         int high=2;
03738                         for(int i=2;i<p3d->entries-1;i++)
03739                         {
03740                                 if(p3d->e[i] > p3d->e[i+1])
03741                                 {
03742                                         high=i+1;
03743                                 }       
03744                         }
03745                         ParticleType a;
03746                         a.type = ParticleType::emshort;
03747                         a.start=0;
03748                         a.stop=high;
03749                         p3d->types.push_back(a);        
03750                 }
03751         }       
03752         
03753         //muon check
03754         if(p3d->entries>1)
03755         for(int i=0;i<p3d->entries;i++)
03756         {
03757                 int low=i;
03758                 int high=i;
03759                 if(p3d->e[i] > lowm && p3d->e[i] < highm)
03760                 {
03761                         for(int j=i;j<p3d->entries;j++)
03762                         {
03763                                 if(p3d->e[j] > lowm && p3d->e[j] < highm)
03764                                 {
03765                                         high=j;
03766                                 }else{
03767                                         if(j < p3d->entries-1 && high == j-1 && p3d->e[j] < highm*2 && p3d->e[j+1] > lowm && p3d->e[j+1] < highm)  //allow 1 out of range hit
03768                                         {
03769                                                 high=j+1;
03770                                                 j++;
03771                                                 continue;
03772                                         }
03773                                         i=+1;
03774                                         break;
03775                                 
03776                                 }
03777                         }
03778                 }
03779                 
03780                 if(high-low+1>=minm)
03781                 {
03782 
03783                         s<<"muon like from "<<low<<" to "<<high<<endl;
03784                         ParticleType a;
03785                         a.type = ParticleType::muon;
03786                         a.start=low;
03787                         a.stop=high;
03788                         p3d->types.push_back(a);        
03789                 }
03790                 
03791                 i=high+1;
03792         }
03793 
03794         //unique muon check --- should we be extracting a muon from a particle that has larger shared hits?
03795         double  mc=0;
03796         double me=0;
03797         int c=0;
03798         for(int i=0;i<p3d->entries;i++)
03799         {
03800 
03801                 if(p3d->shared[i]==0)
03802                 {
03803                         c++;
03804                         if(p3d->e[i] > lowm && p3d->e[i] < highm)
03805                         {
03806                                 mc++;
03807                                 me+=p3d->e[i];
03808                         }
03809                 }
03810         }       
03811 
03812         if(mc/c>0.7)
03813         {
03814                 s<<"unique muon found"<<endl;
03815                 ParticleType a;
03816                 a.type = ParticleType::uniquemuon;
03817                 a.start=-1;
03818                 a.stop=-1;
03819                 p3d->types.push_back(a);        
03820         }
03822 
03823 
03824 
03825         
03826         //prot check // really stopping of +muon
03827         int plow=p3d->entries-1;
03828         int phigh=p3d->entries-1;
03829         if(p3d->e[p3d->entries-1]>highm)
03830         for(int i=p3d->entries-2;i>-1;i--)
03831         {
03832                 if(p3d->e[i]<p3d->e[i+1]) plow=i;
03833                 else break;
03834         }
03835         if(phigh-plow>1)
03836         {
03837 
03838                 s<<"proton/stopping u+ found from "<<plow<<" to "<<phigh<<endl;
03839                 ParticleType a;
03840                 a.type = ParticleType::prot;
03841                 a.start=plow;
03842                 a.stop=phigh;
03843                 p3d->types.push_back(a);        
03844         }
03845         
03846         //we now have a list of types.... go through, and split up the Particle3D as needed until all Particle3Ds have a single type
03847         
03848         
03849         int emt=0;
03850         
03851         p3d->particletype=Particle3D::other;    
03852         for(unsigned int i=0;i<p3d->types.size();i++)
03853         {
03854         
03855         
03856                 if(p3d->types[i].type==ParticleType::uniquemuon)
03857                 {
03858                         std::pair<Particle3D*,Particle3D*> a = StripMuon(p3d);
03859                         if(a.first)
03860                         {
03861                                 pout.push_back(a.first); //thats the stripped muon...
03862                                 if(a.second) //make sure we removed something from p3d...
03863                                 {
03864                                         std::vector<Particle3D*> b =ProcessParticle3D(a.second); //the adjusted remnant needs to be rechecked!
03865                                         for(unsigned int j=0;j<b.size();j++)
03866                                                 pout.push_back(b[j]);
03867                                 }
03868                                 return pout;
03869                         }       
03870                 }
03871                 
03872         
03873                 //see if it is definitely a muon!
03874                 
03875                 if(p3d->types[i].type==ParticleType::muon && p3d->types[i].stop-p3d->types[i].start+1 == p3d->entries)
03876                 {
03877                         p3d->particletype=Particle3D::muon;
03878                         break;
03879                 
03880                 }
03881 
03882                 
03883                 if(p3d->types[i].type==ParticleType::em && p3d->types[i].stop-p3d->types[i].start+1 == p3d->entries)
03884                 {
03885                         p3d->particletype=Particle3D::electron;
03886                         break;
03887                 }
03888 
03889                 if(p3d->types[i].type==ParticleType::em && (double)( p3d->types[i].stop-p3d->types[i].start) / (double) p3d->entries > 0.8) //more than half of it is em....
03890                 {
03891                         p3d->particletype=Particle3D::electron;
03892                         break;
03893                 }
03894 
03895                 if(p3d->types[i].type==ParticleType::em )
03896                 {
03897                         emt+= p3d->types[i].stop-p3d->types[i].start+1;
03898                 }
03899         
03900 
03901         
03902         }
03903 
03904         if(p3d->particletype==0 && p3d->muonfrac>0.6)
03905         {
03906                 p3d->particletype=Particle3D::muon;
03907                         
03908         }       
03909 
03910         if(p3d->particletype==0 && (double)emt / (double)p3d->entries > 40)
03911         {
03912                 p3d->particletype=Particle3D::electron;
03913                         
03914         }       
03915 
03916 
03917         MSG("Finder",Msg::kDebug) << s.str();   
03918         
03919         pout.push_back(p3d);
03920         return pout;
03921         
03922 }
03923 
03924 
03925 std::pair<Particle3D*,Particle3D*> Finder::StripMuon(Particle3D * p3d)
03926 {
03927         std::pair<Particle3D*,Particle3D*>  a;
03928         a.first=0;
03929         a.second=p3d;
03930         
03931         //see if all unique hits are muons hits....
03932         double lowm=0.0;
03933         double highm=3.5;
03934         
03935         int u=0;
03936         int m=0;
03937         double me=0;
03938         
03939         for(int i=0;i<p3d->entries;i++)
03940         {
03941                 if(p3d->shared[i]==0)
03942                 {
03943                         u++;
03944                         if(p3d->e[i] > lowm && p3d->e[i]<highm)
03945                         {
03946                                 m++;
03947                                 me+=p3d->e[i];
03948                         }
03949                 }
03950         }
03951         
03952         if(u==m)
03953         { 
03954                 a.second=0;  //releasing shared particles which cant be part of something else...
03955                 //cout <<"!!!---releasing particle"<<endl;
03956         }
03957         
03958         
03959         Particle3D * c = new Particle3D();
03960         a.first=c;
03961         
03962         
03963         double eavg = me/m;
03964         for(int i=0;i<p3d->entries;i++)
03965         {
03966                 double e = p3d->e[i] > lowm && p3d->e[i]<highm ? p3d->e[i] : eavg;
03967                 e = e > p3d->e[i] ? p3d->e[i] : e;
03968         
03969                 c->add_to_back( p3d->u[i],  p3d->v[i],  p3d->z[i], e, p3d->chain[i], p3d->chainhit[i],  p3d->view[i],0);
03970                 c->lockshared[c->entries-1]=1;
03971                 
03972                 if(a.second)
03973                 {
03974                         double reste=p3d->e[i]-e>0 ? p3d->e[i]-e : 0;
03975                         a.second->e[i]= reste;
03976                         
03977                         
03978                 }
03979         }
03980         c->particletype=Particle3D::muon;
03981 
03982 
03983 
03984         if(a.second)
03985         {
03986                 double sume=0;
03987                 int num0=0;
03988                 for(int i=0;i<a.second->entries;i++)
03989                 {
03990                         sume+=a.second->e[i];
03991                         if(a.second->e[i]<0.01)num0++;
03992                 }
03993                 //cout<<"second e"<<sume<<endl;
03994                 
03995                 if(sume<0.0001 || (double)num0/(double)a.second->entries > 0.8)
03996                 {
03997                         a.second=0;  //releasing shared particles which cant be part of something else...
03998                         //cout <<"!!!---releasing particle"<<endl;
03999                 }
04000         }
04001 
04002         return a;
04003 
04004 }
04005 
04006 
04007 
04008 
04009 
04010 
04011 std::vector<Particle3D*> Finder::ProcessParticle3D1(Particle3D * p3d, int check_unique_muon)
04012 {
04013 
04014         std::vector<Particle3D*> pout;
04015 
04016         ostringstream s;
04017         s<<"\nparticle types:\n";
04018 
04019         //std::vector<ptype> types;
04020 
04021         //for the muon checks
04022         double lowm=0.2;
04023         double highm=3;
04024         int minm=2;
04025 
04026 
04027         //em check
04028         int lastemend=-1;
04029         int lastemlow=-1;
04030         if(p3d->entries>3)
04031         for(int i=0;i<p3d->entries-2;i++)
04032         {
04033                 double p0 = p3d->e[i];
04034                 double p1 = p3d->e[i+1];
04035                 double p2 = p3d->e[i+2];
04036                 if(p0<p1 && p1>p2 && p1 > highm) 
04037                 {
04038 
04039                         int low=i;
04040                         int high=i+2;
04041 
04042                         
04043                         for(int h=i-1;h>-1;h--)
04044                         {
04045                                 if(p3d->e[h]<p3d->e[h+1])
04046                                 {
04047                                         low=h;
04048                                 }else{
04049                                         break;
04050                                 }
04051                         }
04052                         for(int h=i+3;h<p3d->entries;h++)
04053                         {
04054                                 if(p3d->e[h]<p3d->e[h-1])
04055                                 {
04056                                         high=h;
04057                                 }else{
04058                                         break;
04059                                 }
04060                         }
04061                         if(low==lastemend)
04062                         {
04063 
04064                                 s<<"pi0 like - found consecutive em like from "<<lastemlow<<" to "<<high<<endl;
04065                                 ParticleType a;
04066                                 a.type = ParticleType::pi0;
04067                                 a.start=lastemlow;
04068                                 a.stop=high;
04069                                 p3d->types.push_back(a);
04070                         }
04071                         s<<"em like from "<< low << " to " <<high<<endl;
04072                         i=high; //start after this found em like structure
04073                         lastemend=high;
04074                         lastemlow=low;
04075                         ParticleType a;
04076                         a.type = ParticleType::em;
04077                         a.start=low;
04078                         a.stop=high;
04079                         p3d->types.push_back(a);        
04080                 }               
04081         }
04082         
04083         //shortem check
04084         if(p3d->entries>3)
04085         {
04086                 double p0 = p3d->e[0];
04087                 double p1 = p3d->e[1];
04088                 double p2 = p3d->e[2];  
04089                 if(p0>p1 && p1>p2 && p0 > highm)
04090                 {
04091 
04092                         s<<"shortem like"<<endl;
04093                         
04094                         int high=2;
04095                         for(int i=2;i<p3d->entries-1;i++)
04096                         {
04097                                 if(p3d->e[i] > p3d->e[i+1])
04098                                 {
04099                                         high=i+1;
04100                                 }       
04101                         }
04102                         ParticleType a;
04103                         a.type = ParticleType::emshort;
04104                         a.start=0;
04105                         a.stop=high;
04106                         p3d->types.push_back(a);        
04107                 }
04108         }       
04109         
04110         //muon check
04111         if(p3d->entries>1)
04112         for(int i=0;i<p3d->entries;i++)
04113         {
04114                 int low=i;
04115                 int high=i;
04116                 if(p3d->e[i] > lowm && p3d->e[i] < highm)
04117                 {
04118                         for(int j=i;j<p3d->entries;j++)
04119                         {
04120                                 if(p3d->e[j] > lowm && p3d->e[j] < highm)
04121                                 {
04122                                         high=j;
04123                                 }else{
04124                                         if(j < p3d->entries-1 && high == j-1 && p3d->e[j] < highm*2 && p3d->e[j+1] > lowm && p3d->e[j+1] < highm)  //allow 1 out of range hit
04125                                         {
04126                                                 high=j+1;
04127                                                 j++;
04128                                                 continue;
04129                                         }
04130                                         i=+1;
04131                                         break;
04132                                 
04133                                 }
04134                         }
04135                 }
04136                 
04137                 if(high-low+1>=minm)
04138                 {
04139 
04140                         s<<"muon like from "<<low<<" to "<<high<<endl;
04141                         ParticleType a;
04142                         a.type = ParticleType::muon;
04143                         a.start=low;
04144                         a.stop=high;
04145                         p3d->types.push_back(a);        
04146                 }
04147                 
04148                 i=high+1;
04149         }
04150 
04151         //unique muon check --- should we be extracting a muon from a particle that has larger shared hits?
04152 
04153         if(check_unique_muon)
04154         {
04155         double  mc=0;
04156         double me=0;
04157         int c=0;
04158         for(int i=0;i<p3d->entries;i++)
04159         {
04160 
04161 //              if(p3d->shared[i]==0)
04162 //              {
04163                         c++;
04164                         if(p3d->e[i] > lowm && p3d->e[i] < highm)
04165                         {
04166                                 mc++;
04167                                 me+=p3d->e[i];
04168                         }
04169 //              }
04170         }       
04171 
04172         if(mc>0.7*c)
04173         {
04174                 s<<"unique muon found muonlike to all hits ratio "<<mc/c<<endl;
04175                 ParticleType a;
04176                 a.type = ParticleType::uniquemuon;
04177                 a.start=-1;
04178                 a.stop=-1;
04179                 p3d->types.push_back(a);        
04180         }
04181         }
04183 
04184 
04185 
04186         
04187         //prot check // can also be a  stopping of +muon
04188         int plow=p3d->entries-1;
04189         int phigh=p3d->entries-1;
04190         if(p3d->e[p3d->entries-1]>highm)
04191         for(int i=p3d->entries-2;i>-1;i--)
04192         {
04193                 if(p3d->e[i]<p3d->e[i+1]) plow=i;
04194                 else break;
04195         }
04196         if(phigh-plow>0)
04197         {
04198 
04199                 s<<"proton/stopping u+ found from "<<plow<<" to "<<phigh<<endl;
04200                 ParticleType a;
04201                 a.type = ParticleType::prot;
04202                 a.start=plow;
04203                 a.stop=phigh;
04204                 p3d->types.push_back(a);        
04205         }
04206         
04207         //we now have a list of types.... go through, and split up the Particle3D as needed until all Particle3Ds have a single type
04208         
04209         
04210         int emt=0;
04211         
04212         //p3d->particletype=0;
04213         p3d->particletype=Particle3D::other;
04214         
04215         
04216         
04217         std::vector<ParticleType>::iterator it;
04218         
04219         
04220         //cout <<"num of types for this particle "<<  p3d->types.size()<<endl;
04221                 
04222         for(it=p3d->types.begin();it!=p3d->types.end();it++)
04223         {
04224         
04225                 
04226                 if(it->type==ParticleType::uniquemuon)
04227                 {
04228                         ostringstream s;
04229                         s<<"ATTEMPTING TO STRIP MUON\n";
04230                         std::pair<Particle3D*,Particle3D*> a = StripMuon1(p3d);
04231                         if(a.first)
04232                         {
04233                                 s << "STRIPPED MUON\n";
04234                                 pout.push_back(a.first); //thats the stripped muon...
04235                                 if(a.second) //make sure we removed something from p3d...
04236                                 {
04237                                         s <<"  OTHERS REMAIN!\n";
04238                                 
04239                                         std::vector<Particle3D*> b =ProcessParticle3D1(a.second); //the adjusted remnant needs to be rechecked!
04240                                         for(unsigned int j=0;j<b.size();j++)
04241                                                 pout.push_back(b[j]);
04242                                 }
04243                                 //return pout;
04244                                 break;
04245                         }else{  //remove the incorrectly assigned unique muon tag
04246                                 p3d->types.erase(it);
04247                         
04248                         }       
04249                 }
04250                 
04251                 MSG("Finder",Msg::kDebug)<<s;
04252         
04253         
04254                 //see if it is definitely a muon!
04255                 
04256                 if(it->type==ParticleType::muon && it->stop - it->start+1 == p3d->entries)
04257                 {
04258                         p3d->particletype=Particle3D::muon;
04259                 //      break;
04260                 
04261                 }
04262 
04263                 
04264                 if(it->type==ParticleType::em && it->stop - it->start+1 == p3d->entries)
04265                 {
04266                         p3d->particletype=Particle3D::electron;
04267                 //      break;
04268                 }
04269 
04270                 if(it->type==ParticleType::em && (double)( it->stop - it->start) / (double) p3d->entries > 0.8) //more than half of it is em....
04271                 {
04272                         p3d->particletype=Particle3D::electron;
04273                 //      break;
04274                 }
04275 
04276                 if(it->type==ParticleType::em )
04277                 {
04278                         emt+= it->stop - it->start+1;
04279                 }
04280         
04281 
04282         
04283         }
04284 
04285         if(p3d->particletype==0 && p3d->muonfrac>0.6)
04286         {
04287                 p3d->particletype=Particle3D::muon;
04288                         
04289         }       
04290 
04291         if(p3d->particletype==0 && (double)emt / (double)p3d->entries > 40)
04292         {
04293                 p3d->particletype=Particle3D::electron;
04294                         
04295         }       
04296 
04297 
04298         MSG("Finder",Msg::kDebug) << s.str()<<endl;     
04299         
04300         pout.push_back(p3d);
04301         return pout;
04302         
04303 }
04304 
04305 
04306 
04307 std::pair<Particle3D*,Particle3D*> Finder::StripMuon1(Particle3D * p3d)
04308 {
04309         std::pair<Particle3D*,Particle3D*>  a;
04310         a.first=0;
04311         a.second=p3d;
04312         
04313         //see if all unique hits are muons hits....
04314         double lowm=0.0;
04315         double highm=3.5;
04316         
04317         int u=0;
04318         int m=0;
04319         double me=0;
04320         
04321         for(int i=0;i<p3d->entries;i++)
04322         {
04323                 if(p3d->shared[i]==0)
04324                 {
04325                         u++;
04326                         if(p3d->e[i] > lowm && p3d->e[i]<highm)
04327                         {
04328                                 m++;
04329                                 me+=p3d->e[i];
04330                         }
04331                 }
04332         }
04333         
04334         if(u==m)
04335         { 
04336                 a.second=0;  //releasing shared particles which cant be part of something else...
04337                 //cout <<"!!!---releasing particle"<<endl;
04338         }
04339         
04340         
04341         Particle3D * c = new Particle3D();
04342         a.first=c;
04343         
04344         
04345         double eavg = me/m;
04346         for(int i=0;i<p3d->entries;i++)
04347         {
04348                 double e = p3d->e[i] > lowm && p3d->e[i]<highm ? p3d->e[i] : eavg;
04349                 e = e > p3d->e[i] ? p3d->e[i] : e;
04350         
04351                 c->add_to_back( p3d->u[i],  p3d->v[i],  p3d->z[i], e, p3d->chain[i], p3d->chainhit[i],  p3d->view[i],0);
04352                 c->lockshared[c->entries-1]=1;
04353 
04354                 shareholder.Take(p3d->chain[i],p3d->chainhit[i],e);
04355                 
04356                 if(a.second)
04357                 {
04358                         double reste=p3d->e[i]-e>0 ? p3d->e[i]-e : 0;
04359                         a.second->e[i]= reste;
04360                         
04361                         shareholder.Take(p3d->chain[i],p3d->chainhit[i],e);
04362                         
04363                         
04364                 }
04365         }
04366         c->particletype=Particle3D::muon;
04367 
04368         ParticleType pta;
04369         pta.type = ParticleType::muon;
04370         pta.start=0;
04371         pta.stop=p3d->entries;
04372         c->types.push_back(pta);        
04373 
04374 
04375         if(a.second)
04376         {
04377                 double sume=0;
04378                 int num0=0;
04379                 for(int i=0;i<a.second->entries;i++)
04380                 {
04381                         sume+=a.second->e[i];
04382                         if(a.second->e[i]<0.01)num0++;
04383                 }
04384                 MSG("Finder",Msg::kDebug)<<"second e"<<sume<<endl;
04385                 
04386                 if(sume<0.0001 || (double)num0/(double)a.second->entries > 0.8)
04387                 {
04388                         a.second=0;  //releasing shared particles which cant be part of something else...
04389                         //cout <<"!!!---releasing particle"<<endl;
04390                 }
04391                 else  //we are keeping the particle....
04392                 {
04393 
04394 
04395                         //remove the unique muon indicator....
04396                 
04397                         std::vector<ParticleType>::iterator it;
04398                         for(it=a.second->types.begin();it!=a.second->types.end();it++)
04399                         {
04400                                 if(it->type==ParticleType::uniquemuon)
04401                                 {
04402                                         a.second->types.erase(it);
04403                                         it=a.second->types.begin(); //for now restart at the beginning... not the best way
04404                                         MSG("Finder",Msg::kDebug)<<"removed uniquemuon indicator from particle3d "<<endl;
04405                                 }
04406                         
04407                         }
04408 
04409 
04410                         //clear particle list....
04411                         a.second->types.clear();
04412 
04413                 }
04414         }
04415 
04416 
04417         return a;
04418 
04419 }
04420 
04421 
04422 bool p3dsharedsort(Particle3D* a, Particle3D* b)
04423 {
04424         return a->numshared < b->numshared; 
04425 }
04426 
04427 
04428 void Finder::RemoveSharedHits(std::vector<Particle3D*> pv)
04429 {
04430 
04431         MSG("Finder",Msg::kDebug) <<"\ncleaning list\n";
04432         for (unsigned int i=0;i<pv.size();i++)
04433         {
04434                         MSG("Finder",Msg::kDebug) << " removing with "<<pv[i]->numshared<<" shared \n";
04435         
04436                         //first clear out any hits marked as shared that are not!
04437                         for(int j=0;j<pv[i]->entries;j++)
04438                         {
04439                                 if(pv[i]->shared[j])
04440                                 {
04441                                         if(shareholder.GetNumShared(pv[i]->chain[j],pv[i]->chainhit[j])<2)
04442                                                 pv[i]->UnsetShared(pv[i]->chain[j],pv[i]->chainhit[j]);
04443                                         if(shareholder.GetNumShared(pv[i]->chain[j],pv[i]->chainhit[j])==1)
04444                                         {
04445                                                 int c=pv[i]->chain[j];
04446                                                 int ch=pv[i]->chainhit[j];
04447                                                 double e = shareholder.GetEShared(c,ch);
04448                                         
04449                                         
04450                                                 pv[i]->e[j]=e;
04451                                                 shareholder.Take(c,ch,e);
04452                                         }
04453                                 }
04454                         
04455                         }
04456         
04457         }
04458 
04459 
04460         sort(pv.begin(), pv.end(), p3dsharedsort);
04461 
04462         MSG("Finder",Msg::kDebug) <<"\nremoving hits\n";
04463 
04464         for (unsigned int i=0;i<pv.size();i++)
04465         {               
04466                         shareholder.dump();
04467 
04468                         //first clear out any hits marked as shared that are not!
04469                         for(int j=0;j<pv[i]->entries;j++)
04470                         {
04471                                 if(pv[i]->shared[j])
04472                                 {
04473                                         if(shareholder.GetNumShared(pv[i]->chain[j],pv[i]->chainhit[j])<2)
04474                                                 pv[i]->UnsetShared(pv[i]->chain[j],pv[i]->chainhit[j]); 
04475                                         if(shareholder.GetNumShared(pv[i]->chain[j],pv[i]->chainhit[j])==1)
04476                                         {
04477                                                 int c=pv[i]->chain[j];
04478                                                 int ch=pv[i]->chainhit[j];
04479                                                 double e = shareholder.GetEShared(c,ch);
04480                                         
04481                                         
04482                                                 pv[i]->e[j]=e;
04483                                                 shareholder.Take(c,ch,e);
04484                                         }               
04485                                 }
04486                         
04487                         }
04488 
04489 
04490 
04491 
04492 
04493                 if (pv[i]->particletype==Particle3D::muon)
04494                 {
04495                         MSG("Finder",Msg::kDebug)<<"!!muon\n";
04496                 }
04497                 else if (pv[i]->particletype==Particle3D::electron)
04498                 {
04499                         MSG("Finder",Msg::kDebug)<<"!!elec\n";
04500                 }
04501                 else MSG("Finder",Msg::kDebug)<<"!!other "<<pv[i]->particletype<<"\n";
04502                 
04503                 
04504                 //for now, treat all types similary.... 
04505                 //first look for shared hit surrounded by two unshared hits, and set it to the average
04506                 for(int j=1;j<pv[i]->entries-2;j++)
04507                 {
04508                         if(pv[i]->shared[j] && !pv[i]->shared[j-1] && !pv[i]->shared[j+1])
04509                         {
04510                                 int c=pv[i]->chain[j];
04511                                 int ch=pv[i]->chainhit[j];
04512                                 double e = shareholder.GetEShared(c,ch);
04513                                         
04514                                 double totake=(pv[i]->e[j-1]+pv[i]->e[j+1])/2;
04515                                 totake=totake>e?e:totake;
04516                                 
04517                                 pv[i]->e[j]=totake;
04518                                 shareholder.Take(c,ch,totake);
04519                                 pv[i]->UnsetShared(c,ch);
04520                         
04521                         }
04522                 }
04523                 
04524                 //if that doesn't work, try the average of closest unshared hits
04525                 for(int j=0;j<pv[i]->entries;j++)
04526                 {
04527                         int foundupper=-1;
04528                         int foundlower=-1;
04529                         for(int k=j+1;k<pv[i]->entries;k++)
04530                         {
04531                                 //printf("%d(%d) %d(%d)\n",j,pv[i]->shared[j],k,pv[i]->shared[k]);
04532                                 if(pv[i]->shared[j]&&! pv[i]->shared[k])
04533                                 {
04534                                         foundupper=k;
04535                                         break;
04536                                 }
04537                         }
04538                         
04539                         for(int k=j-1;k>-1;k--)
04540                         {
04541                                 if(pv[i]->shared[j]&&! pv[i]->shared[k])
04542                                 {
04543                                         foundlower=k;
04544                                         break;
04545                                 }
04546                         }
04547                         
04548                         double totake=0;
04549                         
04550                         if(foundupper>-1 && foundlower>-1)
04551                         {
04552                                 totake = (pv[i]->e[foundupper]+pv[i]->e[foundlower])/2;
04553                         }
04554                         else if(foundupper>-1)
04555                         {
04556                                 totake = (pv[i]->e[foundupper]);
04557                         }
04558                         else if(foundlower>-1)
04559                         {
04560                                 totake = (pv[i]->e[foundlower]);
04561                         }else continue;
04562                         
04563                         int c=pv[i]->chain[j];
04564                         int ch=pv[i]->chainhit[j];
04565                         double e = shareholder.GetEShared(c,ch);        
04566                         totake=totake>e?e:totake;
04567                         pv[i]->e[j]=totake;
04568                         MSG("Finder",Msg::kDebug)<<"taking from "<<c<<" "<<ch << " with shard "<<shareholder.GetNumShared(c,ch)<<"\n";
04569                         shareholder.Take(c,ch,totake);
04570                         MSG("Finder",Msg::kDebug)<<"now has "<<shareholder.GetNumShared(c,ch)<<" shared\n";
04571                         pv[i]->UnsetShared(c,ch);
04572                         
04573                 }
04574                 
04575                 pv[i]->finalize();
04576                 
04577         }
04578 
04579 
04580 }

Generated on Mon Feb 15 11:06:43 2010 for loon by  doxygen 1.3.9.1