00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include "CalVaLinearity.h"
00012 #include "PulserLinearityCalScheme.h"
00013 #include "MessageService/MsgService.h"
00014 #include "PulserCalibration/PulserConventions.h"
00015 #include "math.h"
00016
00017 ClassImp(PulserLinearityCalScheme)
00018 CVSID("$Id: PulserLinearityCalScheme.cxx,v 1.12 2006/05/18 22:45:00 tagg Exp $");
00019
00020
00021 PulserLinearityCalScheme::PulserLinearityCalScheme() : fPlex(0)
00022 {
00023
00024
00025 MSG("Calib",Msg::kVerbose) << "PulserLinearityCalScheme::PulserLinearityCalScheme"
00026 << endl;
00027 Registry r;
00028 InitializeConfig(r);
00029 }
00030
00031
00032 PulserLinearityCalScheme::~PulserLinearityCalScheme()
00033 {
00034 }
00035
00036
00037
00038
00039 FloatErr PulserLinearityCalScheme::GetLinearized(FloatErr rawcharge,
00040 const PlexStripEndId& seid) const
00041 {
00042
00043
00044
00045
00046 if(seid.GetDetector() == Detector::kNear) {
00047 return GetLinNear(rawcharge, seid);}
00048 if(seid.GetDetector() == Detector::kFar) {
00049 return GetLinFar(rawcharge, seid);}
00050
00051 MSG("Calib",Msg::kError) << "Stripend with invalid detector, cannot linearize"<<endl;
00052 FloatErr result(0.,0.);
00053 return result;
00054 }
00055
00056
00057 FloatErr PulserLinearityCalScheme::DecalLinearity(FloatErr lin,
00058 const PlexStripEndId& seid) const
00059 {
00070
00071 if(seid.GetDetector() == Detector::kNear) {
00072 return DecalLinNear(lin, seid);}
00073 if(seid.GetDetector() == Detector::kFar) {
00074 return DecalLinFar(lin, seid);}
00075
00076 MSG("Calib",Msg::kError) << "Stripend with invalid detector, cannot apply non-linearity"<<endl;
00077 FloatErr result(0.,0.);
00078 return result;
00079 }
00080
00081
00082 FloatErr PulserLinearityCalScheme::GetLinNear(FloatErr rawcharge,
00083 const PlexStripEndId& seid) const
00084 {
00085
00086
00087
00088
00089
00090
00091 Float_t rawchargev = rawcharge.GetValue();
00092 Float_t rawchargee = rawcharge.GetError();
00093 std::pair< PlexPinDiodeId,PlexPinDiodeId > pdids;
00094 PlexPinDiodeId pdidlo, pdidhi;
00095 FloatErr result;
00096 float topin = -9999.;
00097
00098 UInt_t seidkey = (UInt_t)seid.BuildPlnStripEndKey();
00099
00100
00101 Int_t numpoints = 0;
00102 Int_t numpoints2 = 0;
00103
00104 vector<float> pmtmeani;
00105 vector<float> pinmeani;
00106
00107
00108 const PulserGain *pmt = fNearGain.GetRowByIndex(seidkey);
00109
00110
00111 pdids = GetPinDiodeId(seid);
00112
00113 pdidhi = pdids.second;
00114 pdidlo = pdids.first;
00115
00116
00117 const PulserGainPin *pin = 0;
00118 if (pdidlo.GetGain()==1) {
00119 pin = fPin.GetRowByIndex(pdidlo.GetEncoded());
00120 } else {
00121 pin = 0;
00122 }
00123
00124
00125
00126 float linslp = -9999.;
00127 float linchi2 = -9999.;
00128 float linxoff = -9999.;
00129
00130
00131 const CalPulserFits *linfit = fNearLow.GetRowByIndex(seidkey);
00132
00133 if(linfit==0) {
00134 MAXMSG("Calib",Msg::kWarning,10)
00135 << "No CalPulserFits Near-Low database row for StripEnd "
00136 << seid << " indexed as " << seid.BuildPlnStripEndKey() << endl;
00137 linslp = 0.;
00138 linchi2 = 0;
00139 linxoff = 0;
00140
00141 } else {
00142
00143 linslp = linfit->GetSlope();
00144 linchi2 = linfit->GetChisq();
00145 linxoff = linfit->GetXOffset();
00146
00147 }
00148
00149
00150 if (pmt && pin) {
00151
00152
00153 numpoints = pmt->GetNumPoints();
00154
00155
00156 numpoints2 = pin->GetNumPoints();
00157
00158 if (numpoints!=numpoints2) {
00159 MAXMSG("Calib",Msg::kError,10) << "There are " << numpoints << " points at stripend and "
00160 << numpoints2 << " points at pin!!!" << endl;
00161 }
00162
00163
00164
00165 const Float_t * pmtmean = pmt->GetMean();
00166 const Float_t * pmtent = pmt->GetNumEntries();
00167 const Float_t * pmttrg = pmt->GetNumTriggers();
00168
00169 const Float_t * pinmean = pin->GetMean();
00170 const Float_t * pinent = pin->GetNumEntries();
00171 const Float_t * pintrg = pin->GetNumTriggers();
00172
00173
00174
00175 for (int ipoint=0; ipoint< numpoints; ipoint++) {
00176 if (pmttrg[ipoint]){
00177 pmtmeani.push_back(pmtmean[ipoint]*pmtent[ipoint]/pmttrg[ipoint]);
00178 }
00179 else {
00180 pmtmeani.push_back(pmtmean[ipoint]);
00181 }
00182
00183 if (pintrg[ipoint]){
00184 pinmeani.push_back(pinmean[ipoint]*pinent[ipoint]/pintrg[ipoint]);
00185 }
00186 else {
00187 pinmeani.push_back(pinmean[ipoint]);
00188 }
00189
00190 if ((ipoint>0 && rawchargev<pmtmeani[ipoint] && rawchargev>=pmtmeani[ipoint-1])||
00191 (ipoint==numpoints-1 && rawchargev>pmtmeani[ipoint])){
00192
00193
00194
00195
00196
00197
00198 MSG("Calib",Msg::kDebug) << "numEntries at pmt: " << *(pmtent+ipoint) << endl;
00199 MSG("Calib",Msg::kDebug) << "numEntries at pin: " << *(pinent+ipoint) << endl;
00200
00201 if ((pinmeani[ipoint] - pinmeani[ipoint-1])>0) {
00202 Float_t intslp = (pmtmeani[ipoint] - pmtmeani[ipoint-1])/
00203 (pinmeani[ipoint] - pinmeani[ipoint-1]);
00204 if (intslp>0) {
00205
00206 topin = pinmeani[ipoint-1] + (rawchargev-pmtmeani[ipoint-1])/intslp;
00207 } else {
00208 MAXMSG("Calib",Msg::kError,10) << "Invalid slope: " << intslp << endl;
00209 topin = -9999.;
00210 }
00211 } else {
00212
00213 MAXMSG("Calib",Msg::kError,10) << "Invalid pin values: " << pinmeani[ipoint] << ", "
00214 << pinmeani[ipoint-1] << endl;
00215 topin=-9999.;
00216 }
00217 }
00218 }
00219 } else {
00220 MAXMSG("Calib",Msg::kError,10) <<"Can't get data from database for pmt and pin for stripend "<<seid<<endl;
00221 topin=-9999.;
00222 }
00223
00224
00225
00226
00227
00228
00229
00230 if (topin>0.
00231 && linfit && linslp>0. && linchi2>0 && linxoff>-100.
00232 &&rawchargev>6000.
00233 && pmtmeani[numpoints-1]>6000){
00234
00235 MSG("Calib",Msg::kVerbose)<< "pin value = " << topin << " slope from table (fit) = " << linslp << " Fit chi^2 = " << linchi2 << endl;
00236 result.Set((topin-linxoff)*linslp,rawchargee);
00237 }else{
00238 result.Set(rawchargev,rawchargee);
00239
00240 }
00241 return result;
00242 }
00243
00244
00245
00246 FloatErr PulserLinearityCalScheme::DecalLinNear(FloatErr lin,
00247 const PlexStripEndId& seid) const
00248 {
00259
00260 Float_t linchargev = lin.GetValue();
00261 Float_t linchargee = lin.GetError();
00262 std::pair< PlexPinDiodeId,PlexPinDiodeId > pdids;
00263 PlexPinDiodeId pdidlo, pdidhi;
00264 FloatErr result;
00265 float topin = -9999.;
00266
00267 UInt_t seidkey = (UInt_t)seid.BuildPlnStripEndKey();
00268
00269
00270 Int_t numpoints = 0;
00271 Int_t numpoints2 = 0;
00272
00273 vector<float> pmtmeani;
00274 vector<float> pinmeani;
00275
00276
00277 const PulserGain *pmt = fNearGain.GetRowByIndex(seidkey);
00278
00279
00280 pdids = GetPinDiodeId(seid);
00281
00282 pdidhi = pdids.second;
00283 pdidlo = pdids.first;
00284
00285
00286 const PulserGainPin *pin = 0;
00287 if (pdidlo.GetGain()==1) {
00288 pin = fPin.GetRowByIndex(pdidlo.GetEncoded());
00289 } else {
00290 pin = 0;
00291 }
00292
00293
00294
00295 float linslp = -9999.;
00296 float linchi2 = -9999.;
00297 float linxoff = -9999.;
00298
00299
00300 const CalPulserFits *linfit = fNearLow.GetRowByIndex(seidkey);
00301
00302 if(linfit==0) {
00303 MAXMSG("Calib",Msg::kWarning,10)
00304 << "No CalPulserFits Near-Low database row for StripEnd "
00305 << seid << " indexed as " << seid.BuildPlnStripEndKey() << endl;
00306 linslp = 0.;
00307 linchi2 = 0;
00308 linxoff = 0;
00309
00310 } else {
00311
00312 linslp = linfit->GetSlope();
00313 linchi2 = linfit->GetChisq();
00314 linxoff = linfit->GetXOffset();
00315
00316 }
00317
00318 float rawchargev = -9999.;
00319
00320 if (linfit && linslp>0. && linchi2>0 && linxoff>-100.
00321 &&linchargev>6000.){
00322 topin = linchargev/linslp + linxoff;
00323 }
00324 else {
00325 result.Set(linchargev,linchargee);
00326 return result;
00327 }
00328
00329 if (pmt && pin) {
00330 numpoints = pmt->GetNumPoints();
00331 numpoints2 = pin->GetNumPoints();
00332
00333 if (numpoints!=numpoints2) {
00334 MAXMSG("Calib",Msg::kError,10) << "There are " << numpoints << " points at stripend and "
00335 << numpoints2 << " points at pin!!!" << endl;
00336 }
00337
00338
00339
00340 const Float_t * pmtmean = pmt->GetMean();
00341 const Float_t * pmtent = pmt->GetNumEntries();
00342 const Float_t * pmttrg = pmt->GetNumTriggers();
00343
00344 const Float_t * pinmean = pin->GetMean();
00345 const Float_t * pinent = pin->GetNumEntries();
00346 const Float_t * pintrg = pin->GetNumTriggers();
00347
00348 for (int ipoint=0; ipoint< numpoints; ipoint++) {
00349 if (pmttrg[ipoint]){
00350 pmtmeani.push_back(pmtmean[ipoint]*pmtent[ipoint]/pmttrg[ipoint]);
00351 }
00352 else {
00353 pmtmeani.push_back(pmtmean[ipoint]);
00354 }
00355
00356 if (pintrg[ipoint]){
00357 pinmeani.push_back(pinmean[ipoint]*pinent[ipoint]/pintrg[ipoint]);
00358 }
00359 else {
00360 pinmeani.push_back(pinmean[ipoint]);
00361 }
00362
00363 if ((ipoint>0 && topin<pinmeani[ipoint] && topin>=pinmeani[ipoint-1])
00364 ||(ipoint==numpoints-1 && topin > pinmeani[ipoint])){
00365
00366
00367 if ((pmtmeani[ipoint] - pmtmeani[ipoint-1])>0) {
00368 Float_t intslp = (pinmeani[ipoint] - pinmeani[ipoint-1])/
00369 (pmtmeani[ipoint] - pmtmeani[ipoint-1]);
00370 if (intslp>0) {
00371
00372 rawchargev = pmtmeani[ipoint-1] + (topin-pinmeani[ipoint-1])/intslp;
00373 } else {
00374 MAXMSG("Calib",Msg::kError,10) << "Invalid slope: " << intslp << endl;
00375 rawchargev = -9999.;
00376 }
00377 } else {
00378
00379 MAXMSG("Calib",Msg::kError,10) << "Invalid pin values: " << pinmeani[ipoint] << ", "
00380 << pinmeani[ipoint-1] << endl;
00381 rawchargev=-9999.;
00382 }
00383 }
00384 }
00385 } else {
00386 MAXMSG("Calib",Msg::kError,10) <<"Can't get data from database for pmt and pin for stripend "<<seid<<endl;
00387 rawchargev=-9999.;
00388 }
00389
00390 if (rawchargev!=-9999.){
00391 result.Set(rawchargev,linchargee);
00392 }
00393 else result.Set(linchargev,linchargee);
00394
00395 return result;
00396 }
00397
00398
00399
00400 FloatErr PulserLinearityCalScheme::GetLinFar(FloatErr rawcharge,
00401 const PlexStripEndId& seid) const
00402 {
00403
00404
00405
00406 if( !seid.IsValid() ) {
00407 MAXMSG("Calib",Msg::kWarning,1) << seid << " is invalid: no linearity calibrations will be applied to invalid stripends" << endl;
00408 return rawcharge;
00409 }
00410
00411
00412 if( seid.IsVetoShield() ) {
00413
00414
00415 return rawcharge;
00416 }
00417
00418
00419
00420 if(rawcharge.GetValue() < 200.) return rawcharge;
00421
00422
00423 UInt_t seidkey = (UInt_t)seid.BuildPlnStripEndKey();
00424 const CalPulserFits* fit = fNearFar.GetRowByIndex(seidkey);
00425
00426
00427 if(fit != 0) {
00428 if(FitIsOK(*fit)) {
00429
00430
00431 if(fit->GetFitType()==1 && rawcharge.GetValue()<=fit->GetAdcMax()) {
00432 return rawcharge;
00433 }
00434
00435 else if(fit->GetFitType()>=5) {
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445 FloatErr result = GetCorrected(rawcharge,*fit,0);
00446 if(result.GetValue()>=rawcharge.GetValue()) {
00447 if(rawcharge.GetValue()<=fit->GetAdcMax()) {
00448 return result;
00449 }
00450 MeanCor others = GetMeanCorrection(rawcharge,seid,0);
00451 if(others.nstrips>0) {
00452 Float_t diff = result.GetValue()-rawcharge.GetValue() - others.meancor;
00453 result += FloatErr(0.,fabs(diff));
00454 }
00455 else {
00456 result.SetError(2.*result.GetError());
00457 }
00458 return result;
00459 }
00460 }
00461 }
00462 }
00463 else {
00464 MAXMSG("Calib",Msg::kWarning,20) << "No CALPULSERFITS entry for " << seid << endl;
00465 }
00466
00467
00468
00469
00470 MeanCor others = GetMeanCorrection(rawcharge,seid,0);
00471 if(others.nstrips > 0) {
00472 MAXMSG("Calib",Msg::kDebug,20) <<"Using "<<others.nstrips<<" stripends to calibrate "<<seid<<endl;
00473 FloatErr result = rawcharge + FloatErr(others.meancor,others.rmscor);
00474 return result;
00475 }
00476
00477
00478 MAXMSG("Calib",Msg::kWarning,20) << "Stripend" << seid << " not calibrated" << endl;
00479 FloatErr result(rawcharge.GetValue(),rawcharge.GetError());
00480 result *= FloatErr(1.,0.5);
00481 return result;
00482
00483 }
00484
00485
00486
00487 FloatErr PulserLinearityCalScheme::DecalLinFar(FloatErr lin,
00488 const PlexStripEndId& seid) const
00489 {
00490
00491
00492
00493 if( !seid.IsValid() ) {
00494 MAXMSG("Calib",Msg::kWarning,1) << seid << " is invalid: no non-linearity will be applied to invalid stripends" << endl;
00495 return lin;
00496 }
00497
00498
00499 if( seid.IsVetoShield() ) {
00500 MAXMSG("Calib",Msg::kWarning,1) << "No non-linearity will be applied to veto-shield channels" << endl;
00501 return lin;
00502 }
00503
00504
00505 if(lin.GetValue() < 200.) return lin;
00506
00507
00508 UInt_t seidkey = (UInt_t)seid.BuildPlnStripEndKey();
00509 const CalPulserFits* fit = fNearFar.GetRowByIndex(seidkey);
00510
00511
00512 if(fit != 0) {
00513 if(FitIsOK(*fit)) {
00514
00515
00516 if(fit->GetFitType()==1 && lin.GetValue()<=fit->GetAdcMax()) {
00517 return lin;
00518 }
00519
00520 else if(fit->GetFitType()>=5) {
00521
00522
00523 FloatErr result = GetCorrected(lin,*fit,1);
00524
00525 result.SetError(lin.GetError());
00526 return result;
00527 }
00528 }
00529 }
00530 else {
00531 MAXMSG("Calib",Msg::kWarning,20) << "No CALPULSERFITS entry for " << seid << endl;
00532 }
00533
00534
00535
00536 MeanCor others = GetMeanCorrection(lin,seid,1);
00537 if(others.nstrips > 0) {
00538 MAXMSG("Calib",Msg::kInfo,20) <<"Using "<<others.nstrips<<" stripends to unlinearize "<<seid<<endl;
00539 FloatErr result = lin + FloatErr(others.meancor,others.rmscor);
00540
00541 result.SetError(lin.GetError());
00542 return result;
00543 }
00544
00545
00546 MAXMSG("Calib",Msg::kWarning,20) << "Stripend" << seid << " not unlinearized" << endl;
00547 return lin;
00548
00549 }
00550
00551
00552
00553 FloatErr PulserLinearityCalScheme::GetCorrected(FloatErr incharge, const CalPulserFits& fit, Int_t flag)
00554 {
00555
00556
00557
00558
00559 Double_t x = incharge.GetValue();
00560 Double_t dx = incharge.GetError();
00561
00562 Double_t par[8];
00563 par[0] = fit.GetFitType();
00564 if(flag == 0) par[0] -= 1.;
00565 par[1] = fit.GetPar1();
00566 par[2] = fit.GetPar2();
00567 par[3] = fit.GetPar3();
00568 par[4] = fit.GetPar4();
00569 par[5] = 0.;
00570 par[6] = fit.GetXOffset();
00571 par[7] = 1./fit.GetSlope();
00572
00573 Double_t xcor = CalVaLinearity::FitFunction(&x,par);
00574 xcor = (xcor-par[6])/par[7];
00575
00576
00577 Double_t dxcor = fit.GetMeanRes();
00578 if(dxcor < 0.5) dxcor = 0.5;
00579 dxcor *= 0.01*fabs(xcor-x);
00580 dxcor = sqrt(dx*dx+dxcor*dxcor);
00581
00582 FloatErr result(xcor,dxcor);
00583 return result;
00584 }
00585
00586
00587
00588 PulserLinearityCalScheme::MeanCor PulserLinearityCalScheme::GetMeanCorrection(FloatErr incharge, const PlexStripEndId& seid, Int_t flag) const
00589 {
00590
00591
00592
00593
00594
00595
00596 MeanCor result;
00597
00598 PlexSEIdAltL altlist = fPlex->GetSEIdAltL(fPlex->GetRawChannelId(seid));
00599 Int_t n = 0;
00600 Float_t sumcor = 0.;
00601 Float_t sumcor2 = 0.;
00602 for (PlexSEIdAltL::const_iterator it = altlist.begin(); it!=altlist.end();it++) {
00603 const CalPulserFits* fit = fNearFar.GetRowByIndex((*it).GetSEId().BuildPlnStripEndKey());
00604 if(fit != 0) {
00605 if(FitIsOK(*fit)) {
00606 Float_t cor;
00607 if(fit->GetFitType()==1) {cor = 0.;}
00608 else {cor = GetCorrected(incharge,*fit,flag).GetValue() - incharge.GetValue();}
00609
00610
00611 if(flag==0 && (cor<0. || incharge.GetValue()>fit->GetAdcMax())) {continue;}
00612 if(flag !=0 && (cor>0. || incharge.GetValue()+cor>fit->GetAdcMax())) {continue;}
00613 sumcor += cor;
00614 sumcor2 += cor*cor;
00615 n++;
00616 }
00617 }
00618 }
00619
00620 if(n > 0) {
00621 sumcor /= n;
00622 sumcor2 = sumcor2/n - sumcor*sumcor;
00623 if(sumcor2 > 0.) {
00624 sumcor2 = sqrt(sumcor2);
00625 }
00626 else {
00627 sumcor2 = 0.05*sumcor;
00628 }
00629 }
00630
00631 result.nstrips = n;
00632 result.meancor = sumcor;
00633 result.rmscor = sumcor2;
00634 return result;
00635 }
00636
00637
00638
00639 Bool_t PulserLinearityCalScheme::FitIsOK(const CalPulserFits& fit)
00640 {
00641
00642 if(fit.GetFitType()<0) return false;
00643
00644
00645 Int_t npar = 1;
00646 if(fit.GetFitType()==5) npar = 3;
00647 if(fit.GetFitType()==25) {
00648 npar = 5;
00649 if(fabs(fit.GetXOffset())>1.e-5) npar = 6;
00650 }
00651 if(fit.GetNPFit()-npar < 10) return false;
00652 if(fit.GetChisq()/(fit.GetNPFit()-npar) > 3.) return false;
00653
00654
00655 if(fit.GetMeanRes() > 1.) return false;
00656
00657
00658 if(fit.GetFitType()>1) {
00659 if(fit.GetPar1()<10000. || fit.GetPar1()>20000.) return false;
00660 }
00661
00662
00663 return true;
00664 }
00665
00666
00667
00668
00669 void PulserLinearityCalScheme::ConfigModified()
00670 {
00671 }
00672
00673
00674
00675 void PulserLinearityCalScheme::PrintConfig( std::ostream& ) const
00676 {
00677 }
00678
00679
00680
00681 void PulserLinearityCalScheme::DoReset(const VldContext& vc)
00682 {
00683
00684
00685
00686
00687 if (vc.GetDetector()==Detector::kNear) {
00688 fNearGain.NewQuery(vc,Pulser::kNearEnd);
00689 MSG("Calib",Msg::kDebug) << "Done querying PULSERGAIN." << endl;
00690
00691 fPin.NewQuery(vc,1);
00692 MSG("Calib",Msg::kDebug) << "Done querying PULSERGAINPIN." << endl;
00693 }
00694
00695
00696 if (vc.GetDetector()==Detector::kNear) {
00697 fNearLow.NewQuery(vc,Pulser::kNearLow);
00698 fNearHigh.NewQuery(vc,Pulser::kNearHigh);
00699 }
00700 if (vc.GetDetector()==Detector::kFar) {
00701 fNearFar.NewQuery(vc,Pulser::kNearFar);
00702 }
00703
00704 MSG("Calib",Msg::kDebug) << "Done querying CALPULSERFITS." << endl;
00705
00706 if (fPlex) delete fPlex;
00707 MSG("Calib",Msg::kDebug) << "Delete Plex. " << fPlex << endl;
00708
00709 fPlex = new PlexHandle(vc);
00710 MSG("Calib",Msg::kDebug) << "Get new plexhandle." << endl;
00711
00712 }
00713
00715 std::pair< PlexPinDiodeId,PlexPinDiodeId > PulserLinearityCalScheme::GetPinDiodeId(const PlexStripEndId & seid) const
00716 {
00720
00721 PlexPinDiodeId pdid;
00722 PlexLedId lid;
00723 std::pair< PlexPinDiodeId,PlexPinDiodeId > pdids;
00724
00725 if (fPlex) {
00726 lid = fPlex->GetLedId(seid);
00727
00728 pdids = fPlex->GetPinDiodeIds(lid);
00729
00730
00731 }
00732
00733 return pdids;
00734
00735
00736 }
00737
00738
00739