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

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