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

AltAlgSliceList.cxx

Go to the documentation of this file.
00001 
00002 // $Id: AltAlgSliceList.cxx,v 1.25 2007/11/11 08:07:50 rhatcher Exp $
00003 //
00004 // AltAlgSliceList.cxx
00005 //
00006 //    -- Event Slicing Algorithm
00007 //
00008 // Costas Andreopoulos <C.V.Andreopoulos@rl.ac.uk>
00009 // CCLRC, Rutherford Appleton Laboratory
00010 // July 01, 2003
00012 
00013 #include <map>
00014 #include <vector>
00015 #include <sstream>
00016 #include <numeric>
00017 #include <cassert>
00018 #include <cmath>
00019 #include <algorithm>
00020 #include <functional>
00021 
00022 #include "AltAlgSliceList.h"
00023 #include "AltWrapperStlVecStripHandle.h"
00024 
00025 #include "Algorithm/AlgFactory.h"
00026 #include "Algorithm/AlgHandle.h"
00027 #include "Algorithm/AlgConfig.h"
00028 #include "Candidate/CandContext.h"
00029 #include "CandDigit/CandDigitHandle.h"
00030 #include "RecoBase/CandSlice.h"
00031 #include "RecoBase/CandSliceHandle.h"
00032 #include "RecoBase/CandSliceList.h"
00033 #include "RecoBase/CandSliceListHandle.h"
00034 #include "Conventions/Detector.h"
00035 #include "LeakChecker/Lea.h"
00036 #include "MessageService/MsgService.h"
00037 #include "MinosObjectMap/MomNavigator.h"
00038 #include "Navigation/NavKey.h"
00039 #include "Navigation/NavSet.h"
00040 #include "Navigation/XxxItr.h"
00041 #include "RawData/RawDigit.h"
00042 #include "RawData/RawHeader.h"
00043 #include "RawData/RawRecord.h"
00044 #include "RawData/RawChannelId.h"
00045 #include "RawData/RawDigitDataBlock.h"
00046 #include "RecoBase/CandSliceHandle.h"
00047 #include "RecoBase/CandStripHandle.h"
00048 #include "RecoBase/CandStripListHandle.h"
00049 #include "UgliGeometry/UgliGeomHandle.h"
00050 #include "Validity/VldContext.h"
00051 
00052 #include <TCanvas.h>
00053 #include <TPad.h>
00054 #include <TLine.h>
00055 #include <TMath.h>
00056 #include <TH1D.h>
00057 #include <TH2D.h>
00058 #include <TH3D.h>
00059 
00060 ClassImp(AltAlgSliceList)
00061 
00062 //____________________________________________________________________________
00063 CVSID("$Id: AltAlgSliceList.cxx,v 1.25 2007/11/11 08:07:50 rhatcher Exp $");
00064 
00065 //____________________________________________________________________________
00066 // --STL Functors (unary/binary predicates, unary/binary functions etc...)
00067 // --Sorting Functions and Functors to be used with the Navigation Tools
00068 
00069 struct min_time_distance: 
00070            public binary_function<CandStripHandle *, CandStripHandle *, bool>
00071 {
00072    CandStripHandle * _ref;
00073    min_time_distance(CandStripHandle * ref) : _ref(ref) {}
00074 
00075    bool operator() (CandStripHandle * a, CandStripHandle * b) {
00076            return  fabs( a->GetCorrBegTime() - _ref->GetCorrBegTime() ) <
00077                    fabs( b->GetCorrBegTime() - _ref->GetCorrBegTime() );
00078    }
00079 };
00080 struct is_in_z_window_noref:  public unary_function<CandStripHandle *, bool>
00081 {
00082    double _pl_min, _pl_max;
00083    is_in_z_window_noref(double pl_min, double pl_max) :
00084                                          _pl_min(pl_min), _pl_max(pl_max) {}
00085    bool operator()(CandStripHandle * csh) {
00086            return  csh->GetPlane() >= _pl_min && csh->GetPlane() <= _pl_max;
00087    }
00088 };
00089 struct is_in_t_window_noref:  public unary_function<CandStripHandle *, bool>
00090 {
00091    double _t_min, _t_max;
00092    is_in_t_window_noref(double t_min, double t_max) :
00093                                              _t_min(t_min), _t_max(t_max) {}
00094    bool operator()(CandStripHandle * csh) {
00095                return  csh->GetCorrBegTime() >= _t_min && csh->GetCorrBegTime() <= _t_max;
00096    }
00097 };
00098 struct is_in_tz_window:  public unary_function<CandStripHandle *, bool>
00099 {
00100    CandStripHandle * _ref;
00101    double            _dt, _dpln;
00102    is_in_tz_window(CandStripHandle * ref, double dt, double dpln) :
00103                                             _ref(ref), _dt(dt), _dpln(dpln) {}
00104    bool operator()(CandStripHandle * csh) {
00105      return  fabs( csh->GetCorrBegTime()  - _ref->GetCorrBegTime() )  <= _dt  &&
00106              abs(  csh->GetPlane() - _ref->GetPlane() ) <= _dpln;
00107    }
00108 };
00109 struct is_in_tztpos_window:  public unary_function<CandStripHandle *, bool>
00110 {
00111    CandStripHandle * _ref;
00112    double            _dt, _dpln, _tpos;
00113    is_in_tztpos_window(
00114                  CandStripHandle * ref, double dt, double dpln, double tpos) :
00115                                _ref(ref), _dt(dt), _dpln(dpln), _tpos(tpos) {}
00116    bool operator()(CandStripHandle * csh) {
00117      if( csh->GetPlaneView() != _ref->GetPlaneView() ) return false;
00118      return  fabs(csh->GetCorrBegTime()  - _ref->GetCorrBegTime())  <= _dt   &&
00119              abs( csh->GetPlane() - _ref->GetPlane()) <= _dpln &&
00120              fabs( csh->GetTPos()  - _ref->GetTPos())  <= _tpos;
00121    }
00122 };
00123 struct min_t:
00124           public binary_function<CandStripHandle *, CandStripHandle *, bool> {
00125    bool operator()(CandStripHandle * a, CandStripHandle * b) {
00126                 return a->GetCorrBegTime() < b->GetCorrBegTime();
00127    }
00128 };
00129 struct min_plane:
00130           public binary_function<CandStripHandle *, CandStripHandle *, bool> {
00131    bool operator()(CandStripHandle * a, CandStripHandle * b) {
00132                 return a->GetPlane() < b->GetPlane();
00133    }
00134 };
00135 struct peak_before : public binary_function<TimeSlice_t, TimeSlice_t, bool>  {
00136    bool operator()(TimeSlice_t a, TimeSlice_t b) { return a.tpeak < b.tpeak; }
00137 };
00138 struct zero_charge : public unary_function<TimeSlice_t, bool> {
00139    bool operator()(TimeSlice_t a) { return a.q <= 0; }
00140 };
00141 struct sum_q :     public binary_function<double, CandStripHandle *, double> {
00142    double operator()(double sum, CandStripHandle * current) {
00143           return (sum + current->GetCharge());
00144    }
00145 };
00146 struct sum_qtpos : public binary_function<double, CandStripHandle *, double> {
00147    double operator()(double sum, CandStripHandle * current) {
00148           return (sum + (current->GetCharge() * current->GetTPos()));
00149    }
00150 };
00151 struct sum_qz :    public binary_function<double, CandStripHandle *, double> {
00152    double operator()(double sum, CandStripHandle * current) {
00153           return (sum + (current->GetCharge() * current->GetZPos()));
00154    }
00155 };
00156 struct sum_qtime : public binary_function<double, CandStripHandle *, double> {
00157    double operator()(double sum, CandStripHandle * current) {
00158           return (sum + (current->GetCharge() * current->GetCorrBegTime()));
00159    }
00160 };
00161 struct is_u_view : public unary_function<CandStripHandle *, bool> {
00162    bool operator()(CandStripHandle * csh) {
00163           return csh->GetPlaneView() == PlaneView::kU;
00164    }
00165 };
00166 struct is_v_view : public unary_function<CandStripHandle *, bool> {
00167    bool operator()(CandStripHandle * csh) {
00168           return csh->GetPlaneView() == PlaneView::kV;
00169    }
00170 };
00171 struct same_strip : public unary_function<CandStripHandle *, bool> {
00172    CandStripHandle * _ref;
00173    same_strip(CandStripHandle * ref) : _ref (ref) { }
00174    bool operator()(CandStripHandle * csh) {
00175           return csh->GetUidInt() == _ref->GetUidInt();
00176    }
00177 };
00178 class PlaneCandStripHandleKeyFunctor : public CandStripHandleKeyFunctor {
00179 
00180 public:
00181    PlaneCandStripHandleKeyFunctor(int pln, float Q, const char * comp):
00182                            fPln(pln), fQ(Q), fComp(std::string(comp)) { }
00183   ~PlaneCandStripHandleKeyFunctor() { }
00184    virtual NavKey operator() (const CandStripHandle * csh) const {
00185           if(fComp.compare("le") == 0)
00186                  return csh->GetPlane() <= fPln && csh->GetCharge() > fQ;
00187           else if(fComp.compare("g")  == 0)
00188                  return csh->GetPlane() >  fPln && csh->GetCharge() > fQ;
00189           else
00190                  return false;
00191    }
00192    virtual CandStripHandleKeyFunctor * Clone() const
00193                     { return new PlaneCandStripHandleKeyFunctor(*this); }
00194 private:
00195      int fPln;
00196      float fQ;
00197      std::string fComp;
00198 };
00199 
00200 static NavKey StripKeyFromTime(const CandStripHandle * csh) {
00201         return csh->GetCorrBegTime();
00202 }
00203 static NavKey SelectNonZeroQ(const CandStripHandle * csh) {
00204         return (csh->GetCharge() > 0);
00205 }
00206 //____________________________________________________________________________
00207 AltAlgSliceList::AltAlgSliceList()
00208 {
00209   LEA_CTOR;
00210 
00211   internalInit(); // initialize private data members
00212 
00213   //-- Msg formatting objects
00214   fFmtStp  = MsgFormat("%3d");
00215   fFmtPln  = MsgFormat("%3d");
00216   fFmtSlc  = MsgFormat("%3d");
00217   fFmtTime = MsgFormat("%11.10f");
00218   fFmtQ    = MsgFormat("%6.3f");
00219 }
00220 //____________________________________________________________________________
00221 AltAlgSliceList::~AltAlgSliceList()
00222 {
00223   LEA_DTOR;
00224 }
00225 //____________________________________________________________________________
00226 void AltAlgSliceList::Trace(const char * /* c */) const
00227 {
00228 
00229 }
00230 //____________________________________________________________________________
00231 void AltAlgSliceList::RunAlg(AlgConfig & ac, CandHandle & ch,CandContext & cx)
00232 {
00233   MSG("AltAlg",Msg::kInfo)
00234          << "**** Begin of AltAlgSliceList::RunAlg() with parameters" << endl;
00235 
00236   //cout.setf(ios_base::fmtflags(0));
00237   ac.Print();
00238 
00239   assert(cx.GetDataIn());
00240   assert(cx.GetDataIn()->InheritsFrom("CandStripListHandle"));
00241 
00242   //-- get a handle to input CandStripList & and create an iterator
00243 
00244   const CandStripListHandle * cslh =
00245                    dynamic_cast<const CandStripListHandle *> (cx.GetDataIn());
00246 
00247   CandStripHandleItr cshItr   ( cslh->GetDaughterIterator() );
00248   CandStripHandleItr cshItr_u ( cslh->GetDaughterIterator() );
00249   CandStripHandleItr cshItr_d ( cslh->GetDaughterIterator() );
00250   assert( cshItr.GetSet()->Size() > 0 );
00251 
00252   //-- this check will be removed - the algorithm is in principle applicable
00253   //   to far detector as well
00254 
00255   if(cslh->GetVldContext()->GetDetector() != Detector::kNear) {
00256     MSG("AltAlg", Msg::kFatal)
00257              << "DATA COMING FROM A WRONG DETECTOR!! QUITING AT ONCE" << endl;
00258     return;
00259   }
00260 
00261   //====================== get algorithm configuration =======================
00262 
00263   getAlgorithmConfiguration(ac);
00264 
00265   assert(fTimeResolution       > 0);
00266   assert(fPkfNofMergedTimeBins > 0);
00267   assert(fZDiffBetweenPeaks    > 0);
00268   assert(fTimeDiffBetweenPeaks > 0);
00269 
00270   //====== Use Navigation tools to suitably sort/select the NavSets ==========
00271   //======      accessible by my CandStripHandleItr iterators       ==========
00272 
00273   // cshItr            can be used to loop over a time-sorted collection of
00274   //                   all hit strips with Q>0
00275 
00276   CandStripHandleKeyFunc * key_func_1 =  cshItr.CreateKeyFunc();
00277   key_func_1->SetFun(SelectNonZeroQ);
00278   cshItr.GetSet()->AdoptSelectKeyFunc(key_func_1);
00279   key_func_1=0;
00280   CandStripHandleKeyFunc * key_func_2 =  cshItr.CreateKeyFunc();
00281   key_func_2->SetFun(StripKeyFromTime);
00282   cshItr.GetSet()->AdoptSortKeyFunc(key_func_2);
00283   key_func_2=0;
00284 
00285   printStripList(cshItr, "Input CandStripList: Q > 0, time-sorted");
00286 
00287   // cshItr_u          Can be used to loop over a time-sorted collection of
00288   //                   all hit strips with Q>0 in the upstream detector
00289   //                   This is used to exclude the mu-spectrometer hits in ND
00290   // cshItr_d          Like cshItr_u but for the downstream detector
00291   //                   This is used to select only mu-spectrometer hits in ND
00292 
00293   PlaneCandStripHandleKeyFunctor  plane_functor_u(kMuSpec1stPlane-1, 0, "le");
00294   PlaneCandStripHandleKeyFunctor  plane_functor_d(kMuSpec1stPlane-1, 0, "g");
00295 
00296   CandStripHandleKeyFunc * key_func_u1 =  cshItr_u.CreateKeyFunc();
00297   key_func_u1->SetFun(plane_functor_u);
00298   cshItr_u.GetSet()->AdoptSelectKeyFunc(key_func_u1);
00299   key_func_u1=0;
00300   CandStripHandleKeyFunc * key_func_u2 =  cshItr_u.CreateKeyFunc();
00301   key_func_u2->SetFun(StripKeyFromTime);
00302   cshItr_u.GetSet()->AdoptSortKeyFunc(key_func_u2);
00303   key_func_u2=0;
00304 
00305   std::ostringstream sstream_u;
00306   sstream_u  << "Input CandStripList: Pln <= "<< kMuSpec1stPlane-1
00307              << " && Q > 0, time-sorted";
00308   printStripList(cshItr_u, sstream_u.str().c_str());
00309 
00310   CandStripHandleKeyFunc * key_func_d1 =  cshItr_d.CreateKeyFunc();
00311   key_func_d1->SetFun(plane_functor_d);
00312   cshItr_d.GetSet()->AdoptSelectKeyFunc(key_func_d1);
00313   key_func_d1=0;
00314   CandStripHandleKeyFunc * key_func_d2 =  cshItr_d.CreateKeyFunc();
00315   key_func_d2->SetFun(StripKeyFromTime);
00316   cshItr_d.GetSet()->AdoptSortKeyFunc(key_func_d2);
00317   key_func_d2=0;
00318 
00319   std::ostringstream sstream_d;
00320   sstream_d  << "Input CandStripList: Pln > " << kMuSpec1stPlane-1
00321              << " && Q > 0, time-sorted";
00322   printStripList(cshItr_d, sstream_d.str().c_str());
00323 
00324 
00325   //=========================  Get spill time-profile  =======================
00326 
00327   //-- get earliest & latest time in the snarl
00328 
00329   getSnarlTimeBoundaries(&cshItr, ftmin, ftmax);
00330 
00331   MSG("AltAlg", Msg::kDebug)
00332        << "Spill time boundaries: tmin = "
00333        << fFmtTime( ftmin ) << " - tmax = " << fFmtTime( ftmax ) << endl;
00334 
00335   //-- group raw times in bins given by the near det time resolution
00336 
00337   fNTimeBins   = (int) ( (ftmax-ftmin+15*fTimeResolution) / (fTimeResolution) );
00338 
00339   fTimeProfile = new TH1D("fTimeProfile", "time profile", fNTimeBins,
00340                              ftmin-5*fTimeResolution, ftmax+10*fTimeResolution);
00341 
00342   MSG("AltAlg", Msg::kDebug)
00343       << "tprof[min] = " <<  fFmtTime( ftmin -  5*fTimeResolution ) << " "
00344       << "tprof[max] = " <<  fFmtTime( ftmax + 15*fTimeResolution ) << " "
00345       << "nbins = " << fNTimeBins << endl;
00346 
00347   // For the time profile use only strips in the upstream detector
00348   // (the cshItr_u CandStripHandleItr points only to those CandStripHandles -
00349   //  see above how the Sort/Select KeyFucs are applied using NavigationTools)
00350   //
00351   // This is used to exclude hits in the muon spectrometer.
00352   // These strips can not be included in the subsequent 3-D clustering
00353   // (in time, tpos, z) space *as they are* since they are not demuxed.
00354   //
00355   // Muon spectrometer hits are treated separately and are assigned to
00356   // event slices *after* they have been formed (see later)
00357 
00358   cshItr_u.ResetFirst();
00359   while( CandStripHandle * striph = cshItr_u.Ptr() ) {
00360 
00361      (fPkfWeightProfileWithCharge) ?
00362                  fTimeProfile->Fill( striph->GetCorrBegTime(), striph->GetCharge() )  :
00363            fTimeProfile->Fill( striph->GetCorrBegTime() )  ;
00364 
00365      cshItr_u.Next();
00366   }
00367   fTimeProfile->Rebin(fPkfNofMergedTimeBins);
00368   fTimeProfileMax = fTimeProfile->GetMaximum();
00369 
00370   //========================= Compute Slice 'Seeds'  =========================
00371 
00372   MSG("AltAlg", Msg::kInfo) << "--> Finding slice seeds " << endl;
00373 
00374   std::vector<TimeSlice_t> slice_seeds = getSliceSeeds(
00375                                           &cshItr_u, fPkfRecursivePeakSearch);
00376 
00377   MSG("AltAlg", Msg::kInfo)
00378         << "--> " << slice_seeds.size() << " slice seeds were found " << endl;
00379 
00380   //========================= Fill Slice 'Seed' maps =========================
00381 
00382   MSG("AltAlg", Msg::kInfo)
00383             << "--> Filling map<int, vector<CandStripHandle *> > event_slices"
00384             << endl;
00385 
00386   std::map<int, std::vector<CandStripHandle *> >
00387                           event_slices = fillSliceSeeds(cshItr_u, slice_seeds);
00388 
00389   //-- print / draw the event slices (time structure & UZ, VZ views)
00390   printSlices(event_slices, "rough slice seeds");
00391   if(fGrfxDebugGraphics & 1) display(event_slices,
00392                         "before space/time clustering - rough time splitting");
00393 
00394   //======================= Dissolve very small slices =======================
00395 
00396   //-- handle the most obvious cases where a 'fake' slice-seed was created by
00397   //   the recursive peak finder -- usually it must be very small or very
00398   //   scattered slices -- dissolve them and append the orphan strips to the
00399   //   best available slice...
00400 
00401   if( fRefinementDissolving ) {
00402 
00403      MSG("AltAlg", Msg::kInfo) << "--> Slice filtering" << endl;
00404 
00405      initSliceFiltering(event_slices);
00406 
00407      printSlices(event_slices, "after slice filtering");
00408      if(fGrfxDebugGraphics & 2) display(event_slices, "after slice filtering");
00409 
00410   } //if !skipping refinement
00411 
00412   //============================= Merge slices ===============================
00413 
00414   //-- handle the most obvious cases where an event is split between two or
00415   //   more slices...
00416 
00417   if( fRefinementMerging ) {
00418 
00419      MSG("AltAlg", Msg::kInfo)
00420        << "--> Merging slices where it seems that an event was split" << endl;
00421 
00422      sliceMerger(event_slices);
00423 
00424      printSlices(event_slices, "after slice merging");
00425      if(fGrfxDebugGraphics & 4) display(event_slices, "after slice merging");
00426   }
00427 
00428   //============== Re-order "misplaced" strips : 3-D clustering ==============
00429 
00430   //-- compute 3-D clusters in UZT & VZT space with a k-Means
00431   //   clustering algorithm
00432 
00433   if( fRefinementKMeansClustering ) {
00434 
00435      MSG("AltAlg", Msg::kInfo)
00436           << "--> strip 2 slice reassignments based on k-Means 3-D clustering"
00437           << endl;
00438 
00439      eventClustering(event_slices);
00440 
00441      printSlices(event_slices, "after 3-D k-Means clustering");
00442      if(fGrfxDebugGraphics & 8)
00443                  display(event_slices, "after k_Means space/time clustering");
00444   }
00445 
00446   //============== Look for substructure within existing slices ==============
00447 
00448   if( fRefinementMSTClustering ) {
00449 
00450      MSG("AltAlg", Msg::kInfo)
00451       << "--> Look for big slices that could be (better) splitted in N others"
00452       << endl;
00453 
00454      //-- need to code this part
00455 
00456      printSlices(event_slices, "after attempt to split slices");
00457      if(fGrfxDebugGraphics & 16)
00458                                display(event_slices, "after MST clustering");
00459   }
00460 
00461   //=========== Assign muon spectrometer hit strips to the slices ==========
00462 
00463   // this is relevant to the near detector only
00464 
00465   if(cslh->GetVldContext()->GetDetector() == Detector::kNear) {
00466 
00467     MSG("AltAlg", Msg::kInfo)
00468                  << "--> Assign ND Muon Spectrometer hits in slices" << endl;
00469 
00470     //-- hits in the muon spectrometer will be assigned to the closest
00471     //   (t-wise) slice in which hit strips just before the spectrometer
00472     //   have been assigned to...
00473 
00474     assignMuonSpectrHits2Slices(cshItr_d, event_slices);
00475   }
00476 
00477   MSG("AltAlg", Msg::kInfo)
00478       << "--> " << event_slices.size()
00479       << ((event_slices.size() == 1) ? " slice was" : " slices were")
00480       << " found in this spill" << endl;
00481 
00482   printSlices(event_slices, "final reconstructed slices");
00483   if(fGrfxDebugGraphics & 32) display(event_slices, "final slices");
00484 
00485   //========================= Build CandSlice's ============================
00486 
00487   MSG("AltAlg", Msg::kInfo) << "--> Building CandSlices" << endl;
00488 
00489   buildCandidates(event_slices, ch, cx);
00490 
00491   delete fTimeProfile;
00492 
00493   MSG("AltAlg", Msg::kInfo) << "<-- all CandSlices created!" << endl;
00494 }
00495 //____________________________________________________________________________
00496 void AltAlgSliceList::display(
00497                   std::map<int, std::vector<CandStripHandle *> > event_slices,
00498                                                          const char * comment)
00499 {
00500   MSG("AltAlg", Msg::kInfo)
00501                  << "--> Debug graphics requested - start drawing..." << endl;
00502 
00503   TCanvas * c = new TCanvas("c", comment, 20, 20, 800, 800);
00504 
00505   eventDisplay(c,event_slices);
00506   delete c;
00507 
00508   MSG("AltAlg", Msg::kInfo)
00509           << "<-- Graphics displayed - continuing with slice reco..." << endl;
00510 }
00511 //____________________________________________________________________________
00512 void AltAlgSliceList::eventDisplay(TCanvas * c,
00513                   std::map<int, std::vector<CandStripHandle *> > event_slices)
00514 {
00515 // Quick debugging 'tool' for tracking down obvious mistakes almost 'online'.
00516 // For thorough testing I run my debugging macros on the std output ntuples
00517 
00518   //-- create the canvas pads & the display histograms
00519 
00520   TPad * padT   = new TPad("padT","strip times",0.01,0.55,0.99,0.99,0);
00521   TPad * padUZ  = new TPad("padUZ","uz view",0.01,0.01,0.49,0.54,0);
00522   TPad * padVZ  = new TPad("padVZ","vz view",0.51,0.01,0.99,0.54,0);
00523 
00524   std::vector<TH1D *> time_profileVec;
00525   std::vector<TH2D *> hVviewVec;
00526   std::vector<TH2D *> hUviewVec ;
00527 
00528   TH1D * time_profile = 0;
00529   TH2D * hVview = 0;
00530   TH2D * hUview = 0;
00531 
00532   const int kNColors   = 16;
00533   int colors[kNColors] = { 1,40,2,30,3,4,5,6,7,8,9,11,25,42,50,28 };
00534 
00535   int icolor = 0;
00536   int islice = 0;
00537 
00538   //-- beautify...
00539 
00540   c->SetBorderMode(0);
00541   c->SetFillColor(0);
00542   c->Draw();
00543   padT->Draw();
00544   padUZ->Draw();
00545   padVZ->Draw();
00546   padT->SetBorderMode(0);
00547   padUZ->SetBorderMode(0);
00548   padVZ->SetBorderMode(0);
00549 
00550   for(std::map<int, std::vector<CandStripHandle *> >::iterator iter =
00551              event_slices.begin(); iter != event_slices.end(); ++iter) {
00552 
00553      std::vector<CandStripHandle *> slice_strips = (*iter).second;
00554 
00555      //-- instantiate...
00556 
00557      time_profile = new TH1D("","tb - time stamps",
00558               fNTimeBins,ftmin-5*fTimeResolution,ftmax+10*fTimeResolution);
00559      hVview = new TH2D("","VZ-view",200,0,200,100,-4,4);
00560      hUview = new TH2D("","UZ-view",200,0,200,100,-4,4);
00561 
00562      time_profile->SetMaximum( fTimeProfileMax );
00563 
00564      if(fGrfxTimeProfileLogView) {
00565         time_profile->SetMinimum( 0.9 );
00566         padT->SetLogy();
00567      }
00568 
00569      //-- fill...
00570 
00571      for(std::vector<CandStripHandle *>::iterator strip_iter =
00572          slice_strips.begin(); strip_iter != slice_strips.end(); ++strip_iter) {
00573 
00574         //time_profile->Fill( (*strip_iter)->GetCorrBegTime() );
00575 
00576         (fPkfWeightProfileWithCharge) ?
00577            time_profile->Fill( (*strip_iter)->GetCorrBegTime(),
00578                                (*strip_iter)->GetCharge() )  :
00579                  time_profile->Fill( (*strip_iter)->GetCorrBegTime() )  ;
00580 
00581         if( (*strip_iter)->GetPlaneView() == PlaneView::kU)
00582              hUview->Fill((*strip_iter)->GetPlane(), (*strip_iter)->GetTPos());
00583 
00584         if( (*strip_iter)->GetPlaneView() == PlaneView::kV)
00585              hVview->Fill((*strip_iter)->GetPlane(), (*strip_iter)->GetTPos());
00586      }
00587 
00588      //-- format & draw...
00589 
00590      padT->cd();
00591      time_profile->SetStats(kFALSE);
00592      time_profile->SetFillColor(colors[icolor]);
00593      time_profile->SetLineColor(colors[icolor]);
00594      if(islice==0) time_profile->Draw();
00595      else          time_profile->Draw("SAME");
00596 
00597      padUZ->cd();
00598      hUview->SetMarkerStyle(20);
00599      hUview->SetMarkerSize(0.7);
00600      hUview->SetMarkerColor(colors[icolor]);
00601      hUview->SetStats(kFALSE);
00602      if(islice==0) hUview->Draw("P");
00603      else          hUview->Draw("PSAME");
00604 
00605      padVZ->cd();
00606      hVview->SetMarkerStyle(20);
00607      hVview->SetMarkerSize(0.7);
00608      hVview->SetMarkerColor(colors[icolor]);
00609      hVview->SetStats(kFALSE);
00610      if(islice==0) hVview->Draw("P");
00611      else          hVview->Draw("PSAME");
00612 
00613      c->Update();
00614 
00615      icolor = ((icolor == kNColors - 1) ? ( 0 ) : ( icolor+1 ) );
00616      islice++;
00617 
00618      time_profileVec.push_back(time_profile);
00619      hVviewVec.push_back(hVview);
00620      hUviewVec.push_back(hUview);
00621   }
00622 
00623   c->SaveAs("slices.gif");
00624 
00625   //-- delete all allocated memory...
00626 
00627   MSG("AltAlg",Msg::kVerbose)
00628                 << "<< Dellacolating memory for graphics objects..." << endl;
00629   delete padT;
00630   delete padUZ;
00631   delete padVZ;
00632 
00633   for(std::vector<TH2D *>::iterator iterTH2 = hVviewVec.begin();
00634                   iterTH2 != hVviewVec.end(); ++iterTH2)   delete (*iterTH2);
00635   for(std::vector<TH2D *>::iterator iterTH2 = hUviewVec.begin();
00636                   iterTH2 != hUviewVec.end(); ++iterTH2)   delete (*iterTH2);
00637   for(std::vector<TH1D *>::iterator iterTH1 = time_profileVec.begin();
00638             iterTH1 != time_profileVec.end(); ++iterTH1)   delete (*iterTH1);
00639 
00640   MSG("AltAlg",Msg::kVerbose) << "... Done!>>" << endl;
00641 }
00642 //____________________________________________________________________________
00643 void AltAlgSliceList::eventDisplaySingleSlice(TCanvas * c, int sliceKey,
00644                   std::map<int, std::vector<CandStripHandle *> > event_slices)
00645 {
00646   //-- create the canvas pads & the display histograms
00647 
00648   TPad *  padT   = new TPad("padT","strip times",0.01,0.55,0.99,0.99,0);
00649   TPad *  padUZ  = new TPad("padUZ","uz view",0.01,0.01,0.49,0.54,0);
00650   TPad *  padVZ  = new TPad("padVZ","vz view",0.51,0.01,0.99,0.54,0);
00651 
00652   TH1D *  time_profileSlc = new TH1D("time_profileSlc","tb - time stamps",
00653             fNTimeBins,ftmin-5*fTimeResolution,ftmax+10*fTimeResolution);
00654   TH1D *  time_profileAll = new TH1D("time_profileSlc","tb - time stamps",
00655             fNTimeBins,ftmin-5*fTimeResolution,ftmax+10*fTimeResolution);
00656 
00657   TH2D *  hVviewSlc = new TH2D("hVviewSlc","VZ-view",200,0,200,100,-4,4);
00658   TH2D *  hVviewAll = new TH2D("hVviewAll","VZ-view",200,0,200,100,-4,4);
00659   TH2D *  hUviewSlc = new TH2D("hUviewSlc","UZ-view",200,0,200,100,-4,4);
00660   TH2D *  hUviewAll = new TH2D("hUviewAll","UZ-view",200,0,200,100,-4,4);
00661 
00662   //-- beautify...
00663 
00664   c->SetBorderMode(0);
00665   c->SetFillColor(0);
00666   c->Draw();
00667   padT->Draw();
00668   padUZ->Draw();
00669   padVZ->Draw();
00670   padT->SetBorderMode(0);
00671   padUZ->SetBorderMode(0);
00672   padVZ->SetBorderMode(0);
00673 
00674   //-- fill...
00675 
00676   for(std::map<int, std::vector<CandStripHandle *> >::iterator iter =
00677             event_slices.begin(); iter != event_slices.end(); ++iter) {
00678 
00679      std::vector<CandStripHandle *> slice_strips = (*iter).second;
00680 
00681      for(std::vector<CandStripHandle *>::iterator strip_iter =
00682         slice_strips.begin(); strip_iter != slice_strips.end(); ++strip_iter) {
00683 
00684         //time_profileAll->Fill( (*strip_iter)->GetCorrBegTime() );
00685 
00686         (fPkfWeightProfileWithCharge) ?
00687                  time_profileAll->Fill( (*strip_iter)->GetCorrBegTime(),
00688                                         (*strip_iter)->GetCharge() )  :
00689                  time_profileAll->Fill( (*strip_iter)->GetCorrBegTime() )  ;
00690 
00691         if( (*strip_iter)->GetPlaneView() == PlaneView::kU)
00692             hUviewAll->Fill((*strip_iter)->GetPlane(), (*strip_iter)->GetTPos());
00693 
00694         if( (*strip_iter)->GetPlaneView() == PlaneView::kV)
00695             hVviewAll->Fill((*strip_iter)->GetPlane(), (*strip_iter)->GetTPos());
00696 
00697         if(sliceKey == (*iter).first) {
00698 
00699             //time_profileSlc->Fill( (*strip_iter)->GetCorrBegTime() );
00700 
00701            (fPkfWeightProfileWithCharge) ?
00702                  time_profileSlc->Fill( (*strip_iter)->GetCorrBegTime(),
00703                                         (*strip_iter)->GetCharge()  )  :
00704                  time_profileSlc->Fill( (*strip_iter)->GetCorrBegTime() )  ;
00705 
00706             if( (*strip_iter)->GetPlaneView() == PlaneView::kU)
00707                  hUviewSlc->Fill((*strip_iter)->GetPlane(), (*strip_iter)->GetTPos());
00708 
00709             if( (*strip_iter)->GetPlaneView() == PlaneView::kV)
00710                  hVviewSlc->Fill((*strip_iter)->GetPlane(), (*strip_iter)->GetTPos());
00711         }
00712      }
00713 
00714      padT->cd();
00715      time_profileAll->SetStats(kFALSE);
00716      time_profileAll->SetFillColor(8);
00717      time_profileAll->SetLineColor(8);
00718      time_profileSlc->SetStats(kFALSE);
00719      time_profileSlc->SetFillColor(2);
00720      time_profileSlc->SetLineColor(2);
00721      time_profileAll->Draw();
00722      time_profileSlc->Draw("SAME");
00723 
00724      padUZ->cd();
00725      hUviewAll->SetMarkerStyle(20);
00726      hUviewAll->SetMarkerSize(0.7);
00727      hUviewAll->SetMarkerColor(8);
00728      hUviewAll->SetStats(kFALSE);
00729      hUviewSlc->SetMarkerStyle(20);
00730      hUviewSlc->SetMarkerSize(0.7);
00731      hUviewSlc->SetMarkerColor(2);
00732      hUviewSlc->SetStats(kFALSE);
00733      hUviewAll->Draw("P");
00734      hUviewSlc->Draw("PSAME");
00735 
00736      padVZ->cd();
00737      hVviewAll->SetMarkerStyle(20);
00738      hVviewAll->SetMarkerSize(0.7);
00739      hVviewAll->SetMarkerColor(8);
00740      hVviewAll->SetStats(kFALSE);
00741      hVviewSlc->SetMarkerStyle(20);
00742      hVviewSlc->SetMarkerSize(0.7);
00743      hVviewSlc->SetMarkerColor(2);
00744      hVviewSlc->SetStats(kFALSE);
00745      hVviewAll->Draw("P");
00746      hVviewSlc->Draw("PSAME");
00747 
00748      c->Update();
00749   }
00750 
00751   delete padT;
00752   delete padUZ;
00753   delete padVZ;
00754   delete time_profileAll;
00755   delete hVviewAll;
00756   delete hUviewAll;
00757   delete time_profileSlc;
00758   delete hVviewSlc;
00759   delete hUviewSlc;
00760 }
00761 //____________________________________________________________________________
00762 void AltAlgSliceList::plot3DClusters(TCanvas * c,
00763                   std::map<int, std::vector<CandStripHandle *> > event_slices)
00764 {
00765   TPad *  padU  = new TPad("padU","z-tpos-t @ u view",0.01,0.01,0.49,0.99,0);
00766   TPad *  padV  = new TPad("padV","z-tpos-t @ v view",0.51,0.01,0.99,0.99,0);
00767 
00768   std::vector<TH3D *> uview;
00769   std::vector<TH3D *> vview;
00770 
00771   TH3D *  hZTposT_u = 0;
00772   TH3D *  hZTposT_v = 0;
00773 
00774   int colors[26] = {
00775          1,40,2,30,3,4,5,6,7,8,9,11,25,42,50,28,1,40,2,30,3,4,5,6,7,8};
00776   int icolor = 0;
00777 
00778   double clight = 300000000;
00779 
00780   //-- beautify canvas
00781 
00782   c->SetBorderMode(0);
00783   c->SetFillColor(0);
00784   c->Draw();
00785   padU->Draw();
00786   padV->Draw();
00787   padU->SetBorderMode(0);
00788   padV->SetBorderMode(0);
00789 
00790   for(std::map<int, std::vector<CandStripHandle *> >::iterator iter =
00791             event_slices.begin(); iter != event_slices.end(); ++iter) {
00792 
00793 
00794      hZTposT_u = new TH3D("hZTposT_u","",200,0,20,100,-4,4,
00795                                        fNTimeBins,ftmin*clight,ftmax*clight);
00796 
00797      hZTposT_v = new TH3D("hZTposT_v","",200,0,20,100,-4,4,
00798                                        fNTimeBins,ftmin*clight,ftmax*clight);
00799 
00800      std::vector<CandStripHandle *> slice_strips = (*iter).second;
00801 
00802      for(std::vector<CandStripHandle *>::iterator strip_iter =
00803           slice_strips.begin(); strip_iter != slice_strips.end(); ++strip_iter) {
00804 
00805         if( (*strip_iter)->GetPlaneView() == PlaneView::kU)
00806             hZTposT_u->Fill( (*strip_iter)->GetZPos(), (*strip_iter)->GetTPos(),
00807                               clight*(*strip_iter)->GetCorrBegTime());
00808 
00809         if( (*strip_iter)->GetPlaneView() == PlaneView::kV)
00810             hZTposT_v->Fill( (*strip_iter)->GetZPos(), (*strip_iter)->GetTPos(),
00811                              clight*(*strip_iter)->GetCorrBegTime());
00812      }
00813 
00814      uview.push_back(hZTposT_u);
00815      vview.push_back(hZTposT_v);
00816 
00817      hZTposT_u->SetMarkerStyle(20);
00818      hZTposT_u->SetMarkerSize(0.7);
00819      hZTposT_u->SetMarkerColor(colors[icolor]);
00820      hZTposT_u->SetStats(kFALSE);
00821 
00822      hZTposT_v->SetMarkerStyle(20);
00823      hZTposT_v->SetMarkerSize(0.7);
00824      hZTposT_v->SetMarkerColor(colors[icolor]);
00825      hZTposT_v->SetStats(kFALSE);
00826 
00827      if(uview.size() == 1) {
00828          padU->cd();
00829          hZTposT_u->Draw("P");
00830          padV->cd();
00831          hZTposT_v->Draw("P");
00832      } else {
00833          padU->cd();
00834          hZTposT_u->Draw("PSAME");
00835          padV->cd();
00836          hZTposT_v->Draw("PSAME");
00837      }
00838      c->Update();
00839      icolor++;
00840   }
00841 
00842 
00843   c->Update();
00844 
00845   for(std::vector<TH3D *>::iterator iterTH3 = uview.begin();
00846                         iterTH3 != uview.end(); ++iterTH3) delete (*iterTH3);
00847   for(std::vector<TH3D *>::iterator iterTH3 = vview.begin();
00848                         iterTH3 != vview.end(); ++iterTH3) delete (*iterTH3);
00849 }
00850 //____________________________________________________________________________
00851 void AltAlgSliceList::getSnarlTimeBoundaries(CandStripHandleItr * cshItr,
00852                                           double & tmin, double & tmax) const
00853 {
00854 // Get the minimum & the maximum time in the NavSet that the cshItr
00855 // CandStripHandleItr iterates on. The NavSet must be sorted in time (in
00856 // ascending order)
00857 //
00858   CandStripHandle * striph = 0;
00859 
00860   cshItr->ResetFirst();
00861   striph = cshItr->Ptr();
00862   tmin = striph->GetCorrBegTime();
00863 
00864   cshItr->ResetLast();
00865   striph = cshItr->Ptr();
00866   tmax = striph->GetCorrBegTime();
00867 
00868   cshItr->ResetFirst();
00869 }
00870 //____________________________________________________________________________
00871 std::vector<TimeSlice_t> AltAlgSliceList::getSliceSeeds(
00872       CandStripHandleItr * cshItr, bool recursive_mode, PeakFinderConf_t conf)
00873 {
00874 // Recosntruct "slice seeds" ro be refined later.
00875 // The a vector of time boundaries corresponding to the seed slices.
00876 // The vec element i corresponds to the ith seed slice.
00877 // The slice seeds are sorted in pulse height peak time (in ascending order).
00878 //
00879 
00880   MSG("AltAlg", Msg::kDebug)
00881     << "[-] Peak Finder ------- Nesting level: " << ++fPeakFinderNestingLevel
00882     << endl;
00883 
00884   assert(fPeakFinderNestingLevel < 50); // crash if things go very wrong...
00885 
00886   std::vector<TimeSlice_t> slice_seeds;
00887 
00888   MSG("AltAlg", Msg::kDebug)  << " |-->[-] Getting gross slice seeds" << endl;
00889 
00890   peakFinder(slice_seeds, conf);
00891   updateSliceSeedInfo(cshItr, slice_seeds);
00892 
00893   MSG("AltAlg", Msg::kDebug)
00894                   << "      |--> Seeds found= " << slice_seeds.size() << endl;
00895 
00896   printSliceSeeds(slice_seeds, "initial, very gross slice seeds");
00897 
00898   //-- Check the time-window of these slice-seeds.
00899   //   In some cases the time-window might be just too large, much bigger than
00900   //   the typical 'duration' of an event and therefore it collects hit strips
00901   //   from nearby slices where the overall activity was below the initial
00902   //   peak-search threshold
00903   //   In this case just confine the slice seed to an acceptable time-window
00904   //   around the found pulse height peak, set PeakFinderConf_t to kLowActivity
00905   //   and look for smaller peaks below the initial threshold.
00906 
00907   //   This step could be by-passed in conjunction with making the peak-finder
00908   //   very sensitive in the first place (low threshold - small max number of
00909   //   successive empty bins). However, the two approaches might not be equivalent.
00910   //   So, I keep both and I need to fine-tune the algorithm externally.
00911 
00912   if(recursive_mode) {
00913 
00914      // by calling the next function, essentially getSliceSeeds() will start
00915      // calling itself, until the duration  of all currently existing slice seeds
00916      // has been reduced to the maximum allowed duration and all the 'de-allocated'
00917      // time has been searched for smaller peaks...
00918 
00919      reduceTimeWindows(cshItr, slice_seeds);
00920   }
00921 
00922   fPeakFinderNestingLevel--;
00923 
00924   return slice_seeds;
00925 }
00926 //____________________________________________________________________________
00927 void AltAlgSliceList::peakFinder(
00928           std::vector<TimeSlice_t> & slice_seeds, PeakFinderConf_t conf) const
00929 {
00930 // This method is a gross peak finder that goes through a specified time-profile
00931 // in the time window [tmin, tmax] and identifies 'peaks' (i.e. time intervals
00932 // [t_slice_min, t_slice_max]) where 'maxSuccessiveEmptyBins' were encountered
00933 // (bins with content < 'peakFinderThreshold') after at least one bin with
00934 // non-empty contents was found.
00935 //
00936 
00937   MSG("AltAlg",Msg::kDebug)
00938      << "      |--> Time-profile peak search with PeakFinderConf_t conf = "
00939      << asString(conf) << endl;
00940 
00941   int cur_bin, start_bin=0;
00942 
00943   int    n_successive_zeros  = 0;     // zero = ( bin content < threshold )
00944   int    n_non_zero_values   = 0;     // non-zero = (bin content >= threshold)
00945   bool   non_zero_bin_found  = false; // <-- in current slice
00946   bool   slice_is_not_over   = true;
00947   bool   new_slice_starts    = true;
00948   Axis_t content_sum         = 0;
00949 
00950   //-- These values depend on PeakFinderConf_t or the algorithm stage
00951   //   when the peak finder was called
00952 
00953   int     peak_finder_threshold     = 0; // current PeakFinderConf_t value
00954   int     max_successive_empty_bins = 0; // current PeakFinderConf_t value
00955   double  tmin                      = 0; // time window: minimum
00956   double  tmax                      = 0; // time window: maximum
00957   TH1D *  time_profile              = 0; // t-prof. the peak-finder will run on
00958 
00959   switch(conf) {
00960 
00961   case kMuSpectrometer:
00962       peak_finder_threshold     = fPkfMuSpecPeakThreshold;
00963       max_successive_empty_bins = fPkfMuSpecNSuccessiveEmptyBins;
00964       time_profile              = fSubsetTimeProfile;
00965       tmin                      = fSubsettmin;
00966       tmax                      = fSubsettmax;
00967       break;
00968   case kLowActivity:
00969       peak_finder_threshold     = fPkfLowPeakThreshold;
00970       max_successive_empty_bins = fPkfLowNSuccessiveEmptyBins;
00971       time_profile              = fSubsetTimeProfile;
00972       tmin                      = fSubsettmin;
00973       tmax                      = fSubsettmax;
00974       break;
00975   case kDefault:
00976   default:
00977       peak_finder_threshold     = fPkfPeakThreshold;
00978       max_successive_empty_bins = fPkfNSuccessiveEmptyBins;
00979       time_profile              = fTimeProfile;
00980       tmin                      = ftmin;
00981       tmax                      = ftmax;
00982       break;
00983   }
00984 
00985   MsgFormat fmtInt("%4d");
00986 
00987   // Compute threshold:
00988   //     (# of strips / time bin) * (number of merged bins in time profile)
00989   int threshold = peak_finder_threshold * fPkfNofMergedTimeBins;
00990 
00991   // Find the minimum and maximum bin for this search...
00992   // Add/subtract a small dt from tmin/tmax so that we do not widen
00993   // the search range by a bin because of round-off errors if the t value
00994   // is exactly on the bin-boundary - this would lead to non-exclusive
00995   // slice-seeds.
00996   int min_bin  = time_profile->FindBin( (Axis_t) (tmin + fTimeResolution/100.) );
00997   int max_bin  = time_profile->FindBin( (Axis_t) (tmax - fTimeResolution/100.) );
00998 
00999   MSG("AltAlg",Msg::kDebug)
01000     << "      |--> For this peak search: "
01001     << "tmin = " << fFmtTime(tmin) << " bin[" << fmtInt(min_bin) << "] "
01002     << "tmax = " << fFmtTime(tmax) << " bin[" << fmtInt(max_bin) << "] "
01003     << endl;
01004 
01005   MSG("AltAlg",Msg::kVerbose)
01006        << "      |-->[-] Printing time-profile contents & peak finder actions"
01007        << endl;
01008 
01009   // Loop over the time frames for the time window under examination
01010   for(cur_bin=min_bin; cur_bin <= max_bin; cur_bin++) {
01011 
01012      // init a new slice seed & mark its starting time bin
01013      if(new_slice_starts) {
01014 
01015          new_slice_starts = false;
01016          content_sum      = 0;
01017 
01018          // skip leading zeros...
01019          for(start_bin = cur_bin; start_bin <= max_bin; start_bin++) {
01020                   bool skip = time_profile->GetBinContent(start_bin) == 0;
01021 
01022             if(!skip) break;
01023             else  printTimeBin(start_bin, time_profile, "skipped!");
01024          }
01025          cur_bin = start_bin;
01026      }
01027 
01028      // Keep on adding non-empty (>threshold) time frames to this slice seed
01029 
01030      content_sum += time_profile->GetBinContent(cur_bin);
01031 
01032      if( time_profile->GetBinContent(cur_bin) <= threshold )
01033          n_successive_zeros++;
01034      else {
01035          non_zero_bin_found   = true;
01036          n_successive_zeros   = 0;
01037          n_non_zero_values++;
01038      }
01039 
01040      std::ostringstream sstream;
01041      sstream  << " thr: "  << fmtInt( threshold )
01042               << " - N(0's) = " << fmtInt( n_successive_zeros )
01043               << " - N(1's) = " << fmtInt( n_non_zero_values );
01044 
01045      printTimeBin(cur_bin, time_profile, sstream.str().c_str());
01046 
01047      // If
01048      // a) we have not reached the maximum allowed number of successive
01049      //    time frames with pulse height < threshold, or
01050      // b) we have not included any time frame with pulse height > threshold
01051 
01052      if(n_successive_zeros < max_successive_empty_bins || !non_zero_bin_found)
01053 
01054          slice_is_not_over = true;  // then keep on expanding the slice seed
01055      else
01056          slice_is_not_over = false; // else stop expanding the slice seed now!
01057 
01058      // There is no life after tmax:
01059      //  --the current slice seed is forced to stop growing if we reach
01060      //    the 'end of the time window'
01061      //  --this only happens if there was at least one entry in the bins
01062      //    associated with this slice-seed
01063      if(cur_bin == max_bin && content_sum > 0) slice_is_not_over = false;
01064 
01065      if(!slice_is_not_over) {
01066 
01067        MSG("AltAlg",Msg::kVerbose)
01068              << "          **** Peak included - could stop at any time"
01069              << " - adding any trailing bins below threshold"<< endl;
01070 
01071         int end_bin;
01072         for(end_bin = cur_bin+1; end_bin <= max_bin; end_bin++) {
01073           bool expand = time_profile->GetBinContent(end_bin) > 0 &&
01074                          time_profile->GetBinContent(end_bin) <= threshold;
01075 
01076           if(!expand) break;
01077           else printTimeBin(end_bin, time_profile,
01078                                         "trailing bin appended to slice!");
01079         }
01080 
01081         MSG("AltAlg",Msg::kVerbose)
01082             << "          **** Stop! One more slice seed is added" << endl;
01083 
01084         cur_bin = end_bin-1;
01085 
01086         //--- reset for next slice seed within this spill
01087         n_successive_zeros  =  0;
01088         n_non_zero_values   =  0;
01089         non_zero_bin_found  =  false;
01090         slice_is_not_over   =  true;
01091         new_slice_starts    =  true;
01092 
01093         //--- add time info for the added seed
01094 
01095         TimeSlice_t current_slice_seed;
01096 
01097         current_slice_seed.tmin =
01098                         (double)   time_profile->GetBinLowEdge(start_bin);
01099         current_slice_seed.tmax =
01100                         (double)   time_profile->GetBinLowEdge(end_bin);
01101 
01102         // with the new approach that was causing overlaps...
01103         //(double) ( time_profile->GetBinLowEdge(end_bin) +
01104         //           time_profile->GetBinWidth(end_bin)  );
01105 
01106         // this will be update later (and then all_sync = true)
01107         current_slice_seed.tpeak    = -1;
01108         current_slice_seed.qt       = -1;
01109         current_slice_seed.q        = -1;
01110         current_slice_seed.all_sync = false;
01111         slice_seeds.push_back(current_slice_seed);
01112      }
01113 
01114   } // loop over time frames
01115 }
01116 //____________________________________________________________________________
01117 void AltAlgSliceList::updateSliceSeedInfo(CandStripHandleItr * cshItr,
01118                                  std::vector<TimeSlice_t> & slice_seeds) const
01119 {
01120 // Compute <tpeak> = Sum_{i} (charge(i)*time(i)) / Sum_{i} (charge(i)) for all
01121 // strips within slice seed's [tmin, tmax]
01122 //
01123   unsigned int islice = 0;
01124   MsgFormat fmtInt("%3d");
01125 
01126   std::vector<TimeSlice_t>::iterator slice_iter;
01127 
01128   for(slice_iter = slice_seeds.begin();
01129                             slice_iter != slice_seeds.end(); ++slice_iter) {
01130 
01131       MSG("AltAlg", Msg::kDebug)
01132              << "    |-->[-] Updating information for slice-seed: "
01133              << fmtInt(islice++) << endl;
01134 
01135       if(! (*slice_iter).all_sync)
01136                             updateSingleSliceSeedInfo( cshItr, *slice_iter );
01137   }
01138   // Eliminate slice-seeds with 0 charge that might have made it to
01139   // this point doe to relaxed criteria or rearrangements in previous steps
01140 
01141   removeNullSeeds(slice_seeds);
01142 }
01143 //____________________________________________________________________________
01144 void AltAlgSliceList::updateSingleSliceSeedInfo(
01145                         CandStripHandleItr * cshItr, TimeSlice_t & seed) const
01146 {
01147 // Compute <tpeak> = Sum_{i} (charge(i)*time(i)) / Sum_{i} (charge(i)) for all
01148 // strips within slice seed's [tmin, tmax]
01149 //
01150   //cshItr->ResetFirst();
01151 
01152   //-- reset previous selections
01153   cshItr->GetSet()->Slice();
01154 
01155   //-- select strips in this time-window
01156   cshItr->GetSet()->Slice( seed.tmin, seed.tmax  );
01157 
01158   MSG("AltAlg", Msg::kDebug)
01159          << "         |-->[-] t = ["
01160          << fFmtTime(seed.tmin) << ", " << fFmtTime(seed.tmax ) << "]" << endl;
01161 
01162   MSG("AltAlg", Msg::kDebug)
01163          << "              |--> selected "
01164          << cshItr->GetSet()->SizeSelect() << " out of "
01165          << cshItr->GetSet()->Size()       << " entries" << endl;
01166 
01167   seed.q  = 0.;
01168   seed.qt = 0.;
01169 
01170   cshItr->ResetFirst();
01171   while( CandStripHandle * striph = cshItr->Ptr() ) {
01172 
01173       seed.q  += ( striph->GetCharge() );
01174       seed.qt += ( striph->GetCharge() * striph->GetCorrBegTime()   );
01175 
01176       printStrip(striph);
01177 
01178       cshItr->Next();
01179   }
01180 
01181   if( seed.q == 0) resetSliceSeed(seed);
01182   else             seed.tpeak = seed.qt / seed.q;
01183 
01184   seed.all_sync = true;
01185 
01186   printSliceSeed(seed);
01187 }
01188 //____________________________________________________________________________
01189 void AltAlgSliceList::removeNullSeeds(
01190                                  std::vector<TimeSlice_t> & slice_seeds) const
01191 {
01192   MSG("AltAlg", Msg::kDebug)
01193           << "    |-->[-] removing any 'null' slice-seed" << endl;
01194   MSG("AltAlg", Msg::kDebug)
01195           << "         |--> init. size = " << slice_seeds.size() << endl;
01196 
01197   std::vector<TimeSlice_t>::iterator slice_iter_new_end =
01198            remove_if( slice_seeds.begin(), slice_seeds.end(), zero_charge() );
01199   slice_seeds.erase( slice_iter_new_end, slice_seeds.end() );
01200 
01201   MSG("AltAlg", Msg::kDebug)
01202           << "         |--> fin. size = " << slice_seeds.size() << endl;
01203 }
01204 //____________________________________________________________________________
01205 void AltAlgSliceList::reduceTimeWindows(CandStripHandleItr * cshItr,
01206                                        std::vector<TimeSlice_t> & slice_seeds)
01207 {
01208 // The 'recursive' peak finding approach is actually implemented here.
01209 // After the first pass, definite peaks were found and now we are looking
01210 // for smaller peaks in the 'time' between these peaks... by calling the
01211 // method ...that has called this method (and so on, until the full space
01212 // is serached for peaks).
01213 //
01214   MsgFormat fmtInt("%3d");
01215 
01216   // Maximum time interval that can be assigned to any single slice-seed.
01217   // bin width = time resolution
01218   // maximum duration in time resolution units =
01219   //  # bins before peak + # bins after peak + the bin that contains the peak
01220 
01221   double max_duration = fTimeResolution *
01222                           (fPkfTimeWindowBefPeak + fPkfTimeWindowAftPeak + 1);
01223 
01224   MSG("AltAlg", Msg::kDebug)
01225       << "Narrowing seeds: duration limited to "
01226       << fFmtTime(max_duration)
01227       << " (-" << fPkfTimeWindowBefPeak << ", "
01228       << "+"   << fPkfTimeWindowAftPeak << ") bins around peak's bin"
01229       << endl;
01230 
01231   // caution: in this loop I perform insert() / erase() operations on the
01232   //          "std::vector<TimeSlice_t> slice_seeds"...
01233   //          Do not use STL iterators in this case because the condition
01234   //          "iter != slice_seeds.end()" gets invalidated by these operations.
01235 
01236   for(unsigned int islice = 0; islice < slice_seeds.size(); islice++) {
01237 
01238       double dt = slice_seeds[islice].tmax - slice_seeds[islice].tmin;
01239 
01240       if(dt > max_duration) {
01241 
01242           bool search_before_peak = false;
01243           bool search_after_peak  = false;
01244 
01245           MSG("AltAlg", Msg::kDebug)
01246              << "[-] Got a wide slice seed: Dt = " << fFmtTime( dt )
01247              << " > (maxDuration = ) " << fFmtTime(max_duration)
01248              << endl;
01249 
01250           //-- reduce the slice-seed width
01251 
01252           MSG("AltAlg", Msg::kDebug)
01253               << " |-->[-] initial:  t(slc-seed="    << fmtInt( islice ) << ")"
01254               << " = ["  << fFmtTime( slice_seeds[islice].tmin )
01255               << ", "    << fFmtTime( slice_seeds[islice].tmax )
01256               << "] with pulse height peak at t = "
01257               << fFmtTime( slice_seeds[islice].tpeak )
01258               << endl;
01259 
01260           int peak_bin = fTimeProfile->FindBin(
01261                                  (Axis_t) slice_seeds[islice].tpeak );
01262 
01263           int min_bin  = peak_bin - fPkfTimeWindowBefPeak;
01264           int max_bin  = peak_bin + fPkfTimeWindowAftPeak;
01265 
01266           double tmin_new = (double)   fTimeProfile->GetBinLowEdge(min_bin);
01267           double tmax_new = (double) ( fTimeProfile->GetBinLowEdge(max_bin) +
01268                                        fTimeProfile->GetBinWidth(max_bin)  );
01269 
01270           double tmin_old = slice_seeds[islice].tmin;
01271           double tmax_old = slice_seeds[islice].tmax;
01272 
01273           //-- check whether the 'after peak' time boundary should be shifted
01274 
01275           if( tmax_old > tmax_new ) {
01276              search_after_peak            = true;
01277              slice_seeds[islice].tmax     = tmax_new;
01278              slice_seeds[islice].all_sync = false;
01279           }
01280 
01281           //-- check whether the 'before peak' time boundary should be shifted
01282 
01283           if( tmin_old < tmin_new ) {
01284              search_before_peak           = true;
01285              slice_seeds[islice].tmin     = tmin_new;
01286              slice_seeds[islice].all_sync = false;
01287           }
01288 
01289           MSG("AltAlg", Msg::kDebug)
01290               << " |-->[-] updated:  t(slc-seed="    << fmtInt( islice ) << ")"
01291               << " = ["  << fFmtTime( slice_seeds[islice].tmin )
01292               << ", "    << fFmtTime( slice_seeds[islice].tmax )
01293               << "] with pulse height peak at t = "
01294               << fFmtTime( slice_seeds[islice].tpeak ) << endl;
01295 
01296 
01297           //-- tmin/tmax changed --keep all TimeSlice_t info in sync
01298           MSG("AltAlg", Msg::kDebug)
01299               << "      |-[-] sync TimeSlice info" << endl;
01300 
01301           if(!slice_seeds[islice].all_sync)
01302                       updateSingleSliceSeedInfo(cshItr, slice_seeds[islice]);
01303 
01304           //-- change PeakFinderConf_t to kLowActivity and look for new
01305           //   slice seeds in 'de-allocated' time-space
01306 
01307           if( search_after_peak ) {
01308 
01309             MSG("AltAlg", Msg::kDebug)
01310                << "      |-->[-] Looking for small peaks (after the main peak) "
01311                << "in [" << fFmtTime(tmax_new)
01312                << ", "   << fFmtTime(tmax_old) << "] time window" << endl;
01313 
01314             fSubsettmin = tmax_new;
01315             fSubsettmax = tmax_old;
01316 
01317             std::vector<TimeSlice_t> new_seeds = findSmallerPeaks(cshItr);
01318             if(new_seeds.size() > 0) mergeSeeds(new_seeds, slice_seeds);
01319           }
01320 
01321           if( search_before_peak ) {
01322 
01323             MSG("AltAlg", Msg::kDebug)
01324               << "      |-->[-] Looking for small peaks (before the main peak) "
01325               << "in [" << fFmtTime(tmin_old)
01326               << ", "   << fFmtTime(tmin_new) << "] time window" << endl;
01327 
01328             fSubsettmin = tmin_old;
01329             fSubsettmax = tmin_new;
01330 
01331             std::vector<TimeSlice_t> new_seeds = findSmallerPeaks(cshItr);
01332             if(new_seeds.size() > 0) mergeSeeds(new_seeds, slice_seeds);
01333           }
01334 
01335       } //  if dt > max_duration
01336 
01337       //islice++;
01338   } // slice seed iter
01339 
01340 }
01341 //____________________________________________________________________________
01342 std::vector<TimeSlice_t> AltAlgSliceList::findSmallerPeaks(
01343                                                   CandStripHandleItr * cshItr)
01344 {
01345 // Runs the peak-finder (in a kLowActivity configuration state) at a time
01346 // window within spill (the time-window de-allocated when the duration of all
01347 // major peaks was limited) so as to search for smaller peaks.
01348 // The time window must have been defined prior to calling this method
01349 // (by setting the fSubsettmin, fSubsettmax private data members).
01350 //
01351   std::vector<TimeSlice_t> new_seeds;
01352 
01353   //-- select strips in this time-window
01354 
01355   double tmin = fSubsettmin; // copy here because these two data members change
01356   double tmax = fSubsettmax; // in nested calls of the peak-finder
01357 
01358   MSG("AltAlg", Msg::kDebug)
01359      << "           |--> cshItr.GetSet()->Slice("
01360      << fFmtTime(tmin) << ", " << fFmtTime(tmax) << ")" << endl;
01361 
01362   cshItr->GetSet()->Slice();       // reset previous
01363   cshItr->GetSet()->Slice(tmin, tmax);
01364 
01365   MSG("AltAlg", Msg::kDebug)
01366      << "           |--> selected "
01367      << cshItr->GetSet()->SizeSelect() << " out of " << cshItr->GetSet()->Size()
01368      << " entries" << endl;
01369 
01370   if( cshItr->GetSet()->SizeSelect() > 0) {
01371 
01372        // watch out for memory leaks when running the peak finder recursively
01373        if(fSubsetTimeProfile) delete fSubsetTimeProfile;
01374 
01375        fSubsetTimeProfile = createSubsetTimeProfile(cshItr);
01376 
01377        MSG("AltAlg", Msg::kDebug)
01378             << "---------------------------- PEAK FINDER (NESTED LEVEL)/ "
01379             << "---------------------------- " << endl;
01380 
01381        //-- search for new slice-seeds
01382        new_seeds = getSliceSeeds(cshItr, fPkfRecursivePeakSearch, kLowActivity);
01383 
01384        MSG("AltAlg", Msg::kDebug)
01385             << "------------------------------------------- /PEAK FINDER "
01386             << "------------------------------------------- " << endl;
01387 
01388        MSG("AltAlg", Msg::kDebug) << "           |--> search in the ["
01389           << fFmtTime(tmin) << ", " << fFmtTime(tmax)
01390           << "] time window gave " << new_seeds.size() << " more seeds" << endl;
01391 
01392        if(fSubsetTimeProfile) delete fSubsetTimeProfile;
01393        fSubsetTimeProfile = 0;
01394 
01395   } else
01396 
01397        MSG("AltAlg", Msg::kDebug)
01398             << "           |--> cshItr.GetSet()->SizeSelect() = 0, "
01399             << "terminating recursive calls for this window" << endl;
01400 
01401   return new_seeds;
01402 }
01403 //____________________________________________________________________________
01404 void AltAlgSliceList::mergeSeeds(std::vector<TimeSlice_t> new_seeds,
01405                               std::vector<TimeSlice_t> & full_seed_list) const
01406 {
01407   std::vector<TimeSlice_t>::iterator time_slice_iter;
01408 
01409    //-- add new slices
01410    MSG("AltAlg", Msg::kVerbose)
01411             << "           |--> adding new seeds - initial number: "
01412             << full_seed_list.size() << endl;
01413 
01414    for(time_slice_iter = new_seeds.begin();
01415               time_slice_iter != new_seeds.end(); ++time_slice_iter) {
01416 
01417               full_seed_list.push_back( *time_slice_iter );
01418    }
01419    MSG("AltAlg", Msg::kVerbose)
01420             << "           |--> seeds added - new number: "
01421             << full_seed_list.size() << endl;
01422 
01423   //printSliceSeeds(new_seeds, "new seeds that were added in this step");
01424   //printSliceSeeds(full_seed_list, "full list of current slice seeds");
01425 }
01426 //____________________________________________________________________________
01427 std::map<int,std::vector<CandStripHandle *> > AltAlgSliceList::fillSliceSeeds(
01428              CandStripHandleItr cshItr, std::vector<TimeSlice_t> & slice_seeds)
01429 {
01430 // This method is called when the construction of the slice seeds has finished
01431 // and fills the std::map<int,std::vector<CandStripHandle *> > structure that
01432 // will be used for holding the reconstructed slices in the subsequent steps
01433 // of the event slicing algorithm.
01434 // This change is necessary because it will no longer be adequate to describe
01435 // the slices with mutually exclusive [tmin, tmax] time-intervals.
01436 // During slice-refinement, the reconstructed slices might pick up strips from
01437 // other slices so as to minimize a combined temporal-spatial distance and
01438 // therefore *hard* time boundaries might not be respected.
01439 //
01440   MSG("AltAlg", Msg::kDebug) <<  "* Constructing rough slices map"  << endl;
01441 
01442   // 'narrowing' might completely strip a scattered seed
01443   removeNullSeeds(slice_seeds);
01444 
01445   sort( slice_seeds.begin(), slice_seeds.end(), peak_before() );
01446 
01447   printSliceSeeds(slice_seeds, "final slice seeds -- sorted in peak time");
01448 
01449   MSG("AltAlg", Msg::kDebug)
01450          << " |--> selected " << cshItr.GetSet()->SizeSelect()
01451          << " out of "        << cshItr.GetSet()->Size()
01452          << " entries" << endl;
01453 
01454   int islice = 0;
01455   MsgFormat fmtInt("%3d");
01456 
01457   std::map<int, std::vector<CandStripHandle *> >  event_slices;
01458 
01459   std::vector<TimeSlice_t>::const_iterator slice_seeds_iter;
01460 
01461   for(slice_seeds_iter = slice_seeds.begin();
01462                 slice_seeds_iter != slice_seeds.end(); ++slice_seeds_iter ) {
01463 
01464      MSG("AltAlg", Msg::kVerbose)
01465          << "Assigning strips to slice seed: " << fmtInt(islice) << endl;;
01466      MSG("AltAlg", Msg::kVerbose)
01467          << "[-] cshItr.GetSet()->Slice("
01468          <<   "t = " << fFmtTime( (*slice_seeds_iter).tmin )
01469          << ", t = " << fFmtTime( (*slice_seeds_iter).tmax ) << ")"
01470          << " - dt<slice> = "
01471          << fFmtTime( (*slice_seeds_iter).tmax - (*slice_seeds_iter).tmin )
01472          << endl;
01473 
01474      //-- reset previous selections
01475      cshItr.GetSet()->Slice();
01476 
01477      //-- select strips in this time-window
01478      cshItr.GetSet()->Slice( (*slice_seeds_iter).tmin,
01479                              (*slice_seeds_iter).tmax  );
01480 
01481      MSG("AltAlg", Msg::kVerbose)
01482         << " |--> selected " << cshItr.GetSet()->SizeSelect() << " out of "
01483         << cshItr.GetSet()->Size() << " entries" << endl;
01484 
01485      std::vector<CandStripHandle *> slice_strips;
01486 
01487      MSG("AltAlg", Msg::kVerbose)
01488          << "[-] while( CandStripHandle * striph = cshItr.Ptr() )" << endl;
01489 
01490      cshItr.ResetFirst();
01491      while( CandStripHandle * striph = cshItr.Ptr() ) {
01492         slice_strips.push_back(striph);
01493 
01494         MSG("AltAlg", Msg::kVerbose)
01495            << " |--> slice_strips.push_back( "
01496            << "pl = "     << fFmtPln(  striph->GetPlane()   )
01497            << ", str = "  << fFmtStp(  striph->GetStrip()   )
01498            << ", Q = "    << fFmtQ(    striph->GetCharge()  )
01499            << ", view = " << PlaneView::AsString( striph->GetPlaneView() )
01500            << ", t = "    << fFmtTime( striph->GetCorrBegTime() )
01501            << " )" << endl;
01502 
01503         cshItr.Next();
01504      }
01505 
01506      MSG("AltAlg", Msg::kVerbose)
01507          << "[-] add pair: event_slices.insert( "
01508          << "std::map<int, std::vector<CandStripHandle *> >::"
01509          << "value_type(" << islice << ", " << &slice_strips << ") );"
01510          << endl;
01511 
01512      event_slices.insert(
01513        std::map<int, std::vector<CandStripHandle *> >::value_type(
01514                                                       islice, slice_strips) );
01515      islice++;
01516   }
01517 
01518   MSG("AltAlg", Msg::kDebug)
01519                << "* Constructing of rough reco slices map completed" << endl;
01520 
01521   return event_slices;
01522 }
01523 //____________________________________________________________________________
01524 void AltAlgSliceList::sortSlicesInTime(
01525           std::map<int, std::vector<CandStripHandle *> > & event_slices) const
01526 {
01527 // Sorts CandStripHandles associated with each slice is ascending time order
01528 //
01529   MSG("AltAlg", Msg::kDebug) << "* Sorting Slices in time " << endl;
01530 
01531   std::map<int, std::vector<CandStripHandle *> >::iterator slice_iter;
01532 
01533   for(slice_iter = event_slices.begin();
01534                               slice_iter != event_slices.end(); ++slice_iter)
01535      sort( (*slice_iter).second.begin(), (*slice_iter).second.end(), min_t());
01536 }
01537 //____________________________________________________________________________
01538 void AltAlgSliceList::sortSlicesInPlaneNo(
01539           std::map<int, std::vector<CandStripHandle *> > & event_slices) const
01540 {
01541 // Sorts CandStripHandles associated with each slice is ascending plane number
01542 //
01543   MSG("AltAlg", Msg::kDebug) << "* Sorting Slices in plane number " << endl;
01544 
01545   std::map<int, std::vector<CandStripHandle *> >::iterator slice_iter;
01546 
01547   for(slice_iter = event_slices.begin();
01548                                slice_iter != event_slices.end(); ++slice_iter)
01549           sort( (*slice_iter).second.begin(),
01550                                      (*slice_iter).second.end(), min_plane());
01551 }
01552 //____________________________________________________________________________
01553 void AltAlgSliceList::printSliceSeeds(
01554      const std::vector<TimeSlice_t> & slice_seeds, const char * comment) const
01555 {
01556 // Method for printing the slice seeds found by the time-profile peak-finder
01557 //
01558   MSG("AltAlg", Msg::kDebug) << "[-] Printing: " << comment << endl;
01559 
01560   int islice=0;
01561   MsgFormat fmtInt("%3d");
01562 
01563   std::vector<TimeSlice_t>::const_iterator time_slice_iter;
01564 
01565   for(time_slice_iter = slice_seeds.begin();
01566                time_slice_iter != slice_seeds.end(); ++time_slice_iter) {
01567 
01568       if( (*time_slice_iter).tpeak == -1 )
01569         MSG("AltAlg", Msg::kDebug)
01570              << " |--> t(slc-seed ="    << fmtInt( islice++ ) << ")"
01571              << " = ["  << fFmtTime( (*time_slice_iter).tmin )
01572              << ", "    << fFmtTime( (*time_slice_iter).tmax )
01573              << "] with pulse height peak not defined yet" << endl;
01574       else
01575          MSG("AltAlg", Msg::kDebug)
01576              << " |--> t(slc-seed ="    << fmtInt( islice++ ) << ")"
01577              << " = ["  << fFmtTime( (*time_slice_iter).tmin )
01578              << ", "    << fFmtTime( (*time_slice_iter).tmax )
01579              << "] with pulse height peak at t = "
01580              << fFmtTime( (*time_slice_iter).tpeak ) << endl;
01581   }
01582 }
01583 //____________________________________________________________________________
01584 void AltAlgSliceList::printSliceSeed(const TimeSlice_t & seed) const
01585 {
01586    MSG("AltAlg", Msg::kDebug)
01587           << "              |--> Seed info: t = ["
01588           << fFmtTime(seed.tmin) << ", "    << fFmtTime(seed.tmax)
01589           << "] with peak at t = " << fFmtTime(seed.tpeak)
01590           << " and Qtot = " << fFmtQ(seed.q) << endl;
01591 }
01592 //____________________________________________________________________________
01593 void AltAlgSliceList::resetSliceSeed(TimeSlice_t & seed) const
01594 {
01595   seed.tmin  = 0;  seed.tpeak = 0;  seed.tmax  = 0;
01596   seed.q     = 0;  seed.qt    = 0;  seed.all_sync = true;
01597 }
01598 //____________________________________________________________________________
01599 void AltAlgSliceList::printSlices(
01600           const std::map<int, std::vector<CandStripHandle *> > & event_slices,
01601                                                    const char * comment) const
01602 {
01603 // Method for printing the reconstructed event slices
01604 //
01605   MSG("AltAlg", Msg::kDebug) << "* Printing Reco Slices: " << comment << endl;
01606 
01607   std::map<int, std::vector<CandStripHandle *> >::const_iterator slice_iter;
01608 
01609   for(slice_iter = event_slices.begin();
01610                slice_iter != event_slices.end(); ++slice_iter)
01611                                                        printSlice(slice_iter);
01612 
01613   MSG("AltAlg", Msg::kDebug) << "* Printing Reco Slices completed" << endl;
01614 }
01615 //____________________________________________________________________________
01616 void AltAlgSliceList::printSlice(
01617    std::map<int, std::vector<CandStripHandle *> >::const_iterator slice) const
01618 {
01619 // Method for printing the reconstructed event slices
01620 //
01621   int nv = count_if(
01622                  slice->second.begin(), slice->second.end(), is_v_view());
01623   int nu = count_if(
01624                  slice->second.begin(), slice->second.end(), is_u_view());
01625 
01626   MSG("AltAlg", Msg::kDebug)
01627      << "[-] Slice: " << slice->first
01628      << " - (N(U) = " << nu << " -- N(V) = " << nv << ")" << endl;
01629 
01630   const std::vector<CandStripHandle *> & slice_strips = slice->second;
01631   std::vector<CandStripHandle *>::const_iterator strip_iter;
01632 
01633   for(strip_iter = slice_strips.begin();
01634                           strip_iter != slice_strips.end(); ++strip_iter) {
01635 
01636      MSG("AltAlg", Msg::kDebug)
01637         << " |--> Pl = " << fFmtPln(  (*strip_iter)->GetPlane()   )
01638         << " Str = "     << fFmtStp(  (*strip_iter)->GetStrip()   )
01639         << " Q = "       << fFmtQ(    (*strip_iter)->GetCharge()  )
01640         << " tb = "      << fFmtTime( (*strip_iter)->GetCorrBegTime() )
01641         << " view = " << PlaneView::AsString( (*strip_iter)->GetPlaneView() )
01642         << endl;
01643   } // strip_iter
01644 }
01645 //____________________________________________________________________________
01646 void AltAlgSliceList::printSlice(
01647                           const std::vector<CandStripHandle *> & slice) const
01648 {
01649   int nv = count_if(slice.begin(), slice.end(), is_v_view());
01650   int nu = count_if(slice.begin(), slice.end(), is_u_view());
01651 
01652   MSG("AltAlg", Msg::kDebug)
01653      << "[-] printing slice whose id was not specified or a strip collection"
01654      << " - (N(U) = " << nu << " -- N(V) = " << nv << ")" << endl;
01655 
01656   std::vector<CandStripHandle *>::const_iterator strip_iter;
01657 
01658   for(strip_iter = slice.begin(); strip_iter != slice.end(); ++strip_iter) {
01659 
01660      MSG("AltAlg", Msg::kDebug)
01661         << " |--> Pl = " << fFmtPln(  (*strip_iter)->GetPlane()   )
01662         << " Str = "     << fFmtStp(  (*strip_iter)->GetStrip()   )
01663         << " Q = "       << fFmtQ(    (*strip_iter)->GetCharge()  )
01664         << " tb = "      << fFmtTime( (*strip_iter)->GetCorrBegTime() )
01665         << " view = " << PlaneView::AsString( (*strip_iter)->GetPlaneView() )
01666         << endl;
01667   } // strip_iter
01668 }
01669 //____________________________________________________________________________
01670 void AltAlgSliceList::printStripList(
01671                         CandStripHandleItr cshItr, const char * comment) const
01672 {
01673   MSG("AltAlg", Msg::kVerbose) << comment << endl;
01674 
01675   MSG("AltAlg", Msg::kVerbose)
01676       << " |--> selected " << cshItr.GetSet()->SizeSelect()
01677       << " out of "        << cshItr.GetSet()->Size()
01678       << " entries" << endl;
01679 
01680   cshItr.ResetFirst();
01681   while( CandStripHandle * striph = cshItr.Ptr() ) {
01682 
01683      MSG("AltAlg", Msg::kVerbose)
01684         << " |--> Pl = " << fFmtPln(  striph->GetPlane()   )
01685         << " Str = "     << fFmtStp(  striph->GetStrip()   )
01686         << " Q = "       << fFmtQ(    striph->GetCharge()  )
01687         << " tb = "      << fFmtTime( striph->GetCorrBegTime() )
01688         << " view = " << PlaneView::AsString( striph->GetPlaneView() )
01689         << endl;
01690 
01691      cshItr.Next();
01692   }
01693 }
01694 //____________________________________________________________________________
01695 void AltAlgSliceList::printStrip(const CandStripHandle * strip) const
01696 {
01697    MSG("AltAlg", Msg::kVerbose)
01698        << "              |--> Pl = " << fFmtPln(  strip->GetPlane()   )
01699        << " Str = "     << fFmtStp(  strip->GetStrip()   )
01700        << " Q = "       << fFmtQ(    strip->GetCharge()  )
01701        << " tb = "      << fFmtTime( strip->GetCorrBegTime() )
01702        << " view = " << PlaneView::AsString( strip->GetPlaneView() )
01703        << endl;
01704 }
01705 //____________________________________________________________________________
01706 void AltAlgSliceList::printTimeBin(
01707                int bin, const TH1D * time_profile, const char * comment) const
01708 {
01709    MsgFormat fmtInt("%4d");
01710 
01711    MSG("AltAlg",Msg::kVerbose)
01712        << "          |--> bin: "  << fmtInt( bin )
01713        << ":[" << fFmtTime( (double)    time_profile->GetBinLowEdge(bin) )
01714        << ", " << fFmtTime( (double)  ( time_profile->GetBinLowEdge(bin) +
01715                                         time_profile->GetBinWidth(bin)) )
01716        << "], cnt: "  << fmtInt( int( time_profile->GetBinContent(bin) ))
01717        << " / " << comment << endl;
01718 }
01719 //____________________________________________________________________________
01720 std::string AltAlgSliceList::asString(WhichCandSlice_t which_slices) const
01721 {
01722   switch( which_slices ) {
01723   case (eNone):
01724       return std::string("isolated strip - no really good match found");
01725       break;
01726   case (eSame):
01727       return std::string("no action - this strip is @ home");
01728       break;
01729   case (eOther):
01730       return std::string("a single other candidate was found");
01731       break;
01732   case (eMany):
01733       return std::string("many 'candidates' - need to resolve the ambiguity");
01734       break;
01735   default:
01736       return std::string(" --- ");
01737   }
01738 }
01739 //____________________________________________________________________________
01740 std::string AltAlgSliceList::asString(PeakFinderConf_t conf) const
01741 {
01742   switch( conf ) {
01743   case (kDefault):        return std::string("[default config]");      break;
01744   case (kLowActivity):    return std::string("[low activity config]"); break;
01745   case (kMuSpectrometer): return std::string("[mu-spectr. config]");   break;
01746   default:                return std::string(" --- ");
01747   }
01748 }
01749 //____________________________________________________________________________
01750 void AltAlgSliceList::Merge(const std::pair<int, int> & slices_to_merge,
01751           std::map<int, std::vector<CandStripHandle *> > & event_slices) const
01752 {
01753 // Method for handling the map<int, vector<CandStripHandle *> > slice map.
01754 // Gets a pair of slice ids that have to be merged and applies this operation
01755 // the map. All CandStripHandles are appended to the first slice of the pair
01756 // and the other is deleted. At the end, the map is sorted in time.
01757 //
01758   MSG("AltAlg", Msg::kVerbose) << "* Begin Slice Merging" << endl;
01759 
01760   //printSlices(event_slices,"");
01761 
01762   int target_slice = slices_to_merge.first;
01763   int source_slice = slices_to_merge.second;
01764 
01765   std::map<int, std::vector<CandStripHandle *> >::iterator slice_iter;
01766 
01767   slice_iter = event_slices.find(source_slice);
01768 
01769   std::vector<CandStripHandle *> source_strips = slice_iter->second;
01770 
01771   std::vector<CandStripHandle *>::iterator strip_iter;
01772 
01773   for(strip_iter = source_strips.begin();
01774                            strip_iter != source_strips.end(); ++strip_iter) {
01775 
01776      MSG("AltAlg", Msg::kVerbose)
01777              << "   --- Strip: " << fFmtStp( (*strip_iter)->GetStrip() )
01778              << " from plane: "  << fFmtPln( (*strip_iter)->GetPlane() )
01779              << " to be removed from slice: " << fFmtSlc( source_slice )
01780              << " and appended in slice: " << fFmtSlc( target_slice ) << endl;
01781 
01782      //-- Add cand strip handle to target slice
01783      event_slices[target_slice].push_back(*strip_iter);
01784 
01785   } // loop over source slice strips
01786 
01787   MSG("AltAlg", Msg::kVerbose)
01788                        << "   ---- Removing slice: " << source_slice << endl;
01789   event_slices.erase(slice_iter); // remove source slice
01790 
01791   MSG("AltAlg", Msg::kVerbose) << "* Slice Merging Completed" << endl;
01792 }
01793 //____________________________________________________________________________
01794 void AltAlgSliceList::Split(
01795               int slice, std::vector<CandStripHandle *>::size_type n_separator,
01796           std::map<int, std::vector<CandStripHandle *> > & event_slices) const
01797 {
01798 // A specific case of Split(). ** The generic case is coded next **
01799 // In this specific case, the original slice is split in just two parts and
01800 // its vector of strips is somehow sorted to reflect this splitting.
01801 // The first n_separator elements are assigned to the first sub-slice and the
01802 // remaining size()-n_separator elements are assigned to the second one.
01803 //
01804   MSG("AltAlg", Msg::kVerbose) << "[-] splitting slice: " << slice << endl;
01805 
01806   vector<CandStripHandle *>::iterator strip_iter = event_slices[slice].begin();
01807 
01808   advance(strip_iter, n_separator);
01809 
01810   std::vector<CandStripHandle *> new_slice_strips_1(n_separator);
01811   copy(event_slices[slice].begin(),  strip_iter,  new_slice_strips_1.begin());
01812   event_slices.insert(
01813       std::map<int, std::vector<CandStripHandle *> >::value_type(
01814                      nextAvailableSliceId(event_slices), new_slice_strips_1 ));
01815 
01816   std::vector<CandStripHandle *> new_slice_strips_2(
01817                                     event_slices[slice].size() - n_separator);
01818   copy( strip_iter, event_slices[slice].end(), new_slice_strips_2.begin());
01819   event_slices.insert(
01820       std::map<int, std::vector<CandStripHandle *> >::value_type(
01821                     nextAvailableSliceId(event_slices), new_slice_strips_2 ));
01822 
01823   event_slices.erase(slice);
01824 }
01825 //____________________________________________________________________________
01826 void AltAlgSliceList::Split(
01827               int slice, std::vector< std::vector<CandStripHandle *> > groups,
01828           std::map<int, std::vector<CandStripHandle *> > & event_slices) const
01829 {
01830 // Method for updating the slices map to reflect the splitting of an existing
01831 // slice. New slices are created to accomodate the strips of each elemement of
01832 // the std::vector< std::vector<CandStripHandle *> > "groups" STL-vector...
01833 // These elements define a partition of the strips corresponding to the input
01834 // slice identifies.
01835 // After creating the new slices, the original slice is deleted.
01836 //
01837   MSG("AltAlg", Msg::kVerbose) << "[-] splitting slice: " << slice << endl;
01838 
01839   std::vector< std::vector<CandStripHandle *> >::iterator group_iter;
01840 
01841   for(group_iter = groups.begin(); group_iter != groups.end(); ++group_iter)
01842 
01843      event_slices.insert(
01844           std::map<int, std::vector<CandStripHandle *> >::value_type(
01845                            nextAvailableSliceId(event_slices), *group_iter) );
01846 
01847   event_slices.erase(slice);
01848 }
01849 //____________________________________________________________________________
01850 int AltAlgSliceList::nextAvailableSliceId(
01851     const std::map<int, std::vector<CandStripHandle *> > & event_slices) const
01852 {
01853   std::map<int, std::vector<CandStripHandle *> >::const_iterator slice_iter;
01854 
01855   slice_iter = --( event_slices.end() );
01856 
01857   return ( 1 + (int) (*slice_iter).first );
01858 }
01859 //____________________________________________________________________________
01860 void AltAlgSliceList::initSliceFiltering(
01861           std::map<int, std::vector<CandStripHandle *> > & event_slices) const
01862 {
01863 
01864   MSG("AltAlg", Msg::kDebug)
01865      << "[-] Dissolving 'mini'-slices & creating an orphan strip list" << endl;
01866 
01867   std::vector<CandStripHandle *> orphan_strips_list
01868                                             = dissolveMiniSlices(event_slices);
01869 
01870   if(orphan_strips_list.size() > 0) {
01871 
01872      giveOrphanStripsForAdoption(orphan_strips_list, event_slices);
01873      sortSlicesInTime(event_slices);
01874   }
01875 }
01876 //____________________________________________________________________________
01877 std::vector<CandStripHandle *> AltAlgSliceList::dissolveMiniSlices(
01878           std::map<int, std::vector<CandStripHandle *> > & event_slices) const
01879 {
01880 // Removes bad slices from the slices-map and creates a list of orphan
01881 // strips to be appended in nearby slices.
01882 //
01883   MSG("AltAlg", Msg::kDebug)
01884                  << " |-->[-] Trying to eliminate some 'fake' slices" << endl;
01885 
01886   MSG("AltAlg", Msg::kDebug)
01887             << "      |---> Current number of slices: " << event_slices.size()
01888             << endl;
01889 
01890   std::vector<int>* slices_to_delete = findSlicesToBeEliminated(event_slices);
01891 
01892   MSG("AltAlg", Msg::kVerbose)
01893          << "      |---[-] Eliminate slices & copy strips to list of orphans"
01894          << endl;
01895 
01896   std::vector<CandStripHandle *> orphan_strips;
01897   std::vector<CandStripHandle *>::iterator strip_iter;
01898 
01899   std::vector<int>::iterator slice_id;
01900 
01901   for(slice_id = slices_to_delete->begin();
01902                            slice_id != slices_to_delete->end(); ++slice_id) {
01903 
01904       for(strip_iter = event_slices[*slice_id].begin();
01905               strip_iter != event_slices[*slice_id].end(); ++strip_iter)
01906                                       orphan_strips.push_back( *strip_iter );
01907 
01908        event_slices.erase( *slice_id );
01909 
01910        MSG("AltAlg", Msg::kVerbose)
01911                  << "           |--> Deleted slice : " << *slice_id  << endl;
01912   }
01913 
01914   MSG("AltAlg", Msg::kDebug)
01915         << "      |---> Number of slices *after* eliminating the fake ones: "
01916         << event_slices.size() << endl;
01917 
01918   delete slices_to_delete;
01919 
01920   return orphan_strips;
01921 }
01922 //____________________________________________________________________________
01923 std::vector<int> * AltAlgSliceList::findSlicesToBeEliminated(
01924     const std::map<int, std::vector<CandStripHandle *> > & event_slices) const
01925 {
01926   std::vector<int> * slices_to_delete = new std::vector<int>;
01927 
01928   std::map<int, std::vector<CandStripHandle *> >::const_iterator slice_iter;
01929 
01930   for(slice_iter = event_slices.begin();
01931                             slice_iter != event_slices.end(); ++slice_iter) {
01932 
01933      MSG("AltAlg", Msg::kVerbose)
01934          << "      |---[-] Checking slice: " << (*slice_iter).first  << endl;
01935 
01936      if( sliceShouldBeEliminated(slice_iter) )
01937                            slices_to_delete->push_back( (*slice_iter).first );
01938   }
01939 
01940   return slices_to_delete; // the calling function should delete this
01941 }
01942 //____________________________________________________________________________
01943 bool AltAlgSliceList::sliceShouldBeEliminated(
01944    std::map<int, std::vector<CandStripHandle *> >::const_iterator slice) const
01945 {
01946   bool should_be_eliminated = false;
01947 
01948   //**** apply the list of criteria for slice-elimination
01949 
01950   std::vector<bool> check_list;
01951   std::vector<bool>::iterator check;
01952 
01953   check_list.push_back( smallNumberOfHitStrips (slice)  );
01954   check_list.push_back( smallAmountOfCharge    (slice)  );
01955   check_list.push_back( noStripsInOneView      (slice)  );
01956 
01957   for(check = check_list.begin(); check != check_list.end(); ++check)
01958                       should_be_eliminated = should_be_eliminated || (*check);
01959 
01960   return should_be_eliminated;
01961 }
01962 //____________________________________________________________________________
01963 bool AltAlgSliceList::smallNumberOfHitStrips(
01964    std::map<int, std::vector<CandStripHandle *> >::const_iterator slice) const
01965 {
01966 // check for small number of hit strips in the slice
01967 //
01968   if( (int) (*slice).second.size() < fMinNoHitStrips  )  {
01969 
01970      MSG("AltAlg", Msg::kVerbose)
01971            << "           |--> Slice: " << (*slice).first
01972            << " will be eliminated --> too few hit strips: "
01973            << (*slice).second.size() << " < (MinStrips=) " << fMinNoHitStrips
01974            << endl;
01975 
01976   } else return false;
01977 
01978   return true;
01979 }
01980 //____________________________________________________________________________
01981 bool AltAlgSliceList::smallAmountOfCharge(
01982    std::map<int, std::vector<CandStripHandle *> >::const_iterator slice) const
01983 {
01984 // check for small amount of charge in the slice
01985 //
01986 
01987 // double totalCharge = 0;
01988 // for(std::vector<CandStripHandle *>::iterator strip_iter =
01989 //   (*iter).second.begin();strip_iter != (*iter).second.end(); ++strip_iter)
01990 //                       totalCharge += ( (*strip_iter)->GetCharge() );
01991 
01992   double totalCharge = accumulate( (*slice).second.begin(),
01993                                    (*slice).second.end(),  0.0, sum_q());
01994 
01995   if( totalCharge < fMinCharge )  {
01996 
01997       MSG("AltAlg", Msg::kVerbose)
01998             << "           |--> Slice: " << (*slice).first
01999             << " will be eliminated --> too small charge: "
02000             << totalCharge << " < (MinCharge=) " << fMinCharge << endl;
02001 
02002   } else return false;
02003 
02004   return true;
02005 }
02006 //____________________________________________________________________________
02007 bool AltAlgSliceList::noStripsInOneView(
02008    std::map<int, std::vector<CandStripHandle *> >::const_iterator slice) const
02009 {
02010 // check for strips in both views in the slice
02011 //
02012   int nv = count_if(
02013                  (*slice).second.begin(), (*slice).second.end(), is_v_view());
02014   int nu = count_if(
02015                  (*slice).second.begin(), (*slice).second.end(), is_u_view());
02016 
02017   if(nv == 0 || nu == 0) {
02018 
02019       MSG("AltAlg", Msg::kVerbose)
02020            << "           |--> Slice: " << (*slice).first
02021            << " will be eliminated --> 0 strips in one view: "
02022            << "  > N(U) = " << nu << " -- N(V) = " << nv << endl;
02023 
02024   } else return false;
02025 
02026   return true;
02027 }
02028 //____________________________________________________________________________
02029 void AltAlgSliceList::giveOrphanStripsForAdoption(
02030                                  std::vector<CandStripHandle *> orphan_strips,
02031           std::map<int, std::vector<CandStripHandle *> > & event_slices) const
02032 {
02033 // Appends the CandStripHandles found in the orphan_strips STL vector
02034 // to the reco. slice with the minimum distance in the z-time-tpos
02035 // 3-D space...
02036 //
02037   //-- assume that centroids do not change too much by the addition
02038   //   of few orhan strips, so compute them just once...
02039 
02040   MSG("AltAlg", Msg::kVerbose)
02041           << " |-->[-] Appending orphan strips to closest reco slice" << endl;
02042 
02043   std::vector<CandStripHandle *>::iterator strip_iter;
02044   for(strip_iter = orphan_strips.begin();
02045                            strip_iter != orphan_strips.end(); ++strip_iter) {
02046 
02047      MSG("AltAlg", Msg::kVerbose)
02048        << "      |--[-] Looking a home for orphan strip "
02049        << (*strip_iter)->GetUidInt()
02050        << " (pl = "  << fFmtPln(  (*strip_iter)->GetPlane() )
02051        << ", str = " << fFmtStp(  (*strip_iter)->GetStrip() )
02052        << ", t = "   << fFmtTime( (*strip_iter)->GetCorrBegTime() )
02053        << ")" << endl;
02054 
02055      int islice = findBestSliceToAdoptAStrip(
02056                        fOrphanStripsQWeight, fOrphanStripsPlaneWindow,
02057                        fOrphanStripsTimeWindow, *strip_iter, &event_slices );
02058 
02059      event_slices[islice].push_back( *strip_iter );
02060 
02061      MSG("AltAlg", Msg::kVerbose)
02062                      << "          |--> Adopted by slice "  << islice << endl;
02063   } // loop over orphan strips
02064 }
02065 //____________________________________________________________________________
02066 int AltAlgSliceList::findBestSliceToAdoptAStrip(
02067             bool qweight, int dpln, double dt, CandStripHandle * orphan_strip,
02068           std::map<int, std::vector<CandStripHandle *> > * event_slices) const
02069 {
02070 // Finds the best slice (amongst the already existing ones) to adopt the input
02071 // strip from the list of orphan ones.
02072 // The best slice is the one which has the biggest number of hit strips (or
02073 // the biggest amount of charge, if qweight is turned on) inside a temporal
02074 // and spatial window centered in the orphan strip.
02075 // If none is found, the method relaxes the criteria (by increasing the window
02076 // size) and calls itself again.
02077 //
02078   int    best_slice = -1;
02079   double nq_max = 0, nq;
02080 
02081   std::map<int, std::vector<CandStripHandle *> >::iterator slice_iter;
02082 
02083   for(slice_iter = event_slices->begin();
02084                            slice_iter != event_slices->end(); ++slice_iter) {
02085 
02086       //-- no weighting by charge - just count number of hit strips
02087       if(qweight == 0)
02088         nq = (double) count_if(
02089              (*slice_iter).second.begin(), (*slice_iter).second.end(),
02090                                     is_in_tz_window(orphan_strip, dt, dpln) );
02091       //-- weighting by charge
02092       else {
02093 
02094         std::vector<CandStripHandle *>::iterator part_iter = partition(
02095            (*slice_iter).second.begin(), (*slice_iter).second.end(),
02096                                     is_in_tz_window(orphan_strip, dt, dpln) );
02097         nq = accumulate(
02098                        (*slice_iter).second.begin(), part_iter, 0.0, sum_q());
02099       }
02100 
02101       if(nq > nq_max) { nq_max = nq; best_slice = (*slice_iter).first; }
02102 
02103       //MSG("AltAlg", Msg::kVerbose) << "SLICE " << (*slice_iter).first
02104       //   << " ---> nq = " << nq << endl;
02105   }// slice_iter
02106 
02107   // No slice was found - increase the window size and try again...
02108   // Obviously, this can go many levels deep... If, in the next call, none is
02109   // found as well, it will relax the criteria some more and call itself again
02110   // and then possibly again... until the 'best' slice is found...
02111   // In this case the 'best' might not be good enough, but for now all we
02112   // want is to assign all orphan strips to the best available reco slice and
02113   // we will check later if they have substructure and need to be further
02114   // sliced...
02115 
02116   if(best_slice == -1) {
02117      MSG("AltAlg", Msg::kVerbose)
02118        << "          |--> No slice was found to adopt strip - relaxing limits"
02119        << " (dpln < " << fFmtPln(  min(2*dpln, 80) )
02120        << " - dt << " << fFmtTime( 2*dt   ) << ") & re-trying" << endl;
02121 
02122      return findBestSliceToAdoptAStrip(
02123                   qweight, min(2*dpln, 80), 2*dt, orphan_strip, event_slices);
02124   }
02125   return best_slice;
02126 }
02127 //____________________________________________________________________________
02128 void AltAlgSliceList::sliceMerger(
02129           std::map<int, std::vector<CandStripHandle *> > & event_slices) const
02130 {
02131 // Sometimes it might be possible that a real event is split between 2 or more
02132 // reconstructed slices...
02133 // So, if slices are very close in time and span successive (or overlapping)
02134 // areas of the detector, just merge them.
02135 //
02136   MSG("AltAlg", Msg::kVerbose)
02137                           << "[-] Trying to spot slices to be merged" << endl;
02138 
02139   pair<int, int> slices_to_merge;
02140 
02141   while( (slices_to_merge = findSlicesToMerge(event_slices)).first != -1 )
02142                                          Merge(slices_to_merge, event_slices);
02143 }
02144 //____________________________________________________________________________
02145 std::pair<int, int> AltAlgSliceList::findSlicesToMerge(
02146           std::map<int, std::vector<CandStripHandle *> > & event_slices) const
02147 {
02148 // Returns the first pair of slices that should be merged...
02149 //
02150   std::map<int, std::vector<CandStripHandle *> >::iterator slice_iter_0;
02151   std::map<int, std::vector<CandStripHandle *> >::iterator slice_iter_1;
02152 
02153   pair<int, int> slices_to_merge(-1,-1);
02154 
02155   // The following 2-ble loop, loops over all *different* slice-pairs once.
02156   // Each pair will be checked against the 'merging' criteria.
02157 
02158   for(slice_iter_0 = event_slices.begin();
02159                         slice_iter_0 != event_slices.end(); ++slice_iter_0) {
02160 
02161       for( ++(slice_iter_1 = slice_iter_0);
02162                         slice_iter_1 != event_slices.end(); ++slice_iter_1) {
02163 
02164           MSG("AltAlg", Msg::kVerbose) << " |--[-] examining slices "
02165                          << fFmtSlc( (*slice_iter_0).first ) << " and "
02166                          << fFmtSlc( (*slice_iter_1).first ) << endl;
02167 
02168            bool should_be_merged = checkIfSlicesShouldBeMerged(
02169                          (*slice_iter_0).second, (*slice_iter_1).second );
02170 
02171            if(should_be_merged) {
02172                 slices_to_merge.first  = (*slice_iter_0).first;
02173                 slices_to_merge.second = (*slice_iter_1).first;
02174 
02175                 // return this pair *now*. If two slices are merged, then
02176                 // previous checks are potentially invalidated.
02177                 // So merge the slices & then start checking from scratch.
02178                 return slices_to_merge;
02179            }
02180 
02181       } // slice_iter_1
02182   } // slice_iter_0
02183 
02184   MSG("AltAlg", Msg::kVerbose)
02185                  << "* Finished trying to spot clusters to be merged" << endl;
02186 
02187   return slices_to_merge;
02188 }
02189 //____________________________________________________________________________
02190 bool AltAlgSliceList::checkIfSlicesShouldBeMerged(
02191                                std::vector<CandStripHandle *> & slice_0,
02192                                std::vector<CandStripHandle *> & slice_1) const
02193 {
02194 // Applies all the slice merging criteria...
02195 
02196   std::vector<bool> check_list;
02197   std::vector<bool>::iterator check;
02198 
02199   check_list.push_back( checkSliceDistanceInTimeAndSpace( slice_0, slice_1 ) );
02200   // --- push_back() more checks later...
02201   //
02202 
02203   bool merge_them = true;
02204             for(check = check_list.begin();
02205                   check != check_list.end(); ++check)
02206                                          merge_them = merge_them && (*check);
02207   return merge_them;
02208 }
02209 //____________________________________________________________________________
02210 bool AltAlgSliceList::checkSliceDistanceInTimeAndZ(
02211                                std::vector<CandStripHandle *> & slice_0,
02212                                std::vector<CandStripHandle *> & slice_1) const
02213 {
02214 // A simple test to check whether two slices should be merged on the basis of
02215 // small time & z difference
02216 
02217   // check the time difference between the pulse height peaks
02218   if( checkPeakTimeDifference(slice_0, slice_1) ) {
02219 
02220     // check the z-difference between the pulse height peaks
02221     if( checkPeakZDifference(slice_0, slice_1) ) {
02222 
02223         // check the z-diff. between the latest hits of the earliest slice
02224         // and the earliest hits of the latest slice....
02225         if( checkLeadingTrailingEdgeDistance(slice_0, slice_1) ) {
02226 
02227             MSG("AltAlg", Msg::kVerbose)
02228                               << "     |--[*] Slices will be merged" << endl;
02229             return true;
02230         }
02231     }
02232   }
02233   return false;
02234 }
02235 //____________________________________________________________________________
02236 bool AltAlgSliceList::checkSliceDistanceInTimeAndSpace(
02237                                std::vector<CandStripHandle *> & slice_0,
02238                                std::vector<CandStripHandle *> & slice_1) const
02239 {
02240 // A simple test to check whether two slices should be merged on the basis of
02241 // small time & z,u,v difference
02242 
02243   // check the time difference between the pulse height peaks
02244   if( checkPeakTimeDifference(slice_0, slice_1) ) {
02245 
02246     // check the z-difference between the pulse height peaks
02247     if( checkPeakZDifference(slice_0, slice_1) ) {
02248 
02249         // check the z-diff. between the latest hits of the earliest slice
02250         // and the earliest hits of the latest slice....
02251         if( checkLeadingTrailingEdgeDistance(slice_0, slice_1) ) {
02252 
02253             // check uv difference
02254             if( checkPeakUVDifference(slice_0, slice_1) ) {
02255                   MSG("AltAlg", Msg::kVerbose)
02256                               << "     |--[*] Slices will be merged" << endl;
02257                   return true;
02258             }
02259         }
02260     }
02261   }
02262   return false;
02263 }
02264 //____________________________________________________________________________
02265 bool AltAlgSliceList::checkPeakTimeDifference(
02266                          const std::vector<CandStripHandle *> & slice_0,
02267                          const std::vector<CandStripHandle *> & slice_1) const
02268 {
02269 // Checks the difference between the charge weighted average times of the two
02270 // input slices.
02271 // Returns true if dt < fTimeDiffBetweenPeaks
02272 
02273   double q0  = accumulate(slice_0.begin(), slice_0.end(), 0.0, sum_q());
02274   double qt0 = accumulate(slice_0.begin(), slice_0.end(), 0.0, sum_qtime());
02275 
02276   double q1  = accumulate(slice_1.begin(), slice_1.end(), 0.0, sum_q());
02277   double qt1 = accumulate(slice_1.begin(), slice_1.end(), 0.0, sum_qtime());
02278 
02279   //remove this eventually
02280   if(q0 == 0 || q1 == 0) {
02281     MSG("AltAlg", Msg::kWarning) << "Zero charge in one view" << endl;
02282     return false;
02283   }
02284 
02285   assert(q0 > 0); // slices that are striped out of their strips should
02286   assert(q1 > 0); // be removed from the slice map
02287 
02288   double t0 = qt0 / q0;
02289   double t1 = qt1 / q1;
02290 
02291   MSG("AltAlg", Msg::kVerbose)
02292             << "     |--> peak time difference = " << fFmtTime(t0-t1) << endl;
02293 
02294   return ( fabs(t0-t1) < fTimeDiffBetweenPeaks );
02295 }
02296 //____________________________________________________________________________
02297 bool AltAlgSliceList::checkPeakZDifference(
02298                          const std::vector<CandStripHandle *> & slice_0,
02299                          const std::vector<CandStripHandle *> & slice_1) const
02300 {
02301 // Checks the difference between the charged-weighted longitudinal position
02302 // of the input slices.
02303 // Returns true if dz < fZDiffBetweenPeaks
02304 
02305   double q0  = accumulate(slice_0.begin(), slice_0.end(), 0.0, sum_q());
02306   double qz0 = accumulate(slice_0.begin(), slice_0.end(), 0.0, sum_qz());
02307 
02308   double q1  = accumulate(slice_1.begin(), slice_1.end(), 0.0, sum_q());
02309   double qz1 = accumulate(slice_1.begin(), slice_1.end(), 0.0, sum_qz());
02310 
02311   //remove this eventually
02312   if(q0 == 0 || q1 == 0) {
02313     MSG("AltAlg", Msg::kWarning) << "Zero charge in one view" << endl;
02314     return false;
02315   }
02316 
02317   assert(q0 > 0); // slices that are striped out of their strips should
02318   assert(q1 > 0); // be removed from the slice map
02319 
02320   double z0 = qz0 / q0;
02321   double z1 = qz1 / q1;
02322 
02323   MSG("AltAlg", Msg::kVerbose) << "     |--> d<z> = " << z0-z1 << endl;
02324 
02325   return ( fabs(z0-z1) < fZDiffBetweenPeaks );
02326 }
02327 //____________________________________________________________________________
02328 bool AltAlgSliceList::checkPeakUVDifference(
02329                          const std::vector<CandStripHandle *> & slice_0,
02330                          const std::vector<CandStripHandle *> & slice_1) const
02331 {
02332 // Checks the difference between the charged-weighted transverse position
02333 // of the input slices.
02334 // Returns true if du < fUVDiffBetweenPeaks && dv < fUVDiffBetweenPeaks
02335 
02336   //-- u-v partition
02337   std::vector<CandStripHandle *> slice_0_cp( slice_0.size() );
02338   std::vector<CandStripHandle *> slice_1_cp( slice_1.size() );
02339 
02340   copy( slice_0.begin(), slice_0.end(), slice_0_cp.begin() );
02341   copy( slice_1.begin(), slice_1.end(), slice_1_cp.begin() );
02342 
02343   std::vector<CandStripHandle *>::iterator part_iter_0 = partition(
02344                         slice_0_cp.begin(), slice_0_cp.end(), is_v_view() );
02345   std::vector<CandStripHandle *>::iterator part_iter_1 = partition(
02346                         slice_1_cp.begin(), slice_1_cp.end(), is_v_view() );
02347 
02348   // slice 0
02349   double q_v_0 = accumulate(slice_0_cp.begin(), part_iter_0, 0.0, sum_q());
02350   double qtpos_v_0 = accumulate(
02351                         slice_0_cp.begin(), part_iter_0, 0.0, sum_qtpos());
02352 
02353   double q_u_0 = accumulate(part_iter_0, slice_0_cp.end(),   0.0, sum_q());
02354   double qtpos_u_0 = accumulate(
02355                         part_iter_0, slice_0_cp.end(),   0.0, sum_qtpos());
02356 
02357   // slice 1
02358   double q_v_1 = accumulate(slice_1_cp.begin(), part_iter_1, 0.0, sum_q());
02359   double qtpos_v_1 = accumulate(
02360                         slice_1_cp.begin(), part_iter_1, 0.0, sum_qtpos());
02361 
02362   double q_u_1 = accumulate(part_iter_1, slice_1_cp.end(),   0.0, sum_q());
02363   double qtpos_u_1 = accumulate(
02364                         part_iter_1, slice_1_cp.end(),   0.0, sum_qtpos());
02365 
02366   // remove this eventually
02367   if(q_v_0 == 0 || q_u_0 == 0 || q_v_1 == 0 || q_u_1 == 0) {
02368     MSG("AltAlg", Msg::kWarning) << "Zero charge in one view" << endl;
02369     return false;
02370   }
02371   assert(q_v_0 > 0); // slices that are striped out of their strips should
02372   assert(q_u_0 > 0); // be removed from the slice map
02373   assert(q_v_1 > 0);
02374   assert(q_u_1 > 0);
02375 
02376   double u0 = qtpos_u_0 / q_u_0;
02377   double v0 = qtpos_v_0 / q_v_0;
02378   double u1 = qtpos_u_1 / q_u_1;
02379   double v1 = qtpos_v_1 / q_v_1;
02380 
02381   MSG("AltAlg", Msg::kVerbose)
02382          << "     |--> d<u> = " << u0-u1 << " and d<v> = " << v0 - v1 << endl;
02383 
02384   return ( fabs(v0-v1) < fUVDiffBetweenPeaks &&
02385                                           fabs(u0-u1) < fUVDiffBetweenPeaks );
02386 }
02387 //____________________________________________________________________________
02388 bool AltAlgSliceList::checkLeadingTrailingEdgeDistance(
02389                                std::vector<CandStripHandle *> & slice_0,
02390                                std::vector<CandStripHandle *> & slice_1) const
02391 {
02392 // Checks the longitudinal (z) distance between the leading edge of the latest
02393 // slice and the trailing edge of the earliest one...
02394 // Returns true if the distance is smaller than fZDiffBetweenEnds
02395 // This is hoped to prevent slice breaking when use in conjunction with
02396 // temporal cuts.
02397 //
02398   double q0  = accumulate(slice_0.begin(), slice_0.end(), 0.0, sum_q());
02399   double qt0 = accumulate(slice_0.begin(), slice_0.end(), 0.0, sum_qtime());
02400 
02401   double q1  = accumulate(slice_1.begin(), slice_1.end(), 0.0, sum_q());
02402   double qt1 = accumulate(slice_1.begin(), slice_1.end(), 0.0, sum_qtime());
02403 
02404   // remove this eventually
02405   if(q0 == 0 || q1 == 0) {
02406     MSG("AltAlg", Msg::kWarning) << "Zero charge in one view" << endl;
02407     return false;
02408   }
02409 
02410   assert(q0 > 0); // slices that are striped out of their strips should
02411   assert(q1 > 0); // be removed from the slice map
02412 
02413   double t0 = qt0 / q0;
02414   double t1 = qt1 / q1;
02415 
02416   double z_earliest, z_latest;
02417 
02418   if(t0 < t1) {
02419       z_earliest = averageSliceZ( slice_0, t0, maxSliceTime(slice_0) );
02420       z_latest   = averageSliceZ( slice_1, minSliceTime(slice_1), t1 );
02421   } else {
02422       z_earliest = averageSliceZ( slice_1, t1, maxSliceTime(slice_1) );
02423       z_latest   = averageSliceZ( slice_0, minSliceTime(slice_0), t0 );
02424   }
02425 
02426   MSG("AltAlg", Msg::kVerbose)
02427      << "     |--> leading - trailing edge z difference = "
02428                                              << z_earliest - z_latest << endl;
02429 
02430   if(fabs(z_earliest-z_latest) < fZDiffBetweenEnds)  return true;
02431   else return false;
02432 }
02433 //____________________________________________________________________________
02434 double AltAlgSliceList::averageSliceZ(
02435        std::vector<CandStripHandle *> & slice, double tmin, double tmax) const
02436 {
02437 // Computes a (charge weighted) average longitudinal position of the input
02438 // strips for which time e [tmin, tmax]
02439 //
02440   std::vector<CandStripHandle *>::iterator strip_iter = partition(
02441                 slice.begin(), slice.end(), is_in_t_window_noref(tmin, tmax));
02442 
02443   double q  = accumulate(slice.begin(), strip_iter, 0.0, sum_q() );
02444   double qz = accumulate(slice.begin(), strip_iter, 0.0, sum_qz());
02445 
02446   // remove this eventually
02447   if(q==0) {
02448     MSG("AltAlg", Msg::kWarning) << "Zero charge in one view" << endl;
02449     return -999;
02450   }
02451 
02452   assert(q>0);
02453 
02454   return qz/q;
02455 }
02456 //____________________________________________________________________________
02457 double AltAlgSliceList::minSliceTime(
02458                                  std::vector<CandStripHandle *> & slice) const
02459 {
02460 // Returns the earliest strip time in the input vector of strips
02461 
02462   sort(slice.begin(), slice.end(), min_t());
02463 
02464   std::vector<CandStripHandle *>::iterator strip_iter = slice.begin();
02465 
02466   return (*strip_iter)->GetCorrBegTime();
02467 }
02468 //____________________________________________________________________________
02469 double AltAlgSliceList::maxSliceTime(
02470                                  std::vector<CandStripHandle *> & slice) const
02471 {
02472 // Returns the latest strip time in the input vector of strips
02473 
02474   sort(slice.begin(), slice.end(), min_t());
02475 
02476   std::vector<CandStripHandle *>::iterator strip_iter = --(slice.end());
02477 
02478   return (*strip_iter)->GetCorrBegTime();
02479 }
02480 //____________________________________________________________________________
02481 void AltAlgSliceList::eventClustering(
02482                 std::map<int, std::vector<CandStripHandle *> > & event_slices)
02483 {
02484 // Main method for k-Means - based 3-D event clustering. Initiates single
02485 // k-Means clustering method steps until the algorithm has converged.
02486 //
02487   MSG("AltAlg", Msg::kDebug)
02488           << "[-] Applying 3-D (c*time, tpos, z) k-Means clustering"  << endl;
02489 
02490   bool converged   = false;
02491   fkMeansIteration = 0;
02492 
02493   while(!converged) {
02494 
02495       MSG("AltAlg", Msg::kDebug)
02496                    << " |--[-] k-Means clustering has not converged yet - "
02497                    << "next iteration:" << endl;
02498 
02499       converged = singleKMeansIteration(event_slices);
02500   }
02501 
02502   // refilter to catch/remove any slice that has become too 'thin'...
02503   initSliceFiltering(event_slices);
02504 }
02505 //____________________________________________________________________________
02506 bool AltAlgSliceList::singleKMeansIteration(
02507                 std::map<int, std::vector<CandStripHandle *> > & event_slices)
02508 {
02509 // Performs a single iteration of a K-Means clustering algorithm on the
02510 // std::map<int, std::vector<CandStripHandle *> > of reco. slices
02511 // Clustering is performed in time-z-tpos 3D space and strips are
02512 // re-arranged between existing slices as appropriate.
02513 // Returns "true" if the algorithm has converged.
02514 //
02515   bool is_convergent = true;
02516 
02517   // The outer loop can go on for ever if for some reason something goes wrong.
02518   // Plan your escape route, if such an ill case appears... Force convergence:
02519   if( ++fkMeansIteration > 30 ) return true;
02520 
02521   fUpdateCentroids = true; // make known that centroids are not updated
02522 
02523   std::map<int, Centroid_t>  centroids;
02524 
02525   std::map<int, std::vector<CandStripHandle *> >::iterator slice_iter;
02526   for(slice_iter = event_slices.begin();
02527                             slice_iter != event_slices.end(); ++slice_iter) {
02528 
02529      int source = slice_iter->first; // source slice for following strips
02530 
02531      // check if all strips feel like home in this slice...
02532      for(std::vector<CandStripHandle *>::size_type istrip = 0;
02533                               istrip < slice_iter->second.size(); istrip++) {
02534 
02535          CandStripHandle * current_strip = slice_iter->second[istrip];
02536 
02537          pair<int, CandStripHandle *> slc_strip(source, current_strip);
02538 
02539          // try to update centroids - if it fails because it has to re-filter
02540          // the slices, filter them and 'admit' you have not converged yet...
02541 
02542          if ( !updateCentroids(centroids, event_slices) ) return false;
02543 
02544          // find out which is the best slice, amongst the existing ones
02545          // to host this strip...
02546 
02547          int target = findBestSliceToHostStrip(
02548                                          slc_strip, centroids, event_slices);
02549 
02550          if( source != target ) {
02551             //-- k-Means clustering is not convergent yet...
02552             is_convergent = false;
02553 
02554             //-- we rellocate a strip - recompute centroids if needed again
02555             fUpdateCentroids = true;
02556 
02557             //-- rellocate strip
02558             rellocateStrip(source, target, current_strip, event_slices);
02559          }
02560 
02561      } // strips
02562   } // slice_iter
02563 
02564   return is_convergent;
02565 }
02566 //____________________________________________________________________________
02567 bool AltAlgSliceList::needToFilterStrips(
02568     const std::map<int, std::vector<CandStripHandle *> > & event_slices) const
02569 {
02570 // Somethimes it is possible that strip exchanges during the 3-D clustering
02571 // will (almost or completely) strip out a slice from strips.
02572 // In this case, computing slice centroids will fail because Sum{Q}=0 in
02573 // at least one of the views.
02574 // If this is happening then these small slices have to be filtered out.
02575 // In this method I check if this is necessary at *this* point...
02576 
02577   std::map<int, std::vector<CandStripHandle *> >::const_iterator slice_iter;
02578 
02579   for(slice_iter = event_slices.begin();
02580                             slice_iter != event_slices.end(); ++slice_iter) {
02581 
02582       std::vector<CandStripHandle *> slice_strips = slice_iter->second;
02583 
02584       if( ZeroChargeInAView(slice_strips) ) {
02585 
02586         MSG("AltAlg", Msg::kVerbose)
02587            << " |--[-] Oops! At least one of slices was striped out during"
02588            << " strip exchanges -- run the filter to clear them out" << endl;
02589 
02590         return true;
02591       }
02592   }//slices
02593 
02594   return false;
02595 }
02596 //____________________________________________________________________________
02597 bool AltAlgSliceList::ZeroChargeInAView(
02598                            const std::vector<CandStripHandle *> & slice) const
02599 {
02600   //-- u-v partition
02601   std::vector<CandStripHandle *> slice_cp( slice.size() );
02602 
02603   copy( slice.begin(), slice.end(), slice_cp.begin() );
02604 
02605   std::vector<CandStripHandle *>::iterator part_iter = partition(
02606                              slice_cp.begin(), slice_cp.end(), is_v_view() );
02607 
02608   //-- accumulate
02609   double sum_q_v = accumulate(slice_cp.begin(), part_iter, 0.0, sum_q());
02610   double sum_q_u = accumulate(part_iter, slice_cp.end(),   0.0, sum_q());
02611 
02612   //--check
02613   if(sum_q_v <= 0 || sum_q_u <= 0) return true;
02614 
02615   return false;
02616 }
02617 //____________________________________________________________________________
02618 bool AltAlgSliceList::updateCentroids(
02619                                         std::map<int, Centroid_t> & centroids,
02620                 std::map<int, std::vector<CandStripHandle *> > & event_slices)
02621 {
02622 // Try to update centroids... if its needed... and if you can...
02623 // Returns false if it had to re-filter the slices.
02624 
02625   if(fUpdateCentroids) {
02626 
02627      if(needToFilterStrips(event_slices)) {
02628         initSliceFiltering(event_slices);
02629         return false;
02630      } else {
02631         centroids = computeSlicesCentroid(event_slices);
02632         fUpdateCentroids = false;
02633      }
02634   }
02635   return true;
02636 }
02637 //____________________________________________________________________________
02638 std::map<int, Centroid_t> AltAlgSliceList::computeSlicesCentroid(
02639     const std::map<int, std::vector<CandStripHandle *> > & event_slices) const
02640 {
02641 // Method for computing the centroids of the input reconstructed slices.
02642 //
02643   std::map<int, Centroid_t> clusters_centroid;
02644 
02645   std::map<int, std::vector<CandStripHandle *> >::const_iterator slice_iter;
02646 
02647   for(slice_iter = event_slices.begin();
02648                             slice_iter != event_slices.end(); ++slice_iter) {
02649 
02650       std::vector<CandStripHandle *> slice_strips = slice_iter->second;
02651 
02652       Centroid_t centroid = computeSliceCentroid(slice_strips);
02653 
02654       clusters_centroid.insert(
02655             std::map<int, Centroid_t>::value_type(
02656                                               slice_iter->first, centroid) );
02657   }
02658 
02659   return clusters_centroid;
02660 }
02661 //____________________________________________________________________________
02662 Centroid_t AltAlgSliceList::computeSliceCentroid(
02663                            const std::vector<CandStripHandle *> & slice) const
02664 {
02665 // Method for computing the centroids of the input reconstructed slice.
02666 //
02667   Centroid_t centroid;
02668 
02669   //-- u-v partition
02670   std::vector<CandStripHandle *> slice_cp( slice.size() );
02671 
02672   copy( slice.begin(), slice.end(), slice_cp.begin() );
02673 
02674   std::vector<CandStripHandle *>::iterator part_iter = partition(
02675                              slice_cp.begin(), slice_cp.end(), is_v_view() );
02676 
02677   //-- accumulate
02678   double sum_q_v = accumulate(
02679                           slice_cp.begin(), part_iter, 0.0, sum_q());
02680   double sum_qtpos_v = accumulate(
02681                       slice_cp.begin(), part_iter, 0.0, sum_qtpos());
02682   double sum_qz_v = accumulate(
02683                          slice_cp.begin(), part_iter, 0.0, sum_qz());
02684   double sum_qtime_v = accumulate(
02685                       slice_cp.begin(), part_iter, 0.0, sum_qtime());
02686 
02687   double sum_q_u = accumulate(
02688                           part_iter, slice_cp.end(),   0.0, sum_q());
02689   double sum_qtpos_u = accumulate(
02690                       part_iter, slice_cp.end(),   0.0, sum_qtpos());
02691   double sum_qz_u = accumulate(
02692                          part_iter, slice_cp.end(),   0.0, sum_qz());
02693   double sum_qtime_u = accumulate(
02694                       part_iter, slice_cp.end(),   0.0, sum_qtime());
02695 
02696   assert(sum_q_u > 0);
02697   assert(sum_q_v > 0);
02698 
02699   centroid.u  = sum_qtpos_u    / sum_q_u;
02700   centroid.v  = sum_qtpos_v    / sum_q_v;
02701   centroid.zu = sum_qz_u       / sum_q_u;
02702   centroid.zv = sum_qz_v       / sum_q_v;
02703   centroid.tu = sum_qtime_u    / sum_q_u;
02704   centroid.tv = sum_qtime_v    / sum_q_v;
02705 
02706   return centroid;
02707 }
02708 //____________________________________________________________________________
02709 int AltAlgSliceList::findBestSliceToHostStrip(
02710                          const pair<int, CandStripHandle *> & slc_strip,
02711                             const std::map<int, Centroid_t> & centroids,
02712     const std::map<int, std::vector<CandStripHandle *> > & event_slices) const
02713 {
02714 // Find which of the existing reconstructed slices is the best one for hosting
02715 // the input strip.
02716 
02717   int target=0;
02718 
02719   std::vector<int> alt_slices = checkForAlternativeSlices(
02720                                                      slc_strip, event_slices);
02721 
02722   WhichCandSlice_t which_slice = characterizeCandidateSlices(
02723                                                  slc_strip.first, alt_slices);
02724   MSG("AltAlg", Msg::kVerbose)
02725                << "     |--[-] slice = " << fFmtSlc(slc_strip.first) << " -->"
02726                << " plane = "  << fFmtPln( slc_strip.second->GetPlane() )
02727                << ", strip = " << fFmtStp( slc_strip.second->GetStrip() )
02728                << " : " << asString(which_slice) << endl;
02729 
02730   switch( which_slice ) {
02731      case (eNone):
02732            // There is no really good slice candidate... This happens
02733            // with fairly isolated hit strips... Not much you can do
02734            // here & at this stage. Assign the strip to the cluster
02735            // with the closest centroid...
02736            target = getClosestCentroid(slc_strip.second, centroids);
02737            break;
02738      case (eSame):
02739            // There is a single slice candidate and it is the same
02740            // with the one that already owns the strip. No rellocation.
02741            target = slc_strip.first;
02742            break;
02743      case (eOther):
02744            // There is a single candidate that is different from the
02745            // one that already owns the strip. Mark for rellocation.
02746            target = alt_slices[0];
02747            break;
02748      case (eMany):
02749            target = selectBestCandidateSlice(
02750                                          slc_strip, alt_slices, event_slices);
02751      break;
02752   }
02753 
02754   return target;
02755 }
02756 //____________________________________________________________________________
02757 std::vector<int> AltAlgSliceList::checkForAlternativeSlices(
02758                          const pair<int, CandStripHandle *> & slc_strip,
02759     const std::map<int, std::vector<CandStripHandle *> > & event_slices) const
02760 {
02761 // Make a list with all slices that could possibly host the input strip
02762 
02763   std::vector<int> alt_slices;
02764   std::map<int, std::vector<CandStripHandle *> >::const_iterator slice_iter;
02765 
02766   int source = slc_strip.first;
02767   CandStripHandle * current_strip = slc_strip.second;
02768 
02769   // find slices that have hit strips in a time, z, tpos window centered at the
02770   // current strip...
02771 
02772   for(slice_iter = event_slices.begin();
02773                             slice_iter != event_slices.end(); ++slice_iter) {
02774 
02775       int n = count_if(
02776                slice_iter->second.begin(), slice_iter->second.end(),
02777                is_in_tztpos_window(current_strip, fKMeansTimeWindow,
02778                                    fKMeansPlaneWindow, fKMeansTPosWindow) );
02779       if( slice_iter->first == source ) n--;
02780 
02781       if(n > 0) alt_slices.push_back( slice_iter->first );
02782   }
02783 
02784   // if none is found, relax the criteria and check in a t, z window centered
02785   // at the current strip...
02786 
02787   if( alt_slices.size() == 0 ) {
02788 
02789        for(slice_iter = event_slices.begin();
02790                             slice_iter != event_slices.end(); ++slice_iter) {
02791 
02792             int n = count_if(
02793                          slice_iter->second.begin(), slice_iter->second.end(),
02794                          is_in_tz_window(current_strip,
02795                                     fKMeansTimeWindow, 2*fKMeansPlaneWindow) );
02796 
02797             if( slice_iter->first == source ) n--;
02798 
02799             if(n > 0) alt_slices.push_back( slice_iter->first );
02800        }
02801   }
02802 
02803   // return whatever was found - if it is still empty it will be handled later
02804   return alt_slices;
02805 }
02806 //____________________________________________________________________________
02807 WhichCandSlice_t AltAlgSliceList::characterizeCandidateSlices(
02808                         int source, const std::vector<int> & alt_slices) const
02809 {
02810   if( alt_slices.size() == 0 )     return eNone;
02811   else if ( alt_slices.size() == 1 ) {
02812 
02813        if(alt_slices[0] == source) return eSame;
02814        else                        return eOther;
02815 
02816   } else                           return eMany;
02817 
02818   return eSame;
02819 }
02820 //____________________________________________________________________________
02821 int AltAlgSliceList::getClosestCentroid(
02822    CandStripHandle * strip, const std::map<int, Centroid_t> & centroids) const
02823 {
02824   std::multimap<double, int, less<double> > slices_dt_sorted;
02825   std::multimap<double, int, less<double> > slices_dz_sorted;
02826 
02827   std::map<int, Centroid_t>::const_iterator cd_iter;
02828   for(cd_iter = centroids.begin(); cd_iter != centroids.end(); ++cd_iter) {
02829 
02830      double dt = ((*cd_iter).second.tu+(*cd_iter).second.tv)/2. -
02831                                                              strip->GetCorrBegTime();
02832 
02833      double dz = ((*cd_iter).second.zu+(*cd_iter).second.zv)/2. -
02834                                                              strip->GetZPos();
02835 
02836      slices_dt_sorted.insert(std::multimap<double, int>::value_type(
02837                                                  fabs(dt), (*cd_iter).first));
02838      slices_dz_sorted.insert(std::multimap<double, int>::value_type(
02839                                                  fabs(dz), (*cd_iter).first));
02840   }
02841 
02842   // Use this & similar information to decide what is the 'closest' centroid...
02843   // For now just:
02844 
02845   MSG("AltAlg", Msg::kVerbose)
02846        << "         |---> slice with 'closest' centroid: "
02847                                << (*(slices_dt_sorted.begin())).second << endl;
02848 
02849   return (*(slices_dt_sorted.begin())).second;
02850 }
02851 //____________________________________________________________________________
02852 int AltAlgSliceList::selectBestCandidateSlice(
02853                           const pair<int, CandStripHandle *> & slc_strip,
02854                                     const std::vector<int> & cand_slices,
02855      const std::map<int, std::vector<CandStripHandle *> > & event_slices) const
02856 {
02857 // Selects the "best" slice to host a strip, out of a list of good candidates.
02858 // What follows is a first approach
02859 
02860   int source = slc_strip.first;
02861   CandStripHandle * strip = slc_strip.second;
02862 
02863   //-- check how many of these candidate slices have other strips in a t,tpos
02864   //   window (centered at the strip) at the two succesive planes of the same,
02865   //   orientation (1 upstream & 1 downstream)
02866 
02867   std::vector<int> slice_list;
02868   std::vector<int>::const_iterator slice_id_iter;
02869   std::map<int, std::vector<CandStripHandle *> >::const_iterator slice_iter;
02870 
02871   for(slice_id_iter = cand_slices.begin();
02872                        slice_id_iter != cand_slices.end(); ++slice_id_iter) {
02873 
02874       slice_iter = event_slices.find(*slice_id_iter);
02875 
02876       int n = count_if( slice_iter->second.begin(), slice_iter->second.end(),
02877                         is_in_tztpos_window(strip, fKMeansTimeWindow,
02878                                                      2, fKMeansTPosWindow) );
02879 
02880       if( *slice_id_iter == source ) n--; // do not count yourself...
02881 
02882       if(n > 0) slice_list.push_back( *slice_id_iter );
02883   }
02884 
02885   //-- if there was only one then return this as the best candidate
02886   if(slice_list.size() == 1) return slice_list[0];
02887 
02888   else {
02889     //-- select the slice which has more strips in the list of the N closest
02890     //   neighbors...
02891 
02892     std::multimap<double, int, less<double> > slices_dist_sorted =
02893                            MakeDistanceMap(strip, cand_slices, event_slices);
02894 
02895     //-- find the slice with the more occurences in the N closest positions
02896 
02897     int best_cand_slice = moreOccurences(slices_dist_sorted, 10);
02898 
02899     MSG("AltAlg", Msg::kVerbose)
02900        << "         |---> best candidate slice: " << best_cand_slice << endl;
02901 
02902     return best_cand_slice;
02903   }
02904 
02905   MSG("AltAlg", Msg::kVerbose)
02906        << "         |---> keep strip in slice: " << source << endl;
02907 
02908   return source; // if  something go wrong - just leave the strip in its place
02909 }
02910 //____________________________________________________________________________
02911 std::multimap<double, int, less<double> > AltAlgSliceList::MakeDistanceMap(
02912           CandStripHandle * strip, const std::vector<int> & cand_slices,
02913     const std::map<int, std::vector<CandStripHandle *> > & event_slices) const
02914 {
02915 // Create a map of 'distance' -> 'slice_id', sorted in distance.
02916 // The 'distance' is computed with respect to the input CandStripHandle.
02917 
02918   std::multimap<double, int, less<double> > slices_dist_sorted;
02919 
02920   std::vector<int>::const_iterator slice_id_iter;
02921   std::vector<CandStripHandle *>::const_iterator strip_iter;
02922   std::map<int, std::vector<CandStripHandle *> >::const_iterator slice_iter;
02923 
02924   for(slice_id_iter = cand_slices.begin();
02925                        slice_id_iter != cand_slices.end(); ++slice_id_iter) {
02926 
02927      slice_iter = event_slices.find(*slice_id_iter);
02928 
02929      for(strip_iter = slice_iter->second.begin();
02930                       strip_iter != slice_iter->second.end(); ++strip_iter) {
02931 
02932         double cdt = 3.0e8 * ( (*strip_iter)->GetCorrBegTime() -
02933                                                           strip->GetCorrBegTime() );
02934         double dz  = (*strip_iter)->GetZPos() - strip->GetZPos();
02935 
02936         double d2 = cdt*cdt+dz*dz; // neglect tpos for now - keep 2 views
02937 
02938         slices_dist_sorted.insert(
02939                  std::multimap<double, int>::value_type(d2, *slice_id_iter));
02940      } // slice strips
02941   }// slices
02942 
02943   return slices_dist_sorted;
02944 }
02945 //____________________________________________________________________________
02946 int AltAlgSliceList::moreOccurences(
02947                             std::multimap<double, int> slice_ids, int n) const
02948 {
02949 // Finds the slice with the more occurences in the n first slots of the multimap
02950 // The 'double' argument of the multimap is a measure of 'distance' in some
02951 // variable. It therefore represents a "distance" -> "slice id" mapping.
02952 // The multimap<Key, Data, Compare, Alloc> must have Compare = less<double>
02953 // It is a multimap, rather than a map, because, in principle, >1 slices might
02954 // have the same key (generalized distance from something).
02955 // If n exceeds the multimap size it is set equal to it.
02956 // If more than one slice is found then it returns the one of them which has
02957 // the entry with the smallest distance.
02958 
02959   std::vector<int> slc_ids;
02960   std::vector<int> unique_slc_ids;
02961 
02962   std::map<double, int>::iterator id_iter;
02963   std::map<double, int>::iterator id_iter_last = slice_ids.begin();
02964   advance(id_iter_last, min(n, (int) slice_ids.size()) );
02965 
02966   for(id_iter = slice_ids.begin(); id_iter != id_iter_last; ++id_iter) {
02967 
02968        slc_ids.push_back( (*id_iter).second );
02969 
02970        if(! count_if( unique_slc_ids.begin(),  unique_slc_ids.end(),
02971                  bind2nd(equal_to<int>(), (*id_iter).second) ) )
02972                                 unique_slc_ids.push_back( (*id_iter).second );
02973   }
02974 
02975   std::map<int, int, greater<int> > occurences;
02976   std::vector<int>::iterator id;
02977 
02978   for(id = unique_slc_ids.begin(); id != unique_slc_ids.end(); ++id)
02979             occurences.insert( std::map<int, int>::value_type(
02980                         count_if( slc_ids.begin(),  slc_ids.end(),
02981                                        bind2nd(equal_to<int>(), *id) ), *id));
02982 
02983   std::multimap<int, int>::iterator max_occurences =
02984                           max_element( occurences.begin(), occurences.end() );
02985 
02986   return max_occurences->second;
02987 }
02988 //____________________________________________________________________________
02989 void AltAlgSliceList::rellocateStrip(
02990                         int source, int target, CandStripHandle * strip,
02991           std::map<int, std::vector<CandStripHandle *> > & event_slices) const
02992 {
02993 // Rellocates strip from slice: source to slice: target
02994 //
02995   MSG("AltAlg", Msg::kVerbose)
02996            << "         |--[-] strip rellocation is attempted now..." << endl;
02997 
02998   MSG("AltAlg", Msg::kVerbose)
02999              << "             |--> source: " << fFmtSlc( source )
03000              << " [elements = " << event_slices[source].size() << "]"
03001              << " --> target: " << fFmtSlc( target )
03002              << " [elements = " << event_slices[target].size() << "]" << endl;
03003 
03004   event_slices[target].push_back( strip );
03005 
03006   event_slices[source].erase( find_if( event_slices[source].begin(),
03007                                        event_slices[source].end(),
03008                                        same_strip(strip) ));
03009 
03010   MSG("AltAlg", Msg::kVerbose)
03011          << "             |--> strip rellocation done..."
03012          << " [src slice elements] = " << event_slices[source].size()
03013          << " [tgt slice elements] = " << event_slices[target].size() << endl;
03014 }
03015 //____________________________________________________________________________
03016 void AltAlgSliceList::sliceSplitter(
03017             std::map<int, std::vector<CandStripHandle *> > & /*event_slices*/)
03018 {
03019 // Minimal Spanning Tree  code goes here...
03020 // Utility methods go below...
03021 }
03022 //____________________________________________________________________________
03023 void AltAlgSliceList::assignMuonSpectrHits2Slices(CandStripHandleItr cshItr,
03024                 std::map<int, std::vector<CandStripHandle *> > & event_slices)
03025 {
03026 // Method for assigning muon spectrometer strips to upstream detector slices
03027 
03028   // Get slices in the muon spectrometer
03029 
03030   MSG("AltAlg", Msg::kVerbose)
03031                      << "[-] Slicing the muon spectrometer activity" << endl;
03032 
03033   std::map<int, std::vector<CandStripHandle *> > mu_slices =
03034                                                      getMuSpecSlices(cshItr);
03035   printSlices(mu_slices, "muon spectrometer slices");
03036 
03037   // Try to append muon spectrometer slices to existing slice (if one exists
03038   // quite close in space & time). Otherwise, form new slices or append to
03039   // a rubbish slice made exclusively from unmatched mu-spectr. strips...
03040   // to slices.
03041 
03042   MSG("AltAlg", Msg::kVerbose)
03043      << "[-] examine mu-spectrometer & upstream detector slices for matches"
03044      << endl;
03045 
03046   sortSlicesInTime(event_slices);
03047 
03048   sliceMatcher(mu_slices, event_slices);
03049 }
03050 //____________________________________________________________________________
03051 std::map<int, std::vector<CandStripHandle *> >
03052                              AltAlgSliceList::getMuSpecSlices(
03053                                                     CandStripHandleItr cshItr)
03054 {
03055 // Finding slices in the muon spectrometer
03056 
03057   //-- Get the time-profile of muon spectrometer activity:
03058   //   CandStripHandleItr cshItr points only to strips in pl > MaxPlane which
03059   //   defines the max plane before the muon spectrometer
03060   //   Use the same time-resolution as in the fTimeResolution
03061 
03062   MSG("AltAlg", Msg::kVerbose)
03063           << " |--> Getting the muon spectrometer strip time profile" << endl;
03064 
03065   fSubsetTimeProfile = createSubsetTimeProfile(&cshItr);
03066 
03067   fSubsettmin = ftmin;
03068   fSubsettmax = ftmax;
03069 
03070   //-- Use the peak-finder to determine time slices in the profile of the muon
03071   //   spectrometer activity
03072 
03073   MSG("AltAlg", Msg::kVerbose)
03074                   << " |--> Finding time slices in muon spectrometer" << endl;
03075 
03076   std::vector<TimeSlice_t> mu_seeds = getSliceSeeds(
03077                                              &cshItr, false, kMuSpectrometer);
03078 
03079   std::map<int, std::vector<CandStripHandle *> >
03080                                  mu_slices = fillSliceSeeds(cshItr, mu_seeds);
03081 
03082   MSG("AltAlg", Msg::kVerbose)
03083                     << " |--> Muon spectrometer slice seed filtering" << endl;
03084 
03085   //initSliceFiltering(mu_slices);
03086 
03087   sortSlicesInTime(mu_slices);
03088 
03089   delete fSubsetTimeProfile;
03090   fSubsetTimeProfile = 0;
03091 
03092   return mu_slices;
03093 }
03094 //____________________________________________________________________________
03095 void AltAlgSliceList::sliceMatcher(
03096           std::map<int, std::vector<CandStripHandle *> > & mu_slices,
03097           std::map<int, std::vector<CandStripHandle *> > & event_slices) const
03098 
03099 {
03100 // Match muon spectrometer slices with upstream detector slices
03101 
03102   // Find existing slices with 'activity' just before the muon spectrometer
03103 
03104   MSG("AltAlg", Msg::kVerbose)
03105       << " |--[-] Finding existing slices with activity just upstream of the "
03106       << "muon spectrometer" << endl;
03107 
03108   std::vector<int> slice_ids = slicesActiveUpstreamOfMuSpec(event_slices);
03109 
03110   // Examine all muon spectrometer slices for matches with the above slices.
03111 
03112   std::map<int, std::vector<CandStripHandle *> >::iterator mu_slice_iter;
03113 
03114   std::vector<CandStripHandle *> rubbish;
03115 
03116   for(mu_slice_iter = mu_slices.begin();
03117                          mu_slice_iter != mu_slices.end(); ++mu_slice_iter) {
03118 
03119      std::vector<CandStripHandle *> & mu_slice = (*mu_slice_iter).second;
03120 
03121      MSG("AltAlg", Msg::kVerbose)
03122          << " |--[-] muon-spectr. slice: " << (*mu_slice_iter).first << endl;
03123 
03124      // Meaningfull to proceed only if muon spectrometer slice has hit strips
03125      // in the upstream part of the muon spectrometer
03126 
03127      if( sliceHasStripsInUpstreamMuSpectrometer(mu_slice) ) {
03128 
03129         // Check for match... If a match is found the strips will have already
03130         // be appended to the right slice... if no match is found take care of
03131         // the unmatched strips...
03132 
03133         if( ! findMatchForMuSpecSlice(mu_slice, slice_ids, event_slices) ) {
03134 
03135           if(fMuSpecSuppressUnmatchedSlices) {
03136 
03137              // do not create a separate slice for every unmatched mu-spec slc.
03138              MSG("AltAlg", Msg::kVerbose)
03139                 << "     |--> NO match - adding strips to rubbish slc" << endl;
03140              addMuSpecStripsToExistingSlice(mu_slice, rubbish);
03141 
03142           } else {
03143              // do create a separate slice for every unmatched mu-spec slc.
03144              MSG("AltAlg", Msg::kVerbose)
03145                           << "     |--> NO match - creating new slice" << endl;
03146              newSliceToHostMuSpecStrips(mu_slice, event_slices);
03147 
03148           } // if suppress creation of unmatched slices
03149        } // if no match was found
03150      } // if mu spectrometer slice has activity in its upstream section
03151   }// loop over muon spectrometer slices
03152 
03153   // If it chosen to suppress the creation of separate slices for every single
03154   // unmatched mu-spectrometer slice, the rubbish strips are added as a single
03155   // (rubbish) slice...
03156 
03157   if(fMuSpecSuppressUnmatchedSlices)
03158                             newSliceToHostMuSpecStrips(rubbish, event_slices);
03159 }
03160 //____________________________________________________________________________
03161 std::vector<int> AltAlgSliceList::slicesActiveUpstreamOfMuSpec(
03162     const std::map<int, std::vector<CandStripHandle *> > & event_slices) const
03163 {
03164 // Find out which upstream slices have activity in the part just upstream of
03165 // the muon spectrometer (in the most downstream part of the forward detector)
03166 
03167   std::ostringstream sstream;
03168   sstream   << "     |--[-] Using AlgConf params: 'activity' is > "
03169             << fMuSpecNHitStripsBefSpectr  << " hit strips in the "
03170             << fMuSpecNPlnBefSpectr        << " planes before the mu-spectr.";
03171 
03172   MSG("AltAlg", Msg::kDebug) << sstream.str().c_str() << endl;
03173 
03174   std::vector<int> slice_ids;
03175 
03176   int min_plane_inclusive = kMuSpec1stPlane - fMuSpecNPlnBefSpectr;
03177   int max_plane_inclusive = kMuSpec1stPlane - 1;
03178 
03179   std::map<int, std::vector<CandStripHandle *> >::const_iterator slice_iter;
03180   for(slice_iter = event_slices.begin();
03181                            slice_iter != event_slices.end(); ++slice_iter) {
03182 
03183      int nhits = count_if(
03184                     (*slice_iter).second.begin(), (*slice_iter).second.end(),
03185              is_in_z_window_noref(min_plane_inclusive, max_plane_inclusive));
03186 
03187      MSG("AltAlg", Msg::kVerbose)
03188            << "         |--> slice " << (*slice_iter).first<< " has "<< nhits
03189            << " hit strips in planes [" << min_plane_inclusive << ", "
03190            << max_plane_inclusive << "]" << endl;
03191 
03192      if(nhits > fMuSpecNHitStripsBefSpectr) {
03193 
03194          slice_ids.push_back( (*slice_iter).first );
03195 
03196          MSG("AltAlg", Msg::kVerbose)
03197             << "         |--> *** use this one to when checking for matches "
03198             << " with mu-spectrometer activity " << endl;
03199      }
03200   }  // slice_iter
03201 
03202   return slice_ids;
03203 }
03204 //____________________________________________________________________________
03205 bool AltAlgSliceList::findMatchForMuSpecSlice(
03206   std::vector<CandStripHandle *> mu_strips, std::vector<int> slice_ids,
03207          std::map<int, std::vector<CandStripHandle *> > & event_slices) const
03208 {
03209   bool match_found = false;
03210 
03211   // Since we are at this point, it is likely to have a match with an upstream
03212   // spectrometer slice. Find the closest one...
03213   // The closest is decided in terms of temporal distance between the
03214   // most downstream section of the upstream slice and the
03215   // most upstream section of the downstream slice...
03216 
03217   std::vector<int>::iterator slice_id_iter;
03218 
03219   std::map<double, int, less<double> > closest_slices;
03220 
03221   double tmu  = averageTimeAtBeginOfDownstreamSlice(mu_strips);
03222 
03223   MSG("AltAlg", Msg::kVerbose)
03224         << "     |--> t (mu. spec begin) = " << fFmtTime(tmu) << endl;
03225   MSG("AltAlg", Msg::kVerbose)
03226         << "     |--[-] checking for matches " << endl;
03227 
03228   for(slice_id_iter = slice_ids.begin();
03229                          slice_id_iter != slice_ids.end(); ++slice_id_iter) {
03230 
03231       double tslc = averageTimeAtEndOfUpstreamSlice(
03232                                                 event_slices[*slice_id_iter] );
03233 
03234       MSG("AltAlg", Msg::kVerbose)
03235          << "         |--> tend(slc = " << fFmtSlc(*slice_id_iter) << ") = "
03236          << fFmtTime(tslc) << " -- dtbeg(mu.slc - slc) = "
03237          << fFmtTime(tmu-tslc) << endl;
03238 
03239       if(tmu  - tslc < fMuSpecTimeAftUpstrActivity &&
03240          tslc - tmu  < fMuSpecTimeBefUpstrActivity)
03241                closest_slices.insert(std::map<double, int>::value_type(
03242                                              fabs(tslc-tmu), *slice_id_iter));
03243   }
03244 
03245   if(closest_slices.size() >= 1) {
03246 
03247       // if at least one good candidate was found append the strips to the
03248       // closest one - this can be modified to use tpos info...
03249 
03250      std::map<double, int, less<double> >::iterator closest;
03251 
03252      closest = closest_slices.begin();
03253 
03254      MSG("AltAlg", Msg::kVerbose)
03255            << "     |--> mu-slice is appended to slice " << (*closest).second
03256            << " -- the closest out of " << closest_slices.size() << " slices"
03257            << endl;
03258 
03259       match_found = true;
03260       addMuSpecStripsToExistingSlice(
03261                                   mu_strips, event_slices[(*closest).second]);
03262   }
03263 
03264   return match_found;
03265 }
03266 //____________________________________________________________________________
03267 bool AltAlgSliceList::sliceHasStripsInUpstreamMuSpectrometer(
03268                       const std::vector<CandStripHandle *> & mu_strips) const
03269 {
03270 // Check if the muon spectrometer slice has strips in the first few muon
03271 // spectrometer planes
03272 
03273   int nhits = count_if( mu_strips.begin(), mu_strips.end(),
03274                   is_in_z_window_noref( kMuSpec1stPlane,
03275                                         kMuSpec1stPlane+fMuSpecNUpstrPlanes));
03276   MSG("AltAlg", Msg::kVerbose)
03277            << "     |--> slice has " << nhits << " strips (out of "
03278            << mu_strips.size() << " in total) in the forward "
03279            << " mu-spectr. region: planes = [" << kMuSpec1stPlane << ", "
03280            << kMuSpec1stPlane+fMuSpecNUpstrPlanes << "]" << endl;
03281 
03282   if(nhits == 0) {
03283       MSG("AltAlg", Msg::kVerbose) << "     |--> *** skipping" << endl;
03284       return false;
03285   }
03286 
03287   return true;
03288 }
03289 //____________________________________________________________________________
03290 void AltAlgSliceList::addMuSpecStripsToExistingSlice(
03291                              const std::vector<CandStripHandle *> & mu_strips,
03292                           std::vector<CandStripHandle *> & slice_strips) const
03293 {
03294   std::vector<CandStripHandle *>::const_iterator mu_strip_iter;
03295   for(mu_strip_iter = mu_strips.begin();
03296            mu_strip_iter != mu_strips.end(); ++mu_strip_iter)
03297                                      slice_strips.push_back( *mu_strip_iter );
03298 
03299   sort(slice_strips.begin(), slice_strips.end(), min_t());
03300 }
03301 //____________________________________________________________________________
03302 void AltAlgSliceList::newSliceToHostMuSpecStrips(
03303                              const std::vector<CandStripHandle *> & mu_strips,
03304           std::map<int, std::vector<CandStripHandle *> > & event_slices) const
03305 {
03306   int slice_id = nextAvailableSliceId(event_slices);
03307 
03308   event_slices.insert(
03309        std::map<int, std::vector<CandStripHandle *> >::value_type(
03310                                                        slice_id, mu_strips) );
03311 
03312   sort(event_slices[slice_id].begin(), event_slices[slice_id].end(), min_t());
03313 }
03314 //____________________________________________________________________________
03315 TH1D * AltAlgSliceList::createSubsetTimeProfile(CandStripHandleItr * cshItr)
03316 {
03317 // Creates the time-profile for a subset of hit strips.
03318 // The selection of the strip subset (i.e. muon spectrimeter hits only etc)
03319 // is *encapsulated* in the CandStripHandleItr (a proper selection on its
03320 // NavSet using NavTools must have preceded the call to this function).
03321 // The time profile histogram is instantiated by cloning and reseting the
03322 // spill time-profile. This guarantees that the time-profile of all subsets
03323 // have the same bin size (corresponding to the same time resolution)
03324 // The returned object is owned by the calling function.
03325 //
03326   TH1D * subset_time_profile = (TH1D *) fTimeProfile->Clone();
03327   subset_time_profile->Reset("ICE"); // "ICE"--check that I remember correctly
03328 
03329   cshItr->ResetFirst();
03330   while( CandStripHandle * striph = cshItr->Ptr() ) {
03331 
03332      (fPkfWeightProfileWithCharge) ?
03333           subset_time_profile->Fill( striph->GetCorrBegTime(),
03334                                      striph->GetCharge()  )  :
03335           subset_time_profile->Fill( striph->GetCorrBegTime() )  ;
03336 
03337      cshItr->Next();
03338   }
03339 
03340   return subset_time_profile;
03341 }
03342 //____________________________________________________________________________
03343 double AltAlgSliceList::averageTimeAtBeginOfDownstreamSlice(
03344                             std::vector<CandStripHandle *> & mu_strips) const
03345 {
03346   std::vector<CandStripHandle *>::iterator mu_end = partition(
03347                   mu_strips.begin(), mu_strips.end(),
03348                   is_in_z_window_noref( kMuSpec1stPlane,
03349                                         kMuSpec1stPlane+fMuSpecNUpstrPlanes));
03350 
03351   return averageTime( mu_strips, mu_end );
03352 }
03353 //____________________________________________________________________________
03354 double AltAlgSliceList::averageTimeAtEndOfUpstreamSlice(
03355                             std::vector<CandStripHandle *> & slc_strips) const
03356 {
03357   std::vector<CandStripHandle *>::iterator slc_end = partition(
03358                  slc_strips.begin(), slc_strips.end(),
03359                  is_in_z_window_noref( kMuSpec1stPlane - fMuSpecNPlnBefSpectr,
03360                                        kMuSpec1stPlane - 1));
03361 
03362   return averageTime(slc_strips, slc_end );
03363 }
03364 //____________________________________________________________________________
03365 double AltAlgSliceList::averageTime(
03366                      const std::vector<CandStripHandle *> & strips,
03367                      std::vector<CandStripHandle *>::const_iterator end) const
03368 {
03369   double qt = accumulate( strips.begin(), end, 0.0, sum_qtime() );
03370   double q  = accumulate( strips.begin(), end, 0.0, sum_q()     );
03371 
03372   //eventually assert(q!=0)
03373 
03374   if(q==0) {
03375       MSG("AltAlg", Msg::kWarning)
03376            << "Charge = " << q << " -- This should not be happenning" << endl;
03377       return 0;
03378   } else  return qt/q;
03379 }
03380 //____________________________________________________________________________
03381 double AltAlgSliceList::getStripTime(
03382          CandStripHandle * csh, StripTime_t st, StripEnd::StripEnd_t se) const
03383 {
03384   switch ( st ) {
03385   case ( eTime )        : return csh->GetTime(se);       break;
03386   case ( eBegTime )     : return csh->GetBegTime(se);    break;
03387   case ( eEndTime )     : return csh->GetEndTime(se);    break;
03388   case ( eCorrBegTime ) : return csh->GetCorrBegTime();  break;
03389   default               : return 0;
03390   }
03391 }
03392 //____________________________________________________________________________
03393 void AltAlgSliceList::getAlgorithmConfiguration(const AlgConfig & ac)
03394 {
03395   internalInit(); // initialize internal data members
03396 
03397   fGrfxDebugGraphics              =  ac.GetInt("Grfx_DebugGraphics");
03398   fGrfxTimeProfileLogView         =  ac.GetInt("Grfx_TimeProfileLogView");  
03399   fPkfPeakThreshold               =  ac.GetInt("Pkf_PeakThreshold");  
03400   fPkfNSuccessiveEmptyBins        =  ac.GetInt("Pkf_NSuccessiveEmptyBins");     
03401   fPkfMuSpecPeakThreshold         =  ac.GetInt("Pkf_MuSpecPeakThreshold");    
03402   fPkfMuSpecNSuccessiveEmptyBins  =  ac.GetInt("Pkf_MuSpecNSuccessiveEmptyBins");   
03403   fPkfLowPeakThreshold            =  ac.GetInt("Pkf_LowPeakThreshold");  
03404   fPkfLowNSuccessiveEmptyBins     =  ac.GetInt("Pkf_LowNSuccessiveEmptyBins");   
03405   fPkfNofMergedTimeBins           =  ac.GetInt("Pkf_NofMergedTimeBins");  
03406   fPkfWeightProfileWithCharge     = (ac.GetInt("Pkf_WeightProfileWithCharge") == 1);    
03407   fPkfRecursivePeakSearch         = (ac.GetInt("Pkf_RecursivePeakSearch") == 1);
03408   fPkfTimeWindowBefPeak           =  ac.GetInt("Pkf_TimeWindowBefPeak");
03409   fPkfTimeWindowAftPeak           =  ac.GetInt("Pkf_TimeWindowAftPeak");
03410   fRefinementDissolving           = (ac.GetInt("Refinement_Dissolving") == 1);
03411   fRefinementMerging              = (ac.GetInt("Refinement_Merging") == 1);
03412   fRefinementKMeansClustering     = (ac.GetInt("Refinement_KMeansClustering") == 1);
03413   fRefinementMSTClustering        = (ac.GetInt("Refinement_MSTClustering") == 1);
03414   fOrphanStripsQWeight            = (ac.GetInt("OrphanStrips_QWeight") == 1);
03415   fOrphanStripsPlaneWindow        =  ac.GetInt("OrphanStrips_PlaneWindow");
03416   fOrphanStripsTimeWindow         =  ac.GetDouble("OrphanStrips_TimeWindow");    
03417   fKMeansTimeWindow               =  ac.GetDouble("KMeans_TimeWindow");
03418   fKMeansPlaneWindow              =  ac.GetInt("KMeans_PlaneWindow");
03419   fKMeansTPosWindow               =  ac.GetDouble("KMeans_TPosWindow");  
03420   fMuSpecNUpstrPlanes             =  ac.GetInt("MuSpec_NUpstrPlanes");
03421   fMuSpecTimeAftUpstrActivity     =  ac.GetDouble("MuSpec_TimeAftUpstrActivity");
03422   fMuSpecTimeBefUpstrActivity     =  ac.GetDouble("MuSpec_TimeBefUpstrActivity");
03423   fMuSpecNHitStripsBefSpectr      =  ac.GetInt("MuSpec_HitStripsBefSpectr");
03424   fMuSpecNPlnBefSpectr            =  ac.GetInt("MuSpec_NPlnBefSpectr");
03425   fMuSpecSuppressUnmatchedSlices  = (ac.GetInt("MuSpec_SuppressUnmatchedSlices") == 1);
03426   fTimeResolution                 =  ac.GetDouble("TimeResolution");
03427   fMinNoHitStrips                 =  ac.GetInt("MinHitStripsInSlice");  
03428   fTimeDiffBetweenPeaks           =  ac.GetDouble("TimeDiffBetweenPeaks");  
03429   fZDiffBetweenPeaks              =  ac.GetDouble("ZDiffBetweenPeaks");  
03430   fZDiffBetweenEnds               =  ac.GetDouble("ZDiffBetweenEnds");  
03431   fUVDiffBetweenPeaks             =  ac.GetDouble("UVDiffBetweenPeaks");
03432   fMinCharge                      =  ac.GetDouble("MinChargeInSlice");  
03433 }
03434 //____________________________________________________________________________
03435 void AltAlgSliceList::internalInit(void)
03436 {
03437 // Initialize private data members
03438 
03439   //--  ordinary private data members
03440   
03441   fNTimeBins                           = 0;
03442   fUpdateCentroids                     = false;         
03443   fTimeProfileMax                      = 0;
03444   fTimeProfile                         = 0;
03445   ftmin                                = 0;
03446   ftmax                                = 0;
03447   fSubsetTimeProfile                   = 0;
03448   fSubsettmin                          = 0;
03449   fSubsettmax                          = 0;
03450   fPeakFinderNestingLevel              = 0;
03451   fkMeansIteration                     = 0;
03452 
03453   //-- private data members that are set by external AlgConf object
03454 
03455   fGrfxDebugGraphics                   = 0;
03456   fGrfxTimeProfileLogView              = 0;
03457   fPkfPeakThreshold                    = 0;
03458   fPkfNSuccessiveEmptyBins             = 0;
03459   fPkfMuSpecPeakThreshold              = 0;
03460   fPkfMuSpecNSuccessiveEmptyBins       = 0;
03461   fPkfLowPeakThreshold                 = 0;
03462   fPkfLowNSuccessiveEmptyBins          = 0;
03463   fPkfNofMergedTimeBins                = 0;   
03464   fPkfTimeWindowBefPeak                = 0;  
03465   fPkfTimeWindowAftPeak                = 0;  
03466   fOrphanStripsPlaneWindow             = 0;
03467   fKMeansPlaneWindow                   = 0;
03468   fMuSpecNUpstrPlanes                  = 0;
03469   fMuSpecNHitStripsBefSpectr           = 0;
03470   fMuSpecNPlnBefSpectr                 = 0;
03471   fMinNoHitStrips                      = 0;            
03472   fPkfWeightProfileWithCharge          = false;
03473   fPkfRecursivePeakSearch              = false;
03474   fRefinementDissolving                = false;
03475   fRefinementMerging                   = false;      
03476   fRefinementKMeansClustering          = false;
03477   fRefinementMSTClustering             = false;
03478   fMuSpecSuppressUnmatchedSlices       = false;
03479   fOrphanStripsQWeight                 = false;   
03480   fOrphanStripsTimeWindow              = 0.0; 
03481   fKMeansTimeWindow                    = 0.0;
03482   fKMeansTPosWindow                    = 0.0;      
03483   fMuSpecTimeAftUpstrActivity          = 0.0;
03484   fMuSpecTimeBefUpstrActivity          = 0.0;
03485   fTimeResolution                      = 0.0;
03486   fTimeDiffBetweenPeaks                = 0.0;
03487   fZDiffBetweenPeaks                   = 0.0;
03488   fZDiffBetweenEnds                    = 0.0;
03489   fUVDiffBetweenPeaks                  = 0.0;  
03490   fMinCharge                           = 0.0;         
03491 }
03492 //____________________________________________________________________________
03493 void AltAlgSliceList::buildCandidates(
03494                 std::map<int, std::vector<CandStripHandle *> > & event_slices,
03495                                             CandHandle & ch, CandContext & cx) 
03496 {
03497   sortSlicesInTime(event_slices);
03498 
03499   //-- Get an AlgFactory - ask it for a handle to AltAlgSlice algorithm
03500   //   and create a candidate context to supply the algorithm with
03501 
03502   AlgFactory & af = AlgFactory::GetInstance();
03503   AlgHandle    ah = af.GetAlgHandle("AltAlgSlice","default");
03504   
03505   CandContext ccx(this, cx.GetMom());
03506 
03507   std::map<int, std::vector<CandStripHandle *> >::const_iterator slc_iter;
03508   
03509   for( slc_iter = event_slices.begin(); 
03510                                  slc_iter != event_slices.end(); ++slc_iter) {
03511  
03512      MSG("AltAlg", Msg::kDebug) 
03513         << " Slice: " << fFmtSlc( (*slc_iter).first )
03514         << " / Running MakeCandidate on AltAlgSlice & Adding Doughter Link" 
03515         << endl;
03516 
03517      AltWrapperStlVecStripHandle vec_wrapper( (*slc_iter).second );
03518      ccx.SetDataIn( & vec_wrapper); 
03519      CandSliceHandle slchandle = CandSlice::MakeCandidate(ah,ccx);
03520      ch.AddDaughterLink(slchandle);     
03521   }
03522 }
03523 //____________________________________________________________________________
03524 

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