00001
00002
00003
00004
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 #include "DataUtil/GetRawBlock.h"
00030
00031 ClassImp(ChopHelper)
00032
00033 CVSID( " $Id: ChopHelper.cxx,v 1.5 2010/01/06 18:34:37 rhatcher Exp $ ");
00034
00035 struct compareDigitTimes : public binary_function<const CandDigitHandle&, const CandDigitHandle&, bool> {
00036 bool operator()(const CandDigitHandle& d1, const CandDigitHandle& d2) {
00037 return (d1.GetTime() < d2.GetTime());
00038 }
00039 };
00040
00041 const RawChannelId kQieRcid(Detector::kNear,ElecType::kQIE,0,0,false,false);
00042 const float k1pe = 100.;
00043
00044
00045
00046 ChopHelper::ChopHelper(const MomNavigator* mom) : fMom(mom)
00047 {
00048 }
00049
00050
00051 ChopHelper::~ChopHelper()
00052 {
00053 }
00054
00055 class Chop : public DigitVector{
00056 public:
00057 std::map<PlexStripEndId,float> fStripEnergy;
00058 std::map<int, float> fPlaneEnergy;
00059 float fTotalEnergy;
00060 bool fDirty;
00061
00062 Chop() : fDirty(false) {};
00063
00064 void Add(CandDigitHandle& cdh) {
00065 fDirty = true;
00066 push_back(cdh);
00067 }
00068
00069 void BuildMaps() {
00070 if(fDirty) {
00071 fStripEnergy.clear();
00072 fPlaneEnergy.clear();
00073 fTotalEnergy = 0;
00074 for(UInt_t i=0;i<size();i++) {
00075 float sigcor = (*this)[i].GetCharge(CalDigitType::kSigCorr);
00076 PlexStripEndId seid = (*this)[i].GetPlexSEIdAltL().GetBestSEId();
00077 if(seid.IsValid()) {
00078 fStripEnergy[seid] += sigcor;
00079 fPlaneEnergy[seid.GetPlane()] += sigcor;
00080 fTotalEnergy += sigcor;
00081 }
00082 }
00083 }
00084 fDirty = false;
00085 }
00086 };
00087
00088
00089 bool ChopHelper::ShouldSplit( float this_ph,
00090 float next_ph,
00091 float
00092 )
00093 {
00094 float climb = next_ph - this_ph;
00095
00096
00097 float max_climb = 2.5*sqrt(fabs(this_ph)/k1pe)*k1pe;
00098 if(max_climb < (6 * k1pe)) max_climb=max_climb*2;
00099
00100
00101
00102
00103
00104
00105
00106
00107 if( climb >= max_climb ) return true;
00108 else return false;
00109 }
00110
00111
00112
00113 ChopHelp* ChopHelper::GetChopHelp( const CandHandle* ev1,
00114 const CandHandle* ev2,
00115 const CandHandle* ev3,
00116 const CandHandle* ev4,
00117 const CandHandle* ev5 )
00118 {
00119 std::vector<CandHandle> v;
00120 if(ev1) v.push_back(*ev1);
00121 if(ev2) v.push_back(*ev2);
00122 if(ev3) v.push_back(*ev3);
00123 if(ev4) v.push_back(*ev4);
00124 if(ev5) v.push_back(*ev5);
00125
00126 return GetChopHelp(v);
00127 }
00128
00129 ChopHelp* ChopHelper::GetChopHelp( std::vector<CandHandle> events )
00130 {
00131
00135
00136
00137 bool cDoRecombobulation = false;
00138
00139 if (events.size()==0) return 0;
00140
00141 const RawDigitDataBlock* rddb = DataUtil::GetRawBlock<RawDigitDataBlock>(fMom);
00142 if (!rddb) {
00143 MSG("Chop", Msg::kWarning) << "No RawDigitDataBlock in RawRecord." << endl;
00144 return 0;
00145 }
00146
00147 const VldContext &context = *(events[0].GetVldContext());
00148 if(context.GetDetector() != Detector::kNear)
00149 MSG("Chop",Msg::kError) << "Running the Sharp2 algorithm on FD data is a no-no!" << endl;
00150
00151 Calibrator& cal = Calibrator::Instance();
00152 UgliGeomHandle ugli(context);
00153
00154
00155
00156
00157 DigitVector digits;
00158 std::vector<DigitVector> eventDigits(events.size());
00159 for(UInt_t i=0;i<events.size();i++) {
00160 eventDigits[i].FillFrom(&(events[i]));
00161 digits.FillFrom(eventDigits[i],0,eventDigits[i].size(), true);
00162 }
00163
00164 UInt_t ndigits = digits.size();
00165
00166
00167
00168
00169
00170
00171 std::vector<int> digit_tdc(ndigits);
00172 std::vector<UInt_t> digit_plane(ndigits);
00173
00174 for(UInt_t i=0;i<ndigits;i++) {
00175 digit_tdc[i] = (cal.GetTDCFromTime(digits[i].GetTime(CalTimeType::kNone), kQieRcid));
00176 digit_plane[i] = digits[i].GetPlexSEIdAltL().GetPlane();
00177
00178
00179
00180
00181 }
00182
00183
00184 Int_t tfirst = digit_tdc[0];
00185 Int_t tlast = digit_tdc[0];
00186 for(UInt_t i=0;i<ndigits;i++) {
00187 if(digit_tdc[i] < tfirst) tfirst = digit_tdc[i];
00188 if(digit_tdc[i] > tlast ) tlast = digit_tdc[i];
00189 }
00190 tfirst-=5;
00191 tlast +=5;
00192
00193
00194
00195 MSG("Chop",Msg::kDebug) << "Running Chop_Sharp2" << endl;
00196
00197 UInt_t numBins = tlast-tfirst;
00198
00199
00200 std::vector<float> energyVsTime(numBins,0.);
00201
00202 for(UInt_t idig = 0; idig < ndigits; idig++ ) {
00203 float sigcor = digits[idig].GetCharge(CalDigitType::kSigCorr);
00204 int tdcbin = digit_tdc[idig]-tfirst;
00205 if((tdcbin<0) || ((int)numBins<=tdcbin)) MSG("Chop",Msg::kDebug) << "Whups!" << endl;
00206 else if(digit_plane[idig]<=PlexPlaneId::LastPlaneNearCalor()) {
00207 energyVsTime[digit_tdc[idig]-tfirst] += sigcor;
00208 }
00209 }
00210
00211 std::vector<int> cuts;
00212
00213
00214 std::vector<char> binsUsed(numBins,0);
00215 binsUsed[0]=1;
00216 binsUsed[numBins-1]=1;
00217
00218 cuts.push_back(0);
00219 cuts.push_back(numBins-1);
00220
00221
00222 do {
00223
00224 UInt_t biggest_bin = 99999;
00225 float biggest_size = 0;
00226 for(UInt_t i=0;i<numBins;i++) {
00227 if(binsUsed[i]==0)
00228 if(energyVsTime[i]>biggest_size) {
00229 biggest_size = energyVsTime[i];
00230 biggest_bin = i;
00231 }
00232 }
00233
00234 if(biggest_bin==99999) break;
00235 if(biggest_size<=0.) break;
00236
00237
00238
00239 UInt_t bin_start = biggest_bin;
00240 UInt_t bin_stop = biggest_bin;
00241
00242 if(binsUsed[bin_start-1]==0) bin_start--;
00243 if(binsUsed[bin_stop +1]==0) bin_stop++;
00244
00245 bool done = false;
00246 while(!done) {
00247
00248
00249 if(ShouldSplit(energyVsTime[bin_start],
00250 energyVsTime[bin_start-1],
00251 bin_start-1 - biggest_bin ) ) {
00252 done = true;
00253 cuts.push_back(bin_start);
00254 }
00255
00256
00257 if(binsUsed[bin_start-1]) {
00258 done = true;
00259 }
00260
00261 if(!done) {
00262 bin_start--;
00263 }
00264 };
00265
00266
00267
00268 done = false;
00269 while(!done) {
00270
00271
00272 if((energyVsTime[bin_stop+1] < 500.) && (bin_stop+1 < biggest_bin+7)) {
00273
00274 } else {
00275 if(ShouldSplit(energyVsTime[bin_stop],
00276 energyVsTime[bin_stop+1],
00277 bin_stop+1 - biggest_bin) ) {
00278 done = true;
00279 cuts.push_back(bin_stop);
00280 }
00281 }
00282
00283
00284 if(binsUsed[bin_stop+1]) {
00285
00286 done = true;
00287 }
00288
00289
00290 if(!done) bin_stop++;
00291 }
00292
00293
00294 for(UInt_t i=bin_start; i<=bin_stop; i++) {
00295 binsUsed[i] = 1;
00296 }
00297
00298 } while(true);
00299
00300
00301
00302 std::sort(cuts.begin(), cuts.end());
00303
00304
00305 std::vector<Chop> chops(cuts.size());
00306
00307
00308
00309 for(UInt_t icut = 1; icut<= cuts.size(); icut++) {
00310 int bin_start = cuts[icut-1]+1;
00311 int bin_stop = cuts[icut]-1;
00312
00313 int tdc_start = bin_start + tfirst;
00314 int tdc_stop = bin_stop + tfirst;
00315
00316 for(UInt_t idig = 0; idig < ndigits; idig++ ) {
00317 int tdc = digit_tdc[idig];
00318 if((tdc>=(int)tdc_start)&&(tdc<=(int)tdc_stop)) {
00319 chops[icut].Add(digits[idig]);
00320 }
00321 }
00322 }
00323
00324
00325
00326
00327 for(UInt_t icut = 1; icut< cuts.size()-1; icut++) {
00328 int contested_bin = cuts[icut];
00329 int contested_tdc = contested_bin + tfirst;
00330
00331
00332 DigitVector contested_digits;
00333 for(UInt_t idig = 0; idig < ndigits; idig++ ) {
00334 int tdc = digit_tdc[idig];
00335 if(tdc==contested_tdc) {
00336 contested_digits.push_back(digits[idig]);
00337 }
00338 }
00339
00340 if(contested_digits.size()>0) {
00341
00342
00343 int chop1 = icut;
00344 int chop2 = icut+1;
00345
00346
00347 chops[chop1].BuildMaps();
00348 chops[chop2]. BuildMaps();
00349
00350 MSG("Chop",Msg::kDebug) << "Dealing with contested bin " << cuts[icut]
00351 << " with " << contested_digits.size() << " contested digits." << endl;
00352
00353 int assign_strip1 = 0;
00354 int assign_strip2 = 0;
00355 int assign_plane1 = 0;
00356 int assign_plane2 = 0;
00357 int assign_total1 = 0;
00358 int assign_total2 = 0;
00359
00360
00361
00362 for(UInt_t ic=0; ic<contested_digits.size(); ic++) {
00363
00364 CandDigitHandle digit = contested_digits[ic];
00365 PlexStripEndId seid =digit.GetPlexSEIdAltL().GetBestSEId();
00366 float chop1stripE = chops[chop1].fStripEnergy[seid];
00367 float chop2stripE =chops[chop2 ].fStripEnergy[seid];
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382 if(chop1stripE > chop2stripE){
00383 chops[chop1].Add(digit);
00384 assign_strip1++;
00385 } else if(chop2stripE > chop1stripE){
00386 chops[chop2].Add(digit);
00387 assign_strip2++;
00388 } else {
00389
00390
00391
00392 float chop1planeE = chops[chop1].fPlaneEnergy[seid.GetPlane()];
00393 float chop2planeE = chops[chop2].fPlaneEnergy[seid.GetPlane()];
00394 if(chop1planeE > chop2planeE){
00395 chops[chop1].Add(digit);
00396 assign_plane1++;
00397 } else if(chop2planeE > chop1planeE){
00398 chops[chop2].Add(digit);
00399 assign_plane2++;
00400 } else {
00401
00402
00403
00404 if(chops[chop1].fTotalEnergy>=chops[chop2].fTotalEnergy) {
00405 chops[chop1].Add(digit);
00406 assign_total1++;
00407 } else {
00408 chops[chop2].Add(digit);
00409 assign_total2++;
00410 }
00411 }
00412 }
00413 }
00414
00415
00416 MSG("Chop",Msg::kDebug) << " Assigned by strip: " << assign_strip1 << "/" << assign_strip2
00417 << " by plane: " << assign_plane1 << "/" << assign_plane2
00418 << " by total: " << assign_total1 << "/" << assign_total2
00419 << endl;
00420 }
00421
00422
00423 }
00424
00426
00427
00428 if(cDoRecombobulation) {
00429
00430 for(UInt_t ichop=1;ichop<chops.size();ichop++) chops[ichop].BuildMaps();
00431
00432 for(UInt_t icut=1;icut<cuts.size()-1;icut++) {
00433 for(int ilr = 0; ilr<2; ilr++) {
00434 int contested_tdc;
00435 int chopfrom;
00436 int chopto;
00437 if(ilr==0) {
00438 contested_tdc = cuts[icut]-1 + tfirst;
00439 chopfrom = icut;
00440 chopto = icut+1;
00441 } else {
00442 contested_tdc = cuts[icut]+1 + tfirst;
00443 chopfrom = icut+1;
00444 chopto = icut;
00445 }
00446
00447 int moved = 0;
00448
00449 for(UInt_t idig = 0; idig<chops[chopfrom].size(); idig++) {
00450 CandDigitHandle digit = chops[chopfrom][idig];
00451 int tdc = (cal.GetTDCFromTime(digit.GetTime(CalTimeType::kNone), kQieRcid));
00452 if(tdc == contested_tdc) {
00453 PlexStripEndId seid =digit.GetPlexSEIdAltL().GetBestSEId();
00454 float sigcor = digits[idig].GetCharge(CalDigitType::kSigCorr);
00455
00456
00457 if(chops[chopfrom].fStripEnergy[seid] <= sigcor) {
00458
00459 if(chops[chopto].fStripEnergy[seid] > 0) {
00460
00461 chops[chopto].push_back(digit);
00462 chops[chopfrom].erase(chops[chopfrom].begin() + idig);
00463 idig--;
00464 moved++;
00465 }
00466 }
00467 }
00468 }
00469
00470 MSG("Chop",Msg::kDebug) << "Recombobulated " << moved << " digits in bin " << contested_tdc-tfirst
00471 << " from chop " << chopfrom << " to chop " << chopto << endl;
00472 }
00473 }
00474
00475 }
00476
00477
00479
00480
00481 for(UInt_t i=0;i<chops.size();i++) {
00482 if(chops[i].size()==0) {
00483 chops.erase(chops.begin()+i);
00484 i--;
00485 }
00486 }
00487
00489
00490
00491 ChopHelp* chophelp = new ChopHelp(chops.size(), events.size());
00492
00493 for(UInt_t ichop=0;ichop<chops.size();ichop++) {
00494 double tot = 0;
00495 for(UInt_t idig=0;idig<chops[ichop].size(); idig++) {
00496 tot += chops[ichop][idig].GetCharge(CalDigitType::kSigCorr);
00497 }
00498 chophelp->chopph[ichop]=tot;
00499 }
00500
00501 for(UInt_t ievt=0;ievt<events.size();ievt++) {
00502 double tot = 0;
00503 for(UInt_t idig=0;idig<eventDigits[ievt].size(); idig++) {
00504 tot += eventDigits[ievt][idig].GetCharge(CalDigitType::kSigCorr);
00505 }
00506 chophelp->candph[ievt]=tot;
00507 }
00508
00509
00510
00511 for(UInt_t ievt=0;ievt<events.size();ievt++) {
00512 for(UInt_t ichop=0;ichop<chops.size();ichop++) {
00513 double tot = 0;
00514 for(UInt_t idig=0;idig<eventDigits[ievt].size(); idig++) {
00515 CandDigitHandle dig = eventDigits[ievt][idig];
00516 for(UInt_t idig2=0;idig2<chops[ichop].size(); idig2++) {
00517 if(dig == chops[ichop][idig2])
00518 tot+=dig.GetCharge(CalDigitType::kSigCorr);
00519 }
00520 }
00521 chophelp->matchmatrix[ievt*chops.size() + ichop] = tot;
00522 }
00523 }
00524
00525
00526
00527
00528 for(UInt_t ievt=0; ievt<events.size(); ievt++) {
00529 int bestchop=0;
00530 Float_t bestmatch=-1;
00531 for(UInt_t ichop=0;ichop<chops.size();ichop++) {
00532 if(chophelp->matchmatrix[ievt*chops.size() + ichop] > bestmatch) {
00533 bestmatch = chophelp->matchmatrix[ievt*chops.size() + ichop];
00534 bestchop=ichop;
00535 }
00536 }
00537 chophelp->chopmatch[ievt] = bestchop;
00538
00539 chophelp->estpurity[ievt] = chophelp->matchmatrix[ievt*chops.size() + bestchop] / chophelp->candph[ievt];
00540 chophelp->estcompleteness[ievt] = chophelp->matchmatrix[ievt*chops.size() + bestchop] / chophelp->chopph[bestchop];
00541 }
00542
00543
00544 return chophelp;
00545 }
00546
00547