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

AlgSubShowerSRList.cxx

Go to the documentation of this file.
00001 
00002 // $Id: AlgSubShowerSRList.cxx,v 1.30 2007/10/17 11:24:48 scavan Exp $
00003 //
00004 // AlgSubShowerSRList.cxx
00005 //
00006 // AlgSubShowerSRList is a concrete SubShowerSRList Algorithm class.
00007 //
00009 
00010 #include <cassert>
00011 #include <fstream>
00012 #include <vector>
00013 #include "Algorithm/AlgFactory.h"
00014 #include "Algorithm/AlgHandle.h"
00015 #include "Algorithm/AlgConfig.h"
00016 #include "Candidate/CandContext.h"
00017 #include "CandSubShowerSR/AlgSubShowerSR.h"
00018 #include "CandSubShowerSR/AlgSubShowerSRList.h"
00019 #include "CandSubShowerSR/CandSubShowerSR.h"
00020 #include "CandSubShowerSR/CandSubShowerSRHandle.h"
00021 #include "CandSubShowerSR/CandSubShowerSRList.h"
00022 #include "CandSubShowerSR/CandSubShowerSRListHandle.h"
00023 #include "Conventions/PlaneView.h"
00024 #include "CandSubShowerSR/ClusterType.h"
00025 #include "MessageService/MsgService.h"
00026 #include "MinosObjectMap/MomNavigator.h"
00027 #include "Navigation/NavKey.h"
00028 #include "Navigation/NavSet.h"
00029 #include "RecoBase/CandSliceHandle.h"
00030 #include "RecoBase/CandTrackHandle.h"
00031 #include "RecoBase/CandClusterHandle.h"
00032 #include "RecoBase/CandSliceListHandle.h"
00033 #include "RecoBase/CandTrackListHandle.h"
00034 #include "RecoBase/CandClusterListHandle.h"
00035 #include "Validity/VldContext.h"
00036 #include "UgliGeometry/UgliGeomHandle.h"
00037 #include "Calibrator/Calibrator.h"
00038 #include "UgliGeometry/UgliGeomHandle.h"
00039 #include "TSpectrum.h"
00040 #include "TMath.h"
00041 #include "TGraphErrors.h"
00042 #include "TCanvas.h"
00043 #include "TStyle.h"
00044 
00045 #define MAXHOUGHITER 5
00046 #define STRIPWIDTHINMETRES 0.041
00047 #define PITCHINMETRES 0.06
00048 #define FIRSTNDSPECPLANE 121
00049 
00050 ClassImp(AlgSubShowerSRList)
00051 
00052 //______________________________________________________________________
00053 CVSID("$Id: AlgSubShowerSRList.cxx,v 1.30 2007/10/17 11:24:48 scavan Exp $");
00054 //______________________________________________________________________
00055 
00056 AlgSubShowerSRList::AlgSubShowerSRList() :
00057   fLongWindowMipCut(0.0),fLongWindowGapPlaneCut(4),
00058   fMinHoughPlanes(3),fMinHoughPH(1.0), fBestHoughMaxPHFrac(0.75),
00059   fCleanUpTimeCut(50.0),fCleanUpPlaneCut(2),fCleanUpStripCut(2.5),
00060   fFormHalo(1),fHaloMaxPlaneGap(2),fHaloNPeakFindingBins(64)
00061 {
00062   vtxHist = new TH1F("vtxHist","vtxHist",1,-4.,4.);
00063   houghHist = new TH2F("houghHist","Hough Histogram",1,-1,1,1,-1,1);
00064   phHoughHist = new TH2F("phHoughHist","PH Weighted Hough Histogram",1,-1,1,1,-1,1);
00065   ssPol1 = new TF1("ssPol1","pol1",0,500);
00066 }
00067 
00068 //______________________________________________________________________
00069 AlgSubShowerSRList::~AlgSubShowerSRList()
00070 {
00071   delete vtxHist;
00072   delete houghHist;
00073   delete phHoughHist;
00074   delete ssPol1;
00075 }
00076 
00077 //______________________________________________________________________
00078 void AlgSubShowerSRList::RunAlg(AlgConfig &ac, CandHandle &ch,CandContext &cx)
00079 {
00080 
00081   MSG("SubShowerSR", Msg::kDebug) << "Starting AlgSubShowerSRList::RunAlg()" 
00082                                   << endl;
00083   assert(cx.GetDataIn());
00084   if (!(cx.GetDataIn()->InheritsFrom("TObjArray"))) {
00085     return;
00086   }
00087   
00088   const CandSliceListHandle *slicelist = 0;
00089   const CandClusterListHandle *clusterlist = 0;
00090   const CandTrackListHandle *tracklist = 0;
00091   const TObjArray *cxin = dynamic_cast<const TObjArray *>(cx.GetDataIn());
00092   for (Int_t i=0; i<=cxin->GetLast(); i++) {
00093     TObject *tobj = cxin->At(i);
00094     MSG("SubShowerSR", Msg::kDebug) << "cxin->At(" << i << ")"<< endl;
00095     if (tobj->InheritsFrom("CandSliceListHandle")) {
00096       slicelist = dynamic_cast<CandSliceListHandle*>(tobj);
00097       MSG("SubShowerSR", Msg::kDebug) << "Got SliceList" << endl;
00098     }
00099     if (tobj->InheritsFrom("CandClusterListHandle")) {
00100       clusterlist = dynamic_cast<CandClusterListHandle*>(tobj);
00101       MSG("SubShowerSR", Msg::kDebug) << "Got ClusterList" << endl;
00102     }
00103     if (tobj->InheritsFrom("CandTrackListHandle")) {
00104       tracklist = dynamic_cast<CandTrackListHandle*>(tobj);
00105       MSG("SubShowerSR", Msg::kDebug) << "Got TrackList" << endl;
00106     }
00107   }
00108   if (!slicelist || !clusterlist || !tracklist) {
00109     MSG("SubShowerSR",Msg::kInfo) << "CandSliceListHandle or " 
00110                                   << "CandClusterListHandle or " 
00111                                   << "CandTrackListHandle missing\n";
00112     return;
00113   }
00114 
00115   MSG("SubShowerSR", Msg::kDebug) << "Creating CandContext" << endl;
00116   // Create Candcontext
00117   CandContext cxx(this,cx.GetMom());
00118 
00119   //get config for AlgSubShowerSRList
00120   const char *charSubShowerSRAlgConfig = 0;
00121   ac.Get("SubShowerSRAlgConfig",charSubShowerSRAlgConfig);
00122 
00123   Int_t minNTrkOnlyPlanesToUseTrackStrips = ac.GetInt("MinNTrkOnlyPlanesToUseTrackStrips");
00124   Int_t maxPlanesFromVtxToUseTrackStrips  = ac.GetInt("MaxPlanesFromVertexToUseTrackStrips");
00125   Double_t minMIPsToUseTrackStrips        = ac.GetDouble("MinMIPsToUseTrackStrips");
00126 
00127   fLongWindowMipCut      = ac.GetDouble("LongWindowMipCut");
00128   fLongWindowGapPlaneCut = ac.GetInt("LongWindowGapPlaneCut");
00129   fMinHoughPlanes        = ac.GetInt("MinHoughPlanes");
00130   fMinHoughPH            = ac.GetDouble("MinHoughPH");
00131   fBestHoughMaxPHFrac    = ac.GetDouble("BestHoughMaxPHFrac");
00132   fCleanUpTimeCut        = ac.GetDouble("CleanUpTimeCut");
00133   fCleanUpPlaneCut       = ac.GetInt("CleanUpPlaneCut");
00134   fCleanUpStripCut       = ac.GetDouble("CleanUpStripCut");
00135   fFormHalo              = ac.GetInt("FormHalo");
00136   fHaloMaxPlaneGap       = ac.GetInt("HaloMaxPlaneGap");
00137   fHaloNPeakFindingBins  = ac.GetInt("HaloNPeakFindingBins");
00138   
00139   //Get singleton instance of AlgFactory
00140   AlgFactory &af = AlgFactory::GetInstance();
00141   AlgHandle ah = af.GetAlgHandle("AlgSubShowerSR",charSubShowerSRAlgConfig);
00142                                                                    
00143   const CandRecord *candrec = cx.GetCandRecord();
00144   assert(candrec);
00145   const VldContext *vldcptr = candrec->GetVldContext();
00146   assert(vldcptr);
00147   VldContext vldc = *vldcptr;                                         
00148   UgliGeomHandle ugh(vldc);
00149   Int_t detector = 0;
00150   if(vldc.GetDetector()==Detector::kFar) detector = 1;
00151 
00152   Calibrator& calibrator = Calibrator::Instance();
00153 
00154   //keep track of all unassigned strips in all slices and try to add them later
00155   TObjArray unassignedStrips;
00156 
00157   //loop over all slices
00158   Int_t sliceCounter = 0;
00159   CandSliceHandleItr sliceItr(slicelist->GetDaughterIterator());
00160   while (CandSliceHandle *slice = sliceItr()) {
00161 
00162     MSG("SubShowerSR",Msg::kVerbose) << "Slice " <<  sliceCounter << endl;
00163 
00164     //also keep track of cluster planes and track planes
00165     Int_t cluPln[500] = {0};
00166     Int_t trkPln[500] = {0};
00167     Int_t nTrkOnlyPlanes = 0;
00168     if(tracklist!=0) {
00169       //loop through all tracks in track list
00170       CandTrackHandleItr trackItr(tracklist->GetDaughterIterator());
00171       while (CandTrackHandle *track = trackItr()){
00172         //if this track is in the current slice then...
00173         if (*track->GetCandSlice()==*slice) {
00174           for(Int_t i=track->GetBegPlane();i<=track->GetEndPlane();i++){
00175             trkPln[i] += 1;   //if trkPln > 1 => multiple tracks in plane
00176             nTrkOnlyPlanes += 1;
00177           }
00178         }
00179       }
00180     }
00181     if(clusterlist!=0) {
00182       //loop through all clusters in cluster list
00183       CandClusterHandleItr clusterItr(clusterlist->GetDaughterIterator());
00184       while (CandClusterHandle *cluster = clusterItr()){
00185         //if this cluster is in the current slice then...
00186         if (*cluster->GetCandSlice()==*slice) {
00187           for(Int_t i=cluster->GetBegPlane();i<=cluster->GetEndPlane();i+=2){
00188             cluPln[i] += 1;   //if cluPln > 1 => multiple clusters in plane
00189             if(trkPln[i]>0) nTrkOnlyPlanes-=1;
00190             if(detector==1){//account for SM gap
00191               if(i==247) i = 250; 
00192               if(i==248) i = 251;
00193             }
00194           }
00195         }
00196       }
00197     }
00198 
00199     //for each slice, make an Object Array to hold all the 
00200     //non track strips in the slice
00201     TObjArray allUStrips;
00202     TObjArray allVStrips;
00203     
00204     //loop through the strips in the slice
00205     CandStripHandleItr stripslcItr(slice->GetDaughterIterator());    
00206     MSG("SubShowerSR",Msg::kVerbose) << "About to loop through slice strips" 
00207                                      << endl;
00208     
00209     while (CandStripHandle *stp =stripslcItr()) { //while over slice stp
00210       bool gotStrip = false;
00211       MSG("SubShowerSR",Msg::kVerbose) << "PlaneView " 
00212                                        << stp->GetPlaneView() << endl;
00213       
00214       CandClusterHandleItr clusterItr(clusterlist->GetDaughterIterator());
00215       Int_t clusterCounter = 0;
00216       while(CandClusterHandle *cluster = clusterItr()){ 
00217         MSG("SubShowerSR",Msg::kVerbose) 
00218           << "Looking for stp match in cluster " << clusterCounter << endl;
00219         if(*cluster->GetCandSlice()==*slice){
00220           CandStripHandleItr stripcluItr(cluster->GetDaughterIterator());
00221           while (CandStripHandle *stpclu =stripcluItr()){
00222             if(*stp==*stpclu){
00223               gotStrip = true;
00224               //add strip to object array then break out of loop
00225               if(stp->GetPlaneView()==PlaneView::kU ||
00226                  stp->GetPlaneView()==PlaneView::kX) {
00227                 allUStrips.Add(stp);
00228                 MSG("SubShowerSR",Msg::kVerbose) << "Found match! U strip" 
00229                                                  << endl;             
00230               }
00231               else if(stp->GetPlaneView()==PlaneView::kV ||
00232                       stp->GetPlaneView()==PlaneView::kY) {
00233                 allVStrips.Add(stp);
00234                 MSG("SubShowerSR",Msg::kVerbose) << "Found match! V strip" 
00235                                                  << endl;
00236               }
00237               else MSG("SubShowerSR",Msg::kError) 
00238                 << "Unknown PlaneView! Not adding strip to initial ObjArray" 
00239                 << endl;
00240               break;
00241             }
00242           }
00243         }
00244         if(gotStrip) break;
00245         clusterCounter++;
00246       }
00247       
00248       //if this is an ND strip in spectrometer, don't add to array
00249       if(!gotStrip && detector==0 && stp->GetPlane()>=FIRSTNDSPECPLANE) gotStrip=true;
00250 
00251       if(!gotStrip){  //if !gotStrip
00252         bool inTrack = false;
00253         Int_t nPlanesFromBegPlane = 0;
00254         if(tracklist!=0) {
00255           MSG("SubShowerSR",Msg::kVerbose) 
00256             << "No matched strip found in clusters, looking in tracks"
00257             << endl;
00258           
00259           //loop through all tracks in track list
00260           CandTrackHandleItr trackItr(tracklist->GetDaughterIterator());
00261           Int_t trackCounter = 0;
00262           while (CandTrackHandle *track = trackItr()){
00263             MSG("SubShowerSR",Msg::kVerbose) 
00264               << "Looking for match of slc stp with trk stp in track "
00265               << trackCounter << endl;
00266             //if this track is in the current slice then...
00267             if (*track->GetCandSlice()==*slice) {
00268               //...loop over all strips in this track
00269               CandStripHandleItr striptrkItr(track->GetDaughterIterator());
00270               while (CandStripHandle *stptrk =striptrkItr()){
00271                 //if this strip is in this track then...
00272                 if (*stp == *stptrk) {
00273                   MSG("SubShowerSR",Msg::kVerbose) 
00274                     << "Found match! This strip is in a track!" << endl;
00275                   //...break and move on to the next strip in the slice
00276                   inTrack = true;
00277                   nPlanesFromBegPlane = TMath::Abs(stp->GetPlane()-track->GetBegPlane());
00278                   break;
00279                 }
00280               }
00281             }
00282             if(inTrack) break;
00283             trackCounter++;
00284           }
00285         }
00286         
00287         MSG("SubShowerSR",Msg::kVerbose) << "nTrkOnlyPlanes = " 
00288                                          << nTrkOnlyPlanes << endl;
00289         if(inTrack && nTrkOnlyPlanes<minNTrkOnlyPlanesToUseTrackStrips) {
00290           MSG("SubShowerSR",Msg::kDebug) 
00291             << "nTrkOnlyPlanes<" << minNTrkOnlyPlanesToUseTrackStrips 
00292             << " - going to include this strip " 
00293             << "even though it's in a track." << endl;
00294           inTrack = false; //ignore tracks that are buried in showers
00295         }
00296         else if(inTrack && nPlanesFromBegPlane <
00297                 maxPlanesFromVtxToUseTrackStrips) { //near vertex
00298           if(calibrator.GetMIP(stp->GetCharge(CalDigitType::kSigCorr)) >
00299              minMIPsToUseTrackStrips) {
00300             MSG("SubShowerSR",Msg::kDebug) 
00301               << "nPlanesFromBegPlane < "
00302               << maxPlanesFromVtxToUseTrackStrips 
00303               << " for this strip and ph = "
00304               << calibrator.GetMIP(stp->GetCharge(CalDigitType::kSigCorr))
00305               << " mips. "
00306               << "Going to include it even though it's in a track." 
00307               << endl;
00308             inTrack = false;
00309           }
00310         }
00311 
00312         //then: add it to our array
00313         if(!inTrack){
00314           MSG("SubShowerSR",Msg::kVerbose) << "Strip not found in track! ";
00315           if(stp->GetPlaneView()==PlaneView::kU ||
00316              stp->GetPlaneView()==PlaneView::kX) {
00317             allUStrips.Add(stp);
00318             MSG("SubShowerSR",Msg::kVerbose) << "Adding U strip" << endl;
00319           }
00320           else if(stp->GetPlaneView()==PlaneView::kV ||
00321                   stp->GetPlaneView()==PlaneView::kY) {
00322             allVStrips.Add(stp);
00323             MSG("SubShowerSR",Msg::kVerbose) << "Adding V strip" << endl;
00324           }
00325           else MSG("SubShowerSR",Msg::kError) 
00326             << "Unknown PlaneView! Not adding strip to initial ObjArray" 
00327             << endl;
00328         }
00329       }
00330     }
00331 
00332     MSG("SubShowerSR",Msg::kDebug) << "Found total of " 
00333                                    << allUStrips.GetLast()+1 << " U strips" 
00334                                    << " and " << allVStrips.GetLast()+1 
00335                                    << " V strips" << endl;
00336     
00337     //In here put code to pull out the strips belonging to the SubShowers:
00338     bool keepGoingU = true;
00339     bool keepGoingV = true;
00340     while(keepGoingU || keepGoingV){
00341       if(keepGoingU) 
00342         MSG("SubShowerSR",Msg::kDebug) << "Still have " 
00343                                        << allUStrips.GetLast()+1
00344                                        << " U strips to process" << endl;
00345       
00346       else if(keepGoingV) 
00347         MSG("SubShowerSR",Msg::kDebug) << "Still have " 
00348                                        << allVStrips.GetLast()+1
00349                                        << " V strips to process" << endl;
00350 
00351       if(allUStrips.GetLast()+1<=0) keepGoingU = false;
00352       if(allVStrips.GetLast()+1<=0) keepGoingV = false;
00353 
00354       TObjArray newSubShower;
00355       if(keepGoingU){ //do U first
00356         this->FindCluster(&allUStrips,&newSubShower,detector);
00357         this->TimeTest(&newSubShower);
00358         while(this->TestOverLap(&newSubShower,ch,slice));
00359         MSG("SubShowerSR",Msg::kDebug) << "Added " << newSubShower.GetLast()+1 
00360                                        << " U strips to newSubShower" << endl;
00361       }
00362       else if(keepGoingV) { //then V strips
00363         TObjArray protoSubShower;
00364         this->FindCluster(&allVStrips,&newSubShower,detector);
00365         this->TimeTest(&newSubShower);
00366         while(this->TestOverLap(&newSubShower,ch,slice));
00367         MSG("SubShowerSR",Msg::kDebug) << "Added " << newSubShower.GetLast()+1 
00368                                        << " V strips to newSubShower" << endl;
00369      }
00370 
00371       //Everytime you have a newSubShower with all the strips 
00372       //you want to add do this
00373       cxx.SetDataIn(&newSubShower);
00374       MSG("SubShowerSR",Msg::kDebug) << "forming SubShowerSR\n";
00375       CandSubShowerSRHandle subshowersrhandle = 
00376         CandSubShowerSR::MakeCandidate(ah,cxx);
00377       
00378       if(subshowersrhandle.GetNStrip()!=0) {
00379         
00380         MSG("SubShowerSR",Msg::kDebug) << "Formed SubShowerSR with " 
00381                                        << subshowersrhandle.GetNStrip() 
00382                                        << " strips" << endl;
00383         
00384         subshowersrhandle.SetCandSlice(slice);
00385         ch.AddDaughterLink(subshowersrhandle);
00386         
00387         CandStripHandleItr stripItr(subshowersrhandle.GetDaughterIterator());
00388 
00389         std::vector<Int_t> tmpUArray(allUStrips.GetLast()+1,0);
00390         for(int i=0;i<allUStrips.GetLast()+1;i++) tmpUArray[i] = 0;
00391         std::vector<Int_t> tmpVArray(allVStrips.GetLast()+1,0);
00392         for(int i=0;i<allVStrips.GetLast()+1;i++) tmpVArray[i] = 0;     
00393         
00394         while(CandStripHandle *stp = stripItr()){
00395           if(stp->GetPlaneView()==PlaneView::kU ||
00396              stp->GetPlaneView()==PlaneView::kX){
00397             for (int i=0; i<=allUStrips.GetLast(); i++) {
00398               TObject *tobj = allUStrips.At(i);
00399               assert(tobj->InheritsFrom("CandStripHandle"));
00400               CandStripHandle *striphandle = 
00401                 dynamic_cast<CandStripHandle*>(tobj);
00402               if(*stp==*striphandle) {
00403                 tmpUArray[i] = 1;
00404                 break;
00405               }
00406             }
00407           }
00408           else if(stp->GetPlaneView()==PlaneView::kV ||
00409                   stp->GetPlaneView()==PlaneView::kY){
00410             for (int i=0; i<=allVStrips.GetLast(); i++) {
00411               TObject *tobj = allVStrips.At(i);
00412               assert(tobj->InheritsFrom("CandStripHandle"));
00413               CandStripHandle *striphandle = 
00414                 dynamic_cast<CandStripHandle*>(tobj);
00415               if(*stp==*striphandle) {
00416                 tmpVArray[i] = 1;
00417                 break;
00418               }
00419             }
00420           }
00421         }
00422         
00423         //remove used strips from arrays
00424         for(int i=0;i<allUStrips.GetLast()+1;i++) {
00425           if(tmpUArray[i]==1) allUStrips.RemoveAt(i);
00426         }
00427         allUStrips.Compress();
00428         if(allUStrips.GetLast()==-1) keepGoingU = false;
00429         
00430         for(int i=0;i<allVStrips.GetLast()+1;i++) {
00431           if(tmpVArray[i]==1) allVStrips.RemoveAt(i);
00432         }
00433         allVStrips.Compress();
00434         if(allVStrips.GetLast()==-1) keepGoingV = false;
00435       
00436       }
00437       else {
00438         MSG("SubShowerSR",Msg::kDebug) 
00439           << "SubShowerSR formed with 0 strips - not adding to list" 
00440           << endl;
00441         if(keepGoingU) {
00442           MSG("SubShowerSR",Msg::kDebug) << "Running CleanUp() on U Strips" 
00443                                          << endl;       
00444           keepGoingU = CleanUp(&allUStrips,ch,detector,slice);
00445           if(!keepGoingU) {
00446             for(int i=0;i<allUStrips.GetLast()+1;i++) {
00447               unassignedStrips.Add(allUStrips.At(i));
00448             }
00449           }
00450         }
00451         else {
00452           MSG("SubShowerSR",Msg::kDebug) << "Running CleanUp() on V Strips" 
00453                                          << endl;
00454           keepGoingV = CleanUp(&allVStrips,ch,detector,slice);
00455           if(!keepGoingV) {
00456             for(int i=0;i<allVStrips.GetLast()+1;i++) {
00457               unassignedStrips.Add(allVStrips.At(i));
00458             }
00459           }
00460         }
00461       }
00462     }
00463     sliceCounter++;
00464   }
00465 
00466   //slice-wise cleanup
00467   if(fFormHalo&&FormHalo(&unassignedStrips,ch,cxx,ah,slicelist,detector)) 
00468     MSG("SubShowerSR",Msg::kDebug) << "Halo SubShowers formed" << endl;  
00469 
00470 }
00471 
00472 //******************************************************************
00473 Bool_t AlgSubShowerSRList::FindCluster(TObjArray *allStrips,
00474                                        TObjArray *newSubShower,Int_t det)
00475 {
00476 
00477   Int_t nstp = allStrips->GetLast()+1;
00478   if(nstp==0){
00479     MSG("SubShower", Msg::kWarning) << "No strips present!" << endl;
00480     return false;
00481   }
00482 
00483   //Get useful info from candidates for clustering
00484   //Read in info:
00485   std::vector<Int_t> plane(nstp,0);
00486   std::vector<Int_t> strip(nstp,0);
00487   std::vector<Double_t> ph(nstp,0.0);
00488   std::vector<Double_t> pherr(nstp,0.0);
00489   std::vector<Double_t> z(nstp,0.0);
00490   std::vector<Double_t> tpos(nstp,0.0);
00491 
00492   //neighbouring strip info
00493   std::vector<Double_t> TransGradientPlus(nstp,0.0);
00494   std::vector<Double_t> TransGradientMinus(nstp,0.0);
00495   std::vector<Double_t> TransGradientErrorPlus(nstp,0.0);
00496   std::vector<Double_t> TransGradientErrorMinus(nstp,0.0);
00497 
00498   CandStripHandle *usefulStrip = 0;
00499   int begPlane = 500;
00500   int endPlane = 0;
00501   
00502   Int_t doubleCounter = 0;
00503   Int_t alreadyGot[500][192] = {{0}};
00504   Calibrator& calibrator=Calibrator::Instance();
00505   for (Int_t i=0; i<=allStrips->GetLast(); i++) {
00506     TObject *tobj = allStrips->At(i);
00507     assert(tobj->InheritsFrom("CandStripHandle"));
00508     CandStripHandle *stp = dynamic_cast<CandStripHandle*>(tobj);
00509     if(alreadyGot[stp->GetPlane()][stp->GetStrip()]==1) {
00510       for(int j=0;j<i-doubleCounter;j++){
00511         if(plane[j]==stp->GetPlane() && strip[j]==stp->GetStrip()){
00512           ph[j] += calibrator.GetMIP(stp->GetCharge(CalDigitType::kSigCorr));
00513           TransGradientPlus[j] = ph[j];
00514           TransGradientMinus[j] = ph[j];
00515           break;
00516         }
00517       }
00518       doubleCounter+=1;
00519       nstp -= 1;
00520     }
00521     else {
00522       alreadyGot[stp->GetPlane()][stp->GetStrip()] = 1;
00523       plane[i-doubleCounter] = stp->GetPlane();
00524       if (plane[i-doubleCounter]<begPlane) begPlane = plane[i-doubleCounter];
00525       if (plane[i-doubleCounter]>endPlane) endPlane = plane[i-doubleCounter];
00526       strip[i-doubleCounter] = stp->GetStrip();
00527       
00528       ph[i-doubleCounter] = 
00529         calibrator.GetMIP(stp->GetCharge(CalDigitType::kSigCorr));
00530       pherr[i-doubleCounter] = ph[i-doubleCounter] /
00531         TMath::Sqrt(stp->GetCharge(CalDigitType::kPE)); //pe stats err
00532       
00533       z[i-doubleCounter] = stp->GetZPos();
00534       tpos[i-doubleCounter] = stp->GetTPos();
00535       
00536       TransGradientPlus[i-doubleCounter] = ph[i-doubleCounter];
00537       TransGradientErrorPlus[i-doubleCounter] = 
00538         TMath::Power(pherr[i-doubleCounter],2);
00539       
00540       TransGradientMinus[i-doubleCounter] = ph[i-doubleCounter];
00541       TransGradientErrorMinus[i-doubleCounter] = 
00542         TMath::Power(pherr[i-doubleCounter],2);
00543       
00544       usefulStrip = stp;
00545     }
00546   }
00547 
00549   //find transverse neighbour strip index and PH gradient for each strip
00550   for(Int_t i=0;i<nstp;i++){
00551     for(Int_t j=0;j<nstp;j++){
00552       if (plane[j]==plane[i]){
00553         if(strip[j]==strip[i]-1) {
00554           TransGradientMinus[i] = TransGradientMinus[i] - ph[j];
00555           TransGradientErrorMinus[i] = TMath::Sqrt(TransGradientErrorMinus[i]+ 
00556                                                    TMath::Power(pherr[j],2));
00557         }
00558         if(strip[j]==strip[i]+1) {
00559           TransGradientPlus[i] = TransGradientPlus[i] - ph[j];
00560           TransGradientErrorPlus[i] = TMath::Sqrt(TransGradientErrorPlus[i]+ 
00561                                                   TMath::Power(pherr[j],2));
00562           TransGradientErrorMinus[i] = 0;
00563           TransGradientErrorPlus[i] = 0;
00564         }
00565       }
00566     }
00567   }
00568 
00570   //find per plane PH
00571   int npls = (endPlane-begPlane)/2+1;
00572   if(det==1&&(begPlane-249)*(endPlane-249)<0) npls = (endPlane-begPlane-1)/2+1;
00573   std::vector<Int_t> allpl(npls,0);
00574   std::vector<Double_t> allplph(npls,0.0);
00575   std::vector<Int_t> allstp(npls,0);
00576 
00577   for(Int_t i=0;i<npls;i++){
00578     allpl[i] = 2*i+begPlane;
00579     if(det==1&&(begPlane-249)*(endPlane-249)<0&&(2*i+begPlane)>249)
00580       allpl[i] = 2*i+begPlane+1;
00581     allplph[i] = 0.;
00582     allstp[i] = 0;
00583     for(Int_t j=0;j<nstp;j++){
00584       if (plane[j]==allpl[i]){
00585         allplph[i] += ph[j];
00586         allstp[i] += 1;
00587       }
00588     }
00589   }
00590   UgliGeomHandle ugh(*usefulStrip->GetVldContext());
00591 
00593   //Start Clustering: 
00595   //Find contiguous longitudinal windows
00596   MSG("SubShowerSR",Msg::kDebug) <<"start longitudinal clustering"<<endl;
00597 
00598   std::vector<int> zeroPlanes;  //vector of planes with PH = 0
00599   int start = begPlane-2;
00600   if(det==1&&(begPlane-2-249)*(begPlane-249)<0) start = begPlane-3;
00601   zeroPlanes.push_back(start-2);
00602   zeroPlanes.push_back(start);
00603   for(Int_t i=0;i<npls;i++){
00604     if (allplph[i]<=fLongWindowMipCut) zeroPlanes.push_back(allpl[i]);
00605   }
00606   int over = endPlane+2;
00607   if(det==1&&(endPlane+2-249)*(endPlane-249)<0) over = endPlane+3;
00608   zeroPlanes.push_back(over);
00609   zeroPlanes.push_back(over+2);
00610   
00611   MSG("SubShowerSR",Msg::kVerbose) << "Number of Zero Planes = " 
00612                                    << zeroPlanes.size()
00613                                    << " First Zero Plane = " << start 
00614                                    << " Last Zero Plane =  "<< over << endl;
00615   
00617   //Find "Zero PH" windows
00618 
00619   //position of first plane in a longitudinal gap window:
00620   std::vector<int> firstGapPlane;
00621   //position of last plane in a longitudinal gap window:
00622   std::vector<int> lastGapPlane;
00623   int begGap = 0;
00624   int endGap = -5;
00625   //filling gap window vectors:
00626   for (UInt_t i = 0; i<zeroPlanes.size(); i++){
00627     bool foundgap = false;
00628     if(zeroPlanes.at(i)>endGap) {
00629       begGap = zeroPlanes.at(i);
00630       endGap = zeroPlanes.at(i);
00631       int j = 0;
00632       while ((i+j+1)<zeroPlanes.size() && 
00633              zeroPlanes.at(i+j+1)-zeroPlanes.at(i+j) < 
00634              fLongWindowGapPlaneCut) {
00635         foundgap = true;
00636         endGap = zeroPlanes.at(i+j+1);
00637         j++;
00638       }
00639       if (foundgap){
00640         firstGapPlane.push_back(begGap);
00641         lastGapPlane.push_back(endGap);
00642       }
00643     }
00644   }
00645 
00646   //Find highest strip density longitudinal window
00647   Int_t maxWinBegPlane = 0;  //first boundary plane of max window
00648   Int_t maxWinEndPlane = 0;
00649   Float_t maxDensity = 0;
00650   for (UInt_t i = 0; i<firstGapPlane.size(); i++){
00651     if((i+1)<firstGapPlane.size()){
00652       Float_t density = 0;
00653       Int_t bpln = lastGapPlane.at(i);
00654       Int_t epln = firstGapPlane.at(i+1);
00655       for(int j=0;j<npls;j++){
00656         if(allpl[j]>=bpln && allpl[j]<=epln){
00657           density += Float_t(allstp[j]);
00658         }
00659       }
00660       density/=Float_t(epln-bpln+2);
00661       MSG("SubShowerSR",Msg::kDebug) << "Proto-long window [" << bpln
00662                                      << "," << epln << "] density = " 
00663                                      << density << endl;
00664       if(density > maxDensity) {
00665         maxWinBegPlane = bpln;
00666         maxWinEndPlane = epln;
00667         maxDensity = density;
00668       }
00669     }
00670   }
00671 
00672   MSG("SubShowerSR",Msg::kDebug) << "Using Longitudinal Window: "
00673                                  << maxWinBegPlane << "-"
00674                                  << maxWinEndPlane << endl;
00675   
00678   Int_t maxPlane = -1;
00679   Double_t maxPlanePH = 0;
00680   for(int i=0;i<npls;i++){
00681     if(allpl[i]<maxWinEndPlane && allpl[i]>maxWinBegPlane) {
00682       if(allplph[i]>maxPlanePH) {
00683         maxPlane = allpl[i];
00684         maxPlanePH = allplph[i];
00685       }
00686     }
00687   }
00688   MSG("SubShowerSR",Msg::kVerbose) 
00689     << "Maximum PH plane within Long. window = " 
00690     << maxPlane << endl;
00691 
00692   Int_t numPreMaxPlanes = maxPlane - maxWinBegPlane;
00693   Int_t numPostMaxPlanes = maxWinEndPlane - maxPlane;
00694   Int_t numLongPlanes = numPostMaxPlanes + numPreMaxPlanes - 1;
00695 
00697   //Start Transverse Clustering
00698   
00699   //window info:
00700   std::vector<window> winvec;  //vector containing all transverse windows
00701 
00703   //Loop over all planes in long. window
00704   //Find transverse windows per plane
00705 
00706   for (int i=0;i<numLongPlanes;i++){  //loop over numLongPlanes
00707  
00708     //find next appropriate plane to look at starting from max plane:
00709     int pl = -1;
00710     if(numPreMaxPlanes>numPostMaxPlanes){
00711       if (i<numPreMaxPlanes) pl = maxPlane-i;
00712       else pl = maxPlane + i - numPreMaxPlanes + 1; 
00713       //add 1 to prevent re-doing max plane
00714     }
00715     else{
00716       if (i<numPostMaxPlanes) pl = maxPlane+i;
00717       else pl = maxPlane - i + numPostMaxPlanes - 1;
00718       //subtract 1 to prevent re-doing max plane
00719     }
00720 
00721     std::vector<Int_t> winu;  // vector of upper dip
00722     std::vector<Int_t> wind;  // vector of lower dip
00723     std::vector<Double_t> winu_tpos;  // vector of tpos of upper dip
00724     std::vector<Double_t> wind_tpos;  // vector of tpos of lower dip
00725     std::vector<Int_t> wintu; // vector of upper dip type
00726     std::vector<Int_t> wintd; // vector of lower dip type
00727 
00728     //find dips and categorize them
00729     MSG("SubShowerSR",Msg::kVerbose) << "Find Upper/Lower boundaries in plane = "
00730                                      << pl << endl;
00731     for(Int_t i=0;i<nstp;i++){
00732       if(plane[i]==pl){
00733         //using neighbouring strip info from above:
00734         //(only called dips if delta PH is significant given pe stats)
00735         if(TransGradientPlus[i]<0 /*-(TransGradientErrorPlus[i])*/ &&
00736            TransGradientMinus[i]<0 /*-(TransGradientErrorMinus[i])*/){
00737           winu.push_back(strip[i]);
00738           winu_tpos.push_back(tpos[i]);
00739           wintu.push_back(0);      // type-0 (this is a dip) 
00740           MSG("SubShowerSR",Msg::kVerbose) 
00741             << "up dip strip = " << strip[i] << " ph = " << ph[i] 
00742             << " tgp = " << TransGradientPlus[i]
00743             << " tgm = " << TransGradientMinus[i] << endl;
00744         }
00745         else if(TransGradientPlus[i]==ph[i] && 
00746                 TransGradientMinus[i]<=ph[i]){
00747           winu.push_back(strip[i]);
00748           winu_tpos.push_back(tpos[i]);
00749           MSG("SubShowerSR",Msg::kVerbose) 
00750             << "up edge/iso strip = " << strip[i] << " ph = " << ph[i] 
00751             << " tgp = " << TransGradientPlus[i]
00752             << " tgm = " << TransGradientMinus[i] << endl;
00753           if (TransGradientMinus[i]<ph[i]) 
00754             wintu.push_back(1);     // type-1 (this is an edge strip) 
00755           else wintu.push_back(2);  // type-2 (this is an isolated strip)
00756         }
00757         if(TransGradientPlus[i]<0 /*-(TransGradientErrorPlus[i])*/ &&
00758            TransGradientMinus[i]<0 /*-(TransGradientErrorMinus[i])*/ ){
00759           wind.push_back(strip[i]);
00760           wind_tpos.push_back(tpos[i]);
00761           wintd.push_back(0);      // type-0
00762           MSG("SubShowerSR",Msg::kVerbose) 
00763             << "down dip strip = " << strip[i] << " ph = " << ph[i]
00764             << " tgp = " << TransGradientPlus[i]
00765             << " tgm = " << TransGradientMinus[i] << endl;
00766         }
00767         else if(TransGradientMinus[i]==ph[i] && 
00768                 TransGradientPlus[i]<=ph[i]){
00769           wind.push_back(strip[i]);
00770           wind_tpos.push_back(tpos[i]);
00771           MSG("SubShowerSR",Msg::kVerbose) 
00772             << "down edge/iso strip = "  << strip[i] << " ph = " << ph[i]
00773             << " tgp = "  << TransGradientPlus[i]
00774             << " tgm = "  << TransGradientMinus[i] << endl;
00775           if (TransGradientPlus[i]<ph[i]) 
00776             wintd.push_back(1);     //type-1
00777           else wintd.push_back(2);  //type-2
00778         }
00779       }
00780     }
00781 
00783     //use dips to form windows                                   
00784     UInt_t wins = winu.size();
00785     if(wins!=wind.size()) {
00786       MSG("SubShowerSR",Msg::kError) 
00787         << "Number of Upper Transverse Window Boundaries does not equal " 
00788         << "number of Lower Transverse Window Boundaries... "
00789         << "Leaving FindCluster()" << endl;
00790       MSG("SubShowerSR",Msg::kError) << "winu.size() = " << winu.size() << endl;
00791       MSG("SubShowerSR",Msg::kError) << "wind.size() = " << wind.size() << endl;
00792       MSG("SubShowerSR",Msg::kError) << "wins = " << wins << endl;
00793       
00794       return false;
00795     }
00796 
00797     //temporarily hold window info
00798     std::vector<Int_t> win0(wins,0);             // strip of upper dip
00799     std::vector<Int_t> win1(wins,0);             // strip of lower dip
00800     std::vector<Float_t> win0_tpos(wins,0.0);      // tpos of strip of upper dip
00801     std::vector<Float_t> win1_tpos(wins,0.0);      // tpos of strip of lower dip
00802     std::vector<Float_t> win2(wins,0.0);           // PH of window
00803     std::vector<Int_t> win3(wins,0);             // ID of window:
00804                                                  //   0-both dips; 
00805                                                  //   1 or 10-one dip,one gap; 
00806                                                  //   11-both gaps; 
00807                                                  //   22-isolated strip
00808     std::vector<Float_t> win4(wins,0.0);           // Centroid of window in tpos
00809     std::vector<Float_t> win5(wins,0.0);           // PH weighted tpos of window
00810     std::vector<Float_t> win6(wins,0.0);           // PH weighted width of window
00811 
00812     //match up dips to form windows
00813     for (UInt_t w = 0; w<wins; w++){
00814       win0[w] = -1;
00815       win1[w] = -1;
00816       win0_tpos[w] = 0;
00817       win1_tpos[w] = 0;
00818       win2[w] = 0;
00819       win3[w] = -1;
00820       win4[w] = 0;
00821       win5[w] = 0;
00822       win6[w] = 0;
00823       int winw = 200;
00824       for (UInt_t s = 0; s<wind.size(); s++){
00825         int diff = winu.at(w)-wind.at(s);
00826         if ( ( (diff>0  && wintu.at(w)<2  && wintd.at(s)<2) ||
00827                (diff==0 && wintu.at(w)==2 && wintd.at(s)==2) ) &&
00828              diff<winw) {
00829           winw = diff;
00830           win0[w] = winu.at(w);
00831           win1[w] = wind.at(s);
00832           win0_tpos[w] = winu_tpos.at(w);
00833           win1_tpos[w] = wind_tpos.at(s);
00834           win3[w] = wintu.at(w)*10+wintd.at(s);
00835         }
00836       }
00837     }
00838 
00840     //now get PH of windows
00841     //and push_back windows into vectors
00842     for (UInt_t w = 0; w<wins; w++){            
00843       Double_t biggestStripPH = 0;
00844       Int_t n = 0;
00845       for(Int_t i=0;i<nstp;i++){
00846         if (plane[i]==pl && strip[i]<=win0[w] && strip[i]>=win1[w]) {
00847           win2[w] += ph[i];
00848           if(ph[i]>biggestStripPH) {
00849             win4[w] = tpos[i];
00850             biggestStripPH = ph[i];
00851           }
00852           win5[w] += ph[i]*tpos[i];
00853           win6[w] += ph[i]*tpos[i]*tpos[i];
00854           n++;
00855         }
00856       }
00857       win5[w] /= win2[w];
00858       if(n!=1){
00859         win6[w] /= win2[w];
00860         win6[w] -= win5[w]*win5[w];
00861         if(win6[w]>0) win6[w] = TMath::Sqrt(win6[w]);
00862         else win6[w] = STRIPWIDTHINMETRES/TMath::Sqrt(12.); 
00863      }
00864       else win6[w] = STRIPWIDTHINMETRES/TMath::Sqrt(12.);
00865       
00866       window win;
00867       win.plane = pl;
00868       win.upper = win0[w];
00869       win.lower = win1[w];
00870       win.upper_tpos = win0_tpos[w];
00871       win.lower_tpos = win1_tpos[w];
00872       win.ph = win2[w];
00873       win.type = win3[w];
00874       win.centroid = win4[w];
00875       win.phpos = win5[w];
00876       win.phwidth = win6[w];
00877       winvec.push_back(win);
00878 
00879     }
00880   }
00881 
00883   //Perform clustering on windows:
00884 
00885   // if this longitudinal window only contains a single 
00886   // active plane then just return largest window
00887   if(numLongPlanes/2<2){ 
00888     std::vector<window>::iterator winIter = winvec.begin();
00889     std::vector<window>::iterator winEnd = winvec.end();
00890     Int_t best_upper_strip = 0;
00891     Int_t best_lower_strip = 200;
00892     Double_t best_pulse_height = 0;
00893     while(winIter!=winEnd){
00894       if(winIter->ph>best_pulse_height){
00895         best_lower_strip = winIter->lower;
00896         best_upper_strip = winIter->upper;
00897         best_pulse_height = winIter->ph;
00898       }
00899       winIter++;
00900     }
00901     for (Int_t i=0; i<=allStrips->GetLast(); i++) {
00902       TObject *tobj = allStrips->At(i);
00903       assert(tobj->InheritsFrom("CandStripHandle"));
00904       CandStripHandle *stp = dynamic_cast<CandStripHandle*>(tobj);
00905       if(stp->GetPlane()>=maxWinBegPlane && stp->GetPlane()<=maxWinEndPlane &&
00906          stp->GetStrip()>=best_lower_strip && stp->GetStrip()<=best_upper_strip){
00907         newSubShower->Add(stp);
00908       }
00909     }
00910     return true;
00911   }
00912 
00913   //call transverse clustering algorithms
00914   std::vector<window> clusterWinVec = TransCluster(winvec,det);
00915   
00916   //no windows added to cluster:
00917   if(clusterWinVec.size()==0) return false;
00918 
00919   //Clean up proto-subshower
00920   //Check for longitudinal gaps within the proto-subshower
00921   //Remove windows after first gap on both sides of shower max plane
00922   maxPlane = -1;  //recalculate maxPlane
00923   maxPlanePH = 0.;
00924   Double_t PlanePH[500] = {0.};
00925   Int_t non0Win = 0;
00926   std::vector<window>::iterator winIter = clusterWinVec.begin();
00927   std::vector<window>::iterator winEnd = clusterWinVec.end();
00928   while(winIter!=winEnd){
00929     if(winIter->plane>0){
00930       PlanePH[winIter->plane] += winIter->ph;
00931       if(PlanePH[winIter->plane]>0) non0Win++;
00932       if(PlanePH[winIter->plane]>maxPlanePH) {
00933         maxPlane = winIter->plane;
00934         maxPlanePH = PlanePH[maxPlane];
00935       }
00936     }
00937     winIter++;
00938   }
00939   
00940   if(non0Win==0){
00941     MSG("SubShowerSR",Msg::kDebug) <<"No window solutions found"<<endl;
00942     return false;
00943   }
00944 
00945   Int_t maxLongPlane = -1;
00946   Int_t minLongPlane = -1;
00947   Int_t counter = 0;
00948   Int_t delta = 2;
00949   while((maxPlane+counter)>=0&&(PlanePH[maxPlane+counter]>0||(maxPlane+counter)==249)) {
00950     maxLongPlane = maxPlane+counter;
00951     delta = 2;
00952     if(det==1&&(maxLongPlane-249)*(maxLongPlane+delta-249)<0)
00953       delta = 3;
00954     counter+=delta;
00955   }
00956   counter = 0;
00957   while((maxPlane+counter)>=0&&(PlanePH[maxPlane+counter]>0||(maxPlane+counter)==249)) {
00958     minLongPlane = maxPlane+counter;
00959     delta = 2;
00960     if(det==1&&(minLongPlane-249)*(minLongPlane-delta-249)<0)
00961       delta = 3;
00962     counter-=delta;
00963   }
00964   MSG("SubShowerSR",Msg::kDebug) <<"New Longitudinal Window: "<< minLongPlane
00965                                  << "-" << maxLongPlane << endl;
00966 
00967   for (Int_t i=0; i<=allStrips->GetLast(); i++) {
00968     TObject *tobj = allStrips->At(i);
00969     assert(tobj->InheritsFrom("CandStripHandle"));
00970     CandStripHandle *stp = dynamic_cast<CandStripHandle*>(tobj);
00971     if(stp->GetPlane()>=minLongPlane && stp->GetPlane()<=maxLongPlane){
00972       winIter = clusterWinVec.begin();
00973       while(winIter!=winEnd){
00974         if(winIter->plane==stp->GetPlane()){
00975           Int_t strp = stp->GetStrip();
00976           if(strp<=winIter->upper && strp>=winIter->lower) {
00977             newSubShower->Add(stp);
00978             break;
00979           }
00980         }
00981         winIter++;
00982       }
00983     }
00984   }
00985 
00986   return true;
00987 }
00988 
00989 //******************************************************************
00990 std::vector<window> AlgSubShowerSRList::TransCluster(std::vector<window> win,
00991                                                      Int_t det)
00992 {
00993   std::vector<window> cluster;
00994 
00995   Int_t maxPlane = -1;  //calculate maxPlane
00996   Double_t maxPlanePH = 0;
00997   Double_t PlanePH[500] = {0};
00998   std::vector<window>::iterator winIter = win.begin();
00999   std::vector<window>::iterator winEnd = win.end();
01000   while(winIter!=winEnd){
01001     PlanePH[winIter->plane] += winIter->ph;
01002     if(PlanePH[winIter->plane]>maxPlanePH) {
01003       maxPlane = winIter->plane;
01004       maxPlanePH = PlanePH[maxPlane];
01005     }
01006     winIter++;
01007   }
01008 
01009   Int_t maxLongPlane = -1;
01010   Int_t minLongPlane = -1;
01011   Int_t counter = 0;
01012   Int_t delta = 2;
01013   while(PlanePH[maxPlane+counter]>0||(maxPlane+counter)==249) {
01014     maxLongPlane = maxPlane+counter;
01015     delta = 2;
01016     if(det==1&&(maxLongPlane-249)*(maxLongPlane+delta-249)<0)
01017       delta = 3;
01018     counter+=delta;
01019   }
01020   counter = 0;
01021   while(PlanePH[maxPlane+counter]<=0||(maxPlane+counter)==249) {
01022     minLongPlane = maxPlane+counter;
01023     delta = 2;
01024     if(det==1&&(minLongPlane-249)*(minLongPlane-delta-249)<0)
01025       delta = 3;
01026     counter-=delta;
01027   }
01028   Int_t numPreMaxPlanes = maxPlane-minLongPlane+1;
01029   Int_t numPostMaxPlanes = maxLongPlane-maxPlane+1;
01030   Int_t numLongPlanes = numPostMaxPlanes + numPreMaxPlanes - 1;
01031 
01032   //match up windows plane by plane
01033   Double_t shwmid = 0;    // centroid of cluster transversely
01034   Double_t shwwid = 0;    // trans width of widest window in proto-cluster
01035   Double_t maxwid = 0;
01036   Double_t clusterph = 0; // total PH of cluster
01037   Double_t refp = 0;      // reference plane  }  essentially pivot point for 
01038   Double_t refs = 0;      // reference strip  }  cluster
01039   
01040   //long. window info:  
01041   std::vector<Int_t> winpl(numLongPlanes,0);          // plane number 
01042   std::vector<Int_t> winpl0(numLongPlanes,0);         // upper bound
01043   std::vector<Int_t> winpl1(numLongPlanes,0);         // lower bound
01044   std::vector<Float_t> winpl0_tpos(numLongPlanes,0.0);  // upper bound in tpos
01045   std::vector<Float_t> winpl1_tpos(numLongPlanes,0.0);  // lower bound in tpos
01046   std::vector<Double_t> winpl2(numLongPlanes,0.0);      // PH
01047   std::vector<Int_t> winpl3(numLongPlanes,0);         // window type
01048   std::vector<Double_t> winpl4(numLongPlanes,0.0);      // width
01049   std::vector<Double_t> winpl5(numLongPlanes,0.0);      // centroid
01050 
01051   Double_t slopen = 0;
01052   Double_t eslopen = 0;
01053   Bool_t trustslopen = false;
01054 
01055   std::vector<window> houghcluster = HoughTransCluster(win,det);
01056 
01057   if(houghcluster.size()==0) { //houghcluster.size()=0 try usual tracking
01058     for (int d = 0;d<numLongPlanes;d++){
01059       int pl = -1;
01060       if(numPreMaxPlanes>numPostMaxPlanes){
01061         if (d<numPreMaxPlanes) pl = maxPlane-d;
01062         else pl = maxPlane+d-numPreMaxPlanes+1;
01063       }
01064       else{
01065         if (d<numPostMaxPlanes) pl = maxPlane+d;
01066         else pl = maxPlane-d+numPostMaxPlanes-1;
01067       }
01068       winpl[d] = 0;
01069       winpl0[d] = -1;
01070       winpl1[d] = -1;
01071       winpl0_tpos[d] = -10;
01072       winpl1_tpos[d] = -10;
01073       winpl2[d] = 0;
01074       winpl3[d] = 0;
01075       winpl4[d] = -1;
01076       winpl5[d] = -1;
01077       // PH for current best matched window:
01078       double weight = 0.;
01079       //deviation of best matched window from prediction of 
01080       //centroid for this plane:
01081       double weight1 = 10000.;
01082       //loop keeps track of # windows already checked on this plane:
01083       int loop = 0;
01084       // counts number of windows with a good match:
01085       int within = 0;
01086       //prediction of centroid for this plane (not using slope in info):
01087       double mid0 = 0;
01088       //prediction of centroid for this plane using slope info where available:
01089       double mid = 0;
01090       
01091       //loop over all in windows
01092       winIter = win.begin();
01093       while (winIter!=winEnd){
01094         if (winIter->plane==pl){  //if it's in current plane:
01095           loop++;
01096           double dev = shwwid;
01097           if (dev<(winIter->upper_tpos-winIter->lower_tpos+STRIPWIDTHINMETRES))
01098             dev = winIter->upper_tpos-winIter->lower_tpos+STRIPWIDTHINMETRES;
01099           if (dev<2.*STRIPWIDTHINMETRES) dev = 2.*STRIPWIDTHINMETRES;
01100           if (shwmid!=0) {
01101             mid0 = shwmid;
01102             mid = shwmid;
01103           }
01104           else {
01105             mid = (winIter->upper+winIter->lower)/2.;
01106             mid0 = mid;
01107           }
01108           
01109           // check if this window is consistent with previously selected 
01110           // windows and has a higher PH than current best match for this
01111           // plane or else if it's shower max plane
01112           if((shwmid==0 ||
01113               (TMath::Abs(winIter->upper_tpos-mid)<dev &&
01114                TMath::Abs(winIter->lower_tpos-mid)<dev))
01115              && winIter->ph>weight){
01116             
01118             //loop through planes in long. window again to do a local 
01119             //scan to ensure best match is found.
01120             //step forward and backward once each if possible
01121           
01122             int loopp = 0;
01123             int loopm = 0;
01124             int withinp = 0;
01125             int withinm = 0;
01126             //double midp0 = 0;
01127             //double midm0 = 0;
01128             double midp = 0;
01129             double midm = 0;
01130             
01131             // step forward:
01132             std::vector<window>::iterator winIter1 = win.begin();
01133             while(winIter1!=winEnd){
01134               if ((((det==1&&(pl-249)*(pl+2-249)>0)||det==0)
01135                    &&winIter1->plane==pl+2)
01136                   ||(det==1&&(pl-249)*(pl+2-249)<0
01137                      &&winIter1->plane==pl+3)){   //go to next same view plane
01138                 loopp++;
01139                 if(shwmid!=0){  //not shower max plane
01140                   midp = shwmid;
01141                   if(TMath::Abs(winIter1->upper_tpos-midp)<dev/2.
01142                      ||TMath::Abs(winIter1->lower_tpos-midp)<dev/2.){  //good match
01143                     withinp++;
01144                   }
01145                 }
01146                 else if(shwmid==0){  //in shower max plane
01147                   midp = (winIter->upper_tpos+winIter->lower_tpos)/2.;
01148                   if(TMath::Abs(winIter1->upper_tpos-midp)<dev/2.
01149                      ||TMath::Abs(winIter1->lower_tpos-midp)<dev/2.){  //good match
01150                     withinp++;  
01151                   }
01152                 }
01153               }
01154               
01155               //step backwards:
01156               if ((((det==1&&(pl-249)*(pl-2-249)>0)||det==0)
01157                    &&winIter1->plane==pl-2)
01158                   ||(det==1&&(pl-249)*(pl-2-249)<0
01159                      &&winIter1->plane==pl-3)){   
01160                 //go to previous same view plane                
01161                 loopm++;
01162                 if(shwmid!=0){   // not shower max plane
01163                   midm = shwmid;
01164                   if(TMath::Abs(winIter1->upper_tpos-midm)<dev
01165                      ||TMath::Abs(winIter1->lower_tpos-midm)<dev){  //good match
01166                     withinm++;
01167                   }
01168                 }
01169                 else if(shwmid==0){  //shower max plane
01170                   midm = (winIter->upper_tpos+winIter->lower_tpos)/2.;
01171                   if(TMath::Abs(winIter1->upper_tpos-midm)<dev
01172                      ||TMath::Abs(winIter1->lower_tpos-midm)<dev){  //good match
01173                     withinm++;
01174                   }
01175                 }
01176               }
01177               winIter1++;
01178             }
01179             if((withinp>0 && withinm>0) || (loopp==0 && withinm>0) ||
01180                (loopm==0 && withinp>0)){  
01181               //success! current window is a good solution
01182               within++;
01183               // write out solution: 
01184               winpl[d] = winIter->plane;
01185               winpl0[d] = winIter->upper;
01186               winpl1[d] = winIter->lower;
01187               winpl0_tpos[d] = winIter->upper_tpos;
01188               winpl1_tpos[d] = winIter->lower_tpos;
01189               winpl2[d] = winIter->ph;
01190               winpl3[d] = winIter->type;
01191               weight = winIter->ph;
01192               weight1 = (winIter->upper_tpos+winIter->lower_tpos)/2.-mid0;
01193               //these will be overwritten if there is another window 
01194               //which is also a good match, but has more PH, 
01195               //ensuring we get best possible match
01196             }
01197           }
01198         }
01199         winIter++;
01200       }
01201       
01202       if(loop*within>0){   //got a matched window
01203         if (shwmid==0) {   // shower max plane
01204           refp = winpl[d];  // set reference point
01205           refs = (winpl0_tpos[d]+winpl1_tpos[d])/2.;
01206         }
01207         //determine widest window:
01208         if(shwwid<(winpl0_tpos[d]-winpl1_tpos[d]+STRIPWIDTHINMETRES)) 
01209           shwwid = winpl0_tpos[d]-winpl1_tpos[d]+STRIPWIDTHINMETRES; 
01210         // average centroid of event so far:
01211         shwmid = (shwmid*clusterph+(winpl0_tpos[d]+winpl1_tpos[d]) * 
01212                   winpl2[d]/2.)/(clusterph+winpl2[d]); 
01213         clusterph+=winpl2[d];
01214         winpl4[d] = shwwid;
01215         winpl5[d] = shwmid;
01216       }
01217     }
01218   
01219     //Fitting the boundaries of windows matched
01220     Double_t slopetn = 0;
01221     Double_t slopebn = 0;
01222     Double_t eslopetn = 0;
01223     Double_t eslopebn = 0;
01224     Double_t chi2tn = 0;
01225     Double_t chi2bn = 0;
01226     int nt = 0;
01227     int nb = 0;
01228 
01229     for (int d = 0;d<numLongPlanes;d++){
01230       int pl = -1;
01231       if(numPreMaxPlanes>numPostMaxPlanes){
01232         if (d<numPreMaxPlanes) pl = maxPlane-d;
01233         else pl = maxPlane+d-numPreMaxPlanes+1;
01234       }
01235       else{
01236         if (d<numPostMaxPlanes) pl = maxPlane+d;
01237         else pl = maxPlane-d+numPostMaxPlanes-1;
01238       }
01239       if(winpl2[d]>0) {nt++; nb++;}
01240       if (maxwid<winpl4[d]) maxwid = winpl4[d];
01241       if (maxwid<2.*STRIPWIDTHINMETRES) maxwid = 2.*STRIPWIDTHINMETRES;
01242     }
01243     if (nt>2 && nb>2) {
01244       TGraphErrors grat(nt);
01245       TGraphErrors grab(nb);
01246       int t = 0;
01247       int b = 0;
01248       for (int d = 0;d<numLongPlanes;d++){
01249         int pl = -1;
01250         if(numPreMaxPlanes>numPostMaxPlanes){
01251           if (d<numPreMaxPlanes) pl = maxPlane-d;
01252           else pl = maxPlane+d-numPreMaxPlanes+1;
01253         }
01254         else{
01255           if (d<numPostMaxPlanes) pl = maxPlane+d;
01256           else pl = maxPlane-d+numPostMaxPlanes-1;
01257         }
01258         if(winpl2[d]>0) {
01259           grat.SetPoint(t,winpl[d],winpl0_tpos[d]);
01260           grat.SetPointError(t,0,1./TMath::Sqrt(winpl2[d]));
01261           t++;
01262           grab.SetPoint(b,winpl[d],winpl1_tpos[d]);
01263           grab.SetPointError(b,0,1./TMath::Sqrt(winpl2[d]));
01264           b++;
01265         }
01266       }
01267 
01268       grat.Fit("ssPol1","NNLQ");
01269       slopetn = ssPol1->GetParameter(1);
01270       eslopetn = ssPol1->GetParError(1);
01271       chi2tn = ssPol1->GetChisquare();
01272       grab.Fit("ssPol1","NNLQ");
01273       slopebn = ssPol1->GetParameter(1);
01274       eslopebn = ssPol1->GetParError(1);
01275       chi2bn = ssPol1->GetChisquare();
01276       
01277       if ((slopetn+slopebn)!=0. && slopetn*slopebn!=0.){
01278         if(chi2tn/nt<100. && chi2bn/nb<100. &&
01279            ((((eslopetn/TMath::Abs(slopetn)<0.1 && eslopebn/TMath::Abs(slopebn)<0.1
01280                &&chi2tn/nt>0.1 && chi2bn/nb>0.1)) &&
01281              (TMath::Abs(slopetn-slopebn)/TMath::Abs(slopetn+slopebn)<0.25)) ||
01282             TMath::Abs(slopetn-slopebn)==0)) {
01283           slopen = (slopetn+slopebn)/2.;
01284           eslopen = TMath::Sqrt(TMath::Power(eslopetn,2)+TMath::Power(eslopebn,2))/2.;
01285           if(TMath::Abs(slopetn-slopebn)>eslopen) eslopen = TMath::Abs(slopetn-slopebn);
01286           trustslopen = true;
01287         }
01288       }
01289       MSG("SubShowerSR",Msg::kDebug) <<"fit window "<<slopetn<<" "<<slopebn
01290                                      <<" "<<slopen<<" "<<eslopetn<<" "
01291                                      <<eslopebn<<" "<<eslopen<<" "
01292                                      <<chi2tn/nt<<" "<<chi2bn/nb<<" "
01293                                      <<nt<<" "<<nb<<endl;
01294     }
01295     
01296     //check if solution is good:
01297     double usewid = maxwid;
01298     for (Int_t d = 0;d<numLongPlanes;d++){
01299       int pl = -1;
01300       if(numPreMaxPlanes>numPostMaxPlanes){
01301         if (d<numPreMaxPlanes) pl = maxPlane-d;
01302         else pl = maxPlane+d-numPreMaxPlanes+1;
01303       }
01304       else{
01305         if (d<numPostMaxPlanes) pl = maxPlane+d;
01306         else pl = maxPlane-d+numPostMaxPlanes-1;
01307       }
01308     
01309       if(d>0 && (winpl0[d]>=0||winpl1[d]>=0) ){ //if there is a solution
01310         if(!trustslopen && //don't trust new slope
01311            //window is too far away from centroid
01312            (winpl0_tpos[d]-shwmid)*(winpl1_tpos[d]-shwmid) > 
01313            (maxwid/2.)*(maxwid/2.) ){ 
01314           MSG("SubShowerSR",Msg::kDebug) << "removed plane " << winpl[d] 
01315                                          << " " << winpl0[d] << " " 
01316                                          << winpl1[d] << " " 
01317                                          << winpl0_tpos[d] << " " 
01318                                          << winpl1_tpos[d] << endl;
01319           shwmid = (shwmid*clusterph-(winpl0_tpos[d]+winpl1_tpos[d]) * 
01320                     winpl2[d]/2.)/(clusterph-winpl2[d]);
01321           winpl0[d] = -1;
01322           winpl1[d] = -1;
01323           winpl0_tpos[d] = -10;
01324           winpl1_tpos[d] = -10;
01325           winpl2[d] = 0;
01326           winpl3[d] = 0;
01327           winpl4[d] = -1;
01328           winpl5[d] = -1;
01329         }
01330         else if(trustslopen){ 
01331           //this time account for slope on window boundaries:
01332           //try to find another window as a reference point       
01333           //to compare the window in this plane with
01334           int i = 0;  
01335           while(winpl2[i]==0&&i<=d) i++;
01336           if(i==d){
01337             while(winpl2[i]==0&&i<numLongPlanes) i++;
01338           }
01339           if(usewid<TMath::Abs(winpl[d]-winpl[i])*eslopen)  
01340             //find appropriate cut value on window width
01341             usewid = TMath::Abs(winpl[d]-winpl[i])*eslopen; 
01342           //expected centroid for plane:
01343           double expmid = (winpl0_tpos[i] + 
01344                            winpl1_tpos[i])/2.+(winpl[d]-winpl[i])*slopen; 
01345           if((winpl0_tpos[d]-expmid)*(winpl1_tpos[d]-expmid) >
01346              (usewid/2.)*(usewid/2.)){ 
01347             MSG("SubShowerSR",Msg::kDebug) <<"removed plane using slope "
01348                                            <<winpl[d]<<" "<<winpl0[d]<<" "
01349                                            <<winpl1[d]<<" with pl "
01350                                            <<maxPlane<<" "<<winpl[i]
01351                                            <<" "<<expmid<<" "<<usewid<<endl;
01352             shwmid = (shwmid*clusterph-(winpl0_tpos[d]+winpl1_tpos[d]) * 
01353                       winpl2[d]/2.)/(clusterph-winpl2[d]);
01354             clusterph-=winpl2[d];
01355             winpl0[d] = -1;
01356             winpl1[d] = -1;
01357             winpl0_tpos[d] = -10;
01358             winpl1_tpos[d] = -10;
01359             winpl2[d] = 0;
01360             winpl3[d] = 0;
01361             winpl4[d] = -1;
01362             winpl5[d] = -1;
01363           }
01364         }
01365       }
01366     }
01367   }
01368   else { //use hough solution as a starting point:
01369     for (int d = 0;d<numLongPlanes;d++){  
01370       int pl = -1;
01371       if(numPreMaxPlanes>numPostMaxPlanes){
01372         if (d<numPreMaxPlanes) pl = maxPlane-d;
01373         else pl = maxPlane+d-numPreMaxPlanes+1;
01374       }
01375       else{
01376         if (d<numPostMaxPlanes) pl = maxPlane+d;
01377         else pl = maxPlane-d+numPostMaxPlanes-1;
01378       }
01379       winpl[d] = 0;
01380       winpl0[d] = -1;
01381       winpl1[d] = -1;
01382       winpl0_tpos[d] = -10;
01383       winpl1_tpos[d] = -10;
01384       winpl2[d] = 0;
01385       winpl3[d] = 0;
01386       winpl4[d] = -1;
01387       winpl5[d] = -1;
01388 
01389       //loop over all in windows
01390       std::vector<window>::iterator hcIter = houghcluster.begin();
01391       std::vector<window>::iterator hcEnd = houghcluster.end();      
01392       while (hcIter!=hcEnd){
01393         if (hcIter->plane==pl){  //if it's in current plane:
01394           winpl[d] = hcIter->plane;
01395           winpl0[d] = hcIter->upper;
01396           winpl1[d] = hcIter->lower;
01397           winpl0_tpos[d] = hcIter->upper_tpos;
01398           winpl1_tpos[d] = hcIter->lower_tpos;
01399           winpl2[d] = hcIter->ph;
01400           winpl3[d] = hcIter->type;
01401                 
01402           if (shwmid==0) {   // shower max plane
01403             refp = winpl[d];  // set reference point
01404             refs = (winpl0_tpos[d]+winpl1_tpos[d])/2.;
01405           }
01406           //determine widest window:
01407           if(shwwid<(winpl0_tpos[d]-winpl1_tpos[d]+STRIPWIDTHINMETRES)) 
01408             shwwid = winpl0_tpos[d]-winpl1_tpos[d]+STRIPWIDTHINMETRES; 
01409           // average centroid of event so far:
01410           shwmid = (shwmid*clusterph+(winpl0_tpos[d]+winpl1_tpos[d]) * 
01411                     winpl2[d]/2.)/(clusterph+winpl2[d]); 
01412           // calculate average distance to centroid:
01413           clusterph += winpl2[d];
01414           winpl4[d] = shwwid;
01415           winpl5[d] = shwmid;
01416           if (maxwid<winpl4[d]) maxwid = winpl4[d];
01417           if (maxwid<2.*STRIPWIDTHINMETRES) maxwid = 2.*STRIPWIDTHINMETRES;
01418         }
01419         hcIter++;
01420       }
01421     }
01422     std::vector<Double_t> MCV = BestHough(houghcluster,false);
01423     if(MCV[5]!=0){
01424       slopen = MCV[5];
01425       eslopen = MCV[8];
01426       trustslopen = true;
01427     }
01428     else if(MCV[0]!=0){
01429       slopen = MCV[0];
01430       eslopen = MCV[3];
01431       trustslopen = true;
01432     }
01433     else {
01434       slopen = 0;
01435       eslopen = 0;
01436       trustslopen = false;
01437     }
01438   }
01439   
01441   //Try to fill planes with no windows
01442   
01443   //First find centroid and width for +/- 1 planes
01444   
01445   for (Int_t d = 0;d<numLongPlanes;d++){
01446     int pl = -1;
01447     if(numPreMaxPlanes>numPostMaxPlanes){
01448       if (d<numPreMaxPlanes) pl = maxPlane-d;
01449       else pl = maxPlane+d-numPreMaxPlanes+1;
01450     }
01451     else{
01452       if (d<numPostMaxPlanes) pl = maxPlane+d;
01453       else pl = maxPlane-d+numPostMaxPlanes-1;
01454     }
01455     
01456     double minwei = 200.;   //minimum distance to centroid (weight)
01457     double minwei_tpos = 10.;   //minimum distance to centroid (weight)
01458     int newwinpl0 = -1;     //new window upper and lower strip bounds
01459     int newwinpl1 = -1;
01460     Float_t newwinpl0_tpos = -10; //new window upp and low strip tpos bounds
01461     Float_t newwinpl1_tpos = -10;
01462     double newwinpl2 = 0.;
01463     int newwinpl3 = 0;
01464 
01465     if(winpl0[d]==-1&&winpl1[d]==-1){  //does this plane have a solution?
01466       
01467       int p = 0;
01468       int m = 0;
01469       if (det==0||(det==1&&(pl-249)*(pl+2-249)>0)) p = 2;
01470       else p = 3;
01471       if (det==0||(det==1&&(pl-249)*(pl-2-249)>0)) m = 2;
01472       else m = 3;
01473       
01474       double pmid = -1;   //centroid for next plane (plus)
01475       double mmid = -1;   //centroid for prev plane (minus)
01476       double pwid = -1;   //width
01477       double mwid = -1;   
01478       int pwt = -1;      // window type  plus
01479       int mwt = -1;     //               minus
01480       bool useslopep = false; 
01481       bool useslopem = false;
01482       
01483       for (Int_t c = 0;c<numLongPlanes;c++){
01484         if (winpl[c]==pl+p) {
01485           pmid = winpl5[c];
01486           if (trustslopen) useslopep = true;
01487           pwid = winpl4[c];
01488           pwt = winpl3[c];
01489         }
01490         if (winpl[c]==pl-m) {
01491           mmid = winpl5[c];      
01492           if (trustslopen) useslopem = true;
01493           mwid = winpl4[c];
01494           mwt = winpl3[c];
01495         }
01496       }
01497       
01498       //Find compatible windows
01499       
01500       double usewid = maxwid;
01501       if(maxwid>0){
01502         if((mmid==-1&&pmid==-1)||
01503            (!useslopem&&mmid>=0&&TMath::Abs(shwmid-mmid)>maxwid)||
01504            (!useslopep&&pmid>=0&&TMath::Abs(shwmid-pmid)>maxwid)||
01505            (useslopem&&mmid>=0&&
01506               (TMath::Abs(shwmid-mmid-(maxPlane-pl+m)*slopen)>maxwid)||
01507             (TMath::Abs(shwmid-mmid-(maxPlane-pl+m)*slopen) > 
01508              TMath::Abs(maxPlane-pl+m)*eslopen))||
01509            (useslopep&&pmid>=0&&
01510               (TMath::Abs(shwmid-pmid-(maxPlane-pl-p)*slopen)>maxwid)||
01511             (TMath::Abs(shwmid-pmid-(maxPlane-pl-p)*slopen) > 
01512              TMath::Abs(maxPlane-pl-p)*eslopen))){
01513           minwei = 200.;
01514           minwei_tpos = 10.;
01515           newwinpl0 = -1;
01516           newwinpl1 = -1;
01517           newwinpl0_tpos = -10;
01518           newwinpl1_tpos = -10;
01519           newwinpl2 = 0.;
01520           winIter = win.begin();
01521           while(winIter!=winEnd){
01522             if(winIter->plane==pl){
01523               if (//shwmid>=0&&
01524                   ((winIter->upper_tpos-shwmid) * 
01525                    (winIter->lower_tpos-shwmid)<=
01526                    (maxwid/2.)*(maxwid/2.)) && 
01527                   TMath::Abs((winIter->upper_tpos + 
01528                               winIter->lower_tpos)/2.-shwmid)<minwei){
01529                 minwei = TMath::Abs((winIter->upper_tpos + 
01530                                      winIter->lower_tpos)/2.-shwmid);
01531                 newwinpl0 = winIter->upper;
01532                 newwinpl1 = winIter->lower;
01533                 newwinpl0_tpos = winIter->upper_tpos;
01534                 newwinpl1_tpos = winIter->lower_tpos;
01535                 newwinpl2 = winIter->ph;
01536                 newwinpl3 = winIter->type;
01537               }
01538             }
01539             winIter++;
01540           }
01541         }
01542         else{
01543           minwei = 200.;
01544           minwei_tpos = 10.;
01545           newwinpl0 = -1;
01546           newwinpl1 = -1;
01547           newwinpl0_tpos = -10.;
01548           newwinpl1_tpos = -10.;
01549           newwinpl2 = 0.;
01550           winIter = win.begin();
01551           while(winIter!=winEnd){
01552             if(winIter->plane==pl){
01553               if (!useslopem&&mmid>=0
01554                   &&((winIter->upper_tpos-mmid) * 
01555                      (winIter->lower_tpos-mmid) <=
01556                      (maxwid/2.)*(maxwid/2.)) &&
01557                   TMath::Abs((winIter->upper_tpos + 
01558                               winIter->lower_tpos)/2.-mmid)<minwei){
01559                 minwei = TMath::Abs((winIter->upper_tpos + 
01560                                      winIter->lower_tpos)/2.-mmid);
01561                 newwinpl0 = winIter->upper;
01562                 newwinpl1 = winIter->lower;
01563                 newwinpl0_tpos = winIter->upper_tpos;
01564                 newwinpl1_tpos = winIter->lower_tpos;
01565                 newwinpl2 = winIter->ph;
01566                 newwinpl3 = winIter->type;
01567               }
01568               else if (!useslopep&&pmid>=0
01569                        &&((winIter->upper_tpos-pmid) * 
01570                           (winIter->lower_tpos-pmid) <= 
01571                           (maxwid/2.)*(maxwid/2.))
01572                        && TMath::Abs((winIter->upper_tpos + 
01573                                       winIter->lower_tpos)/2.-pmid)<minwei){
01574                 minwei = TMath::Abs((winIter->upper_tpos + 
01575                                      winIter->lower_tpos)/2.-pmid);
01576                 newwinpl0 = winIter->upper;
01577                 newwinpl1 = winIter->lower;
01578                 newwinpl0_tpos = winIter->upper_tpos;
01579                 newwinpl1_tpos = winIter->lower_tpos;
01580                 newwinpl2 = winIter->ph;
01581                 newwinpl3 = winIter->type;
01582               }
01583               else if (useslopem&&mmid>=0){
01584                 if(usewid<m*eslopen) usewid = m*eslopen;
01585                 else usewid = maxwid;
01586                 if((winIter->upper_tpos-mmid-m*slopen) * 
01587                    (winIter->lower_tpos-mmid-m*slopen) <= 
01588                    (usewid/2.)*(usewid/2.)
01589                    &&TMath::Abs((winIter->upper_tpos + 
01590                                  winIter->lower_tpos)/2.-mmid-m*slopen)<minwei){
01591                   minwei = TMath::Abs((winIter->upper_tpos + 
01592                                        winIter->lower_tpos)/2.-mmid-m*slopen);
01593                   newwinpl0 = winIter->upper;
01594                   newwinpl1 = winIter->lower;
01595                   newwinpl0_tpos = winIter->upper_tpos;
01596                   newwinpl1_tpos = winIter->lower_tpos;
01597                   newwinpl2 = winIter->ph;
01598                   newwinpl3 = winIter->type;
01599                 }
01600               }
01601               else if (useslopep&&pmid>=0){
01602                 if(usewid<p*eslopen) usewid = p*eslopen;
01603                 else usewid = maxwid; 
01604                 if((winIter->upper_tpos-pmid+p*slopen) * 
01605                    (winIter->lower_tpos-pmid+p*slopen) <= 
01606                    (usewid/2.)*(usewid/2.)
01607                    &&TMath::Abs((winIter->upper_tpos + 
01608                                  winIter->lower_tpos)/2.-pmid+p*slopen)<minwei){
01609                   minwei = TMath::Abs((winIter->upper_tpos + 
01610                                        winIter->lower_tpos)/2.-pmid+p*slopen);
01611                   newwinpl0 = winIter->upper;
01612                   newwinpl1 = winIter->lower;
01613                   newwinpl0_tpos = winIter->upper_tpos;
01614                   newwinpl1_tpos = winIter->lower_tpos;
01615                   newwinpl2 = winIter->ph;
01616                   newwinpl3 = winIter->type;
01617                 }
01618               }
01619             }
01620             winIter++;
01621           }
01622         }
01623       }
01624       if(newwinpl0>=0) {
01625         winpl0[d] = newwinpl0;
01626         winpl1[d] = newwinpl1;
01627         winpl0_tpos[d] = newwinpl0_tpos;
01628         winpl1_tpos[d] = newwinpl1_tpos;
01629         winpl2[d] = newwinpl2;
01630         winpl3[d] = newwinpl3;
01631         shwmid = (shwmid*clusterph + 
01632                   (winpl0_tpos[d]+winpl1_tpos[d]) * 
01633                   winpl2[d]/2.)/(clusterph+winpl2[d]);
01634         clusterph+=winpl2[d];
01635         MSG("SubShowerSR",Msg::kDebug) <<"find missed windows "<<pl
01636                                        <<" "<<newwinpl0<<" "
01637                                        <<newwinpl1<<" "<<minwei<<endl;
01638       }
01639     }
01640     
01641     window winSolution;
01642     winSolution.plane = pl;
01643     winSolution.upper = winpl0[d];
01644     winSolution.lower = winpl1[d];
01645     winSolution.upper_tpos = winpl0_tpos[d];
01646     winSolution.lower_tpos = winpl1_tpos[d];
01647     winSolution.ph = winpl2[d];
01648     winSolution.type = winpl3[d];
01649     winSolution.centroid = 0.;
01650     winSolution.phpos = 0.;
01651     winSolution.phwidth = 0.;
01652     cluster.push_back(winSolution);
01653   }
01654 
01655   return cluster;
01656 }
01657 
01658 
01659 //******************************************************************
01660 std::vector<window> AlgSubShowerSRList::HoughTransCluster(std::vector<window> win,
01661                                                           Int_t det)
01662 {
01663 
01664   MSG("SubShowerSR",Msg::kDebug) << "In HoughTransCluster()" << endl;
01665   
01666   std::vector<window> cluster;
01667   std::vector<window> nonCluster;
01668   std::vector<window> emptyCluster;
01669   
01670   //copy all windows into nonCluster:
01671   //also get best vertex estimate in first plane
01672   Int_t vertexPlane = 500;
01673   Double_t vertexPlanePH = 0;
01674   Double_t vertexTPos = 0;
01675   Double_t vertexTPosWidth = 0;
01676 
01677   //use these to calculate the density of hits in the long. window
01678   //this can be used to decide which Hough method to use
01679   Double_t totStrips = 0; 
01680   Double_t maxTpos = -5.0;
01681   Double_t minTpos = 5.0;
01682   Int_t lastPlane = 0;
01683 
01684   std::vector<window>::iterator wIt = win.begin();
01685   std::vector<window>::iterator wEn = win.end();
01686   while(wIt!=wEn){
01687     nonCluster.push_back(*wIt);
01688     if(wIt->plane<vertexPlane) {
01689       if(wIt->ph>1.0) {
01690         vertexPlane = wIt->plane;
01691         vertexPlanePH = wIt->ph;
01692         vertexTPos = wIt->phpos;
01693         vertexTPosWidth = wIt->phwidth;
01694         if(vertexTPosWidth<STRIPWIDTHINMETRES) vertexTPosWidth=STRIPWIDTHINMETRES;
01695       }
01696       else if(vertexPlanePH<1.0){
01697         vertexPlane = wIt->plane;
01698         vertexPlanePH = wIt->ph;
01699         vertexTPos = wIt->phpos;
01700         vertexTPosWidth = wIt->phwidth;
01701         if(vertexTPosWidth<STRIPWIDTHINMETRES) vertexTPosWidth=STRIPWIDTHINMETRES;
01702       }
01703     }
01704     else if(wIt->plane==vertexPlane){
01705       if(wIt->ph>vertexPlanePH){
01706         vertexPlanePH = wIt->ph;
01707         vertexTPos = wIt->phpos;
01708         vertexTPosWidth = wIt->phwidth;
01709         if(vertexTPosWidth<STRIPWIDTHINMETRES) vertexTPosWidth=STRIPWIDTHINMETRES;
01710       }
01711     }
01712     if(wIt->ph>1.0) {
01713       if(wIt->plane>lastPlane) lastPlane = wIt->plane;
01714       if(wIt->upper_tpos>maxTpos) maxTpos = wIt->upper_tpos;
01715       if(wIt->lower_tpos<minTpos) minTpos = wIt->lower_tpos;      
01716       totStrips += Double_t(wIt->upper - wIt->lower + 1);
01717     }
01718     wIt++;
01719   }
01720 
01721   //keep track of some quantities for quality checking at the end:
01722   Int_t   lowPlane  = 500;
01723   Int_t   uppPlane  = 0;
01724   Double_t nStrips  = 0;
01725   Double_t   avePH  = 0;
01726   Double_t aveWidth = 0;
01727   
01728   //keep looping until we have all windows
01729   Bool_t keepGoing = true;
01730   Int_t nLoops = 0;
01731   while(keepGoing && nLoops<MAXHOUGHITER) {
01732     
01733     MSG("SubShowerSR",Msg::kDebug) << "Running BestHough(): Loop number " 
01734                                    << nLoops << endl;
01735 
01736     //remember number of strips in cluster after last loop
01737     //once this value does not change, then stop looping
01738     Double_t oldNStrips = nStrips;
01739 
01740     //Get Hough m,c:
01741     std::vector<Double_t> MCV(14,0.0);
01742     Int_t badGradient[4] = {0};
01743 
01744     //If we are on the first loop, use all windows to get angle
01745     //If we are not on first loop, just use previously 
01746     //selected windows to get better determination of angle
01747     if(cluster.size()==0){
01748       MSG("SubShowerSR",Msg::kDebug) << "cluster.size()=0" << endl;
01749       MCV = BestHough(win,false);
01750 
01751       //verify that best hough passes reasonably close to vertex:
01752       if(true){
01753         MSG("SubShowerSR",Msg::kDebug) << "vertexPlane = " 
01754                                        << vertexPlane << endl;
01755         MSG("SubShowerSR",Msg::kDebug) << "vertexTPos = " 
01756                                        << vertexTPos << endl;
01757         MSG("SubShowerSR",Msg::kDebug) << "vertexTPosWidth = " 
01758                                        << vertexTPosWidth << endl;
01759         
01760         double vertexY_simple = (vertexPlane - MCV[2])*MCV[0] + MCV[1];
01761         double vertexY_simple_peak = (vertexPlane - MCV[2])*MCV[10] + MCV[11];
01762         
01763         MSG("SubShowerSR",Msg::kDebug) << "vertexY_simple = " 
01764                                        << vertexY_simple << endl;
01765         
01766         if( vertexY_simple < vertexTPos - vertexTPosWidth ||
01767             vertexY_simple > vertexTPos + vertexTPosWidth ||
01768             MCV[0]==0 ) badGradient[0] = 1;
01769         if( vertexY_simple_peak < vertexTPos - vertexTPosWidth || 
01770             vertexY_simple_peak > vertexTPos + vertexTPosWidth || 
01771             MCV[10]==0 ) badGradient[1] = 1;
01772     
01773         double vertexY_ph      = (vertexPlane - MCV[7])*MCV[5] + MCV[6];
01774         double vertexY_ph_peak = (vertexPlane - MCV[7])*MCV[12] + MCV[13];
01775         MSG("SubShowerSR",Msg::kDebug) << "vertexY_ph = " 
01776                                        << vertexY_ph << endl;
01777         if( vertexY_ph < vertexTPos - vertexTPosWidth || 
01778             vertexY_ph > vertexTPos + vertexTPosWidth ||
01779             MCV[5]==0 ) badGradient[2] = 1;
01780         if( vertexY_ph_peak < vertexTPos - vertexTPosWidth || 
01781             vertexY_ph_peak > vertexTPos + vertexTPosWidth ||
01782             MCV[12]==0 ) badGradient[3] = 1;
01783       }
01784     }
01785     else {
01786       MSG("SubShowerSR",Msg::kDebug) << "cluster.size()=" 
01787                                      << cluster.size() << endl;
01788       MCV = BestHough(cluster,false);
01789     }
01790 
01791     MSG("SubShowerSR",Msg::kDebug) 
01792       << "\nHough gradient, intercept, plane vertex: " 
01793       << MCV[0] << "+/-" << MCV[3] << " " 
01794       << MCV[1] << "+/-" << MCV[4] << " " << MCV[2]
01795       << "\nPH Hough gradient, intercept, plane vertex: " 
01796       << MCV[5] << "+/-" << MCV[8] << " " 
01797       << MCV[6] << "+/-" << MCV[9] << " " << MCV[7]
01798       << "\n Hough Max Bin Gradient and Intercept Values: "
01799       << MCV[10] << " " << MCV[11] << " "
01800       << MCV[12] << " " << MCV[13] << endl;
01801     
01802     //if we've learnt nothing from first run of BestHough
01803     //stop now and try other clustering algorithm
01804     if(badGradient[0]==1 && badGradient[1]==1 && 
01805        badGradient[2]==1 && badGradient[3]==1 && 
01806        cluster.size()==0) return emptyCluster;
01807 
01808     cluster.clear();
01809     avePH = 0;
01810     aveWidth = 0;
01811     nStrips = 0;
01812     lowPlane = 500;
01813     uppPlane = 0;
01814     std::vector<int> tempcluster[4];
01815     std::vector<window>::iterator winIter = nonCluster.begin();
01816     std::vector<window>::iterator winEnd  = nonCluster.end();
01817     Int_t counter = 0;
01818     while(winIter!=winEnd){
01819       double y[4] = {};
01820       double y_upp[4] = {};
01821       double y_low[4] = {};
01822       y[0] = (winIter->plane - MCV[2])*MCV[0]  + MCV[1];
01823       y[1] = (winIter->plane - MCV[2])*MCV[10] + MCV[11];
01824       y[2] = (winIter->plane - MCV[7])*MCV[5]  + MCV[6];
01825       y[3] = (winIter->plane - MCV[7])*MCV[12] + MCV[13];
01826       
01827       if(cluster.size()==0) {
01828         for(int ii=0;ii<4;ii++) {
01829           y_upp[ii] = y[ii] + STRIPWIDTHINMETRES; 
01830           y_low[ii] = y[ii] - STRIPWIDTHINMETRES;
01831         }
01832       }
01833       else {
01834         for(int ii=0;ii<4;ii++) {
01835           y_upp[ii] = y[ii] + MCV[4+int(ii/2)*5];
01836           y_low[ii] = y[ii] - MCV[4+int(ii/2)*5];
01837         }
01838       }
01839       
01840       for(int ii=0;ii<4;ii++){
01841         if( ( winIter->upper_tpos>=y[ii] && winIter->lower_tpos<=y[ii] ) ||
01842             ( winIter->phpos<=y_upp[ii]  && winIter->phpos>=y_low[ii]  ) ) {
01843           if(badGradient[ii]==0) {
01844             tempcluster[ii].push_back(counter);
01845           }
01846         }
01847       }
01848       winIter++;
01849       counter++;
01850     }
01851     
01852     Int_t best_cluster = -1;
01853     UInt_t max_size = 0;
01854     for(int ii=0;ii<4;ii++){
01855       if(tempcluster[ii].size()>max_size) {
01856         max_size = tempcluster[ii].size();
01857         best_cluster = ii;
01858       }
01859     }
01860     if(best_cluster>=0 && best_cluster<=3) {
01861       std::vector<window>::iterator winIter = nonCluster.begin();
01862       std::vector<window>::iterator winEnd  = nonCluster.end();
01863       std::vector<int>::iterator tempIter = tempcluster[best_cluster].begin();
01864       std::vector<int>::iterator tempEnd  = tempcluster[best_cluster].end();
01865       counter = 0;
01866       while(winIter!=winEnd){
01867         if(tempIter!=tempEnd && (*tempIter) == counter) {
01868           cluster.push_back(*winIter);
01869           avePH += winIter->ph;
01870           aveWidth += winIter->upper_tpos - winIter->lower_tpos;
01871           nStrips += Double_t(winIter->upper - winIter->lower + 1);
01872           if(winIter->plane<lowPlane) lowPlane = winIter->plane;
01873           if(winIter->plane>uppPlane) uppPlane = winIter->plane;
01874           tempIter++;
01875         }
01876         winIter++;
01877         counter++;
01878       }
01879     }
01880     
01881     MSG("SubShowerSR",Msg::kDebug) << "Proto-SubShower currently has " 
01882                                    << (uppPlane-lowPlane+2)/2
01883                                    << " planes and " << nStrips 
01884                                    << " strips" << endl;
01885 
01886     if(nStrips == oldNStrips) keepGoing = false;
01887     nLoops+=1;
01888   }
01889 
01890   if(nStrips<=0) return emptyCluster;
01891     
01892   MSG("SubShowerSR",Msg::kDebug) 
01893     << "Returning Proto-SubShower from HoughTransCluster()" << endl;
01894   
01895   if( det==1 && uppPlane>249 && lowPlane<249 ) return cluster;
01896   avePH/=nStrips;
01897   if( ((uppPlane - lowPlane + 2)/2)<fMinHoughPlanes && 
01898       avePH<fMinHoughPH ) return emptyCluster;
01899   
01900   return cluster;
01901 
01902 }
01903 
01904 //******************************************************************
01905 Bool_t AlgSubShowerSRList::TestOverLap(TObjArray *newSubShower,CandHandle &ch,
01906                                        const CandSliceHandle *slice)
01907 {
01908   //Going to check that proto-subshower does not go through an existing subshower  
01909   //if it does, take largest, plane-wise contiguous set of strips
01910 
01911   MSG("SubShowerSR", Msg::kDebug) << "Running TestOverLap()" << endl;
01912 
01913   //if no strips return false. Empty subshower will be caught later.
01914   Int_t totStp = newSubShower->GetLast()+1;  
01915   if(totStp<=1) return false;
01916 
01917   assert(ch.InheritsFrom("CandSubShowerSRListHandle"));
01918   CandSubShowerSRListHandle &csslh = dynamic_cast<CandSubShowerSRListHandle &>(ch);
01919   //if this is the first subshower, just return false:
01920   if(csslh.GetNDaughters()==0) return false;
01921 
01922   //Get plane view:
01923   TObject *firstObj = newSubShower->At(0);
01924   assert(firstObj->InheritsFrom("CandStripHandle"));
01925   CandStripHandle *firstStp = dynamic_cast<CandStripHandle*>(firstObj);
01926   PlaneView::PlaneView_t pv = firstStp->GetPlaneView();
01927   MSG("SubShowerSR", Msg::kDebug) << "PlaneView = " << pv << endl;
01928 
01929   //loop through subshowers in view + energy order
01930   //so that newSubShower is tested against largest subshower first
01931   CandSubShowerSRHandleItr subshowerItr(csslh.GetDaughterIterator());
01932   CandSubShowerSRHandleKeyFunc *engKF = subshowerItr.CreateKeyFunc();
01933   engKF->SetFun(CandSubShowerSRHandle::KeyFromViewEnergy);
01934   subshowerItr.GetSet()->AdoptSortKeyFunc(engKF);
01935   while (CandSubShowerSRHandle *subshower = subshowerItr()) {
01936     if((*subshower->GetCandSlice())!=(*slice)) continue;
01937     if(subshower->GetPlaneView()!=pv) continue;
01938     if(subshower->GetClusterID()==ClusterType::kXTalk ||
01939        subshower->GetClusterID()==ClusterType::kHalo) continue;
01940     //Get vertex and angle of subshower:
01941     Double_t tpos_vtx = 0;
01942     Double_t z_vtx = subshower->GetVtxZ();
01943     if((subshower->GetPlaneView()==PlaneView::kU || 
01944         subshower->GetPlaneView()==PlaneView::kX)) 
01945       tpos_vtx = subshower->GetVtxU();
01946     if((subshower->GetPlaneView()==PlaneView::kV || 
01947         subshower->GetPlaneView()==PlaneView::kY)) {
01948       tpos_vtx = subshower->GetVtxV();
01949     }
01950     Double_t slope = subshower->GetSlope();
01951     Int_t beg_plane = subshower->GetBegPlane();
01952     Int_t end_plane = subshower->GetEndPlane();
01953 
01954     //for calculating asymmetry:
01955     Double_t n_upp = 0;
01956     Double_t n_low = 0;
01957     Double_t ph_upp = 0;
01958     Double_t ph_low = 0;
01959     Double_t n_plane_upp[500] = {0};
01960     Double_t n_plane_low[500] = {0};
01961     Double_t ph_plane_upp[500] = {0};
01962     Double_t ph_plane_low[500] = {0};
01963 
01964     Int_t firstPlane = 500;
01965     Int_t lastPlane = 0;
01966 
01967     //calculate number of strips above and below axis of subshower
01968     for(int i=0;i<totStp;i++){
01969       CandStripHandle *stp = dynamic_cast<CandStripHandle*>(newSubShower->At(i));
01970       if(firstPlane>stp->GetPlane()) firstPlane = stp->GetPlane();
01971       if(lastPlane<stp->GetPlane()) lastPlane = stp->GetPlane();
01972       if(stp->GetTPos() > (slope*(stp->GetZPos()-z_vtx) + tpos_vtx)) {
01973         n_plane_upp[stp->GetPlane()] += 1;
01974         ph_plane_upp[stp->GetPlane()] += stp->GetCharge(CalDigitType::kSigCorr);
01975         if(stp->GetPlane()>=beg_plane && stp->GetPlane()<=end_plane) {
01976           n_upp += 1;
01977           ph_upp += stp->GetCharge(CalDigitType::kSigCorr);
01978         }
01979       }
01980       else {
01981         n_plane_low[stp->GetPlane()] += 1;
01982         ph_plane_low[stp->GetPlane()] += stp->GetCharge(CalDigitType::kSigCorr);
01983         if(stp->GetPlane()>=beg_plane && stp->GetPlane()<=end_plane) {  
01984           n_low += 1;
01985           ph_low += stp->GetCharge(CalDigitType::kSigCorr);
01986         }
01987       }
01988     }
01989 
01990     //if asymmetry < 95% (should be 100%!) in the plane 
01991     //range of the current subshower then only keep the 
01992     //larger part of the new subshower:
01993     Double_t asymmetry = 1;
01994     Double_t asymmetryPH = 1;
01995     if( n_upp + n_low > 1 ) asymmetry = TMath::Abs(n_upp-n_low)/(n_upp+n_low);
01996     if( ph_upp + ph_low > 1 ) asymmetryPH = TMath::Abs(ph_upp-ph_low)/(ph_upp+ph_low);
01997     MSG("SubShowerSR", Msg::kDebug) << "Asymmetry = " << asymmetry
01998                                     << " AsymmetryPH = " << asymmetryPH
01999                                     << " TotStp = " << totStp
02000                                     << " n_upp = " << n_upp
02001                                     << " n_low = " << n_low
02002                                     << " ph_upp = " << ph_upp
02003                                     << " ph_low = " << ph_low
02004                                     << endl;
02005     if(asymmetry < 0.95) {
02006       //we know now that this proto-subshower is cutting through another subshower
02007       //find the greatest number of contiguous planes above or below slope
02008       //and take those strips only
02009 
02010       Int_t bestAsymFirstPlane = firstPlane;
02011       Int_t bestAsymLastPlane = firstPlane;
02012       Int_t AsymFirstPlane = firstPlane;
02013       Int_t currentSense = 0;
02014       Int_t bestSense = 0;
02015 
02016       //loop through all planes and find longest segments
02017       for(int i=firstPlane;i<=lastPlane;i+=2){
02018         //find longest set of contiguous planes with same asym sign:
02019         if(n_plane_upp[i]>n_plane_low[i] || 
02020            ( n_plane_upp[i]==n_plane_low[i] && 
02021              ph_plane_upp[i]>ph_plane_low[i]) ) {
02022           if(currentSense==0) {
02023             AsymFirstPlane = i;
02024             currentSense = 1;
02025           }
02026           else if(currentSense>0) currentSense += 1;
02027           else if(currentSense<0) { //sense has changed:
02028             if(TMath::Abs(currentSense)>TMath::Abs(bestSense)){
02029               bestSense = currentSense;
02030               bestAsymFirstPlane = AsymFirstPlane;
02031               bestAsymLastPlane = i-1;
02032             }
02033             currentSense = 1;
02034             AsymFirstPlane = i;
02035           }
02036         }
02037         else if(n_plane_low[i]>n_plane_upp[i] || 
02038                 ( n_plane_upp[i]==n_plane_low[i] && 
02039                   ph_plane_low[i]>ph_plane_upp[i]) ){
02040           if(currentSense==0) {
02041             AsymFirstPlane = i;
02042             currentSense = -1;
02043           }
02044           else if(currentSense<0) currentSense -= 1;
02045           else if(currentSense>0) {
02046             if(TMath::Abs(currentSense)>TMath::Abs(bestSense)){
02047               bestSense = currentSense;
02048               bestAsymFirstPlane = AsymFirstPlane;
02049               bestAsymLastPlane = i-1;
02050             }
02051             currentSense = -1;
02052             AsymFirstPlane = i;
02053           }
02054         }
02055       }
02056 
02057       if(TMath::Abs(currentSense)>TMath::Abs(bestSense)){
02058         bestSense = currentSense;
02059         bestAsymFirstPlane = AsymFirstPlane;
02060         bestAsymLastPlane = lastPlane;
02061       }
02062 
02063       for(int i=0;i<totStp;i++){
02064         CandStripHandle *stp = dynamic_cast<CandStripHandle*>(newSubShower->At(i));
02065         if(stp->GetPlane()<bestAsymFirstPlane || stp->GetPlane()>bestAsymLastPlane){
02066           newSubShower->RemoveAt(i);
02067         }
02068       }
02069       newSubShower->Compress();
02070       if(newSubShower->GetLast()+1<totStp) {
02071         return true;
02072       }
02073     }
02074   }
02075   return false;
02076 }
02077 
02078 //******************************************************************
02079 Bool_t AlgSubShowerSRList::TimeTest(TObjArray *newSubShower,TObjArray *allStrips)
02080 {
02081   //Going to check that proto-subshower does not have hits with extreme times
02082   MSG("SubShowerSR", Msg::kDebug) << "Running TestTime()" << endl;
02083 
02084   //if no strips return false. Empty subshower will be caught later.
02085   Int_t totStp = newSubShower->GetLast()+1;
02086   if(totStp<=1) return false;
02087   
02088   //Look for >50ns gaps in time structure:
02089   std::vector<Double_t> stripTime(totStp,0.0);
02090   std::vector<Float_t> stripCharge(totStp,0.0);
02091   for(int i=0;i<totStp;i++){
02092     CandStripHandle *stp = dynamic_cast<CandStripHandle*>(newSubShower->At(i));
02093     Int_t nEarlier = 0;
02094     Int_t nRepeats = 0;
02095     for(int j=0;j<totStp;j++){
02096       if(i==j) continue;
02097       CandStripHandle *stp2 = dynamic_cast<CandStripHandle*>(newSubShower->At(j));    
02098       if(stp->GetTime()>stp2->GetTime()) nEarlier+=1;
02099       else if(stp->GetTime()==stp2->GetTime()) {
02100         if(stp->GetPlane()>stp2->GetPlane()) nEarlier+=1;
02101         else if(stp->GetPlane()==stp2->GetPlane()) {
02102           if(stp->GetStrip()>stp2->GetStrip()) nEarlier+=1;
02103           else if(stp->GetStrip()==stp2->GetStrip()) {
02104             if(stp->GetPlaneView()>stp2->GetPlaneView()) nEarlier+=1;
02105             else if(stp->GetPlaneView()==stp2->GetPlaneView()) nRepeats += 1;         
02106           }
02107         }
02108       }
02109     }
02110     //Fill vectors with time and charge information in time order (earliest first)
02111     stripTime[nEarlier] = stp->GetTime()*1e9;
02112     stripCharge[nEarlier] = stp->GetCharge(CalDigitType::kSigCorr);
02113     for(int j=1;j<=nRepeats;j++) {
02114       stripTime[nEarlier+j] = stp->GetTime()*1e9;
02115       stripCharge[nEarlier+j] = stp->GetCharge(CalDigitType::kSigCorr);
02116     }
02117   }
02118 
02119   //Loop through time vector to find gaps greater than 50ns
02120   //count the number of gaps
02121   Int_t nGaps = 0;
02122   for(int i=0;i<totStp-1;i++){
02123     if(stripTime[i+1] - stripTime[i] > fCleanUpTimeCut) {
02124       nGaps+=1;
02125     }
02126   }
02127   //if no gaps, return now
02128   if(nGaps==0) return false;
02129   //otherwise find the largest chunk of charge between the gaps
02130   std::vector<Float_t> totalCharge(nGaps+1,0.0);
02131   nGaps = 0;
02132   for(int i=0;i<totStp-1;i++) {
02133     totalCharge[nGaps] += stripCharge[i];
02134     if(stripTime[i+1] - stripTime[i] > fCleanUpTimeCut) {
02135       nGaps+=1;
02136     }
02137   }
02138   //don't forget to add in the last strip!
02139   totalCharge[nGaps] += stripCharge[totStp-1];
02140 
02141   //find the biggest chunk:
02142   Int_t biggestChunk = -1;
02143   Double_t biggestCharge = 0;
02144   for(int i=0;i<nGaps+1;i++) {
02145     if(totalCharge[i] > biggestCharge){
02146       biggestChunk = i;
02147       biggestCharge = totalCharge[i];
02148     }
02149   }
02150 
02151   //now go back to time vector to get the min, max times to use
02152   Double_t minTime = -1;
02153   Double_t maxTime = 0;
02154   nGaps = 0;
02155   for(int i=0;i<totStp-1;i++){
02156     if(nGaps>biggestChunk) break;
02157     if(nGaps == biggestChunk) {
02158       if(minTime<0) minTime = stripTime[i];
02159       maxTime = stripTime[i];
02160     }
02161     if(stripTime[i+1] - stripTime[i] > fCleanUpTimeCut) {
02162       nGaps+=1;
02163     }
02164   }
02165 
02166   //loop through strip list again and remove strips outside of time range
02167   for(int i=0;i<totStp;i++){
02168     CandStripHandle *stp = dynamic_cast<CandStripHandle*>(newSubShower->At(i));
02169     if(stp->GetTime()*1e9<minTime - fCleanUpTimeCut || 
02170        stp->GetTime()*1e9>maxTime + fCleanUpTimeCut) {
02171       newSubShower->RemoveAt(i);
02172       if(allStrips) allStrips->Add(stp);
02173       MSG("SubShowerSR",Msg::kDebug) << "Removing Strip From SubShower" << endl;
02174     }
02175   }
02176   newSubShower->Compress();
02177 
02178   if(newSubShower->GetLast()+1<totStp) return true;
02179   return false;
02180 
02181 }
02182 
02183 //******************************************************************
02184 Bool_t AlgSubShowerSRList::CleanUp(TObjArray *allStrips,CandHandle &ch,
02185                                    Int_t det,const CandSliceHandle *cslice)
02186 {
02187   MSG("SubShowerSR", Msg::kDebug) << "Running CleanUp()" << endl;
02188 
02189   Int_t totUnassigned = allStrips->GetLast()+1;
02190   if(totUnassigned==0) return false;
02191 
02192   Calibrator& calibrator=Calibrator::Instance();
02193 
02194   assert(ch.InheritsFrom("CandSubShowerSRListHandle"));
02195   CandSubShowerSRListHandle &csslh = 
02196     dynamic_cast<CandSubShowerSRListHandle &>(ch);
02197 
02198   //Get planeview for this cleanup
02199   TObject *firstObj = allStrips->At(0);
02200   assert(firstObj->InheritsFrom("CandStripHandle"));
02201   CandStripHandle *firstStp = dynamic_cast<CandStripHandle*>(firstObj);
02202   PlaneView::PlaneView_t pv = firstStp->GetPlaneView();
02203   MSG("SubShowerSR", Msg::kDebug) << "PlaneView = " << pv << endl;
02204 
02205   //Any changes made?
02206   Bool_t anyChanges = false;
02207   //once strips have been assigned do not try to assign again:
02208   std::vector<Bool_t> useStrip(totUnassigned,0);
02209   std::vector<Bool_t> assignedStrip(totUnassigned,0);
02210   
02211   for(int i=0;i<totUnassigned;i++) {
02212     assignedStrip[i] = false;
02213     //if cslice defined, check that strip is part of slice:
02214     if(cslice){
02215       useStrip[i] = false;
02216       TObject *tobj = allStrips->At(i);
02217       CandStripHandle *unassigned = dynamic_cast<CandStripHandle*>(tobj);
02218       CandStripHandleItr stpSliceItr(cslice->GetDaughterIterator());
02219       while(CandStripHandle *stp = stpSliceItr()) {
02220         if(*stp==*unassigned) {
02221           useStrip[i] = true;
02222           break;
02223         }
02224       }
02225     }
02226     else useStrip[i] = true;
02227   }
02228   MSG("SubShowerSR", Msg::kDebug) << "Checking " << totUnassigned 
02229                                   << " strips" << endl;
02230 
02231   //going to check if any isolated strips are nearby within +/- 2 strip
02232   for (Int_t i=0; i<totUnassigned; i++) {
02233     
02234     MSG("SubShowerSR", Msg::kVerbose) << "Checking unassigned strip " 
02235                                       << i << endl;
02236 
02237     TObject *tobj = allStrips->At(i);
02238     if(!useStrip[i]) continue;
02239     MSG("SubShowerSR", Msg::kVerbose) << "Can still use unassigned strip " 
02240                                       << i << endl;
02241 
02242     CandStripHandle *unassigned = dynamic_cast<CandStripHandle*>(tobj);
02243     std::vector<Float_t> StripDistance(csslh.GetNDaughters(),0.0);
02244     Float_t theCharge = 
02245       calibrator.GetMIP(unassigned->GetCharge(CalDigitType::kSigCorr));
02246 
02247     //loop through existing subshowers
02248     Int_t ssCount = 0;
02249     CandSubShowerSRHandleItr subshowerItr(csslh.GetDaughterIterator());
02250     while (CandSubShowerSRHandle *subshower = subshowerItr()) {       
02251 
02252       StripDistance[ssCount] = 99999; //set to 999999 as a flag
02253 
02254       //increment early because of continue statements, later use ssCount-1
02255       ssCount++; 
02256 
02257       //if a slice is given in argument list
02258       //demand that slices are the same
02259       if(cslice){
02260         if(*subshower->GetCandSlice()!=*cslice) continue;
02261       }
02262 
02263       //demand that any hit added to subshower is within +/- 50 ns
02264       if(TMath::Abs(subshower->GetAveTime() - 
02265                     unassigned->GetTime())*1.0e9 > fCleanUpTimeCut) continue;
02266       
02267       //only look at the right planeview subshowers
02268       if(subshower->GetPlaneView()!=pv) continue; 
02269       
02270       MSG("SubShowerSR", Msg::kVerbose) << "SubShower " << ssCount-1 
02271                                         << " in the same planeview" << endl;
02272 
02273       // if plane of strip is more than fCleanUpPlaneCut planes away
02274       // don't try to add it to this subshower 
02275       // (also beware of SM boundary in FarDet)
02276       Int_t thePlane = unassigned->GetPlane();
02277       if(thePlane<subshower->GetBegPlane()-fCleanUpPlaneCut || 
02278          thePlane>subshower->GetEndPlane()+fCleanUpPlaneCut || 
02279          (det==1 && 
02280           ( (subshower->GetBegPlane()>249 && thePlane<249) || 
02281             (subshower->GetEndPlane()<249 && thePlane>249) ))) continue;
02282 
02283       MSG("SubShowerSR", Msg::kVerbose) << "SubShower " << ssCount-1 
02284                                         << " in the same plane range" << endl;
02285  
02286       //loop through strips in subshower
02287       //check for proximity to other strips in subshower
02288       //(on a plane-by-plane basis)
02289       Bool_t checkProximity = false;
02290       Float_t theStrip_tpos = unassigned->GetTPos();
02291       CandStripHandleItr stripItr(subshower->GetDaughterIterator());
02292       while(CandStripHandle *stp = stripItr()){
02293         //check we're on the same plane 
02294         //or on the begin plane if the unassigned plane < begin plane
02295         //or on the end plane if the unassigned plane > end plane
02296         if((stp->GetPlane() == thePlane) ||
02297            (thePlane < subshower->GetBegPlane() && 
02298             stp->GetPlane() == subshower->GetBegPlane()) ||
02299             (thePlane > subshower->GetEndPlane() && 
02300             stp->GetPlane() == subshower->GetEndPlane())) {
02301           //allow +/-fCleanUpStripCut strips:
02302           if(TMath::Abs(theStrip_tpos-stp->GetTPos()) <=
02303              fCleanUpStripCut*STRIPWIDTHINMETRES) { 
02304             MSG("SubShowerSR",Msg::kVerbose) 
02305               << "TMath::Abs(theStrip_tpos-stp->GetTPos())=" 
02306               << TMath::Abs(theStrip_tpos-stp->GetTPos()) 
02307               << " stp->Plane()=" << stp->GetPlane()
02308               << " stp->Strip()=" << stp->GetStrip()
02309               << endl;
02310             checkProximity = true;
02311           }
02312         }
02313       }
02314       if(!checkProximity) continue;  //not close enough to this subshower
02315 
02316       MSG("SubShowerSR", Msg::kVerbose) 
02317         << "SubShower " << ssCount-1 
02318         << " has strips in the same tpos range" 
02319         << endl;
02320 
02321       //calculate pH weighted distance from cluster centre
02322       //get subshower vertex and angle:
02323       Double_t tposVtx = 0;
02324       if(pv==PlaneView::kU || 
02325          pv==PlaneView::kX) tposVtx = subshower->GetVtxU();
02326       else if(pv==PlaneView::kV || 
02327               pv==PlaneView::kY) tposVtx = subshower->GetVtxV();      
02328       Double_t zposVtx = subshower->GetVtxZ();
02329       Float_t slope = subshower->GetSlope(); 
02330       Float_t avgdev = subshower->GetAvgDev();
02331       //get strip position and charge:
02332       Float_t tpos = unassigned->GetTPos();
02333       Float_t zpos = unassigned->GetZPos();
02334       if(avgdev!=0.) { 
02335         StripDistance[ssCount-1] = 
02336           (TMath::Abs(tpos - (tposVtx + slope*(zpos - zposVtx))) * 
02337            TMath::Cos(TMath::ATan(slope)))*theCharge/avgdev; 
02338       }
02339       else {
02340         MSG("SubShowerSR",Msg::kVerbose) << "SubShower " << ssCount-1 
02341                                          << " has AvgDev = 0!" << endl;
02342         StripDistance[ssCount-1] = 99998;
02343       }
02344 
02345       MSG("SubShowerSR", Msg::kVerbose) 
02346         << "Unassigned strip " << i 
02347         << " and SubShower " << ssCount-1 
02348         << " are a good match with dev(strip)/avgdev(subshower) = " 
02349         << StripDistance[ssCount-1] << endl;
02350     }
02351 
02352     //make decision here about closest subshower
02353     Float_t minSD = 99999;
02354     Int_t bestSS = -1;
02355     for(int j=0;j<csslh.GetNDaughters();j++){
02356       if(StripDistance[j]<minSD) {
02357         minSD = StripDistance[j];
02358         bestSS = j;
02359       }
02360     }
02361     if(bestSS!=-1){
02362       MSG("SubShowerSR", Msg::kVerbose) << "Best match for strip " << i 
02363                                         << ": SubShower " 
02364                                         << bestSS << " Adding plane: " 
02365                                         << unassigned->GetPlane() 
02366                                         << " strip: " 
02367                                         << unassigned->GetStrip() << endl; 
02368       
02369       CandSubShowerSRHandleItr subshowerItr(csslh.GetDaughterIterator());
02370       ssCount = 0;
02371       while(CandSubShowerSRHandle *cssh = subshowerItr()){
02372         if(ssCount==bestSS){
02373           MSG("SubShowerSR",Msg::kVerbose) << "Before: cssh->GetNStrip() = " 
02374                                            <<  cssh->GetNStrip() 
02375                                            << " cssh->GetEnergy() = " 
02376                                            << cssh->GetEnergy() << endl; 
02377                                          
02378           cssh->AddDaughterLink(*unassigned);
02379           Double_t mip2gev = cssh->GetEnergy() / 
02380             calibrator.GetMIP(cssh->GetCharge(CalStripType::kSigCorr));
02381           cssh->SetEnergy(cssh->GetEnergy()+mip2gev*theCharge);
02382           
02383           MSG("SubShowerSR",Msg::kVerbose) << "After: cssh->GetNStrip() = " 
02384                                            << cssh->GetNStrip() 
02385                                            << " cssh->GetEnergy() = " 
02386                                            << cssh->GetEnergy() << endl;
02387           
02388           assignedStrip[i] = true;
02389           anyChanges = true;
02390           break;
02391         }
02392         ssCount+=1;
02393       }
02394     }
02395     else {
02396       MSG("SubShowerSR", Msg::kVerbose) 
02397         << "No matching subshower for unassigned strip " 
02398         << i << endl;
02399     }
02400   }
02401   
02402   //remove assigned strips
02403   Int_t assigned = 0;
02404   for(int i=0;i<totUnassigned;i++) {
02405     if(assignedStrip[i]) {
02406       allStrips->RemoveAt(i);
02407       assigned+=1;
02408     }  
02409   }
02410   allStrips->Compress();
02411   
02412   if(anyChanges) {
02413     MSG("SubShowerSR", Msg::kDebug) 
02414       << assigned << "/" << totUnassigned
02415       << " strips assigned to SubShowers" << endl;
02416   }
02417   else {
02418     MSG("SubShowerSR", Msg::kDebug) 
02419       << "No Changes made to SubShowers" << endl;
02420   }
02421   return anyChanges;
02422   
02423 }
02424 
02425 //******************************************************************
02426 Bool_t AlgSubShowerSRList::FormHalo(TObjArray *allStrips,CandHandle &ch,
02427                                     CandContext &cxx,AlgHandle &ah,
02428                                     const CandSliceListHandle *slicelist,
02429                                     Int_t det)
02430 {
02431 
02432   MSG("SubShowerSR", Msg::kDebug) << "Running FormHalo()" << endl;
02433   
02434   assert(ch.InheritsFrom("CandSubShowerSRListHandle"));
02435 
02436   Int_t totUnassigned = allStrips->GetLast()+1;
02437   if(totUnassigned==0) return false;
02438   
02439   MSG("SubShowerSR", Msg::kDebug) << "Forming slice-wise, " 
02440                                   << "plane-wise Halo clusters from " 
02441                                   << totUnassigned 
02442                                   << " unassigned strips" << endl;
02443   
02444   //loop over slices
02445   Int_t nslice = 0;
02446   CandSliceHandleItr sliceItr(slicelist->GetDaughterIterator());
02447   while (CandSliceHandle *slice = sliceItr()) {
02448     MSG("SubShowerSR",Msg::kDebug) << "Slice " << nslice << endl;
02449     
02450     //get valid plane ranges for this slice:
02451     CandSubShowerSRListHandle &subshowerlist = 
02452       dynamic_cast<CandSubShowerSRListHandle&>(ch);
02453     CandSubShowerSRHandleItr subshowerItr(subshowerlist.GetDaughterIterator());
02454     Int_t plane[500] = {0};
02455     Int_t firstPlane = 500;
02456     Int_t lastPlane = 0;
02457     while (CandSubShowerSRHandle *subshower = subshowerItr()) {
02458       if (*subshower->GetCandSlice()==*slice) { 
02459         for(int i=subshower->GetBegPlane();i<=subshower->GetEndPlane();i++){
02460           plane[i] = 1;
02461           if(i<firstPlane) firstPlane = i;
02462           if(i>lastPlane) lastPlane = i;
02463         }
02464       }
02465     }
02466 
02467     //loop over valid plane ranges and look for gaps > fHaloMaxPlaneGap
02468     while(firstPlane<=lastPlane){
02469       Int_t begPlane = 500;
02470       Int_t endPlane = 0;
02471       Int_t nGaps = 0;
02472       for(int i=firstPlane;i<=lastPlane;i++){
02473         if(plane[i]==0) {
02474           if(begPlane!=500) nGaps+=1;
02475         }
02476         else {
02477           if(begPlane==500) begPlane = i;
02478           endPlane = i;
02479         }
02480         plane[i] = 0;
02481         if(nGaps>fHaloMaxPlaneGap) {
02482           break;
02483         }
02484       }
02485       firstPlane = endPlane+1;
02486 
02487       //use plane range between begPlane and endPlane to form subshowers
02488       //loop over views:
02489       for(Int_t pv=0;pv<2;pv++){
02490 
02491         MSG("SubShowerSR",Msg::kDebug) << "View : " << pv << endl;
02492 
02493         //first loop through subshower list again and histogram tposvtx
02494         //in order to look for peaks
02495         vtxHist->Reset();
02496         vtxHist->SetBins(fHaloNPeakFindingBins+2,
02497                  -4. - 8./Float_t(fHaloNPeakFindingBins),
02498                  +4. + 8./Float_t(fHaloNPeakFindingBins));
02499 
02500         subshowerItr.ResetFirst();
02501         while (CandSubShowerSRHandle *subshower = subshowerItr()) {
02502           if (*subshower->GetCandSlice()==*slice && 
02503               subshower->GetClusterID()!=ClusterType::kXTalk) {
02504             if(pv==0 && 
02505                (subshower->GetPlaneView()==PlaneView::kV || 
02506                 subshower->GetPlaneView()==PlaneView::kY)) continue;
02507             else if(pv==1 && 
02508                     (subshower->GetPlaneView()==PlaneView::kU || 
02509                      subshower->GetPlaneView()==PlaneView::kX)) continue;
02510             if(subshower->GetBegPlane()>=begPlane && 
02511                subshower->GetBegPlane()<=endPlane){
02512               if(pv==0) {
02513                 MSG("SubShowerSR",Msg::kDebug) 
02514                   << "Filling vtxHist with Subshower "
02515                   << " with tposvtv = " << subshower->GetVtxU() 
02516                   << " and energy = " << subshower->GetEnergy() 
02517                   << " and slope = " << subshower->GetSlope()
02518                   << " and AvgDev = " << subshower->GetAvgDev()
02519                   << endl;
02520                 CandStripHandleItr stripssItr(subshower->GetDaughterIterator());
02521                 while (CandStripHandle *stp = stripssItr()) {
02522                   //fill with max charge for this tpos
02523                   Float_t val = stp->GetCharge(CalDigitType::kSigCorr) - 
02524                     vtxHist->GetBinContent(vtxHist->FindBin(stp->GetTPos()));
02525                   if(val>0) vtxHist->Fill(stp->GetTPos(),val);
02526                 }
02527               }
02528               else if(pv==1) {
02529                 MSG("SubShowerSR",Msg::kDebug) 
02530                   << "Filling vtxHist with Subshower "
02531                   << " with tposvtv = " << subshower->GetVtxV() 
02532                   << " and energy = " << subshower->GetEnergy() 
02533                   << " and slope = " << subshower->GetSlope()
02534                   << " and AvgDev = " << subshower->GetAvgDev()
02535                   << endl;
02536                 CandStripHandleItr stripssItr(subshower->GetDaughterIterator());
02537                 while (CandStripHandle *stp = stripssItr()) {
02538                   //fill with max charge for this tpos
02539                   Float_t val = stp->GetCharge(CalDigitType::kSigCorr) - 
02540                     vtxHist->GetBinContent(vtxHist->FindBin(stp->GetTPos()));
02541                   if(val>0) vtxHist->Fill(stp->GetTPos(),val);            
02542                 }
02543               }
02544             }
02545           }
02546         }
02547 
02548         if(false){
02549           TCanvas *can = new TCanvas();
02550           can->cd(1);
02551           vtxHist->Draw();
02552           char nomus[256];
02553           sprintf(nomus,"peakPlot_FH_view%i_slice%i.eps",pv,nslice);
02554           can->Print(nomus);
02555           delete can;
02556         }
02557         
02558         //width of shower in units of number of bins
02559         //assume shower typically has a width of ~4 strips
02560         Double_t sigma = (4.*0.0417/8.)*(fHaloNPeakFindingBins);
02561         //don't let width be <=1 bin to prevent
02562         //against clipping error messages
02563         if(sigma<=1.0) sigma = 1.01;
02564 
02565         Int_t nPeaks = 0;
02566         Float_t peakPos[10] = {};
02567         Float_t peakVal[10] = {};
02568         Float_t tmp_peakPos = vtxHist->GetBinCenter(vtxHist->GetMaximumBin());
02569         Float_t tmp_peakVal = vtxHist->GetMaximum();
02570         for(int bins = 1;bins<=vtxHist->GetNbinsX();bins++){
02571           if(vtxHist->GetBinContent(bins)>0) nPeaks++;
02572         }
02573         if(nPeaks==1) {
02574           peakPos[0] = tmp_peakPos;
02575           peakVal[0] = tmp_peakVal;
02576         }
02577         else if(nPeaks>0) {
02578           TSpectrum spec(10);
02579           Float_t *source = new Float_t[vtxHist->GetNbinsX()];
02580           Float_t *dest = new Float_t[vtxHist->GetNbinsX()];
02581           for(int h_loop=0;h_loop<vtxHist->GetNbinsX();h_loop++){
02582             source[h_loop] = vtxHist->GetBinContent(h_loop+1);
02583             dest[h_loop] = 0;
02584           }
02585 #if ROOT_VERSION_CODE >= ROOT_VERSION(5,9,1)
02586           nPeaks = spec.SearchHighRes(source,dest,
02587                                       vtxHist->GetNbinsX(),
02588                                       sigma,5,0,1,0,1);
02589 #else
02590           nPeaks = spec.Search1HighRes(source,dest,
02591                                       vtxHist->GetNbinsX(),
02592                                       sigma,5,0,1,0,1);
02593 #endif
02594           Float_t *posX = spec.GetPositionX();
02595           for(Int_t p_loop=0;p_loop<nPeaks;p_loop++){
02596             Int_t bin = 1+Int_t(posX[p_loop]+0.5);
02597             peakPos[p_loop] = vtxHist->GetBinCenter(bin);
02598             peakVal[p_loop] = vtxHist->GetBinContent(bin);
02599           }
02600           delete [] source;
02601           delete [] dest;
02602           //spec.Search(vtxHist,sigma);
02603           //nPeaks = spec.GetNPeaks();
02604         }
02605 
02606         //if no peaks are found
02607         //then there's no reconstructed subshower 
02608         //in this slice + plane range + view
02609         if(nPeaks==0) {
02610           MSG("SubShowerSR",Msg::kDebug) << "No peaks found" << endl;
02611           //so take everything and put it in a subshower
02612           CandStripHandleItr stripslcItr(slice->GetDaughterIterator());
02613           TObjArray newSubShower;
02614           while (CandStripHandle *stp = stripslcItr()) {
02615             if(pv==0 && (stp->GetPlaneView()==PlaneView::kV || 
02616                          stp->GetPlaneView()==PlaneView::kY)) continue;
02617             else if(pv==1 && (stp->GetPlaneView()==PlaneView::kU || 
02618                               stp->GetPlaneView()==PlaneView::kX)) continue;
02619             //is this strip in the subshower plane range?
02620             //allow +/- 2 planes in this window
02621             if(stp->GetPlane()>endPlane+2 || 
02622                stp->GetPlane()<begPlane-2) continue;
02623             //loop over unassigned strips, and see if it's there
02624             for (Int_t i=0; i<allStrips->GetLast()+1; i++) {
02625               TObject *tobj = allStrips->At(i);
02626               CandStripHandle *unassigned = 
02627                 dynamic_cast<CandStripHandle*>(tobj);
02628               if(*unassigned == *stp) {
02629                 newSubShower.Add(unassigned);
02630                 allStrips->RemoveAt(i);
02631               }
02632             }
02633             allStrips->Compress();
02634           }
02635           //make a new subshower with the unassigned strips in this slice
02636           if(newSubShower.GetLast()+1>0){
02637             TimeTest(&newSubShower,allStrips);
02638             cxx.SetDataIn(&newSubShower);
02639             MSG("SubShowerSR",Msg::kDebug) << "forming SubShowerSR\n";
02640             CandSubShowerSRHandle subshowersrhandle = 
02641               CandSubShowerSR::MakeCandidate(ah,cxx);
02642             if(subshowersrhandle.GetNStrip()!=0) {
02643               MSG("SubShowerSR",Msg::kDebug) << "Formed SubShowerSR " 
02644                                              << ch.GetNDaughters()
02645                                              << " with " 
02646                                              << subshowersrhandle.GetNStrip()
02647                                              << " strips" << endl;
02648               subshowersrhandle.SetClusterID(ClusterType::kHalo);
02649               subshowersrhandle.SetCandSlice(slice);
02650               ch.AddDaughterLink(subshowersrhandle);          
02651             }
02652           }
02653           continue;
02654         }
02655       
02656         //have one or more peak => maybe one or 
02657         //more shower in this plane range
02658         //first find acceptable limits in tpos for a halo
02659         //subshower to be formed:
02660         std::vector<Float_t> peakPosLow(nPeaks,0.0);
02661         std::vector<Float_t> peakPosUpp(nPeaks,0.0);
02662         MSG("SubShowerSR",Msg::kDebug) << "Number of Peaks found = "
02663                                        << nPeaks 
02664                                        << " with positions, heights "
02665                                        << "and bounds: "  << endl;
02666         for (int i=0;i<nPeaks;i++){
02667           if(i==0) peakPosLow[i] = -4;
02668           else peakPosLow[i] = peakPosUpp[i-1];
02669           if(i==nPeaks-1) peakPosUpp[i] = 4;
02670           else {
02671             if(peakVal[i]+peakVal[i+1] == 0) {
02672               MSG("SubShowerSR",Msg::kError) << "peakVal[" << i << "]=" << peakVal[i] 
02673                                              << " peakVal[" << i+1 << "]=" << peakVal[i+1]
02674                                              << " - Setting nPeaks=1!" << endl;
02675               nPeaks=1;
02676               peakPosUpp[0] = 4;
02677               break;
02678             }
02679             peakPosUpp[i] = peakPos[i] + 
02680               (peakVal[i])*(peakPos[i+1] - peakPos[i]) / 
02681               ((peakVal[i]) + (peakVal[i+1]));
02682           }
02683           MSG("SubShowerSR",Msg::kDebug) << peakPos[i] << " " 
02684                                          << peakVal[i] << " ["
02685                                          << peakPosLow[i] << "," 
02686                                          << peakPosUpp[i] << "]" 
02687                                          << endl;
02688         }
02689 
02690         //loop through peaks and assign strips to form halo subshowers
02691         //according to acceptable tpos and plane ranges
02692         for(int i=0;i<nPeaks;i++){
02693           //loop through slice strips
02694           CandStripHandleItr stripslcItr(slice->GetDaughterIterator());
02695           TObjArray newSubShower;
02696         
02697           //loop over strips in slices in this view:
02698           // (have to loop through slice strips and not just
02699           // unassigned strips because you cannot get slice number
02700           // from strip handle)
02701           while (CandStripHandle *stp = stripslcItr()) {
02702           
02703             //only look at one view at a time:
02704             if(pv==0 && (stp->GetPlaneView()==PlaneView::kV || 
02705                          stp->GetPlaneView()==PlaneView::kY)) continue;
02706             else if(pv==1 && (stp->GetPlaneView()==PlaneView::kU || 
02707                               stp->GetPlaneView()==PlaneView::kX)) continue;
02708           
02709             //is this strip in the subshower plane range?
02710             //allow +/- 2 planes in this window
02711             if(stp->GetPlane()>endPlane+2 || 
02712                stp->GetPlane()<begPlane-2) continue;
02713             
02714             //is this strip in the tpos range
02715             if(stp->GetTPos()>peakPosUpp[i] ||
02716                stp->GetTPos()<=peakPosLow[i]) continue;
02717 
02718             //loop over unassigned strips, and see if it's there
02719             for (Int_t i=0; i<allStrips->GetLast()+1; i++) {
02720               TObject *tobj = allStrips->At(i);
02721               CandStripHandle *unassigned = 
02722                 dynamic_cast<CandStripHandle*>(tobj);
02723               if(*unassigned == *stp) {
02724                 newSubShower.Add(unassigned);
02725                 allStrips->RemoveAt(i);
02726               }
02727             }
02728             allStrips->Compress();
02729           }
02730           
02731           //make a new subshower with the unassigned strips in this slice
02732           if(newSubShower.GetLast()+1>0){  
02733             TimeTest(&newSubShower,allStrips);
02734             cxx.SetDataIn(&newSubShower);
02735             MSG("SubShowerSR",Msg::kDebug) << "forming SubShowerSR\n";
02736             CandSubShowerSRHandle subshowersrhandle = 
02737               CandSubShowerSR::MakeCandidate(ah,cxx);
02738             if(subshowersrhandle.GetNStrip()!=0) {
02739               MSG("SubShowerSR",Msg::kDebug) << "Formed SubShowerSR with " 
02740                                              << subshowersrhandle.GetNStrip()
02741                                              << " strips" << endl;
02742               subshowersrhandle.SetClusterID(ClusterType::kHalo);
02743               subshowersrhandle.SetCandSlice(slice);
02744               ch.AddDaughterLink(subshowersrhandle); 
02745             }
02746           }
02747         }
02748       }
02749     }
02750     //slice-wise clean up
02751     Int_t numberOfCleanUps = 0;
02752     while(CleanUp(allStrips,ch,det,slice)) {
02753       numberOfCleanUps+=1;
02754       //prevent against infinite loop! (which should NEVER happen)
02755       if(numberOfCleanUps>1000) break;
02756     }
02757     nslice++;
02758   }
02759   //snarl-wide clean up
02760   Int_t numberOfCleanUps = 0;
02761   while(CleanUp(allStrips,ch,det)) {
02762     numberOfCleanUps+=1;
02763     //prevent against infinite loop! (which should NEVER happen)
02764     if(numberOfCleanUps>1000) break;
02765   }
02766   return true;
02767 }
02768 
02769 //******************************************************************
02770 std::vector<Double_t> AlgSubShowerSRList::BestHough(std::vector<window> winVec,
02771                                                     Bool_t makeEPS)
02772 {
02773 
02774   std::vector<window>::iterator winIterBeg = winVec.begin();
02775   std::vector<window>::iterator winIterEnd = winVec.end();
02776   std::vector<Double_t> MCV(14,0.0);
02777   for(int i=0;i<14;i++) MCV[i] = 0.0;
02778 
02779   //get extrema of windows:
02780   Int_t MaxPlane = 0;
02781   Int_t MinPlane = 500;
02782   Double_t MaxStrip = -5.;
02783   Double_t MinStrip = 5.;
02784   //total PH:
02785   Double_t totPH = 0;
02786   //PH of window with max PH:
02787   Double_t maxWinPH = 0;
02788   //plane with maximum PH, and value of max PH:
02789   Int_t maxPlanePos = -1;
02790   Double_t maxPlanePosPH = 0;
02791   //plane by plane sum PH:
02792   Double_t PlanePH[500] = {0};
02793   while(winIterBeg!=winIterEnd){
02794     if(MaxPlane<winIterBeg->plane) MaxPlane = winIterBeg->plane;
02795     if(MinPlane>winIterBeg->plane) MinPlane = winIterBeg->plane;
02796     if(MaxStrip<winIterBeg->upper_tpos) MaxStrip = winIterBeg->upper_tpos;
02797     if(MinStrip>winIterBeg->lower_tpos) MinStrip = winIterBeg->lower_tpos;
02798     if(maxWinPH<winIterBeg->ph) maxWinPH = winIterBeg->ph;
02799     totPH+=winIterBeg->ph;
02800     PlanePH[winIterBeg->plane] += winIterBeg->ph;
02801     if(PlanePH[winIterBeg->plane]>maxPlanePosPH) {
02802       maxPlanePos = winIterBeg->plane;
02803       maxPlanePosPH = PlanePH[maxPlanePos];
02804     }
02805     winIterBeg++;
02806   }
02807   
02808   //window tpos position with max PH, and value of max PH
02809   Double_t maxWindowPos = 0.;
02810   Double_t maxWindowPH = 0.;
02811   winIterBeg = winVec.begin();
02812   while(winIterBeg!=winIterEnd){
02813     if(winIterBeg->plane==maxPlanePos){
02814       if(winIterBeg->ph>maxWindowPH){
02815         maxWindowPos = winIterBeg->phpos;
02816         maxWindowPH = winIterBeg->ph;
02817       }
02818     }
02819     winIterBeg++;
02820   }
02821 
02822   if(winVec.size()<=1 || MinPlane==MaxPlane){
02823     MCV[0] = 0;
02824     MCV[1] = maxWindowPos;
02825     MCV[2] = maxPlanePos;
02826     MCV[3] = 0;
02827     MCV[4] = 0;
02828     MCV[5] = 0;
02829     MCV[6] = maxWindowPos;
02830     MCV[7] = maxPlanePos;
02831     MCV[8] = 0;
02832     MCV[9] = 0;
02833     MCV[10] = 0;
02834     MCV[11] = maxWindowPos;
02835     MCV[12] = 0;
02836     MCV[13] = maxWindowPos;
02837     return MCV;
02838   }
02839 
02840   Double_t TPosWin = MaxStrip-MinStrip+STRIPWIDTHINMETRES;
02841 
02842   MSG("SubShowerSR",Msg::kDebug) << "Hough extrema: plane " << MinPlane 
02843                                  << " to " << MaxPlane
02844                                  << " strip tpos " << MinStrip 
02845                                  << " to " << MaxStrip << endl;
02846   
02847   //define "x=0" to be at MinPlane-2, 
02848   //so y-intercept is strip value at MinPlane-2
02849   //gradient is in units of Delta(tpos) per plane
02850 
02851   houghHist->Reset();
02852   houghHist->SetBins(Int_t(TPosWin/STRIPWIDTHINMETRES) + 
02853                      MaxPlane-MinPlane+2,
02854                      -2.*TPosWin/Float_t(MaxPlane-MinPlane+2),
02855                      2.*TPosWin/Float_t(MaxPlane-MinPlane+2),
02856                      Int_t(2.*TPosWin/STRIPWIDTHINMETRES),
02857                      MinStrip-TPosWin,
02858                      MaxStrip+TPosWin);
02859 
02860   phHoughHist->Reset();
02861   phHoughHist->SetBins(Int_t(TPosWin/STRIPWIDTHINMETRES) + 
02862                        MaxPlane-MinPlane+2,
02863                        -2.*TPosWin/Float_t(MaxPlane-MinPlane+2),
02864                        2.*TPosWin/Float_t(MaxPlane-MinPlane+2),
02865                        Int_t(2.*TPosWin/STRIPWIDTHINMETRES),
02866                        MinStrip-TPosWin,
02867                        MaxStrip+TPosWin);
02868   
02869   winIterBeg = winVec.begin();
02870   while(winIterBeg!=winIterEnd){
02871     Int_t plane = winIterBeg->plane;
02872     Double_t strip = winIterBeg->phpos;
02873     Double_t ph = winIterBeg->ph;
02874     Int_t lastBin = -1;
02875     for(Double_t c=MinStrip-TPosWin; c<=MaxStrip+TPosWin;
02876         c+=STRIPWIDTHINMETRES){
02877       Double_t m = (strip - c)/Float_t(plane-MinPlane+2);
02878       MSG("SubShowerSR",Msg::kVerbose) << "Hough entries: " << m << " " 
02879                                        << c << " " << ph << endl;      
02880       if(houghHist->FindBin(m,c)!=lastBin){
02881         houghHist->Fill(m,c,1);
02882         phHoughHist->Fill(m,c,TMath::Sqrt(ph));
02883         lastBin = houghHist->FindBin(m,c);
02884       }
02885     }
02886     winIterBeg++;
02887   }
02888 
02889   Int_t maxBin = houghHist->GetMaximumBin();
02890   Float_t maxVal = houghHist->GetMaximum();
02891   Int_t xbin = maxBin%(houghHist->GetNbinsX()+2);
02892   Int_t ybin = maxBin/(houghHist->GetNbinsX()+2);
02893   Int_t phMaxBin = phHoughHist->GetMaximumBin();
02894   Float_t phMaxVal = phHoughHist->GetMaximum();
02895   Int_t phXbin = phMaxBin%(phHoughHist->GetNbinsX()+2);
02896   Int_t phYbin = phMaxBin/(phHoughHist->GetNbinsX()+2);
02897 
02898   Double_t totx = 0;
02899   Double_t sumx=0,sumx2=0;
02900   Double_t ptotx = 0;
02901   Double_t psumx=0,psumx2=0;
02902 
02903   Double_t toty=0;
02904   Double_t sumy=0,sumy2=0;
02905   Double_t ptoty = 0;
02906   Double_t psumy=0,psumy2=0;
02907 
02908   for(int xx = 1;xx<=houghHist->GetNbinsX();xx++){
02909     for(int yy = 1;yy<=houghHist->GetNbinsY();yy++){
02910 
02911       if(houghHist->GetBinContent(xx,yy)>maxVal*fBestHoughMaxPHFrac) {
02912         
02913         totx += houghHist->GetBinContent(xx,yy);
02914         sumx += ( houghHist->GetBinContent(xx,yy) * 
02915                   houghHist->GetXaxis()->GetBinCenter(xx)  );
02916         sumx2 += ( houghHist->GetBinContent(xx,yy) * 
02917                    houghHist->GetXaxis()->GetBinCenter(xx)  *
02918                    houghHist->GetXaxis()->GetBinCenter(xx)  );
02919         
02920         toty += houghHist->GetBinContent(xx,yy);
02921         sumy += ( houghHist->GetBinContent(xx,yy) * 
02922                   houghHist->GetYaxis()->GetBinCenter(yy)  );
02923         sumy2 += ( houghHist->GetBinContent(xx,yy) * 
02924                    houghHist->GetYaxis()->GetBinCenter(yy)  *
02925                    houghHist->GetYaxis()->GetBinCenter(yy)  );
02926       }
02927 
02928       if(phHoughHist->GetBinContent(xx,yy)>phMaxVal*fBestHoughMaxPHFrac) {
02929 
02930         ptotx += phHoughHist->GetBinContent(xx,yy);
02931         psumx += ( phHoughHist->GetBinContent(xx,yy) * 
02932                    phHoughHist->GetXaxis()->GetBinCenter(xx)  );
02933         psumx2 += ( phHoughHist->GetBinContent(xx,yy) * 
02934                     phHoughHist->GetXaxis()->GetBinCenter(xx)  *
02935                     phHoughHist->GetXaxis()->GetBinCenter(xx)  );
02936         
02937         ptoty += phHoughHist->GetBinContent(xx,yy);
02938         psumy += ( phHoughHist->GetBinContent(xx,yy) * 
02939                    phHoughHist->GetYaxis()->GetBinCenter(yy)  );
02940         psumy2 += ( phHoughHist->GetBinContent(xx,yy) * 
02941                     phHoughHist->GetYaxis()->GetBinCenter(yy)  *
02942                     phHoughHist->GetYaxis()->GetBinCenter(yy)  );
02943       }
02944 
02945     }
02946   }
02947 
02948   MCV[2] = MinPlane - 2;
02949   if(totx>0) {
02950     MCV[0] = sumx/totx;
02951     MCV[3] = (sumx2/totx - TMath::Power(MCV[0],2))/totx;
02952     if(MCV[3]>0) MCV[3] = TMath::Sqrt(MCV[3]);
02953     else MCV[3] = 0;
02954   }
02955   if(toty>0) {
02956     MCV[1] = sumy/toty;
02957     MCV[4] = (sumy2/toty - TMath::Power(MCV[1],2))/toty;
02958     if(MCV[4]>0) MCV[4] = TMath::Sqrt(MCV[4]);
02959     else MCV[4] = 0;
02960   }
02961   if(MCV[3]<houghHist->GetXaxis()->GetBinWidth(1))
02962     MCV[3] = houghHist->GetXaxis()->GetBinWidth(1);
02963   if(MCV[4]<houghHist->GetYaxis()->GetBinWidth(1))
02964     MCV[4] = houghHist->GetYaxis()->GetBinWidth(1);
02965 
02966   MCV[7] = MinPlane - 2;
02967   if(ptotx>0) {
02968     MCV[5] = psumx/ptotx;
02969     MCV[8] = (psumx2/ptotx - TMath::Power(MCV[5],2))/ptotx;
02970     if(MCV[8]>0) MCV[8] = TMath::Sqrt(MCV[8]);
02971     else MCV[8] = 0;
02972   }
02973   if(ptoty>0) {
02974     MCV[6] = psumy/ptoty;
02975     MCV[9] = (psumy2/ptoty - TMath::Power(MCV[6],2))/ptoty;
02976     if(MCV[9]>0) MCV[9] = TMath::Sqrt(MCV[9]);
02977     else MCV[9] = 0;  
02978   }
02979   if(MCV[8]<phHoughHist->GetXaxis()->GetBinWidth(1))
02980     MCV[8] = phHoughHist->GetXaxis()->GetBinWidth(1);  
02981   if(MCV[9]<phHoughHist->GetYaxis()->GetBinWidth(1))
02982     MCV[9] = phHoughHist->GetYaxis()->GetBinWidth(1);
02983 
02984   MCV[10] = houghHist->GetXaxis()->GetBinCenter(xbin);
02985   MCV[11] = houghHist->GetYaxis()->GetBinCenter(ybin);
02986   MCV[12] = phHoughHist->GetXaxis()->GetBinCenter(phXbin);
02987   MCV[13] = phHoughHist->GetYaxis()->GetBinCenter(phYbin);
02988 
02989   if(makeEPS) {
02990     gStyle->SetOptStat(0);
02991     TCanvas *can = new TCanvas();
02992     can->Divide(2,2);
02993     can->cd(1);
02994     houghHist->Draw("COLZ");
02995     can->cd(2);
02996     phHoughHist->Draw("COLZ");
02997     can->cd(3);
02998     houghHist->Draw("LEGO2");
02999     can->cd(4);
03000     phHoughHist->Draw("LEGO2");
03001     Int_t countr = 0;
03002     Bool_t noPlot = true;
03003     while(noPlot){
03004       char name[256];
03005       sprintf(name,"best_%i.root",countr);
03006       std::ifstream Test(name);
03007       if(!Test) { //if files does not exist:
03008         can->Print(name);
03009         noPlot = false;
03010       }
03011       countr+=1;
03012     }
03013     delete can;
03014   }
03015 
03016   MSG("SubShowerSR",Msg::kDebug) 
03017     << "Before Cuts in BestHough:"
03018     << "\nHough gradient, intercept, plane vertex: " 
03019     << MCV[0] << "+/-" << MCV[3] << " " 
03020     << MCV[1] << "+/-" << MCV[4] << " " << MCV[2]
03021     << "\nPH Hough gradient, intercept, plane vertex: " 
03022     << MCV[5] << "+/-" << MCV[8] << " " 
03023     << MCV[6] << "+/-" << MCV[9] << " " << MCV[7] 
03024     << "\n Hough Max Bin Gradient and Intercept Values: "
03025     << MCV[10] << " " << MCV[11] << " "
03026     << MCV[12] << " " << MCV[13] << endl;
03027 
03028   //check that there is a coincidence of 3 or more windows
03029   //and gradient is bigger than error
03030   if(maxVal < 3 || 
03031      (TMath::Abs(MCV[0])-MCV[3]<0 && 
03032       TMath::Abs(MCV[10])-MCV[3]<0)) {
03033     MCV[0] = 0;
03034     MCV[1] = maxWindowPos;
03035     MCV[2] = maxPlanePos;
03036     MCV[3] = 0;
03037     MCV[4] = 0; 
03038     MCV[10] = 0;
03039     MCV[11] = maxWindowPos;
03040   }
03041   
03042   if((phMaxVal - maxWindowPH)/(totPH - maxWindowPH) < 0.1 || 
03043      (TMath::Abs(MCV[5])-MCV[8]<0 ) &&
03044      (TMath::Abs(MCV[12])-MCV[8]<0 )) {
03045     MCV[5] = 0;
03046     MCV[6] = maxWindowPos;
03047     MCV[7] = maxPlanePos;
03048     MCV[8] = 0;
03049     MCV[9] = 0;
03050     MCV[12] = 0;
03051     MCV[13] = maxWindowPos;
03052   }
03053   return MCV;
03054   
03055 }
03056 
03057 // ----------------------------------------------------------
03058 NavKey AlgSubShowerSRList::StripKeyFromPlane(const CandStripHandle *strip)
03059 {
03060   return const_cast<CandStripHandle *>(strip)->GetPlane();
03061 }
03062 
03063 // ----------------------------------------------------------
03064 void AlgSubShowerSRList::Trace(const char * /* c */) const
03065 {
03066 }
03067 

Generated on Thu Nov 1 11:49:15 2007 for loon by  doxygen 1.3.9.1