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
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.;
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,
00089 float next_ph,
00090 float
00091 )
00092 {
00093 float climb = next_ph - this_ph;
00094
00095
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
00100
00101
00102
00103
00104
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
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
00160
00161
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
00172
00173
00174
00175
00176 std::vector<int> digit_tdc(ndigits);
00177 std::vector<UInt_t> digit_plane(ndigits);
00178
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
00183
00184
00185
00186 }
00187
00188
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
00200 MSG("Chop",Msg::kDebug) << "Running Chop_Sharp2" << endl;
00201
00202 UInt_t numBins = tlast-tfirst;
00203
00204
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
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
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;
00240 if(biggest_size<=0.) break;
00241
00242
00243
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
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
00262 if(binsUsed[bin_start-1]) {
00263 done = true;
00264 }
00265
00266 if(!done) {
00267 bin_start--;
00268 }
00269 };
00270
00271
00272
00273 done = false;
00274 while(!done) {
00275
00276
00277 if((energyVsTime[bin_stop+1] < 500.) && (bin_stop+1 < biggest_bin+7)) {
00278
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);
00285 }
00286 }
00287
00288
00289 if(binsUsed[bin_stop+1]) {
00290
00291 done = true;
00292 }
00293
00294
00295 if(!done) bin_stop++;
00296 }
00297
00298
00299 for(UInt_t i=bin_start; i<=bin_stop; i++) {
00300 binsUsed[i] = 1;
00301 }
00302
00303 } while(true);
00304
00305
00306
00307 std::sort(cuts.begin(), cuts.end());
00308
00309
00310 std::vector<Chop> chops(cuts.size());
00311
00312
00313
00314 for(UInt_t icut = 1; icut<= cuts.size(); icut++) {
00315 int bin_start = cuts[icut-1]+1;
00316 int bin_stop = cuts[icut]-1;
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
00330
00331
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
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
00347
00348 int chop1 = icut;
00349 int chop2 = icut+1;
00350
00351
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
00367 for(UInt_t ic=0; ic<contested_digits.size(); ic++) {
00368
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
00376
00377
00378
00379
00380
00381
00382
00383
00384
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
00395
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
00408
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 }
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
00432
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++) {
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
00462 if(chops[chopfrom].fStripEnergy[seid] <= sigcor) {
00463
00464 if(chops[chopto].fStripEnergy[seid] > 0) {
00465
00466 chops[chopto].push_back(digit);
00467 chops[chopfrom].erase(chops[chopfrom].begin() + idig);
00468 idig--;
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 }
00478 }
00479
00480 }
00481
00482
00484
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
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
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 }
00529
00530
00531
00532
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