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

ChopHelper.cxx

Go to the documentation of this file.
00001 
00002 // $Id: ChopHelper.cxx,v 1.3 2007/11/11 08:26:13 rhatcher Exp $
00003 //
00004 // ChopHelper.cxx
00005 //
00007 
00008 #include <cassert>
00009 #include <cmath>
00010 
00011 #include "ChopHelper.h"
00012 #include "ChopHelp.h"
00013 #include "DigitVector.h"
00014 #include "CandData/CandHeader.h"
00015 #include "CandData/CandRecord.h"
00016 #include "CandDigit/CandDigitHandle.h"
00017 #include "CandDigit/CandDigitListHandle.h"
00018 #include "CandDigit/CandDigitList.h"
00019 #include "Candidate/CandContext.h"
00020 #include "MessageService/MsgService.h"
00021 #include "MinosObjectMap/MomNavigator.h"
00022 #include "RawData/RawHeader.h"
00023 #include "RawData/RawRecord.h"
00024 #include "RawData/RawDigitDataBlock.h"
00025 #include "UgliGeometry/UgliGeomHandle.h"
00026 #include "UgliGeometry/UgliStripHandle.h"
00027 #include "Validity/VldContext.h"
00028 #include "Calibrator/Calibrator.h"
00029 
00030 ClassImp(ChopHelper)
00031 
00032 CVSID( " $Id: ChopHelper.cxx,v 1.3 2007/11/11 08:26:13 rhatcher Exp $ ");
00033 
00034 struct compareDigitTimes : public binary_function<const CandDigitHandle&, const CandDigitHandle&, bool> {
00035   bool operator()(const CandDigitHandle& d1, const CandDigitHandle& d2) {
00036     return (d1.GetTime() < d2.GetTime());
00037   }
00038 };
00039 
00040 const RawChannelId kQieRcid(Detector::kNear,ElecType::kQIE,0,0,false,false);
00041 const float k1pe = 100.; // About 1 pe.
00042 
00043 
00044 //______________________________________________________________________
00045 ChopHelper::ChopHelper(const MomNavigator* mom) : fMom(mom)
00046 {
00047 }
00048 
00049 //______________________________________________________________________
00050 ChopHelper::~ChopHelper()
00051 {
00052 }
00053 
00054 class Chop : public DigitVector{
00055 public:
00056   std::map<PlexStripEndId,float> fStripEnergy;
00057   std::map<int, float>           fPlaneEnergy;
00058   float                          fTotalEnergy;
00059   bool                           fDirty;
00060 
00061   Chop() : fDirty(false) {};
00062 
00063   void Add(CandDigitHandle& cdh) { 
00064     fDirty = true;
00065     push_back(cdh);
00066   }
00067 
00068   void BuildMaps() {
00069     if(fDirty) {
00070       fStripEnergy.clear();
00071       fPlaneEnergy.clear();
00072       fTotalEnergy = 0;
00073       for(UInt_t i=0;i<size();i++) {
00074         float sigcor = (*this)[i].GetCharge(CalDigitType::kSigCorr);
00075         PlexStripEndId seid = (*this)[i].GetPlexSEIdAltL().GetBestSEId();
00076         if(seid.IsValid()) {
00077           fStripEnergy[seid] += sigcor;
00078           fPlaneEnergy[seid.GetPlane()] += sigcor;
00079           fTotalEnergy += sigcor;
00080         }
00081       }
00082     }
00083     fDirty = false;
00084   }
00085 };
00086 
00087 //______________________________________________________________________
00088 bool ChopHelper::ShouldSplit( float this_ph, // sigcorrs in current bin
00089                                       float next_ph, // sigcorrs in next/prev bin we want to expand into
00090                                      float /*d_tmax*/   // distance from next bin to peak of event.
00091                                       )
00092 {
00093   float climb = next_ph - this_ph;
00094   
00095   // the maximum delta that the algorithm will climb before making a new chop
00096   float max_climb = 2.5*sqrt(fabs(this_ph)/k1pe)*k1pe;
00097   if(max_climb < (6 * k1pe)) max_climb=max_climb*2;
00098 
00099   // the maximum pulse height in this bin if we're making a new chop.
00100   //const float size_limit = 20 * k1pe; 
00101   //const float min_time = 2;
00102 
00103   //if(d_tmax  < min_time) return false;
00104   //if(this_ph < size_limit) return false;
00105 
00106   if( climb >= max_climb ) return true;
00107   else return false;    
00108 }
00109 
00110 
00111 //______________________________________________________________________
00112 ChopHelp* ChopHelper::GetChopHelp( const CandHandle* ev1, 
00113                                    const CandHandle* ev2,
00114                                    const CandHandle* ev3,
00115                                    const CandHandle* ev4,
00116                                    const CandHandle* ev5 )
00117 {
00118   std::vector<CandHandle> v;
00119   if(ev1) v.push_back(*ev1);
00120   if(ev2) v.push_back(*ev2);
00121   if(ev3) v.push_back(*ev3);
00122   if(ev4) v.push_back(*ev4);
00123   if(ev5) v.push_back(*ev5);
00124   
00125   return GetChopHelp(v);
00126 }
00127 
00128 ChopHelp* ChopHelper::GetChopHelp( std::vector<CandHandle> events )
00129 {
00130  
00134 
00135   // Config.
00136   bool cDoRecombobulation = false;
00137 
00138   if(events.size()==0) return 0;
00139   
00140    RawRecord *rr = dynamic_cast<RawRecord *>(fMom->GetFragment("RawRecord"));
00141    if (!rr) {
00142      MSG("Chop", Msg::kWarning) << "No RawRecord in MOM." << endl;
00143      return 0;
00144    }
00145    const RawDigitDataBlock *rddb = dynamic_cast<const RawDigitDataBlock *>
00146      (rr->FindRawBlock("RawDigitDataBlock"));
00147    if (!rddb) {
00148      MSG("Chop", Msg::kWarning) << "No RawDigitDataBlock in RawRecord." << endl;
00149      return 0;
00150    }
00151    
00152    const VldContext &context = *(events[0].GetVldContext());
00153    if(context.GetDetector() != Detector::kNear) 
00154      MSG("Chop",Msg::kError) << "Running the Sharp2 algorithm on FD data is a no-no!" << endl;
00155 
00156    Calibrator& cal = Calibrator::Instance();
00157    UgliGeomHandle ugli(context);
00158   
00159    // Now do the actual slicing.
00160 
00161    // First, make a nice stl vector of the digits.
00162    DigitVector digits;
00163    std::vector<DigitVector> eventDigits(events.size());
00164    for(UInt_t i=0;i<events.size();i++) {
00165      eventDigits[i].FillFrom(&(events[i]));
00166      digits.FillFrom(eventDigits[i],0,eventDigits[i].size(), true);
00167    }
00168 
00169    UInt_t ndigits = digits.size();
00170     
00171    // Sort the list by time.
00172    // Not neccessary for this algorithm.
00173    // std::sort(digits.begin(), digits.end(), compareDigitTimes());
00174 
00175    // Also, I want some other pieces of info:
00176    std::vector<int>    digit_tdc(ndigits);
00177    std::vector<UInt_t> digit_plane(ndigits);
00178    //std::vector<float>  digit_tpos(ndigits);
00179    for(UInt_t i=0;i<ndigits;i++) {
00180      digit_tdc[i] = (cal.GetTDCFromTime(digits[i].GetTime(CalTimeType::kNone), kQieRcid));
00181      digit_plane[i] = digits[i].GetPlexSEIdAltL().GetPlane(); 
00182      //if(digit_plane[i]<=PlexPlaneId::LastPlaneNearCalor())
00183      //  digit_tpos[i]  = ugli.GetStripHandle(digits[i].GetPlexSEIdAltL().GetBestSEId()).GetTPos(); 
00184      //else 
00185      //  digit_tpos[i]  = -999;
00186    }
00187 
00188    // Find first and last times. Add some padding so sertain operations are easier to code.
00189    Int_t tfirst = digit_tdc[0];
00190    Int_t tlast  = digit_tdc[0];
00191    for(UInt_t i=0;i<ndigits;i++) {
00192      if(digit_tdc[i] < tfirst) tfirst = digit_tdc[i];
00193      if(digit_tdc[i] > tlast ) tlast  = digit_tdc[i];
00194    }
00195    tfirst-=5;
00196    tlast +=5;
00197 
00198 
00199    // Make the energy histogram.
00200    MSG("Chop",Msg::kDebug) << "Running Chop_Sharp2" << endl;
00201       
00202    UInt_t numBins = tlast-tfirst;
00203 
00204    // Create the energy-time profile.
00205    std::vector<float> energyVsTime(numBins,0.);
00206    
00207    for(UInt_t idig = 0; idig < ndigits; idig++ ) {
00208      float sigcor = digits[idig].GetCharge(CalDigitType::kSigCorr);
00209      int tdcbin = digit_tdc[idig]-tfirst;
00210      if((tdcbin<0) || ((int)numBins<=tdcbin)) MSG("Chop",Msg::kDebug) << "Whups!" << endl;
00211      else if(digit_plane[idig]<=PlexPlaneId::LastPlaneNearCalor()) {
00212        energyVsTime[digit_tdc[idig]-tfirst] += sigcor; 
00213      }
00214    }
00215    
00216    std::vector<int> cuts;
00217 
00218    // Used bins:
00219    std::vector<char> binsUsed(numBins,0);
00220    binsUsed[0]=1;
00221    binsUsed[numBins-1]=1;
00222 
00223    cuts.push_back(0);
00224    cuts.push_back(numBins-1);
00225 
00226 
00227    do {
00228      // Look for biggest peak. 
00229      UInt_t biggest_bin  = 99999;
00230      float  biggest_size = 0;
00231      for(UInt_t i=0;i<numBins;i++) {
00232        if(binsUsed[i]==0) 
00233          if(energyVsTime[i]>biggest_size) {
00234            biggest_size = energyVsTime[i];
00235            biggest_bin = i;
00236          }
00237      }
00238      
00239      if(biggest_bin==99999) break; // We've gone through all of them.
00240      if(biggest_size<=0.) break; // We've hit rock bottom.
00241      
00242      // Collect the start and stop time for this chop.
00243      // Start 1 bin before the peak, and at least 1 bin after the peak.
00244      UInt_t bin_start = biggest_bin;
00245      UInt_t bin_stop =  biggest_bin;
00246      
00247      if(binsUsed[bin_start-1]==0) bin_start--;
00248      if(binsUsed[bin_stop +1]==0) bin_stop++;
00249      
00250      bool done = false;
00251      while(!done) {
00252 
00253        // Stop if there's a rise. If so, mark as a contested bin.
00254        if(ShouldSplit(energyVsTime[bin_start], 
00255                       energyVsTime[bin_start-1],
00256                       bin_start-1 - biggest_bin ) ) {
00257          done = true;
00258          cuts.push_back(bin_start);
00259        }
00260        
00261        // Stop if we've hit another chop.
00262        if(binsUsed[bin_start-1]) {
00263          done = true;
00264        }
00265        
00266        if(!done) {
00267          bin_start--;
00268        }
00269      };
00270      
00271      // Expand forwards until the energy starts climbing.
00272      // But, allow small pulses in for the first 5 buckets.
00273      done = false;
00274      while(!done) {
00275        
00276        // Allow 5 buckets worth of small stuff:
00277        if((energyVsTime[bin_stop+1] < 500.) && (bin_stop+1 < biggest_bin+7)) {
00278          // keep going
00279        } else {
00280          if(ShouldSplit(energyVsTime[bin_stop],
00281                         energyVsTime[bin_stop+1],
00282                         bin_stop+1 - biggest_bin) ) {
00283            done = true;
00284            cuts.push_back(bin_stop); // mark this one as contested.
00285          }
00286        }
00287        
00288        // Stop if we hit another chop.
00289        if(binsUsed[bin_stop+1]) {
00290          //MSG("Chop",Msg::kDebug) << "Didn't move forward; hit another chop." << endl;
00291          done = true;
00292        }
00293        
00294        // If we're ok, increment and continue.
00295        if(!done) bin_stop++;
00296      }
00297      
00298      // Zero out these buckets so they won't be caught again.
00299      for(UInt_t i=bin_start; i<=bin_stop; i++) {
00300        binsUsed[i] = 1;
00301      }
00302      
00303    } while(true); 
00304 
00305 
00306    // Time-order the cuts.
00307    std::sort(cuts.begin(), cuts.end());
00308 
00309    // One chop for every cut, corresponding to the cut that ends the chop.
00310    std::vector<Chop> chops(cuts.size());
00311 
00312    // Build initial cuts, excluding hits in contested bins.
00313    // loop cuts, 1 to n
00314    for(UInt_t icut = 1; icut<= cuts.size(); icut++) {
00315      int bin_start = cuts[icut-1]+1; // Excluding last contested bin
00316      int bin_stop  = cuts[icut]-1;   // Excluding current contested bin.
00317 
00318      int tdc_start = bin_start + tfirst;
00319      int tdc_stop  = bin_stop  + tfirst;
00320      
00321      for(UInt_t idig = 0; idig < ndigits; idig++ ) {
00322        int tdc = digit_tdc[idig];
00323        if((tdc>=(int)tdc_start)&&(tdc<=(int)tdc_stop)) {
00324          chops[icut].Add(digits[idig]);
00325        }
00326      }     
00327    }
00328 
00329    // Now loop through again and deal with any contested bins.
00330    // Ignore the first and last cuts, since they are at the start
00331    // and end of the event.
00332    for(UInt_t icut = 1; icut< cuts.size()-1; icut++) {
00333      int contested_bin = cuts[icut];
00334      int contested_tdc = contested_bin + tfirst;
00335      
00336      // Make a list of digits in the contested bin.
00337      DigitVector contested_digits;
00338      for(UInt_t idig = 0; idig < ndigits; idig++ ) {
00339        int tdc = digit_tdc[idig];
00340        if(tdc==contested_tdc) {
00341          contested_digits.push_back(digits[idig]);
00342        }
00343      }
00344 
00345      if(contested_digits.size()>0) {
00346        // only bother if there's actually some digits in the contested bin.
00347 
00348        int chop1 = icut;
00349        int chop2 = icut+1;
00350 
00351        // Tell the fighting chops to build maps.
00352        chops[chop1].BuildMaps();
00353        chops[chop2].  BuildMaps();
00354 
00355        MSG("Chop",Msg::kDebug) << "Dealing with contested bin " << cuts[icut] 
00356             << " with " << contested_digits.size() << " contested digits." << endl;
00357 
00358        int assign_strip1 = 0;
00359        int assign_strip2 = 0;
00360        int assign_plane1 = 0;
00361        int assign_plane2 = 0;
00362        int assign_total1 = 0;
00363        int assign_total2 = 0;
00364 
00365        
00366        // Now loop through contested digits and assign them:
00367        for(UInt_t ic=0; ic<contested_digits.size(); ic++) {
00368          // Assign to chop with most energy on same strip:
00369          CandDigitHandle digit = contested_digits[ic];
00370          PlexStripEndId seid =digit.GetPlexSEIdAltL().GetBestSEId();
00371          float chop1stripE = chops[chop1].fStripEnergy[seid];
00372          float chop2stripE  =chops[chop2  ].fStripEnergy[seid];
00373 
00374          /*
00375          MSG("Chop",Msg::kDebug) << "  Consider " << seid.AsString() << " q=" << digit.GetCharge(CalDigitType::kSigCorr)
00376               << "  chop1(s/p/t) = " 
00377               << chops[chop1].fStripEnergy[seid] << "/"
00378               << chops[chop1].fPlaneEnergy[seid.GetPlane()] << "/"
00379               << chops[chop1].fTotalEnergy 
00380               << "  chop2(s/p/t) = " 
00381               << chops[chop2].fStripEnergy[seid] << "/"
00382               << chops[chop2].fPlaneEnergy[seid.GetPlane()] << "/"
00383               << chops[chop2].fTotalEnergy 
00384               << endl;
00385          */
00386 
00387          if(chop1stripE > chop2stripE){
00388            chops[chop1].Add(digit);
00389            assign_strip1++;
00390          } else if(chop2stripE > chop1stripE){
00391            chops[chop2].Add(digit);
00392            assign_strip2++;
00393          } else {
00394            // Darn. The strip content is the same in both. (probably 0)
00395            // So compare on the plane level:
00396            
00397            float chop1planeE = chops[chop1].fPlaneEnergy[seid.GetPlane()];
00398            float chop2planeE = chops[chop2].fPlaneEnergy[seid.GetPlane()];
00399            if(chop1planeE > chop2planeE){
00400              chops[chop1].Add(digit);
00401              assign_plane1++;
00402            } else  if(chop2planeE > chop1planeE){
00403              chops[chop2].Add(digit);
00404              assign_plane2++;      
00405            } else {
00406 
00407              // Ok, so there's nothing in either plane. Assign it to the biggest chop,
00408              // or the earlier one if tied.
00409              if(chops[chop1].fTotalEnergy>=chops[chop2].fTotalEnergy) {
00410                chops[chop1].Add(digit);
00411                assign_total1++;
00412              } else {
00413                chops[chop2].Add(digit);
00414                assign_total2++;
00415              }
00416            }
00417          }
00418        } //uuuuuuugly!
00419        
00420       
00421        MSG("Chop",Msg::kDebug) << "  Assigned by strip: " << assign_strip1 << "/" << assign_strip2
00422             << "   by plane: "         << assign_plane1 << "/" << assign_plane2
00423             << "   by total: "         << assign_total1 << "/" << assign_total2
00424             << endl;
00425      }
00426     
00427 
00428    }
00429    
00431    // And now...
00432    // Recombobulate!
00433    if(cDoRecombobulation) {
00434 
00435      for(UInt_t ichop=1;ichop<chops.size();ichop++) chops[ichop].BuildMaps();
00436      
00437      for(UInt_t icut=1;icut<cuts.size()-1;icut++) {
00438        for(int ilr = 0; ilr<2; ilr++) { //loop left and right
00439          int contested_tdc;
00440          int chopfrom;
00441          int chopto;
00442          if(ilr==0) {
00443            contested_tdc = cuts[icut]-1 + tfirst;
00444            chopfrom      = icut;
00445            chopto        = icut+1;
00446          } else {
00447            contested_tdc = cuts[icut]+1 + tfirst;
00448            chopfrom      = icut+1;
00449            chopto        = icut;
00450          }
00451          
00452          int moved = 0;
00453          
00454          for(UInt_t idig = 0; idig<chops[chopfrom].size(); idig++) {
00455            CandDigitHandle digit = chops[chopfrom][idig];
00456            int tdc = (cal.GetTDCFromTime(digit.GetTime(CalTimeType::kNone), kQieRcid));
00457            if(tdc == contested_tdc) {
00458              PlexStripEndId seid =digit.GetPlexSEIdAltL().GetBestSEId();
00459              float sigcor = digits[idig].GetCharge(CalDigitType::kSigCorr);
00460              
00461              // If the chop that owns the digit has no other digits on that strip:
00462              if(chops[chopfrom].fStripEnergy[seid] <= sigcor) {
00463                // If the neigboring chop HAS got some energy on that strip
00464                if(chops[chopto].fStripEnergy[seid] > 0) {
00465                  // Then move the digit.
00466                  chops[chopto].push_back(digit);
00467                  chops[chopfrom].erase(chops[chopfrom].begin() + idig);
00468                  idig--; // set so we look at the next element instead of skipping one.
00469                  moved++;
00470                }
00471              }
00472            }
00473          }
00474          
00475          MSG("Chop",Msg::kDebug) << "Recombobulated " << moved << " digits in bin " << contested_tdc-tfirst
00476                                  << " from chop " << chopfrom << " to chop " << chopto << endl;
00477        } // End left/right loop
00478      } // End loop over cuts
00479      
00480    } // end Recombobulation
00481    
00482 
00484    // Remove empty chops.
00485    
00486    for(UInt_t i=0;i<chops.size();i++) {
00487      if(chops[i].size()==0) {
00488        chops.erase(chops.begin()+i);
00489        i--;
00490      }
00491    }
00492 
00494    // Finally, evaluate the chops vs the events.
00495 
00496    ChopHelp* chophelp = new ChopHelp(chops.size(), events.size());
00497 
00498    for(UInt_t ichop=0;ichop<chops.size();ichop++) {
00499      double tot = 0;
00500      for(UInt_t idig=0;idig<chops[ichop].size(); idig++) {
00501        tot += chops[ichop][idig].GetCharge(CalDigitType::kSigCorr);
00502      }
00503      chophelp->chopph[ichop]=tot;
00504    }
00505 
00506    for(UInt_t ievt=0;ievt<events.size();ievt++) {
00507      double tot = 0;
00508      for(UInt_t idig=0;idig<eventDigits[ievt].size(); idig++) {
00509        tot += eventDigits[ievt][idig].GetCharge(CalDigitType::kSigCorr);
00510      }
00511      chophelp->candph[ievt]=tot;
00512    }
00513 
00514    // Fill correlation matrix.
00515 
00516    for(UInt_t ievt=0;ievt<events.size();ievt++) {
00517      for(UInt_t ichop=0;ichop<chops.size();ichop++) {
00518        double tot = 0;
00519        for(UInt_t idig=0;idig<eventDigits[ievt].size(); idig++) {
00520          CandDigitHandle dig = eventDigits[ievt][idig];
00521          for(UInt_t idig2=0;idig2<chops[ichop].size(); idig2++) {
00522            if(dig == chops[ichop][idig2]) 
00523              tot+=dig.GetCharge(CalDigitType::kSigCorr);
00524          }
00525        }
00526        chophelp->matchmatrix[ievt*chops.size() + ichop] = tot;
00527      }
00528    } // uuuuugly again
00529 
00530 
00531 
00532    // Now find the best matches and fill the eff/pur values.
00533    for(UInt_t ievt=0; ievt<events.size(); ievt++) {
00534      int bestchop=0;
00535      Float_t bestmatch=-1;
00536      for(UInt_t ichop=0;ichop<chops.size();ichop++) {
00537        if(chophelp->matchmatrix[ievt*chops.size() + ichop] > bestmatch) {
00538          bestmatch = chophelp->matchmatrix[ievt*chops.size() + ichop];
00539          bestchop=ichop;
00540        }
00541      }
00542      chophelp->chopmatch[ievt] = bestchop;
00543 
00544      chophelp->estpurity[ievt] = chophelp->matchmatrix[ievt*chops.size() + bestchop] / chophelp->candph[ievt];
00545      chophelp->estcompleteness[ievt] = chophelp->matchmatrix[ievt*chops.size() + bestchop] / chophelp->chopph[bestchop];
00546    }
00547    
00548    
00549    return chophelp;
00550 }
00551 
00552 

Generated on Mon Jun 16 14:56:49 2008 for loon by  doxygen 1.3.9.1