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

PulserGainFit.cxx

Go to the documentation of this file.
00001 
00002 // $Id: PulserGainFit.cxx,v 1.11 2007/01/23 17:01:56 rhatcher Exp $
00003 //
00004 // PulserGainFit
00005 //
00006 // Perform linear fits to pulser gain data and store results
00007 // in CalPulserFits table in database.
00008 //
00009 // Author: Pat Ward 13/09/2005
00010 //
00011 // $Log: PulserGainFit.cxx,v $
00012 // Revision 1.11  2007/01/23 17:01:56  rhatcher
00013 // Ongoing changes to ROOT headers mean we need more explicit #include's
00014 // in various user classes (ie. can't rely on implicit includes).
00015 //
00016 // Revision 1.10  2006/09/15 13:18:20  cpw1
00017 // Make min/max aggregate configurable
00018 //
00019 // Revision 1.9  2006/08/23 13:48:22  cpw1
00020 // Add setable DBSimMask and DBCommment
00021 //
00022 // Revision 1.8  2006/04/19 20:00:55  rhatcher
00023 // convert DetectorType:: to Detector:: everywhere.
00024 //
00025 // Revision 1.7  2006/04/07 22:02:06  tagg
00026 // Add <math.h> to make gcc 4.0 happy
00027 //
00028 // Revision 1.6  2006/03/29 11:21:50  cpw1
00029 // Updates for 60-point gain curve
00030 //
00031 // Revision 1.5  2006/01/27 09:19:20  cpw1
00032 // Fix bug in loop index in FarMeans
00033 //
00034 // Revision 1.4  2006/01/25 14:07:48  cpw1
00035 // Mods for new definition of CalPulserFits; split Run method into RunPinFits and RunNearFarFits and add code for near-far fits
00036 //
00037 // Revision 1.3  2006/01/12 20:01:43  murgia
00038 // Abot DbiWriter only if last pass.
00039 // Use SetRange to define fit interval.
00040 //
00041 // Revision 1.2  2005/10/27 09:35:21  cpw1
00042 // Use zero-corrected values in fits and add number of fit points to CalPulserFits
00043 //
00044 // Revision 1.1  2005/09/28 09:39:59  cpw1
00045 // Fill CalPulserFits table
00046 //
00047 //
00049 
00050 #include "TH1.h"
00051 
00052 #include "MessageService/MsgService.h"
00053 #include "Calibrator/CalVaLinearity.h"
00054 #include "PulserCalibration/PulserGainFit.h"
00055 #include "DatabaseInterface/DbiResultSet.h"
00056 #include "DatabaseInterface/DbiValidityRec.h"
00057 #include "Plex/PlexPinDiodeId.h"
00058 #include "Plex/PlexStripEndId.h"
00059 #include <math.h>
00060 
00061 ClassImp(PulserGainFit)
00062 
00063 CVSID("$Id: PulserGainFit.cxx,v 1.11 2007/01/23 17:01:56 rhatcher Exp $\n  \
00064       CVSID_DBIRESULTPTR ");
00065 
00066 // Constructors and destructor
00067 PulserGainFit::PulserGainFit(const Detector::Detector_t &det, VldTimeStamp &tsin, VldTimeStamp &tein)
00068 {
00069   // With this constructor we set the validity range for the output to be
00070   // the same as that in the input database entry for each aggregate
00071   fUseSameValidity = 1;
00072 
00073   // Set detector and timestamps
00074   fDetector = det;
00075   fStartin = tsin;
00076   fEndin = tein;
00077   MSG("Pulser",Msg::kInfo)<<"PulserGainFit created for detector "<<Detector::AsString(fDetector)<<endl;
00078   MSG("Pulser",Msg::kInfo)<<"Input timestart = "<<fStartin.AsString()<<endl;
00079   MSG("Pulser",Msg::kInfo)<<"Input timeend = "<<fEndin.AsString()<<endl;
00080   MSG("Pulser",Msg::kInfo)<<"Output timestart and timend will be taken from validity range of input data"<<endl;
00081 
00082   // Initialize output times so can create a range, but these values are not used
00083   fStartout = fStartin;
00084   fEndout = fEndin;
00085 
00086   this->Init();
00087 
00088 }
00089 
00090 PulserGainFit::PulserGainFit(const Detector::Detector_t &det, VldTimeStamp &tsin, VldTimeStamp &tein, VldTimeStamp &tsout, VldTimeStamp &teout)
00091 {
00092   // With this constructor we set the validity range for the output is set
00093   // by the user
00094   fUseSameValidity = 0;
00095 
00096   // Set detector and timestamps
00097   fDetector = det;
00098   fStartin = tsin;
00099   fEndin = tein;
00100   fStartout = tsout;
00101   fEndout = teout;
00102   MSG("Pulser",Msg::kInfo)<<"PulserGainFit created for detector "<<Detector::AsString(fDetector)<<endl;
00103   MSG("Pulser",Msg::kInfo)<<"Input timestart = "<<fStartin.AsString()<<endl;
00104   MSG("Pulser",Msg::kInfo)<<"Input timeend = "<<fEndin.AsString()<<endl;
00105   MSG("Pulser",Msg::kInfo)<<"Output timestart = "<<fStartout.AsString()<<endl;
00106   MSG("Pulser",Msg::kInfo)<<"Output timeend = "<<fEndout.AsString()<<endl;
00107 
00108   this->Init();
00109 
00110 }
00111 
00112 PulserGainFit::~PulserGainFit() {
00113   if(fFile) {
00114     fFile->Write();
00115     fFile->Close();
00116   }
00117 }
00118 
00119 // Initialization
00120 void PulserGainFit::Init() {
00121   // Set default configuration variables
00122   Registry r;
00123   r.Set("WriteDB",0);
00124   r.Set("DBSimMask",5);
00125   r.Set("DBName","temp");
00126   r.Set("DBComment","");
00127   r.Set("WritePlots",0);
00128   r.Set("PlotsFile","plots.root");
00129   r.Set("Adcmin",300.);
00130   r.Set("Adcmax",8000.);
00131   r.Set("Npass",1);
00132   r.Set("MinAggNo",-1);
00133   r.Set("MaxAggNo",-1);
00134   InitializeConfig(r); 
00135 
00136   // Create fit functions
00137   // Line
00138   fFitLine = new TF1("line","[0]*(x-[1])");
00139   fFitLine->FixParameter(1,0.);
00140 
00141   // Pole only 
00142   fFitPole = new TF1("pole",CalVaLinearity::FitFunction,200.,15000.,8);
00143   // First parameter is fit function type
00144   fFitPole->FixParameter(0,5.);
00145   // Parameter 5 is not used
00146   fFitPole->FixParameter(5,0.);
00147   // Fix pedestal to zero 
00148   fFitPole->FixParameter(6,0.);
00149   // k3, k4 not used for pole only
00150   fFitPole->FixParameter(3,0.);
00151   fFitPole->FixParameter(4,0.);
00152 
00153   // Pole+kicker with fixed pedestal
00154   fFitPK1 = new TF1("pk1",CalVaLinearity::FitFunction,200.,15000.,8);
00155   // First parameter is fit function type
00156   fFitPK1->FixParameter(0,25.);
00157   // Parameter 5 is not used
00158   fFitPK1->FixParameter(5,0.);
00159   // Fix pedestal to zero 
00160   fFitPK1->FixParameter(6,0.);
00161 
00162   // Pole+kicker with free pedestal
00163   fFitPK2 = new TF1("pk2",CalVaLinearity::FitFunction,200.,15000.,8);
00164   // First parameter is fit function type
00165   fFitPK2->FixParameter(0,25.);
00166   // Parameter 5 is not used
00167   fFitPK2->FixParameter(5,0.);
00168 
00169   fFile = 0;
00170   fNextra = 0;
00171 }
00172 
00173 // Set configuration
00174 void PulserGainFit::ConfigModified()
00175 {
00176   fWriteDB = GetConfig().GetInt("WriteDB");
00177   fDBSimMask = GetConfig().GetInt("DBSimMask");
00178   fDBName = GetConfig().GetCharString("DBName");
00179   fDBComment = GetConfig().GetCharString("DBComment");
00180   fWritePlots = GetConfig().GetInt("WritePlots");
00181   fPlotsFile = GetConfig().GetCharString("PlotsFile");
00182   GetConfig().Get("Adcmin",fAdcmin);
00183   GetConfig().Get("Adcmax",fAdcmax);
00184   GetConfig().Get("Npass",fNpass);
00185   GetConfig().Get("MinAggNo",fMinAggNo);
00186   GetConfig().Get("MaxAggNo",fMaxAggNo);
00187 
00188   fWriterl.SetDbName(fDBName);
00189   fWriterh.SetDbName(fDBName);
00190   fWriternf.SetDbName(fDBName);
00191 
00192   MSG("Pulser",Msg::kInfo)<<"Configuration: WriteDB = "<<fWriteDB<<" WritePlots = " <<fWritePlots<<" Adcmin = "<<fAdcmin<<" Adcmax = "<<fAdcmax<<" Npass = "<<fNpass<<endl;
00193   if(fWriteDB > 0) {MSG("Pulser",Msg::kInfo)<<"Writing to database "<<fDBName<<" with SimMask "<<fDBSimMask<<" Comment "<<fDBComment<<endl;}
00194   if(fWritePlots > 0) {MSG("Pulser",Msg::kInfo)<<"Writing plots to "<<fPlotsFile<<endl;}
00195 }
00196 
00197 // Set timestamps for including extra runs for split gain curves
00198 void PulserGainFit::AddRun(VldTimeStamp &ts, VldTimeStamp &te) {
00199 
00200   // Check max runs not exceeded
00201   if(fNextra == 3) {
00202   MSG("Pulser",Msg::kError)<<"Maximum runs exceeded, ignoring run"<<endl;
00203   return;
00204   }
00205 
00206   // Warning if trying to use same validity context for output
00207   if(fUseSameValidity) {
00208   MSG("Pulser",Msg::kWarning)<<"Output validity will not be changed by call to AddRun"<<endl;
00209   }
00210 
00211   // Set time stamps
00212   fStartExtra[fNextra] = ts;
00213   fEndExtra[fNextra] = te;
00214   fNextra++;
00215 }
00216 
00217 // Run stripend v Pin fits on all data and store values
00218 void PulserGainFit::RunPinFits() {
00219 
00220   // Create file for plots and book some histograms
00221   if(fWritePlots) {
00222     if(fFile == 0) {
00223       fFile = new TFile(GetConfig().GetCharString("PlotsFile"),"RECREATE");
00224     }
00225     hSlopeNL = new TH1F("hSlopeNL","hSlopeNL",100,0.,20.);
00226     hSlopeNH = new TH1F("hSlopeNH","hSlopeNH",100,0.,20.);
00227     hSlopeFL = new TH1F("hSlopeFL","hSlopeFL",100,0.,20.);
00228     hSlopeFH = new TH1F("hSlopeFH","hSlopeFH",100,0.,20.);
00229     hChisqNL = new TH1F("hChisqNL","hChisqNF",100,0.,20.);
00230     hChisqNH = new TH1F("hChisqNH","hChisqNF",100,0.,20.);
00231     hChisqFL = new TH1F("hChisqFL","hChisqNF",100,0.,20.);
00232     hChisqFH = new TH1F("hChisqFH","hChisqNF",100,0.,20.);
00233     hNumPointsNL = new TH1F("hNumPointsNL","hNumPointsNL",20,0.,20.);
00234     hNumPointsNH = new TH1F("hNumPointsNH","hNumPointsNH",20,0.,20.);
00235     hNumPointsFL = new TH1F("hNumPointsFL","hNumPointsFL",20,0.,20.);
00236     hNumPointsFH = new TH1F("hNumPointsFH","hNumPointsFH",20,0.,20.);
00237   }
00238 
00239   // Set validity range for output data
00240   // Note that this may be changed later
00241   VldRange range(fDetector,SimFlag::kData,fStartout,fEndout,fDBName);
00242 
00243   // Get plex
00244   VldContext vldc(fDetector,SimFlag::kData,fStartin);
00245   PlexHandle plex(vldc);
00246 
00247   // Retrieve PIN data and store pointers in maps
00248   GetPinData();
00249 
00250   // Instantiate DbiResultPtr for stripend data
00251   DbiResultPtr<PulserGain> rsStripEnd; 
00252 
00253   // Set min and max aggregate number according to detector type,
00254   // unless already set by user
00255   if (fMinAggNo < 0) {
00256     if (fDetector==Detector::kNear) fMinAggNo = 1;
00257     if (fDetector==Detector::kFar) fMinAggNo = 1;
00258   }
00259   MSG("Pulser",Msg::kInfo)<<"Set min aggregate to " << fMinAggNo << " for "<<Detector::AsString(fDetector)<< " detector." <<endl;
00260   if (fMaxAggNo < 0) {
00261     if (fDetector==Detector::kNear) fMaxAggNo = 139;
00262     if (fDetector==Detector::kFar) fMaxAggNo = 980;
00263   }
00264   MSG("Pulser",Msg::kInfo)<<"Set max aggregate to " << fMaxAggNo << " for "<<Detector::AsString(fDetector)<< " detector." <<endl;
00265 
00266   // Loop over near/far ends and fit PMT v PIN
00267   for (int task = 1; task <=2; task++) {
00268 
00269     // Loop over aggregates
00270     for (int aggregateno = fMinAggNo; aggregateno <=fMaxAggNo; aggregateno++ ) {
00271       // Task = 1: Near end v low gain pin
00272       //        2: Far end v low gain pin
00273       //        3: Near end v high gain pin
00274       //        4: Far end v high gain pin
00275 
00276       // Set extended validity context for input data and get data
00277       DbiSqlContext inContext(DbiSqlContext::kStarts,fStartin,fEndin,fDetector,SimFlag::kData);
00278       inContext << " and AGGREGATENO=" << aggregateno;
00279       MSG("Pulser",Msg::kInfo)<<"Aggregate " << aggregateno << endl;
00280       rsStripEnd.NewQuery(inContext,task); 
00281       const int numStripEnd = rsStripEnd.GetNumRows();
00282       MSG("Pulser",Msg::kInfo)<<"Retrieved " << numStripEnd << " stripend rows" << endl;
00283       if (numStripEnd == 0 ) {continue;}
00284 
00285       // Change validity range of output to be that of input 
00286       if(fUseSameValidity) {
00287         const DbiValidityRec* vrec = rsStripEnd.GetValidityRec();
00288         const VldRange& vrng = vrec->GetVldRange();
00289         //vrng.Print();
00290         fStartout = vrng.GetTimeStart();
00291         fEndout = fStartout;
00292         fEndout.Add(VldTimeStamp(3600*24*62,0));
00293         range.SetTimeStart(fStartout);
00294         range.SetTimeEnd(fEndout);
00295       }
00296 
00297       // Allow for two passes
00298       Float_t lxoff = 0.;
00299       Float_t hxoff = 0.;
00300       for (int ipass = 1; ipass <= fNpass; ipass++) {
00301         // Free intercept if this is not last pass
00302         if(ipass < fNpass) {fFitLine->ReleaseParameter(1);}
00303 
00304         // Open DbiWriters 
00305         if(fWriteDB > 0 && ipass == fNpass) {
00306           fWriterl.Open(range,aggregateno,task,0,fDBName);
00307           fWriterh.Open(range,aggregateno,task+2,0,fDBName);
00308         }
00309 
00310         // Loop over rows
00311         for (int ir=0; ir<numStripEnd; ir++) {
00312          //Pointer to row
00313          const PulserGain* rs = rsStripEnd.GetRow(ir);
00314          int skey = rs->GetStripEnd();
00315          PlexStripEndId seid = PlexStripEndId::UnbuildPlnStripEndKey(fDetector, skey);
00316 
00317          // Fit with low gain pin; fix intercept if last pass
00318          if(ipass == fNpass) {fFitLine->FixParameter(1,lxoff);}
00319          Fit(*(lgpinmap.find(aggregateno)->second),*(const_cast<PulserGain*>(rs)));
00320          float lslope = fFitLine->GetParameter(0);
00321          float lslopeerr = fFitLine->GetParError(0);
00322          float lxoffset = fFitLine->GetParameter(1);
00323          float lchisq = fFitLine->GetChisquare();
00324          int lnumpoints = fFitLine->GetNumberFitPoints();
00325          MSG("Pulser",Msg::kDebug)<<"Stripend "<<seid<<" Pin "<<lgpinmap.find(aggregateno)->second->GetPinDiodeId()<<" fit slope= "<<lslope<< " xoffset= "<<lxoffset<<"  numpoints = "<<lnumpoints<<endl;
00326 
00327          if(fWritePlots) {
00328            if(task==1) {
00329              hSlopeNL->Fill(lslope);
00330              hChisqNL->Fill(lchisq);
00331              hNumPointsNL->Fill(lnumpoints);
00332            }
00333            if(task==2) {
00334              hSlopeFL->Fill(lslope);
00335              hChisqFL->Fill(lchisq);
00336              hNumPointsFL->Fill(lnumpoints);
00337            }
00338          }
00339 
00340          if (ipass < fNpass) {
00341            // For mean x offset
00342            lxoff += lxoffset;
00343          }
00344          else {
00345            // Add row to database
00346            if(fWriteDB) {
00347              CalPulserFits lrow(aggregateno,skey,lnumpoints,lslope,lslopeerr,lxoffset,lchisq);
00348              fWriterl << lrow;
00349            }
00350          }
00351 
00352          // Fit with high gain pin; fix intercept if last pass
00353          if(ipass == fNpass) {fFitLine->FixParameter(1,hxoff);}
00354          Fit(*(hgpinmap.find(aggregateno)->second),*(const_cast<PulserGain*>(rs)));
00355          float hslope = fFitLine->GetParameter(0);
00356          float hslopeerr = fFitLine->GetParError(0);
00357          float hxoffset = fFitLine->GetParameter(1);
00358          float hchisq = fFitLine->GetChisquare();
00359          int hnumpoints = fFitLine->GetNumberFitPoints();
00360          MSG("Pulser",Msg::kDebug)<<"Stripend "<<seid<<" Pin "<<hgpinmap.find(aggregateno)->second->GetPinDiodeId()<<" fit slope= "<<hslope<< " xoffset= "<<hxoffset<<"  numpoints = "<<hnumpoints<<endl;
00361 
00362          if(fWritePlots) {
00363            if(task==1) {
00364              hSlopeNH->Fill(hslope);
00365              hChisqNH->Fill(hchisq);
00366              hNumPointsNH->Fill(hnumpoints);
00367            }
00368            if(task==2) {
00369              hSlopeFH->Fill(hslope);
00370              hChisqFH->Fill(hchisq);
00371              hNumPointsFH->Fill(hnumpoints);
00372            }
00373          }
00374          if (ipass < fNpass) {
00375            // For mean x offset
00376            hxoff += hxoffset;
00377          }
00378          else {
00379            // Add row to database
00380            if(fWriteDB) {
00381              CalPulserFits hrow(aggregateno,skey,hnumpoints,hslope,hslopeerr,hxoffset,hchisq);
00382              fWriterh << hrow;
00383            }
00384          }
00385         }
00386         lxoff = lxoff/(float)numStripEnd;
00387         hxoff = hxoff/(float)numStripEnd;
00388       }
00389     }
00390   }
00391 
00392   if(fWriteDB) {
00393     if(fWriterl.IsOpen()) {fWriterl.Close();}
00394     if(fWriterh.IsOpen()) {fWriterh.Close();}
00395   }
00396 
00397 }
00398 
00399 // Retrieve pin data and store pointers
00400 void PulserGainFit::GetPinData() {
00401 
00402   // Set extended validity context for input data
00403   DbiSqlContext inContext(DbiSqlContext::kStarts,fStartin,fEndin,fDetector,SimFlag::kData);
00404 
00405   // Retrieve pin data
00406   DbiResultPtr<PulserGainPin> rsPin("PULSERGAINPIN",inContext,Dbi::kAnyTask); 
00407   const int numPin = rsPin.GetNumRows();
00408   MSG("Pulser",Msg::kInfo)<<"Retrieved " << numPin << " pin rows" << endl;
00409 
00410   // Loop over pin rows and store pointers in maps
00411   for (int ir=0; ir<numPin; ir++) {
00412     //Pointer to row
00413     const PulserGainPin* rs = rsPin.GetRow(ir);
00414     int pingain = rs->GetPinDiodeId().GetGain();
00415     int aggregateno = rs->GetAggregateNo();
00416     //If low gain (gain = 1) 
00417     if (pingain == 1) {
00418       lgpinmap.insert(pair<int,PulserGainPin*>(aggregateno,const_cast<PulserGainPin*>(rs) ));
00419     }
00420     //If high gain (gain = 0)
00421     if (pingain == 0) { 
00422       hgpinmap.insert(pair<int,PulserGainPin*>(aggregateno,const_cast<PulserGainPin*>(rs) ));
00423     }
00424   } // end loop over pin rows
00425 
00426 }
00427 
00428 // Perform fit to stripend v pin
00429 void PulserGainFit::Fit(PulserGainPin &pin, PulserGain &stripend){
00430   // Fit stripend v pin. N.B. arguments reversed from PulserXScale
00431   // as (x,y) corresponds to convention in e.g. TH2, TGraph etc.
00432 
00433   assert(stripend.GetNumPoints()==pin.GetNumPoints());
00434   assert(stripend.GetAggregateNo()==pin.GetAggregateNo());
00435 
00436   // Points for fit
00437   //  const Float_t *x = pin.GetMean();
00438   //  const Float_t *y = stripend.GetMean();
00439   //  const Float_t *er_x = pin.GetError();
00440   //  const Float_t *er_y = stripend.GetError();
00441   Float_t x[40];
00442   Float_t y[40];
00443   Float_t er_x[40];
00444   Float_t er_y[40];
00445   for(int i=0; i<pin.GetNumPoints(); i++) {
00446     x[i] = pin.ZCMean(i);
00447     y[i] = stripend.ZCMean(i);
00448     er_x[i] = pin.ZCError(i);
00449     er_y[i] = stripend.ZCError(i);
00450   }
00451   TGraphErrors g(pin.GetNumPoints(),x,y,er_x,er_y);
00452 
00453   // Set range of fit
00454   float xmin = fAdcmin;
00455   float xmax = fAdcmax;
00456   for (int i=0;i<pin.GetNumPoints();i++) {
00457     if (y[i] < fAdcmin && x[i] > fAdcmin) xmin =x[i]+1;
00458     if (y[i] > fAdcmax && x[i] < fAdcmax) {
00459       xmax = x[i]-1;
00460       break;
00461     }
00462   }
00463 
00464   // Set range (verifies that Adcmin<Adcmax) (SM)
00465   fFitLine->SetRange(fAdcmin,fAdcmax);
00466   // Initialize slope (to prevent a silly value causing problems for
00467   // subsequent fits
00468   fFitLine->SetParameter(0,1.);
00469 
00470   // Perform fit
00471   g.Fit(fFitLine,"Q"," ",xmin,xmax);
00472 
00473 }
00474 
00475 // Run Near v Far fits on all data and store values
00476 void PulserGainFit::RunNearFarFits() {
00477 
00478   // Open file and create ntuple
00479   if(fWritePlots) {
00480     if(fFile==0) {
00481       fFile = new TFile(GetConfig().GetCharString("PlotsFile"),"RECREATE");
00482     }
00483     fNearFarTree = new TTree("nftree","Near-Far fits");
00484     fNearFarTree->Branch("plane",&fPlane,"plane/I");
00485     fNearFarTree->Branch("strip",&fStrip,"strip/I");
00486     fNearFarTree->Branch("bay",&fBay,"bay/I");
00487     fNearFarTree->Branch("rack",&fRack,"rack/I");
00488     fNearFarTree->Branch("tube",&fTube,"tube/I");
00489     fNearFarTree->Branch("pixel",&fPixel,"pixel/I");
00490     fNearFarTree->Branch("spot",&fSpot,"spot/I");
00491     fNearFarTree->Branch("pb",&fPb,"pb/I");
00492     fNearFarTree->Branch("led",&fLed,"led/I");
00493     fNearFarTree->Branch("adcmin",&fMinadc,"adcmin/F");
00494     fNearFarTree->Branch("adcmax",&fMaxadc,"adcmin/F");
00495     fNearFarTree->Branch("ftype",&fFtype,"ftype/I");
00496     fNearFarTree->Branch("npar",&fNpar,"npar/I");
00497     fNearFarTree->Branch("npfit",&fNpfit,"npfit/I");
00498     fNearFarTree->Branch("gain",&fGain,"gain/F");
00499     fNearFarTree->Branch("ped",&fPed,"ped/F");
00500     fNearFarTree->Branch("dped",&fDped,"dped/F");
00501     fNearFarTree->Branch("k1",&fK1,"k1/F");
00502     fNearFarTree->Branch("k2",&fK2,"k2/F");
00503     fNearFarTree->Branch("k3",&fK3,"k3/F");
00504     fNearFarTree->Branch("k4",&fK4,"k4/F");
00505     fNearFarTree->Branch("chisq",&fChisq,"chisq/F");
00506     fNearFarTree->Branch("meanres",&fMeanres,"meanres/F");
00507     fNearFarTree->Branch("maxres",&fMaxres,"maxres/F");
00508     fNearFarTree->Branch("delta200",&fDelta200,"delta200/F");
00509     fNearFarTree->Branch("delta7500",&fDelta7500,"delta7500/F");
00510   }
00511 
00512   // Set validity range for output data
00513   // Note that this may be changed later
00514   VldRange range(fDetector,fDBSimMask,fStartout,fEndout,fDBName);
00515 
00516   // Get plex
00517   VldContext vldc(fDetector,SimFlag::kData,fStartin);
00518   PlexHandle plex(vldc);
00519 
00520   // Instantiate DbiResultPtr for stripend data (near and far)
00521   DbiResultPtr<PulserGain> rsStripEndf[3]; 
00522   DbiResultPtr<PulserGain> rsStripEndn[3];
00523 
00524   // Set min and max aggregate number according to detector type,
00525   // unless already set by user
00526   if (fMinAggNo < 0) {
00527     if (fDetector==Detector::kNear) fMinAggNo = 1;
00528     if (fDetector==Detector::kFar) fMinAggNo = 1;
00529   }
00530   MSG("Pulser",Msg::kInfo)<<"Set min aggregate to " << fMinAggNo << " for "<<Detector::AsString(fDetector)<< " detector." <<endl;
00531   if (fMaxAggNo < 0) {
00532     if (fDetector==Detector::kNear) fMaxAggNo = 139;
00533     if (fDetector==Detector::kFar) fMaxAggNo = 980;
00534   }
00535   MSG("Pulser",Msg::kInfo)<<"Set max aggregate to " << fMaxAggNo << " for "<<Detector::AsString(fDetector)<< " detector." <<endl;
00536 
00537   // Loop over aggregates
00538   for (int aggregateno = fMinAggNo; aggregateno <=fMaxAggNo; aggregateno++ ) {
00539     DbiSqlContext inContext(DbiSqlContext::kStarts,fStartin,fEndin,fDetector,SimFlag::kData);
00540     inContext << " and AGGREGATENO=" << aggregateno;
00541     MSG("Pulser",Msg::kInfo)<<"Aggregate " << aggregateno << endl;
00542     rsStripEndn[0].NewQuery(inContext,Pulser::kNearEnd); 
00543     const int numStripEndn = rsStripEndn[0].GetNumRows();
00544     rsStripEndf[0].NewQuery(inContext,Pulser::kFarEnd); 
00545     const int numStripEndf = rsStripEndf[0].GetNumRows();
00546     MSG("Pulser",Msg::kInfo)<<"Retrieved "<<numStripEndn<<" Near stripend rows and "<<numStripEndf<< " Far stripend rows"<< endl;
00547     if (numStripEndn == 0 || numStripEndf == 0 ) {continue;}
00548 
00549     // Change validity range of output to be that of input 
00550     if(fUseSameValidity) {
00551       const DbiValidityRec* vrec = rsStripEndn[0].GetValidityRec();
00552       const VldRange& vrng = vrec->GetVldRange();
00553       fStartout = vrng.GetTimeStart();
00554       fEndout = fStartout;
00555       fEndout.Add(VldTimeStamp(3600*24*62,0));
00556       range.SetTimeStart(fStartout);
00557       range.SetTimeEnd(fEndout);
00558     }
00559 
00560     // Open DbiWriter
00561     if(fWriteDB) {
00562       Bool_t iok = fWriternf.Open(range,aggregateno,5,0,fDBName,fDBComment);
00563       if(!iok) {MSG("Pulser",Msg::kError)<<"Dbiwriter error"<< endl;}
00564     }
00565 
00566     // Add data from extra runs
00567     if(fNextra>0) {
00568       for(int j=0; j<fNextra; j++) {
00569       DbiSqlContext context(DbiSqlContext::kStarts,fStartExtra[j],fEndExtra[j],fDetector,SimFlag::kData);
00570       context << " and AGGREGATENO=" << aggregateno;
00571       rsStripEndn[j+1].NewQuery(context,Pulser::kNearEnd); 
00572       const int numn = rsStripEndn[j+1].GetNumRows();
00573       rsStripEndf[j+1].NewQuery(context,Pulser::kFarEnd); 
00574       const int numf = rsStripEndf[j+1].GetNumRows();
00575       MSG("Pulser",Msg::kInfo)<<"Retrieved "<<numn<<" Near stripend rows and "<<numf<< " Far stripend rows"<< endl;
00576       }
00577     }
00578 
00579     // Arrays for means of far data
00580     Double_t x[60];
00581     Double_t er_x[60];
00582 
00583     // Calculate means
00584     Int_t test = FarMeans(rsStripEndf,x,er_x);
00585     if(test != 0) {
00586       MSG("Pulser",Msg::kInfo)<<"Aggregate "<<aggregateno<<" Far Fits failed, ngood = "<<test<<endl;
00587       continue;
00588     }
00589 
00590     const PulserGain* rsn[3];
00591 
00592     // Loop over near rows
00593     for (int ir=0; ir<numStripEndn; ir++) {
00594       // Pointer to row
00595       rsn[0] = rsStripEndn[0].GetRow(ir);
00596       int skey = rsn[0]->GetStripEnd();
00597 
00598       // Pointers to extra rows
00599       for (int j=1; j<3; j++) {rsn[j] = 0;}
00600       if(fNextra>0) {
00601         for (int j=1; j<=fNextra; j++) {
00602           rsn[j] = rsStripEndn[j].GetRowByIndex(skey);
00603         }
00604       }
00605       // Get points for fit; we plot Near(y) v Far(x)
00606       Double_t y[60];
00607       Double_t er_y[60];
00608       Int_t ntot = 0;
00609       for (int j=0; j<fNextra+1; j++) {
00610         for(int i=0; i<rsn[j]->GetNumPoints(); i++) {
00611           y[ntot+i] = rsn[j]->ZCMean(i);
00612           er_y[ntot+i] = rsn[j]->ZCError(i);
00613           // Put floor on errors
00614           if(er_y[ntot+i]<0.003*y[ntot+i]) {er_y[ntot+i] = 0.003*y[ntot+i];}
00615         }
00616         ntot += rsn[j]->GetNumPoints();
00617       }
00618       fMinadc = y[0];
00619       fMaxadc = y[ntot-1];
00620       // Create and fill graph
00621       TGraphErrors* g = new TGraphErrors(ntot,x,y,er_x,er_y);
00622       // Fit Graph
00623       fFtype = Fit(g);
00624       // Add row to database
00625       if(fWriteDB) {
00626         CalPulserFits row(aggregateno,skey,fFtype,fFit,fMeanRes,fMaxRes,fMaxadc);
00627         fWriternf << row;
00628       }
00629       // Fill ntuple
00630       if(fNearFarTree!=0) {
00631         PlexStripEndId seid = PlexStripEndId::UnbuildPlnStripEndKey(fDetector, skey);
00632         fPlane = seid.GetPlane();
00633         fStrip = seid.GetStrip();
00634         PlexPixelSpotId spotid = plex.GetPixelSpotId(seid);
00635         fBay = spotid.GetRackBay();
00636         fRack = spotid.GetInRack();
00637         fTube = spotid.GetTube();
00638         fPixel = spotid.GetPixel();
00639         fSpot = spotid.GetSpot();
00640         PlexLedId ledid = plex.GetLedId(seid);
00641         fPb = ledid.GetPulserBox();
00642         fLed = ledid.GetLedInBox();
00643         // No fit
00644         if(fFtype < -25 || fFit == 0) {
00645           fNpar = 0;
00646           fNpfit = 0;
00647           fGain = 0;
00648           fPed = 0;
00649           fDped = 0;
00650           fK1 = 0;
00651           fK2 = 0;
00652           fK3 = 0;
00653           fK4 = 0;
00654           fChisq = 0;
00655           fDelta200 = 0;
00656           fDelta7500 = 0;
00657         }
00658         // Line fit only
00659         if(abs(fFtype) == 1) {
00660           fNpar = 1;
00661           fNpfit = fFit->GetNumberFitPoints();
00662           fGain = 1.0/fFit->GetParameter(0);
00663           fPed = fFit->GetParError(0);
00664           fDped = fFit->GetParameter(1);
00665           fK1 = 0;
00666           fK2 = 0;
00667           fK3 = 0;
00668           fK4 = 0;
00669           fChisq = fFit->GetChisquare();
00670           fDelta200 = 0;
00671           fDelta7500 = 0;
00672         }
00673         if(abs(fFtype) == 5 || abs(fFtype) == 25) {
00674           fNpar = fFit->GetNumberFreeParameters()+1;
00675           fNpfit = fFit->GetNumberFitPoints();
00676           fGain = fFit->GetParameter(7);
00677           fPed = fFit->GetParameter(6);
00678           fDped = fFit->GetParError(6);
00679           fK1 = fFit->GetParameter(1);
00680           fK2 = fFit->GetParameter(2);
00681           if(abs(fFtype) == 25) {
00682             fK3 = fFit->GetParameter(3);
00683             fK4 = fFit->GetParameter(4);
00684           }
00685           else {
00686             fK3 = 0;
00687             fK4 = 0;
00688           }
00689           fChisq = fFit->GetChisquare();
00690           Double_t par[8];
00691           for (int j=0; j<8; j++) {par[j] = fFit->GetParameter(j);}
00692           par[0] -= 1.;
00693           Double_t xtest = 200.;
00694           Double_t ytest = (CalVaLinearity::FitFunction(&xtest,par)-par[6])/par[7];
00695           fDelta200 = 100.*(ytest-xtest)/xtest;
00696           xtest = 7500.;
00697           ytest = (CalVaLinearity::FitFunction(&xtest,par)-par[6])/par[7];
00698           fDelta7500 = 100.*(ytest-xtest)/xtest;
00699         }
00700         fMeanres = fMeanRes;
00701         fMaxres = fMaxRes;
00702         fNearFarTree->Fill();
00703       }
00704       delete g;
00705     }
00706   }
00707 
00708   if(fWriteDB) {
00709     if(fWriternf.IsOpen()) {fWriternf.Close();}
00710   }
00711 }
00712 
00713 Int_t PulserGainFit::FarMeans(DbiResultPtr<PulserGain> rsPtrf[3], Double_t* x, Double_t* er_x) {
00714 
00715   // Number of far rows
00716   Int_t numRowsf = rsPtrf[0].GetNumRows();
00717 
00718   // Pointers to database rows
00719   const PulserGain* rs[3];
00720 
00721   // Array for strip-end status
00722   Int_t sgood[1000];
00723   for(int i=0; i<1000; i++) {sgood[i]=0;}
00724   Int_t ngood = 0;
00725 
00726   // Use linear fit function with fixed pedestal
00727   fFitLine->FixParameter(1,0.);
00728 
00729   // Iterate to find good strips
00730   Int_t nitmax = 3;
00731   Int_t ngood_last = numRowsf;
00732   for(int it=0; it<nitmax; it++) {
00733 
00734     // Loop over far rows and calculate means
00735     ngood = 0;
00736     for(int i=0; i<60; i++) {
00737       x[i] = 0.;
00738       er_x[i] = 0.;
00739     }
00740 
00741     for (int ir = 0; ir < numRowsf; ++ir) {
00742       // Get pointer to first row for first run
00743       rs[0] = rsPtrf[0].GetRow(ir);
00744       Int_t skey = rs[0]->GetStripEnd();
00745 
00746       // Check this is good stripend
00747       if(sgood[ir]!=0) {continue;}
00748       Int_t nmax = rs[0]->GetNumPoints() - 1;
00749       Float_t adcmax = rs[0]->ZCMean(nmax);
00750       // Get pointers to extra runs
00751       for (int j=1; j<3; j++) {rs[j] = 0;}
00752       if(fNextra > 0) {
00753         for (int j=1; j<=fNextra; j++) {
00754           rs[j] = rsPtrf[j].GetRowByIndex(skey);
00755           nmax = rs[j]->GetNumPoints() - 1;
00756           if(rs[j]->ZCMean(nmax) > adcmax) {adcmax = rs[j]->ZCMean(nmax);}
00757         }
00758       }
00759       if(adcmax<1000 || adcmax>6000) {continue;}
00760       ngood++;
00761       // Now calculate sums for means
00762       Int_t ntot = 0;
00763       for (int j=0; j<fNextra+1; j++) {
00764         for(int i=0; i<rs[j]->GetNumPoints(); i++) {
00765           Double_t error = rs[j]->ZCError(i);
00766           x[ntot+i] += rs[j]->ZCMean(i)/(error*error);
00767           er_x[ntot+i] += 1./(error*error);
00768         }
00769         ntot += rs[j]->GetNumPoints();
00770       }
00771     }
00772 
00773     // Calculate means
00774     for(int i=0; i<60; i++) {
00775       if(er_x[i] > 0.) {
00776         x[i] = x[i] / er_x[i];
00777         er_x[i] = 1./sqrt(er_x[i]);
00778       }
00779     }
00780 
00781     // Stop here if number of good strips not reducing
00782     if(ngood_last-ngood < 0.01*ngood_last) {break;}
00783     ngood_last = ngood;
00784 
00785     // Loop over rows, make plots and fit
00786     for (int ir = 0; ir < numRowsf; ++ir) {
00787       // Get pointer to row
00788       rs[0] = rsPtrf[0].GetRow(ir);
00789       Int_t skey = rs[0]->GetStripEnd();
00790 
00791       // Get points for fit
00792       Double_t y[60];
00793       Double_t er_y[60];
00794       for(int i=0; i<rs[0]->GetNumPoints(); i++) {
00795         y[i] = rs[0]->ZCMean(i);
00796         er_y[i] = rs[0]->ZCError(i);
00797       }
00798       Int_t ntot = rs[0]->GetNumPoints();
00799       if(fNextra > 0) {
00800         for (int j=1; j<=fNextra; j++) {
00801           rs[j] = rsPtrf[j].GetRowByIndex(skey);
00802           for(int i=0; i<rs[j]->GetNumPoints(); i++) {
00803             y[ntot+i] = rs[j]->ZCMean(i);
00804             er_y[ntot+i] = rs[j]->ZCError(i);
00805           }
00806           ntot += rs[j]->GetNumPoints();
00807         }
00808       }
00809 
00810       // Create and fill graph
00811       TGraphErrors* g = new TGraphErrors(ntot,x,y,er_x,er_y);
00812 
00813       // Fit graph
00814       Int_t ifit = LineFit(g,fFitLine);
00815 
00816       // Check fit
00817       if(ifit==0) {
00818         if(fFitLine->GetNumberFitPoints()<5) {
00819           sgood[ir] = 1;
00820         }
00821         else {
00822           if(fFitLine->GetChisquare()/(fFitLine->GetNumberFitPoints()-1.)>2.) {
00823             sgood[ir] = 2;
00824           }
00825         }
00826       }
00827       else {sgood[ir] = 3;}
00828 
00829       delete g;
00830     }    
00831   }
00832   MSG("Pulser",Msg::kInfo)<<"FarMeans: ngood = "<<ngood<<endl;
00833   if( ngood > 50) {
00834     return 0;
00835   }
00836   else {
00837     return ngood;
00838   }
00839 }
00840 
00841 Int_t PulserGainFit::LineFit(TGraphErrors* g, TF1* fFitLine) {
00842 
00843   Int_t n = g->GetN();
00844   Double_t* x = g->GetX();
00845   Double_t* y = g->GetY();
00846 
00847   // Set range of fit
00848   float xmin = fAdcmin;
00849   float xmax = fAdcmax;
00850   float ymin = fAdcmin;
00851   float ymax = fAdcmax;
00852   int imin = -1;
00853   int imax = n-1;
00854   for (int i=0;i<n;i++) {
00855     if (x[i] > fAdcmin && y[i] > fAdcmin) {
00856       imin = i;
00857       if(i>0) {
00858         xmin = 0.5*(x[i-1]+x[i]);
00859         ymin = 0.5*(y[i-1]+y[i]);
00860       }
00861       break;
00862     }
00863   }
00864   for (int i=0;i<n;i++) {
00865     if (x[i] > fAdcmax || y[i] > fAdcmax) {
00866       imax = i-1;
00867       if (i>0) {
00868         xmax = 0.5*(x[i-1]+x[i]);
00869         ymax = 0.5*(y[i-1]+y[i]);
00870       }
00871       break;
00872     }
00873   }
00874 
00875   // Initialize slope (to prevent a silly value causing problems for
00876   // subsequent fits
00877   fFitLine->SetParameter(0,1.);
00878 
00879   // Perform fit: unless we have no point to fit
00880   if(imin>=0 && imax>imin) {
00881     g->Fit(fFitLine,"Q"," ",xmin,xmax);
00882     return 0;
00883   }
00884   return 1;
00885 }
00886 
00887 // Fit graph to appropriate function and calculate residuals
00888 Int_t PulserGainFit::Fit(TGraphErrors* g)
00889 {
00890   // Internal variables
00891   Int_t ftype = -100;
00892   Int_t npar = 0;
00893   Int_t npfit = 0;
00894   Double_t gain = 0.;
00895   Double_t gain_frac_err = 0.;
00896   Double_t k1;
00897   Double_t k2;
00898   Double_t chisq = 9999.;
00899   Double_t par[8];
00900   for (int j=0; j<8; j++) {par[j] = 0.;}
00901   Float_t sres = 0.;
00902   Float_t mres = 0.;
00903 
00904   // Number of points
00905   Int_t n = g->GetN();
00906   Double_t* x = g->GetX();
00907   Double_t* er_x = g->GetEX();
00908   Double_t* y = g->GetY();
00909   Double_t* er_y = g->GetEY();
00910 
00911   // First do linear fit up to maximum ADC value
00912   // If this is good we don't do any more fits
00913   // Set minimum point using same min ADC as pin fits
00914   Double_t xmin = fAdcmin;
00915   Double_t ymin = fAdcmin;
00916   Int_t imin = -1;
00917   for (int i=0;i<n;i++) {
00918     if (x[i] > fAdcmin && y[i] > fAdcmin) {
00919       imin = i;
00920       if(i>0) {
00921         xmin = 0.5*(x[i-1]+x[i]);
00922         ymin = 0.5*(y[i-1]+y[i]);
00923       }
00924       break;
00925     }
00926   }
00927 
00928   // If no points are above minimum we can't do any fits.
00929   // In this case give up
00930   if(imin<0) {return ftype;}
00931 
00932   // Maximum point
00933   Int_t imax = n-1;
00934   Double_t xmax = x[imax]+1.;
00935   Double_t ymax = y[imax]+1.;
00936 
00937   // Perform fit if at least 1 point in range
00938   fFitLine->SetParameter(0,5.);
00939   if(imax>=imin) {
00940     g->Fit(fFitLine,"Q"," ",xmin,xmax);
00941     fFit = fFitLine;
00942     ftype = 1;
00943     npar = 1;
00944     npfit = fFitLine->GetNumberFitPoints();
00945     gain = 1.0/fFitLine->GetParameter(0);
00946     gain_frac_err = fFitLine->GetParError(0)/fFitLine->GetParameter(0);
00947     chisq = fFitLine->GetChisquare();
00948     Float_t slope = fFitLine->GetParameter(0);
00949     sres = 0.;
00950     mres = 0.;
00951     for (int i=imin; i<=imax; i++) {
00952       Float_t res = y[i] - slope*x[i];
00953       if(slope*x[i]!=0) {res=100.*res/(slope*x[i]);}
00954       sres+=fabs(res);
00955       if(fabs(res)>mres) {mres = fabs(res);}
00956     }
00957     sres/=(imax-imin+1);
00958     fMeanRes = sres;
00959     fMaxRes = mres;
00960   }
00961   else {
00962     // If no points in full range give up
00963     return ftype;
00964   }
00965 
00966   // If we have too few points for Pole fit stop here
00967   if(npfit < 3) {
00968     ftype = -1;
00969     return ftype;
00970   }
00971 
00972   // If full range gives a good linear fit stop here
00973   if(chisq/(npfit-npar)<2) {return ftype;}
00974 
00975   // If highest point is still in expected linear region stop 
00976   if(y[n-1] < 7000) {return ftype;}
00977 
00978   // Now do linear fit in expected linear region
00979   // Set range of fit: minimum is already set
00980   // We use same max ADC as pin fits
00981   xmax = fAdcmax;
00982   ymax = fAdcmax;
00983   for (int i=0;i<n;i++) {
00984     if (x[i] > fAdcmax || y[i] > fAdcmax) {
00985       imax = i-1;
00986       if (i>0) {
00987         xmax = 0.5*(x[i-1]+x[i]);
00988         ymax = 0.5*(y[i-1]+y[i]);
00989       }
00990       break;
00991     }
00992   }
00993 
00994   // Perform fit if at least 1 point in range
00995   fFitLine->SetParameter(0,5.);
00996   if(imax>=imin) {
00997     g->Fit(fFitLine,"Q"," ",xmin,xmax);
00998     fFit = fFitLine;
00999     ftype = 1;
01000     npar = 1;
01001     npfit = fFitLine->GetNumberFitPoints();
01002     gain = 1.0/fFitLine->GetParameter(0);
01003     gain_frac_err = fFitLine->GetParError(0)/fFitLine->GetParameter(0);
01004     chisq = fFitLine->GetChisquare();
01005     Float_t slope = fFitLine->GetParameter(0);
01006     sres = 0.;
01007     mres = 0.;
01008     for (int i=imin; i<=imax; i++) {
01009       Float_t res = y[i] - slope*x[i];
01010       if(slope*x[i]!=0) {res=100.*res/(slope*x[i]);}
01011       sres+=fabs(res);
01012       if(fabs(res)>mres) {mres = fabs(res);}
01013     }
01014     sres/=(imax-imin+1);
01015     fMeanRes = sres;
01016     fMaxRes = mres;
01017   }
01018   else {
01019     // If no points in linear region give up
01020     ftype = -100;
01021     return ftype;
01022   }
01023 
01024   // Scale x values with gain for future fits 
01025   if( gain != 0) {
01026     for (int i=0;i<n;i++) {
01027       x[i] /= gain;
01028       er_x[i] /= gain;
01029       g->SetPoint(i,x[i],y[i]);
01030       g->SetPointError(i,er_x[i],er_y[i]);
01031     }
01032     xmin /= gain;
01033   }
01034   else {
01035     MSG("Pulser",Msg::kWarning)<<"Zero gain after linear fit"<<endl;
01036   }
01037 
01038   // Now fit full range with pole only; 
01039   // Set range of fit: xmin already set, max is last point
01040   imax = n-1;
01041   xmax = x[imax]+1.;
01042   ymax = y[imax]+1.;
01043 
01044   // If too few points give up, saving anything from linear fit
01045   if(imax-imin<3) {
01046     ftype = -1;
01047     return ftype;
01048   }
01049 
01050   // Set starting parameters
01051   fFitPole->SetParameter(1,15000.);
01052   fFitPole->SetParameter(2,5.);
01053   if(gain != 0.) {
01054     fFitPole->FixParameter(7,1.0);
01055   }
01056   else {
01057     // This is not necessary if we don't fit channels with no points in linear region, but you never know
01058     fFitPole->ReleaseParameter(7);
01059     fFitPole->SetParameter(7,1.0);
01060   }
01061 
01062   // Perform fit
01063   g->Fit(fFitPole,"Q"," ",xmin,xmax);
01064 
01065   // Following is now not necessary, but leave anyway
01066   // If linear fit used same points and pole does not improve chisq sufficiently, store linear fit and give up
01067   if(npfit==fFitPole->GetNumberFitPoints()) {
01068     if(chisq/(npfit-npar) - fFitPole->GetChisquare()/(fFitPole->GetNumberFitPoints()-3) < 0.25) {
01069       return ftype;
01070     }
01071   }
01072 
01073   // Set error on slope from linear fit
01074   fFitPole->SetParError(7,gain_frac_err);
01075 
01076   // Save Pole results
01077   ftype = 5;
01078   npar = 3;
01079   fFit = fFitPole;
01080   npfit = fFitPole->GetNumberFitPoints();
01081   gain = fFitPole->GetParameter(7);
01082   k1 = fFitPole->GetParameter(1); 
01083   k2 = fFitPole->GetParameter(2);
01084   chisq = fFitPole->GetChisquare();
01085   for (int j=0; j<8; j++) {par[j] = fFitPole->GetParameter(j);}
01086   sres = 0.;
01087   mres = 0.;
01088   for (int i=imin; i<=imax; i++) {
01089     Double_t fy = CalVaLinearity::FitFunction(&x[i],par);
01090     Float_t res = y[i] - fy;
01091     if(fy!=0) {res=100.*res/fy;}
01092     sres+=fabs(res);
01093     if(fabs(res)>mres) {mres = fabs(res);}
01094   }
01095   sres/=(imax-imin+1);
01096   fMeanRes = sres;
01097   fMaxRes = mres;
01098   // Check and flag problem fits
01099   par[0] -= 1.;
01100   Double_t xtest = 200.;
01101   Double_t ytest = CalVaLinearity::FitFunction(&xtest,par)/par[7];
01102   if(fabs(ytest-xtest)/xtest > 0.01) ftype = -ftype;
01103   xtest = 7500.;
01104   ytest = CalVaLinearity::FitFunction(&xtest,par)/par[7];
01105   if(fabs(ytest-xtest)/xtest > 0.10) ftype = -ftype;
01106 
01107   // If too few points for pole+kicker stop here
01108   if(imax-imin<5) {return ftype;}
01109 
01110   // Fit pole + kicker with fixed ped
01111   // Set starting parameters
01112   if(chisq < 10*(npfit-npar)) {
01113     fFitPK1->SetParameter(1,k1);
01114     fFitPK1->SetParameter(2,k2);
01115   }
01116   else {
01117     fFitPK1->SetParameter(1,15000.);
01118     fFitPK1->SetParameter(2,5.);
01119   }
01120   fFitPK1->SetParameter(3,6000.);
01121   fFitPK1->SetParameter(4,50000.);
01122   if(gain != 0.) {
01123     fFitPK1->FixParameter(7,1.0);
01124   }
01125   else {
01126     fFitPK1->ReleaseParameter(7);
01127     fFitPK1->SetParameter(7,1.0);
01128   }
01129 
01130   // Perform fit
01131   g->Fit(fFitPK1,"Q+"," ",xmin,xmax);
01132 
01133   // Set error on slope from linear fit
01134   fFitPK1->SetParError(7,gain_frac_err);
01135 
01136   // If this an improvement on pole only save values
01137   if((chisq/(npfit-npar) > fFitPK1->GetChisquare()/(fFitPK1->GetNumberFitPoints()-5)) || ftype < 0) {
01138     ftype = 25;
01139     npar = 5;
01140     fFit = fFitPK1;
01141     npfit = fFitPK1->GetNumberFitPoints();
01142     gain = fFitPK1->GetParameter(7); 
01143     k1 = fFitPK1->GetParameter(1); 
01144     k2 = fFitPK1->GetParameter(2); 
01145     chisq = fFitPK1->GetChisquare();
01146     for (int j=0; j<8; j++) {par[j] = fFitPK1->GetParameter(j);}
01147     Float_t sres = 0.;
01148     Float_t mres = 0.;
01149     for (int i=imin; i<=imax; i++) {
01150       Double_t fy = CalVaLinearity::FitFunction(&x[i],par);
01151       Float_t res = y[i] - fy;
01152       if(fy!=0) {res=100.*res/fy;}
01153       sres+=fabs(res);
01154       if(fabs(res)>mres) {mres = fabs(res);}
01155     }
01156     sres/=(imax-imin+1);
01157     fMeanRes = sres;
01158     fMaxRes = mres;
01159     // Check and flag problem fits
01160     par[0] -= 1.;
01161     Double_t xtest = 200.;
01162     Double_t ytest = CalVaLinearity::FitFunction(&xtest,par)/par[7];
01163     if(fabs(ytest-xtest)/xtest > 0.01) ftype = -ftype;
01164     xtest = 7500.;
01165     ytest = CalVaLinearity::FitFunction(&xtest,par)/par[7];
01166     if(fabs(ytest-xtest)/xtest > 0.10) ftype = -ftype;
01167   }
01168 
01169   // STOP HERE
01170 
01171   /*    
01172   // If too few points to free ped, stop here
01173   if(imax-imin<6) {return ftype;}
01174 
01175   // If pole or pole+kicker fit has good chisq stop;
01176   // otherwise try freeing pedestal
01177   if(ftype >=5 && chisq/(npfit-npar) < 2.) {return ftype;}
01178 
01179   // Fit pole + kicker with free ped
01180   // Set starting parameters
01181   if(chisq < 10*(npfit-npar)) {
01182     fFitPK2->SetParameter(1,k1);
01183     fFitPK2->SetParameter(2,k2);
01184     fFitPK2->SetParameter(7,1.0);
01185   }
01186   else {
01187     fFitPK2->SetParameter(1,15000.);
01188     fFitPK2->SetParameter(2,5.);
01189     fFitPK2->SetParameter(7,1.0);
01190   }
01191   fFitPK2->SetParameter(3,5000.);
01192   fFitPK2->SetParameter(4,40000.);
01193 
01194   // Perform fit
01195   g->Fit(fFitPK2,"Q+"," ",xmin,xmax);
01196 
01197   // If this an improvement save values
01198   if((chisq/(npfit-npar) > fFitPK2->GetChisquare()/fFitPK2->GetNumberFreeParameters()) || ftype < 0) {
01199     ftype = 25;
01200     fFit = fFitPK2;
01201     for (int j=0; j<8; j++) {par[j] = fFitPK2->GetParameter(j);}
01202     Float_t sres = 0.;
01203     Float_t mres = 0.;
01204     for (int i=imin; i<=imax; i++) {
01205       Double_t fy = CalVaLinearity::FitFunction(&x[i],par);
01206       Float_t res = y[i] - fy;
01207       if(fy!=0) {res=100.*res/fy;}
01208       sres+=fabs(res);
01209       if(fabs(res)>mres) {mres = fabs(res);}
01210     }
01211     sres/=(imax-imin+1);
01212     fMeanRes = sres;
01213     fMaxRes = mres;
01214     // Check and flag problem fits
01215     par[0] -= 1.;
01216     Double_t xtest = 200.;
01217     Double_t ytest = (CalVaLinearity::FitFunction(&xtest,par)-par[6])/par[7];
01218     if(fabs(ytest-xtest)/xtest > 0.01) ftype = -ftype;
01219     xtest = 7500.;
01220     ytest = CalVaLinearity::FitFunction(&xtest,par)/par[7];
01221     if(fabs(ytest-xtest)/xtest > 0.10) ftype = -ftype;
01222   }
01223   */
01224 
01225   return ftype;
01226 }
01227 

Generated on Mon Feb 15 11:07:26 2010 for loon by  doxygen 1.3.9.1