00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00014
00015
00016 #include "Calibrator/CalLinearity.h"
00017 #include "MessageService/MsgService.h"
00018 #include "DatabaseInterface/DbiOutRowStream.h"
00019 #include "DatabaseInterface/DbiResultSet.h"
00020 #include "DatabaseInterface/DbiValidityRec.h"
00021 #include "TGraph.h"
00022 #include "TF1.h"
00023 #include "TCanvas.h"
00024 #include "TMath.h"
00025 #include <cmath>
00026 ClassImp(CalLinearity)
00027
00028
00029
00030 CVSID("$Id: CalLinearity.cxx,v 1.7 2007/01/15 19:52:00 rhatcher Exp $ \n CVSID_DBIRESULTPTR ");
00031
00032 #include "DatabaseInterface/DbiResultPtr.tpl"
00033 template class DbiResultPtr<CalLinearity>;
00034
00035 #include "DatabaseInterface/DbiWriter.tpl"
00036 template class DbiWriter<CalLinearity>;
00037
00038 CalLinearity::CalLinearity(int aggno, PlexStripEndId &seid, int task): fAggregateNo(aggno), fStripEndKey(seid.BuildPlnStripEndKey()), fStripEndId(seid.GetEncoded())
00039 {
00040 fTask = task;
00041 switch (task) {
00042 case 2:
00043 fSplines[0].startx = 0;
00044 fSplines[0].starty = 0;
00045 fSplines[0].slope = 1;
00046 fSplines[0].alpha = 0;
00047 fSplines[0].endx = 7000;
00048 fSplines[0].endy = 7000;
00049 fNsplines = 1;
00050 break;
00051 default:
00052 MSG("Calib",Msg::kWarning)<<"CalLinearity doesn't know how to construct a default map for task "<<task<<endl;
00053 };
00054
00055 }
00056
00057 CalLinearity::CalLinearity(int aggno, PlexStripEndId &seid,
00058 vector<float> &x,vector<float> &y): fAggregateNo(aggno), fStripEndKey(seid.BuildPlnStripEndKey()),fStripEndId(seid.GetEncoded())
00059 {
00060
00061 assert(x.size()==y.size());
00062 fTask=2;
00063
00064 unsigned int i;
00065 unsigned int q;
00066 int target=0;
00067 for (q=0;q<x.size();q++) {
00068
00069 if (x[q]>100 && y[q]>100) break;
00070 }
00071
00072
00073 for (i=q;i<x.size();i++) {
00074
00075 if (y[i]>6000) break;
00076
00077 }
00078 if (i==q) {
00079 fSplines[0].startx = 0;
00080 fSplines[0].starty = 0;
00081 fSplines[0].slope = 1;
00082 fSplines[0].alpha = 0;
00083 fSplines[0].endx = 16000;
00084 fSplines[0].endy = 16000;
00085 ++target;
00086 goto banana;
00087
00088 }
00089
00090 {
00091 TGraph g1(i-q,&(x[q]),&(y[q]));
00092 TF1 line("line","x*[0]",0,x[i-1] + 1);
00093 g1.Fit("line","RQ");
00094 fSplines[0].startx = 0;
00095 fSplines[0].starty = 0;
00096 fSplines[0].slope = line.GetParameter(0);
00097 fSplines[0].alpha = 0;
00098 fSplines[0].endx = x[i-1];
00099 fSplines[0].endy = (x[i-1])*fSplines[0].slope;
00100
00101
00102
00103
00104 ++target;
00105 }
00106 cout<<fSplines[0].slope<<fSplines[0].endx<<" "<<fSplines[0].endy<<endl;
00107
00108 {
00109
00110 TGraph g2(x.size(),&(x[0]),&(y[0]));
00111 for(;;){
00112 unsigned int j;
00113 for (j=i;j<x.size();j++) {
00114 if (x[j]-x[i]>1000) break;
00115 }
00116 if (j==x.size()) break;
00117 if (target>8) target=8;
00118 if ((j-i)>1) {
00119 cout<<"target "<<target<<" Fit from "<<i<<" to "<<j<<" of "<<x.size()<< " ["<<x[i]<<":"<<x[j]<<" "<<y[i]<<":"<<y[j]<<"]\n";
00120 fSplines[target].startx = fSplines[target-1].endx;
00121 fSplines[target].starty = fSplines[target-1].endy;
00122 TF1 func("func","[0]+[2]*(x-[1]) + [3]*(x-[1])*(x-[1])",x[i]-1,x[j]+1);
00123 func.SetParameter(0,fSplines[target].starty);
00124 func.SetParameter(1,fSplines[target].startx);
00125 func.SetParLimits(0,fSplines[target].starty,fSplines[target].starty);
00126 func.SetParLimits(1,fSplines[target].startx,fSplines[target].startx);
00127 func.SetParLimits(3,-10,0);
00128 g2.Fit("func","RQ");
00129 fSplines[target].endx = x[j];
00130 fSplines[target].endy = func.Eval(x[j]);
00131 fSplines[target].slope = func.GetParameter(2);
00132 fSplines[target].alpha = func.GetParameter(3);
00133 }
00134 else if ((j-i)==1) {
00135 cout<<"Line from "<<i<<" to "<<j<<" ["<<x[i]<<":"<<x[j]<<"]\n";
00136 fSplines[target].startx = fSplines[target-1].endx;
00137 fSplines[target].starty = fSplines[target-1].endy;
00138 fSplines[target].endx = x[j];
00139 fSplines[target].endy = y[j];
00140 fSplines[target].slope = (fSplines[target].endy-fSplines[target].starty)/(fSplines[target].endx-fSplines[target].startx);
00141 fSplines[target].alpha = 0;
00142 }
00143 else if ((j-i)==0) {
00144 cout<<"No data\n";
00145 --target;
00146 }
00147 i=j;
00148 ++target;
00149 cout<<" "<<fSplines[target-1].endx<<" "<<fSplines[target-1].endy<<endl;
00150 }
00151 }
00152
00153 banana:
00154
00155
00156 fSplines[target].startx = fSplines[target-1].endx;
00157 fSplines[target].starty = fSplines[target-1].endy;
00158 fSplines[target].endx = 160000;
00159 fSplines[target].slope = fSplines[target-1].slope + 2*fSplines[target-1].alpha*(fSplines[target-1].endx-fSplines[target-1].startx);
00160 if ( fSplines[target].slope<0) fSplines[target].slope =0;
00161 fSplines[target].endy = fSplines[target].starty + fSplines[target].slope*(fSplines[target].endx-fSplines[target].startx);
00162 fSplines[target].alpha = 0;
00163
00164 fNsplines = target+1;
00165
00166
00167 float xscale = fSplines[0].slope;
00168
00169
00170
00171
00172
00173 cout<<xscale<<" "<<fSplines[fNsplines-1].endx<<" "<<fSplines[fNsplines-1].endy<<endl;
00174
00175 for (int i=0;i<fNsplines;i++) {
00176 fSplines[i].startx*=xscale;
00177 fSplines[i].endx*=xscale;
00178 fSplines[i].slope/=xscale;
00179 fSplines[i].alpha/=(xscale*xscale);
00180 }
00181
00182
00183 if (this->ADCtoLin(8000) < 8000)
00184 {
00185 cout<<" "<<this->ADCtoLin(8000)<<" ^^^^^^^^^^^^^\n";
00186 fNsplines=1;
00187 fSplines[0].startx = 0;
00188 fSplines[0].starty = 0;
00189 fSplines[0].slope = 1;
00190 fSplines[0].alpha = 0;
00191 fSplines[0].endx = 20000;
00192 fSplines[0].endy = 20000;
00193
00194
00195 }
00196
00197
00198 if (fSplines[fNsplines-1].endx < 20000) {
00199 fSplines[fNsplines-1].endx = 20000 ;
00200 fSplines[fNsplines-1].endy = fSplines[fNsplines-1].starty + fSplines[fNsplines-1].slope*(fSplines[fNsplines-1].endx-fSplines[fNsplines-1].startx) ;
00201
00202 }
00203
00204 cout<<xscale<<" "<<fSplines[fNsplines-1].endx<<" "<<fSplines[fNsplines-1].endy<<endl;
00205
00206 }
00207
00208
00209
00210
00211 CalLinearity::CalLinearity(int aggno, PlexStripEndId &seid, vector<float> &x, vector<float> &y, vector<float> &, vector<float> & , CalLinearity & lin, bool horizontal) :fAggregateNo(aggno), fStripEndKey(seid.BuildPlnStripEndKey()), fStripEndId(seid.GetEncoded())
00212 {
00213 bool zero = false;
00214 fTask = 2;
00215 top:
00216 if (zero||x.size()==0||y.size()==0) {
00217 fSplines[0].startx = 0;
00218 fSplines[0].starty = 0;
00219 fSplines[0].slope = 1;
00220 fSplines[0].alpha = 0;
00221 fSplines[0].endx = 7000;
00222 fSplines[0].endy = 7000;
00223 fNsplines = 1;
00224 fNumXPoints = 0;
00225 }
00226 else {
00227
00228
00229
00230
00231
00232
00233 vector<float> xlin;
00234
00235 int middle=0;
00236 for (unsigned int i=0;i<x.size();i++) {
00237 if (x[i]<lin.GetLimit()) {
00238 xlin.push_back(lin.ADCtoLin(x[i]));
00239
00240 } else {
00241 break;
00242 }
00243 if (middle==0) {
00244 if (y[i]>7000) middle = i-1;
00245 }
00246 }
00247 if (xlin.size()==0) {
00248 zero = true;
00249 goto top;
00250 }
00251 if (middle==0) middle = xlin.size()-1;
00252 fNumXPoints = xlin.size();
00253 TGraph graph(xlin.size(),&(xlin[0]),&(y[0]));
00254
00255 TF1 line("line","x*[0]",0,xlin[middle] + 1);
00256 graph.Fit("line","RQ");
00257
00258
00259
00260
00261 fSplines[0].startx = 0;
00262 fSplines[0].starty = 0;
00263 fSplines[0].slope = line.GetParameter(0);
00264 fSplines[0].alpha = 0;
00265 fSplines[0].endx = xlin[middle] + 1;
00266 fSplines[0].endy = (xlin[middle] + 1)*fSplines[0].slope;
00267 int target=0;
00268
00269
00270
00271 ++target;
00272 for (unsigned int i=middle+1;i<xlin.size();i++) {
00273
00274 if (target>6) target=6;
00275 fSplines[target].startx = fSplines[target-1].endx;
00276 fSplines[target].endx = xlin[i];
00277 fSplines[target].endy = y[i];
00278 fSplines[target].starty = fSplines[target-1].endy;
00279 fSplines[target].slope = fSplines[target-1].slope + fSplines[target-1].alpha*(fSplines[target-1].endx-fSplines[target-1].startx);
00280 fSplines[target].alpha = (fSplines[target].endy-fSplines[target].starty -
00281 fSplines[target].slope*
00282 (fSplines[target].endx-fSplines[target].startx))/
00283 ((fSplines[target].endx-fSplines[target].startx)*(fSplines[target].endx-fSplines[target].startx));
00284
00285
00286
00287
00288 ++target;
00289 }
00290
00291
00292 if (horizontal) {
00293 fSplines[target].startx = fSplines[target-1].endx;
00294 fSplines[target].starty = fSplines[target-1].endy;
00295 fSplines[target].endx = 160000;
00296 fSplines[target].endy = fSplines[target].starty;
00297 fSplines[target].slope = 0;
00298 fSplines[target].alpha = 0;
00299
00300
00301
00302 }
00303 else {
00304 fSplines[target].startx = fSplines[target-1].endx;
00305 fSplines[target].starty = fSplines[target-1].endy;
00306 fSplines[target].endx = 160000;
00307 fSplines[target].slope = fSplines[target-1].slope + fSplines[target-1].alpha*(fSplines[target-1].endx-fSplines[target-1].startx);
00308 fSplines[target].endy = fSplines[target].starty + fSplines[target].slope*(fSplines[target].endx-fSplines[target].startx);
00309 fSplines[target].alpha = 0;
00310
00311
00312
00313 }
00314 fNsplines = target + 1;
00315
00316
00317
00318 float xscale = fSplines[0].slope;
00319
00320
00321
00322
00323 for (int i=0;i<fNsplines;i++) {
00324 fSplines[i].startx*=xscale;
00325 fSplines[i].endx*=xscale;
00326 fSplines[i].slope/=xscale;
00327 fSplines[i].alpha/=(xscale*xscale);
00328 }
00329
00330
00331 if (this->ADCtoLin(8000) < 8000)
00332 {
00333 cout<<" "<<this->ADCtoLin(8000)<<" ^^^^^^^^^^^^^\n";
00334 fNsplines=1;
00335 fSplines[0].startx = 0;
00336 fSplines[0].starty = 0;
00337 fSplines[0].slope = 1;
00338 fSplines[0].alpha = 0;
00339 fSplines[0].endx = 20000;
00340 fSplines[0].endy = 20000;
00341
00342
00343 }
00344
00345 }
00346 }
00347
00348
00349 void CalLinearity::Fill(DbiResultSet& rs,
00350 const DbiValidityRec* )
00351 {
00352 rs >> fAggregateNo >> fTask >> fStripEndKey >> fStripEndId >> fNumber;
00353 for (int i=0;i<40;i++) rs >> fParam[i];
00354
00355
00356 fNsplines = fNumber;
00357 int pos = 0;
00358 for (int i=0;i<fNsplines;i++) {
00359 fSplines[i].startx = fParam[pos++];
00360 fSplines[i].starty = fParam[pos++];
00361 fSplines[i].slope = fParam[pos++];
00362 fSplines[i].alpha = fParam[pos++];
00363 if (i>0) {
00364 fSplines[i-1].endx = fSplines[i].startx;
00365 fSplines[i-1].endy = fSplines[i].starty;
00366 }
00367 }
00368 fSplines[fNsplines-1].endx = fParam[pos];
00369 fSplines[fNsplines-1].endy = fSplines[fNsplines-1].starty +
00370 fSplines[fNsplines-1].slope*(fSplines[fNsplines-1].endx-fSplines[fNsplines-1].startx) +
00371 fSplines[fNsplines-1].alpha*(fSplines[fNsplines-1].endx-fSplines[fNsplines-1].startx)*
00372 (fSplines[fNsplines-1].endx-fSplines[fNsplines-1].startx);
00373 }
00374
00375
00376 void CalLinearity::Store(DbiOutRowStream& ors,
00377 const DbiValidityRec* ) const
00378 {
00379
00380 int pos = 0;
00381 for (int i=0;i<fNsplines;i++) {
00382 fParam[pos++] = fSplines[i].startx;
00383 fParam[pos++] = fSplines[i].starty;
00384 fParam[pos++] = fSplines[i].slope;
00385 fParam[pos++] = fSplines[i].alpha;
00386 }
00387 fParam[pos] = fSplines[fNsplines-1].endx;
00388 for (int i=pos+1;i<40;i++) fParam[i] =0;
00389 fNumber = fNsplines;
00390 ors << fAggregateNo << fTask << fStripEndKey << fStripEndId << fNumber;
00391 for (int i=0;i<40;i++) ors << fParam[i];
00392
00393 }
00394
00395
00396 Float_t CalLinearity::ADCtoLin(const Float_t charge) const
00397 {
00398 switch (fTask) {
00399 default:
00400 MSG("Calib",Msg::kWarning)<<"CalLinearity::ADCtoLin has task "
00401 << fTask <<" but doesn't know how to decode it. \n Defaulting to task 2\n";
00402 case 2:
00403
00404
00405 for (int i=0;i<fNsplines; i++) {
00406 if (fSplines[i].endy >= charge && fSplines[i].starty<= charge) {
00407
00408 float m = fSplines[i].slope;
00409 float a = fSplines[i].alpha;
00410 float c = charge - fSplines[i].starty;
00411 float x0 = fSplines[i].startx;
00412 if (a==0) return x0 + c/m;
00413 return x0 + (a/fabs(a)) * (-m + TMath::Sqrt(m*m+4*a*c))/(2*fabs(a));
00414 }
00415 }
00416
00417
00418 if (fNsplines==1) return fSplines[0].endx;
00419 return fSplines[fNsplines-2].endx;
00420 break;
00421 };
00422 }
00423
00424 Float_t CalLinearity::LintoADC(const Float_t charge) const
00425 {
00426 switch (fTask) {
00427 default:
00428 MSG("Calib",Msg::kWarning)<<"CalLinearity::ADCtoLin has task "
00429 << fTask <<" but doesn't know how to decode it. \n Defaulting to task 2\n";
00430 case 2:
00431
00432
00433 for (int i=0;i<fNsplines; i++) {
00434 if (fSplines[i].endx >= charge && fSplines[i].startx<= charge) {
00435
00436 float m = fSplines[i].slope;
00437 float a = fSplines[i].alpha;
00438 float y0 = fSplines[i].starty;
00439 float x0 = fSplines[i].startx;
00440 return y0 + m*(charge-x0) + a*(charge-x0)*(charge-x0);
00441 }
00442 }
00443
00444
00445
00446 if (fNsplines==1) return fSplines[0].endy;
00447 return fSplines[fNsplines-2].endy;
00448 break;
00449 };
00450 }