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

LITuning.cxx

Go to the documentation of this file.
00001 
00002 
00003 // Program name: LITuning.cxx                
00004 //
00005 // Package: LISummary          
00006 //
00007 // Coded by Jeff Hartnell Feb/2003                             
00008 //
00009 // Purpose: To provide algorithms for the tuning of the LI system
00010 //
00011 // Contact: jeffrey.hartnell@physics.ox.ac.uk                         
00013 
00014 #include "TString.h"
00015 
00016 #include "MessageService/MsgService.h"
00017 
00018 #include "LISummary/LITuning.h"
00019 #include "LISummary/LIRun.h"
00020 #include <cmath>
00021 
00022 ClassImp(LITuning)
00023   
00024   CVSID("$Id: LITuning.cxx,v 1.27 2007/11/11 08:00:53 rhatcher Exp $");
00025 
00026 //......................................................................
00027 
00028 LITuning::LITuning()
00029 {
00030   MSG("LITuning", Msg::kDebug) 
00031     <<"Running LITuning constructor..."<<endl;
00032 
00033   this->InitialiseDataMembers(Detector::kUnknown);
00034 
00035   //some good runs to test the code on:
00036   //15853 - has lots of really low points
00037   //17681 - a drift point run
00038   //17661 - has a very saturated led and a bad pin
00039   //      - also has some missing info at low ph; 0 adc and 0 ph
00040   //17616 - led 1 has two bad pins and doesn't saturate!!!!!
00041 
00042   MSG("LITuning", Msg::kDebug) 
00043     <<"Constructed LITuning object"<<endl;
00044 }
00045 
00046 //......................................................................
00047 
00048 LITuning::~LITuning()
00049 {
00050   MSG("LITuning", Msg::kDebug) 
00051     <<"Running LITuning destructor..."<<endl;
00052 
00053   MSG("LITuning", Msg::kDebug) 
00054     <<"Finished LITuning destructor"<<endl;
00055 }
00056 
00057 //......................................................................
00058 
00059 void LITuning::InitialiseDataMembers(Detector::Detector_t det)
00060 {
00061   MSG("LITuning", Msg::kDebug) 
00062     <<"Running InitialiseDataMembers method..."<<endl;
00063 
00064   //initialise data members
00065  
00066   if (det==Detector::kFar){
00067     fAdcAtStartOfSaturation=8000;
00068     fdADCdPHAtSat=1;
00069     fDetector=det;
00070     fFirstGcPointAdc=350;
00071     fGainCurve=0;//set pointer to zero
00072     fIdealAdc=3500;
00073     fLastGcPointAdc=13800;
00074     fPinHighestMaxHG=8000;
00075     fPinHighestMaxLG=8000;
00076     fPinLowestMaxHG=400;
00077     fPinLowestMaxLG=200;
00078     fPinLowestMinHG=80;
00079     fPinLowestMinLG=80;
00080     fMaxPossAdc=15000;
00081     fMaxPossPh=1023;
00082     fMaxPossPin=11000;
00083     fMinHGdPINdPH=3;
00084     fMinLGdPINdPH=0.5;
00085     fMinPossAdc=0;
00086     fMinPossPh=0;
00087     fMinPossPin=0;
00088     fNumCalibPoints=15;
00089     fNumGainPoints=20;
00090     fS="";
00091   }
00092   else if (det==Detector::kNear){
00093     //these have not been set properly
00094     //jjh added best guesses on 19/Dec/04
00095     fAdcAtStartOfSaturation=40000;
00096     fdADCdPHAtSat=1;
00097     fDetector=det;
00098     fFirstGcPointAdc=350;
00099     fGainCurve=0;//set pointer to zero
00100     fIdealAdc=5000;
00101     fLastGcPointAdc=30000;
00102     fPinHighestMaxHG=60000;
00103     fPinHighestMaxLG=60000;
00104     fPinLowestMaxHG=100;
00105     fPinLowestMaxLG=100;
00106     fPinLowestMinHG=70;
00107     fPinLowestMinLG=70;
00108     fMaxPossAdc=60000;
00109     fMaxPossPh=1023;
00110     fMaxPossPin=60000;
00111     fMinHGdPINdPH=3;
00112     fMinLGdPINdPH=0.5;
00113     fMinPossAdc=0;
00114     fMinPossPh=0;
00115     fMinPossPin=0;
00116     fNumCalibPoints=15;
00117     fNumGainPoints=20;
00118     fS="";
00119   }
00120   else if (det==Detector::kUnknown){//make default same as FD
00121     fAdcAtStartOfSaturation=8000;
00122     fdADCdPHAtSat=1;
00123     fDetector=Detector::kFar;
00124     fFirstGcPointAdc=350;
00125     fGainCurve=0;//set pointer to zero
00126     fIdealAdc=3500;
00127     fLastGcPointAdc=13800;
00128     fPinHighestMaxHG=8000;
00129     fPinHighestMaxLG=8000;
00130     fPinLowestMaxHG=400;
00131     fPinLowestMaxLG=200;
00132     fPinLowestMinHG=80;
00133     fPinLowestMinLG=80;
00134     fMaxPossAdc=15000;
00135     fMaxPossPh=1023;
00136     fMaxPossPin=11000;
00137     fMinHGdPINdPH=3;
00138     fMinLGdPINdPH=0.5;
00139     fMinPossAdc=0;
00140     fMinPossPh=0;
00141     fMinPossPin=0;
00142     fNumCalibPoints=15;
00143     fNumGainPoints=20;
00144     fS="";
00145   }
00146   else {
00147     MSG("LITuning", Msg::kFatal) 
00148       <<"Detector Type "<<Detector::AsString(fDetector)
00149       <<" not implemented"<<endl
00150       <<"Exiting now..."<<endl<<endl;
00151     exit(0);
00152   }
00153 
00154   MSG("LITuning", Msg::kDebug) 
00155     <<"Finished InitialiseDataMembers method"<<endl;
00156 }
00157 
00158 //......................................................................
00159 
00160 void LITuning::InputDataGc(vector<LIRun>& gc) 
00161 {
00162   this->InitialiseDataMembers(gc.begin()->GetDetector());
00163 
00164   //set data member according to input
00165   fGainCurve=&gc;//get the address of the vector
00166 }
00167 
00168 //......................................................................
00169 
00170 void LITuning::SetNumCalibPoints(Int_t i) 
00171 {
00172   if (i<=1){
00173     MSG("LITuning", Msg::kFatal) 
00174       <<endl
00175       <<" *** Warning: Number of calib points <= 1 *** "<<endl
00176       <<"Data input is most likely a drift point run!"<<endl
00177       <<"Exiting now..."<<endl<<endl;
00178     exit(0);
00179   }
00180 
00181   fNumCalibPoints=i;
00182 }
00183 
00184 //......................................................................
00185 
00186 void LITuning::SetNumGainPoints(Int_t i)
00187 {
00188   if (i<=1){
00189     MSG("LITuning", Msg::kFatal) 
00190       <<endl
00191       <<" *** Warning: Number of gain curve points <= 1 *** "<<endl
00192       <<"Exiting now..."<<endl<<endl;
00193     exit(0);
00194   }
00195 
00196   fNumGainPoints=i;
00197 }
00198 
00199 //......................................................................
00200 
00201 void LITuning::PrintConfig()
00202 {
00203   MSG("LITuning", Msg::kInfo) 
00204     <<endl
00205     <<"LITuning object has the following configuration:"<<endl
00206     <<"fDetector="<<Detector::AsString(fDetector)<<endl
00207     <<"fNumGainPoints="<<fNumGainPoints<<endl
00208     <<"fIdealAdc="<<fIdealAdc<<endl
00209     <<"fFirstGcPointAdc="<<fFirstGcPointAdc
00210     <<", fLastGcPointAdc="<<fLastGcPointAdc<<endl
00211     <<"fdADCdPHAtSat="<<fdADCdPHAtSat<<endl
00212     <<"fAdcAtStartOfSaturation="<<fAdcAtStartOfSaturation<<endl
00213     <<"fNumCalibPoints="<<fNumCalibPoints<<endl
00214     <<"fPinHighestMaxLG="<<fPinHighestMaxLG
00215     <<", fPinHighestMaxHG="<<fPinHighestMaxHG<<endl
00216     <<"fPinLowestMaxLG="<<fPinLowestMaxLG
00217     <<", fPinLowestMaxHG="<<fPinLowestMaxHG<<endl
00218     <<"fPinLowestMinLG="<<fPinLowestMinLG
00219     <<", fPinLowestMinHG="<<fPinLowestMinHG<<endl
00220     <<"fMinPossAdc="<<fMinPossAdc
00221     <<", fMaxPossAdc="<<fMaxPossAdc<<endl
00222     <<"fMinPossPh="<<fMinPossPh
00223     <<", fMaxPossPh="<<fMaxPossPh<<endl
00224     <<"fMinPossPin="<<fMinPossPin
00225     <<", fMaxPossPin="<<fMaxPossPin<<endl
00226     <<"fMinLGdPINdPH="<<fMinLGdPINdPH
00227     <<", fMinHGdPINdPH="<<fMinHGdPINdPH<<endl
00228     <<endl;
00229 }
00230 
00231 //......................................................................
00232 
00233 void LITuning::PrintPhPinMsg(vector<Double_t>::iterator adc,
00234                              vector<Double_t>::iterator ph,
00235                              vector<Double_t>::iterator pin,
00236                              Double_t interpPh,
00237                              Double_t interpPin)
00238 {
00239   MSG("LITuning",Msg::kInfo)
00240     <<"    Lower point: adc="<<static_cast<Int_t>(*(adc-1))
00241     <<", PH="<<static_cast<Int_t>(*(ph-1))
00242     <<endl<<"    Upper point: adc="<<static_cast<Int_t>(*adc)
00243     <<", PH="<<static_cast<Int_t>(*ph)
00244     <<", Interpolated PH="<<static_cast<Int_t>(interpPh)
00245     <<endl<<"In PIN space:"
00246     <<endl<<"    Lower point: pinAdc="<<static_cast<Int_t>(*(pin-1))
00247     <<", PH="<<static_cast<Int_t>(*(ph-1))
00248     <<endl<<"    Upper point: pinAdc="<<static_cast<Int_t>(*pin)
00249     <<", PH="<<static_cast<Int_t>(*ph)
00250     <<", Interpolated Pin="<<static_cast<Int_t>(interpPin)<<endl;
00251 }
00252 
00253 //......................................................................
00254 
00255 void LITuning::PrintPhMsg(vector<Double_t>::iterator adc,
00256                           vector<Double_t>::iterator ph,
00257                           Double_t interpPh)
00258 {
00259   MSG("LITuning",Msg::kInfo)
00260     <<"    Lower point: adc="<<static_cast<Int_t>(*(adc-1))
00261     <<", PH="<<static_cast<Int_t>(*(ph-1))
00262     <<endl<<"    Upper point: adc="<<static_cast<Int_t>(*adc)
00263     <<", PH="<<static_cast<Int_t>(*ph)
00264     <<", Interpolated PH="<<static_cast<Int_t>(interpPh)<<endl;
00265 }
00266 
00267 //......................................................................
00268 
00269 void LITuning::PrintPinMsg(vector<Double_t>::iterator pin,
00270                            vector<Double_t>::iterator ph,
00271                            Double_t interpAdc,
00272                            Double_t interpPh)
00273 {
00274   MSG("LITuning",Msg::kInfo)
00275     <<"    Lower point: pin="<<static_cast<Int_t>(*(pin-1))
00276     <<", PH="<<static_cast<Int_t>(*(ph-1))
00277     <<endl<<"    Upper point: pin="<<static_cast<Int_t>(*pin)
00278     <<", PH="<<static_cast<Int_t>(*ph)
00279     <<", Interpolated PH="<<static_cast<Int_t>(interpPh)<<endl
00280     <<"    Corresponding adc="<<interpAdc<<endl; 
00281 }
00282 
00283 //......................................................................
00284 
00285 void LITuning::PrintFirstLastMsg(Double_t firstPh,Double_t lastPh,
00286                                  Double_t firstPin,Double_t lastPin)
00287 {
00288     MSG("LITuning_TuneGc",Msg::kInfo) 
00289       <<"Input calculated first/last GC data points are:"<<endl
00290       <<static_cast<Int_t>(firstPh)<<" < PH < "
00291       <<static_cast<Int_t>(lastPh)<<endl
00292       <<static_cast<Int_t>(firstPin)<<" < PIN < "
00293       <<static_cast<Int_t>(lastPin)<<endl
00294       <<"Number of required GC points = "<<fNumGainPoints<<endl;
00295 }
00296 
00297 
00298 //......................................................................
00299 
00300 Float_t LITuning::FindLowerFraction(map<Float_t,Int_t>& inputMap,
00301                                       Float_t fraction,
00302                                       Int_t totalNumHits)
00303 { 
00304   MSG("LITuning",Msg::kDebug)  
00305     <<endl<<" ** Running FindLowerFraction method... ** "<<endl; 
00306 
00307   if (totalNumHits<=0){
00308     MSG("LITuning",Msg::kWarning)
00309       <<"Can't find lower fraction: Total number of hits is zero"<<endl;
00310     MSG("LITuning",Msg::kDebug)
00311       <<endl<<" ** Finished FindLowerFraction method ** "<<endl; 
00312     return -1;
00313   }
00314 
00315   //loop over all the hits for a calib point
00316   map<Float_t,Int_t>::iterator hit=inputMap.begin();
00317 
00318   Int_t totalHitsIteratedOver=0;
00319   
00320   //find the lower mean at X% of hits
00321   while (hit!=inputMap.end()){
00322     
00323     totalHitsIteratedOver+=hit->second;
00324     
00325     MSG("LITuning",Msg::kVerbose)
00326       <<"mean="<<hit->first
00327       <<", num="<<hit->second
00328       <<", runTotal="<<totalHitsIteratedOver
00329       <<endl;
00330     
00331     if (totalHitsIteratedOver>totalNumHits*fraction){
00332       MSG("LITuning",Msg::kDebug)
00333         <<"Found lower bound, mean="<<hit->first
00334         <<", num="<<totalHitsIteratedOver<<"/"<<totalNumHits
00335         <<" (="<<100.*totalHitsIteratedOver/totalNumHits
00336         <<"%)"<<endl;
00337 
00338       MSG("LITuning",Msg::kDebug)
00339         <<endl<<" ** Finished FindLowerFraction method ** "<<endl; 
00340       return hit->first;
00341     }
00342     
00343     hit++;
00344   }
00345   
00346   MSG("LITuning",Msg::kDebug)
00347     <<endl<<" ** Finished FindLowerFraction method ** "<<endl; 
00348   return -1;
00349 }
00350 
00351 //......................................................................
00352 
00353 Float_t LITuning::FindUpperFraction(map<Float_t,Int_t>& inputMap,
00354                                       Float_t fraction,
00355                                       Int_t totalNumHits)
00356 { 
00357   MSG("LITuning",Msg::kDebug)  
00358     <<endl<<" ** Running FindUpperFraction method... ** "<<endl; 
00359 
00360   if (totalNumHits<=0){
00361     MSG("LITuning",Msg::kWarning)
00362       <<"Can't find upper fraction: Total number of hits is zero"<<endl;
00363     MSG("LITuning",Msg::kDebug)  
00364       <<endl<<" ** Finished FindUpperFraction method... ** "<<endl; 
00365     return -1;
00366   }
00367 
00368   //loop over all the hits for a calib point
00369   map<Float_t,Int_t>::iterator hit=inputMap.end();
00370   hit--;
00371 
00372   Int_t totalHitsIteratedOver=0;
00373   
00374   //find the upper mean at X% of hits
00375   while (hit!=inputMap.begin()){
00376     
00377     totalHitsIteratedOver+=hit->second;
00378     
00379     MSG("LITuning",Msg::kVerbose)
00380       <<"mean="<<hit->first
00381       <<", num="<<hit->second
00382       <<", runTotal="<<totalHitsIteratedOver
00383       <<endl;
00384     
00385     if (totalHitsIteratedOver>totalNumHits*fraction){
00386       MSG("LITuning",Msg::kDebug)
00387         <<"Found upper bound, mean="<<hit->first
00388         <<", num="<<totalHitsIteratedOver<<"/"<<totalNumHits
00389         <<" (="<<100.*totalHitsIteratedOver/totalNumHits
00390         <<"%)"<<endl;
00391 
00392       MSG("LITuning",Msg::kDebug)
00393         <<endl<<" ** Finished FindUpperFraction method ** "<<endl; 
00394       return hit->first;
00395     }
00396     
00397     hit--;
00398   }
00399   
00400   MSG("LITuning",Msg::kDebug)
00401     <<endl<<" ** Finished FindUpperFraction method ** "<<endl; 
00402   return -1;
00403 }
00404 
00405 //......................................................................
00406 
00407 Float_t LITuning::FindMidFractionAv(map<Float_t,Int_t>& inputMap,
00408                                       Float_t lowerFraction,
00409                                       Float_t upperFraction,
00410                                       Int_t totalNumHits)
00411 { 
00413 
00414   MSG("LITuning",Msg::kDebug)  
00415     <<endl<<" ** Running FindMidFractionAv method... ** "<<endl; 
00416   
00417   if (totalNumHits<=0){
00418     MSG("LITuning",Msg::kWarning)
00419       <<"Can't find mid fraction average: Total number of hits is zero"
00420       <<endl;
00421     MSG("LITuning",Msg::kDebug)  
00422       <<endl<<" ** Finished FindMidFractionAv method... ** "<<endl; 
00423     return -1;
00424   }
00425   
00426   map<Float_t,Int_t>::iterator hit=inputMap.begin();
00427   Int_t totalHitsIteratedOver=0;
00428   Float_t midFractionAv=0;  
00429   Int_t numMidFractionHits=0;
00430 
00431   //find the upper mean at X% of hits
00432   while (hit!=inputMap.end()){
00433     
00434     totalHitsIteratedOver+=hit->second;
00435     
00436     //ignore the lower X% and the upper Y%
00437     if (totalHitsIteratedOver<totalNumHits*lowerFraction ||
00438         totalHitsIteratedOver>totalNumHits*(1-upperFraction)){
00439 
00440       MSG("LITuning",Msg::kVerbose)
00441         <<"mean="<<hit->first
00442         <<", num="<<hit->second
00443         <<", runTotal="<<totalHitsIteratedOver
00444         <<endl;
00445       hit++;
00446       continue;
00447     }
00448 
00449     //add up the total mean (there might be more than one)
00450     midFractionAv+=hit->second*hit->first;
00451     //count the number of hits added
00452     numMidFractionHits+=hit->second;
00453 
00454     MSG("LITuning",Msg::kVerbose)
00455         <<"Using hit, mean="<<hit->first
00456         <<", num="<<totalHitsIteratedOver<<"/"<<totalNumHits
00457         <<" ("<<100.*totalHitsIteratedOver/totalNumHits
00458         <<"%)"
00459         <<", run total="<<midFractionAv
00460         <<", num added="<<numMidFractionHits
00461         <<endl;
00462 
00463     hit++;
00464   }
00465   
00466   //calculate the average
00467   if (numMidFractionHits>0){
00468     midFractionAv/=numMidFractionHits;
00469     MSG("LITuning",Msg::kDebug)
00470       <<"Mid fraction average="<<midFractionAv<<endl;
00471   }
00472   else if (totalNumHits==1){
00473     MSG("LITuning",Msg::kDebug)
00474       <<"Only 1 hit for this led point"
00475       <<", returning mid fraction average of zero"<<endl;
00476   }
00477   else{
00478     MSG("LITuning",Msg::kWarning)
00479       <<endl
00480       <<"Avoided FPE: Number of hits in mid fraction average is zero"
00481       <<", returning zero mean"
00482       <<endl<<"Total number of hits for this led is "<<totalNumHits
00483       <<endl;
00484   }
00485 
00486   MSG("LITuning",Msg::kDebug)
00487     <<endl<<" ** Finished FindMidFractionAv method ** "<<endl; 
00488   return midFractionAv;
00489 }
00490 
00491 //......................................................................
00492 
00493 Double_t LITuning::CalcAv_dPINdPH(vector<LIRun>::iterator gcData,
00494                                   Int_t pinNumber)
00495 {
00496   MSG("LITuning", Msg::kDebug) 
00497     <<"Running CalcAv_dPINdPH..."<<endl;
00498 
00499   //get iterators to gc components
00500   vector<Double_t> ph;
00501   ph=gcData->GetPh();
00502   vector<Double_t> pin;
00503   pin=gcData->GetPin(pinNumber);
00504   
00505   Double_t av_dPINdPH=0;
00506   Int_t counter=0;
00507 
00508   Double_t pinMin=-1;
00509   Double_t pinMax=-1;
00510 
00511   if (pinNumber==1){
00512     pinMin=fPinLowestMinHG;
00513     pinMax=fPinHighestMaxHG;
00514   }
00515   else if (pinNumber==2){
00516     pinMin=fPinLowestMinLG;
00517     pinMax=fPinHighestMaxLG;
00518   }
00519 
00520   //loop and add up gradients    
00521   for (UInt_t i=0;i<ph.size()-1;i++){
00522     //don't include points above max
00523     //don't include points with zero pulse height
00524     if ((ph[i+1]-ph[i])!=0 && pin[i]<pinMax && ph[i]>0){
00525       av_dPINdPH+=(pin[i+1]-pin[i])/(ph[i+1]-ph[i]);
00526       counter++;
00527     }
00528   }
00529   
00530   //calc average
00531   if (counter!=0) av_dPINdPH/=counter;
00532 
00533   MSG("LITuning",Msg::kDebug) 
00534     <<"CalcAv_dPINdPH method finished"<<endl;
00535   return av_dPINdPH;
00536 }
00537 
00538 //......................................................................
00539 
00540 Double_t LITuning::CalcLastGcPointAdc(vector<LIRun>::iterator gcData)
00541 {
00542   MSG("LITuning", Msg::kDebug) 
00543     <<"Running CalcLastGcPointAdc method..."<<endl;
00544 
00545   //get iterators to gc components
00546   vector<Double_t> ph;
00547   ph=gcData->GetPh();
00548   vector<Double_t> adc;
00549   adc=gcData->GetAdc();
00550   
00551   Int_t led=gcData->GetLed();
00552   Int_t pb=gcData->GetPb();
00553 
00554   Double_t dADCdPH=-1;
00555   Double_t adcAfterSat=-1;
00556   UInt_t pointAfterSat=0;
00557   Double_t dADCdPHAfterSat=-1;
00558   
00559   Double_t adcAtSat=1;
00560   Bool_t saturatedPointFound=false;
00561 
00562   //reset the general purpose string
00563   fS="";
00564 
00565   for (UInt_t i=0;i<ph.size()-1;i++){
00566     //avoid fpe and only check for points up near saturation
00567     if ((ph[i+1]-ph[i])!=0 && adc[i]>fAdcAtStartOfSaturation){
00568 
00569       //calc grad of adc vs ph
00570       dADCdPH=(adc[i+1]-adc[i])/(ph[i+1]-ph[i]);
00571       string s=Form("%f",static_cast<Float_t>(dADCdPH));
00572       fS+=s+",";
00573       if (dADCdPH<fdADCdPHAtSat){
00574         if (MsgService::Instance()->IsActive("LITuning_LastGc",
00575                                              Msg::kDebug)){
00576           MSG("LITuning",Msg::kInfo)
00577             <<"dADCdPH is bad ("<<dADCdPH<<") for point "<<i
00578             <<", adc="<<adc[i]<<", ph="<<ph[i]<<endl;
00579         }
00580         if (!saturatedPointFound) {
00581           adcAfterSat=adc[i];
00582           pointAfterSat=i;
00583           dADCdPHAfterSat=dADCdPH;
00584         }
00585         saturatedPointFound=true;
00586       }
00587     }
00588   }
00589 
00590   if (MsgService::Instance()->IsActive("LITuning_LastGc",
00591                                        Msg::kDebug)){
00592     MSG("LITuning",Msg::kInfo) 
00593       <<"Gradients are: "<<fS<<endl;
00594   }
00595 
00596   if (!saturatedPointFound){
00597     MSG("LITuning",Msg::kWarning) 
00598       <<endl
00599       <<"("<<pb<<":"<<led<<")"
00600       <<" Saturation point never reached in data gain curve"
00601       <<", last dADCdPH="<<dADCdPH<<endl;
00602   }
00603   else{
00604     if (MsgService::Instance()->IsActive("LITuning_LastGc",
00605                                          Msg::kDebug)){
00606       MSG("LITuning",Msg::kInfo)
00607         <<"("<<pb<<":"<<led<<")"
00608         <<" adcAfterSat="<<static_cast<Int_t>(adcAfterSat)
00609         <<", fLastGcPointAdc"<<static_cast<Int_t>(fLastGcPointAdc)
00610         <<", diff="<<static_cast<Int_t>(fLastGcPointAdc-adcAfterSat)
00611         <<endl
00612         <<"       pointAfterSat="<<pointAfterSat
00613         <<", dADCdPHAfterSat="<<dADCdPHAfterSat<<endl;
00614     }
00615 
00616     Int_t i=pointAfterSat;
00617     
00618     if (pointAfterSat>0){
00619       if ((ph[i]-ph[i-1])!=0 && (ph[i+1]-ph[i])!=0){
00620         //interpolate (y-y2)*m+x2;
00621         //to find adc corresponding to fdADCdPHAtSat
00622         Double_t dADCdPH1=(adc[i]-adc[i-1])/(ph[i]-ph[i-1]);
00623         Double_t dADCdPH2=(adc[i+1]-adc[i])/(ph[i+1]-ph[i]);
00624         //perhaps I should average the two adcs!!! rather than extremes
00625         Double_t m=(adc[i+1]-adc[i-1])/(dADCdPH2-dADCdPH1);
00626         adcAtSat=this->Interpolate(fdADCdPHAtSat,dADCdPH2,m,adc[i+1]);
00627 
00628         if (MsgService::Instance()->IsActive("LITuning_LastGc",
00629                                              Msg::kDebug)){
00630           MSG("LITuning",Msg::kInfo)
00631             <<"dADCdPH1="<<dADCdPH1<<", dADCdPH2="<<dADCdPH2
00632             <<",   m="<<m<<", adcAtSat="<<adcAtSat<<endl
00633             <<"adc[i-1]="<<static_cast<Int_t>(adc[i-1])
00634             <<",   adc[i+1]="<<static_cast<Int_t>(adc[i+1])<<endl
00635             <<" ph[i-1]="<<ph[i-1]<<",      ph[i+1]="<<ph[i+1]
00636             <<endl;
00637         }
00638       }
00639     }
00640   }
00641   
00642   MSG("LITuning",Msg::kDebug) 
00643     <<"CalcLastGcPointAdc method finished"<<endl;
00644   return adcAtSat;
00645 }
00646 
00647 //......................................................................
00648 
00649 void LITuning::CalcFirstGcPoint(vector<LIRun>::iterator gcData,
00650                                 Int_t goodPin,Double_t& firstPh,
00651                                 Double_t& firstPin)
00652 {
00653   //need to find where led switches on
00654   //this method sets firstPin and firstPh
00655 
00656   MSG("LITuning", Msg::kDebug) 
00657     <<"Running CalcFirstGcPoint..."<<endl;
00658 
00659   Bool_t pointFound=false;
00660   Bool_t firstPointTooHigh=false;
00661 
00662   //get iterators to gc components
00663   vector<Double_t> phVector;
00664   vector<Double_t>::iterator ph;
00665   phVector=gcData->GetPh();
00666   ph=phVector.begin();
00667   vector<Double_t> adcVector;
00668   vector<Double_t>::iterator adc;
00669   adcVector=gcData->GetAdc();
00670   adc=adcVector.begin();
00671   vector<Double_t>pinVector;
00672   vector<Double_t>::iterator pin;
00673   pinVector=gcData->GetPin(goodPin);
00674   pin=pinVector.begin();
00675   
00676   Int_t led=gcData->GetLed();
00677   Int_t pb=gcData->GetPb();
00678 
00679   MSG("LITuning_FirstGc", Msg::kDebug) 
00680     <<"("<<pb<<":"<<led<<")"
00681     <<"Looking for lowest gain curve point..."<<endl;
00682 
00683   Int_t counter=0;//already done one point
00684   //loop over the points
00685   while(ph!=phVector.end()){
00686     //counter
00687     counter++;
00688 
00689     //check if the first data point has an adc value greater than the
00690     //first required point
00691     if (*adc>fFirstGcPointAdc && adc==adcVector.begin()){
00692         
00693       //set control variables
00694       pointFound=false;
00695       firstPointTooHigh=true;
00696         
00697       //jump out of the loop
00698       break;
00699     }
00700     
00701     //check if the current point has an adc value greater than the
00702     //first required point
00703     //and whether a point has been found yet
00704     if (*adc>fFirstGcPointAdc && !pointFound){
00705 
00706       //set control variable
00707       pointFound=true;
00708 
00710       //it's best to use two known points than one effectively
00711       //unknown point
00712       if (*(adc-1)==0 || *(adc-1)==1){//==1 is a hack, remove eventually
00713         if ((adc+1)!=phVector.end()){
00714           MSG("LITuning_FirstGc", Msg::kInfo) 
00715             <<"("<<pb<<":"<<led<<")"
00716             <<" Wanted to interpolate using a zero adc point"<<endl
00717             <<"       but using two higher points instead"<<endl;
00718 
00719           //interpolate in pmt adc space (y-y2)*m+x2;
00720           Double_t m=(*(ph+1)-*ph)/(*(adc+1)-*adc);
00721           firstPh=this->Interpolate(fFirstGcPointAdc,*(adc+1),m,
00722                                     *(ph+1));
00723           
00724           //work out the pin value that corresponds to the led
00725           //just having switched on
00726           //calculate gradient in pin adc space
00727           m=(*(pin+1)-*pin)/(*(ph+1)-*ph);
00728           firstPin=this->Interpolate(firstPh,*(ph+1),m,*(pin+1));
00729 
00730           //correct the values if necessary       
00731           this->CorrectInterpValues(adc+1,ph+1,pin+1,led,pb,
00732                                     fFirstGcPointAdc,firstPh,firstPin);
00733           //jump out of the loop
00734           break;
00735         }
00736         else{
00737           //else just continue and use the zero point - rare case
00738           MSG("LITuning_FirstGc", Msg::kInfo) 
00739             <<" ("<<pb<<":"<<led<<")"
00740             <<"Wanted to avoid interpolating using a zero adc point"
00741             <<endl
00742             <<", but no higher point"<<endl;
00743         }
00744       }
00745 
00746       //interpolate in pmt adc space (y-y2)*m+x2;
00747       Double_t m=(*ph-*(ph-1))/(*adc-*(adc-1));
00748       firstPh=this->Interpolate(fFirstGcPointAdc,*adc,m,*ph);
00749       
00750       //calculate gradient in pin adc space
00751       m=(*pin-*(pin-1))/(*ph-*(ph-1));
00752       firstPin=this->Interpolate(firstPh,*ph,m,*pin);
00753 
00754       if (MsgService::Instance()->IsActive("LITuning_FirstGc",
00755                                            Msg::kDebug)){
00756         MSG("LITuning_FirstGc",Msg::kInfo)
00757           <<"("<<pb<<":"<<led<<")"
00758           <<" Lowest GC point found"
00759           <<" ("<<counter<<"/"<<adcVector.size()<<")"
00760           <<", Required Point="<<fFirstGcPointAdc<<endl;
00761         this->PrintPhPinMsg(adc,ph,pin,firstPh,firstPin);
00762       }
00763 
00764       //jump out of the loop when point is found
00765       break;
00766     }
00767     
00768     //go to the next point
00769     ph++;
00770     adc++;
00771     pin++; 
00772   }
00773 
00774   //check on success of finding point
00775   if (firstPointTooHigh){
00776     this->InterpolateAboveOrBelow(kGcUnknown,
00777                                   adcVector.begin()+1,
00778                                   phVector.begin()+1,
00779                                   pinVector.begin()+1,led,pb,
00780                                   fFirstGcPointAdc,firstPh,firstPin);
00781     //set control variable
00782     pointFound=true;
00783   }
00784   else if (!pointFound){//i.e. first data point was too low
00785     this->InterpolateAboveOrBelow(kGcUnknown,
00786                                   adcVector.end()-1,phVector.end()-1,
00787                                   pinVector.end()-1,led,pb,
00788                                   fFirstGcPointAdc,firstPh,firstPin);
00789     //set control variable
00790     pointFound=true;
00791   }
00792 
00794   //this is a bit of a hack
00796   if (firstPin==0){
00797     MSG("LITuning_FirstGc",Msg::kWarning)
00798       <<endl
00799       <<"("<<pb<<":"<<led<<")"
00800       <<" Looking for first GC point but first PIN value has"
00801       <<" been set to zero"<<endl;
00802     
00803     ph=phVector.begin()+1;
00804     adc=adcVector.begin()+1;
00805     pin=pinVector.begin()+1;
00806     
00807     Bool_t pinFound=false;
00808     Bool_t lookForSecondPinNow=false;
00809 
00810     Int_t counter=0;//already done one point
00811     //loop over the points
00812     while(pin!=pinVector.end()){
00813       //counter
00814       counter++;
00815 
00816       MSG("LITuning_FirstGc",Msg::kVerbose)
00817         <<"("<<pb<<":"<<led<<")"<<" Looping...   counter="
00818         <<counter<<endl;
00819       
00820       //check if the current point has an adc value greater than the
00821       //first required point
00822       //and whether a point has been found yet
00823       if (*pin>fMinPossPin && lookForSecondPinNow && !pinFound){
00824 
00825         if (MsgService::Instance()->IsActive("LITuning_FirstGc",
00826                                              Msg::kDebug)){     
00827           MSG("LITuning_FirstGc",Msg::kInfo)
00828             <<"("<<pb<<":"<<led<<")"
00829             <<" Found 2nd non-zero PIN"<<endl;
00830         }
00831 
00832         pinFound=true;
00833 
00834         //recalculate gradient in pin adc space
00835         Double_t m=0;
00836         if (*ph-*(ph-1)!=0) m=(*pin-*(pin-1))/(*ph-*(ph-1));
00837         firstPin=this->Interpolate(firstPh,*ph,m,*pin); 
00838 
00839         if (MsgService::Instance()->IsActive("LITuning_FirstGc",
00840                                              Msg::kDebug)){   
00841           MSG("LITuning_FirstGc",Msg::kInfo)
00842             <<"("<<pb<<":"<<led<<")"<<" Interpolated ok, counter="
00843             <<counter<<endl;
00844           this->PrintPhPinMsg(adc,ph,pin,firstPh,firstPin);
00845         }
00846 
00847         //jump out of loop
00848         break;
00849       }
00850 
00851       if (*pin>fMinPossPin){
00852         lookForSecondPinNow=true;
00853         if (MsgService::Instance()->IsActive("LITuning_FirstGc",
00854                                              Msg::kDebug)){
00855           MSG("LITuning_FirstGc",Msg::kInfo)
00856             <<"("<<pb<<":"<<led<<")"
00857             <<" Found first non-zero pin, looking for second..."<<endl;
00858         }
00859       }
00860       pin++;
00861       adc++;
00862       ph++;
00863     }
00864 
00865     if (MsgService::Instance()->IsActive("LITuning_FirstGc",
00866                                          Msg::kDebug)){
00867       MSG("LITuning_FirstGc",Msg::kInfo)
00868         <<endl
00869         <<"("<<pb<<":"<<led<<")"
00870         <<" After recalculating pin value:"
00871         <<endl;
00872       this->PrintPhPinMsg(adc,ph,pin,firstPh,firstPin);
00873     }
00874 
00875     //correct the values if needed
00876     this->CorrectInterpValues(adc,ph,pin,led,pb,fFirstGcPointAdc,
00877                               firstPh,firstPin);
00878   }
00879 
00880   MSG("LITuning",Msg::kDebug) 
00881     <<"CalcFirstGcPoint method finished"<<endl;
00882 }
00883 
00884 //......................................................................
00885 
00886 void LITuning::CalcLastGcPoint(vector<LIRun>::iterator gcData,
00887                                Int_t goodPin,Double_t& lastPh,
00888                                Double_t& lastPin)
00889 {
00890   //need to find where led saturates pmt
00891   //this method sets lastPin and lastPh
00892 
00893   MSG("LITuning", Msg::kVerbose) 
00894     <<"Running CalcLastGcPoint..."<<endl;
00895 
00896   Bool_t pointFound=false;
00897   Bool_t firstPointTooHigh=false;
00898 
00899   //get iterators to gc components
00900   vector<Double_t> phVector;
00901   vector<Double_t>::iterator ph;
00902   phVector=gcData->GetPh();
00903   ph=phVector.begin();
00904   vector<Double_t> adcVector;
00905   vector<Double_t>::iterator adc;
00906   adcVector=gcData->GetAdc();
00907   adc=adcVector.begin();
00908   vector<Double_t>pinVector;
00909   vector<Double_t>::iterator pin;
00910   pinVector=gcData->GetPin(goodPin);
00911   pin=pinVector.begin();
00912   
00913   Int_t led=gcData->GetLed();
00914   Int_t pb=gcData->GetPb();
00915 
00916   MSG("LITuning_LastGc", Msg::kDebug) 
00917     <<" ("<<pb<<":"<<led<<")"
00918     <<"Looking for highest gain curve point..."<<endl;
00919 
00920   //declare the variable used to find the last/highest GC point
00921   //initialise to default
00922   Double_t lastGcPointAdc=fLastGcPointAdc;
00923 
00924   //only try and calculate last point adc if far detector
00925   if (fDetector==-1){
00926     Double_t tempAdc=this->CalcLastGcPointAdc(gcData);
00927     
00928     if (fLastGcPointAdc-lastGcPointAdc>4000 ||
00929         fLastGcPointAdc-lastGcPointAdc<-4000){
00930       MSG("LITuning_LastGc",Msg::kWarning)
00931         <<endl
00932         <<"("<<pb<<":"<<led<<")"
00933         <<" Calculated lastGcPointAdc="
00934         <<static_cast<Int_t>(tempAdc)
00935         <<", fLastGcPointAdc="<<static_cast<Int_t>(fLastGcPointAdc)<<endl
00936         <<"       Difference="
00937         <<static_cast<Int_t>(fLastGcPointAdc-tempAdc)
00938         <<". Note: Using fLastGcPointAdc"<<endl;
00939       lastGcPointAdc=tempAdc;
00940     }
00941   }
00942   else{
00943     //just use the one-size-fits-all maximum fLastGcPointAdc
00944   }
00945 
00946   Int_t counter=0;
00947   //loop over the points
00948   while(ph!=phVector.end()){
00949     //counter
00950     counter++;
00951 
00952     //check if the first data point has an adc value greater than the
00953     //last required point
00954     if (*adc>lastGcPointAdc && adc==adcVector.begin()){
00955         
00956       //set control variables
00957       pointFound=false;
00958       firstPointTooHigh=true;
00959         
00960       //jump out of the loop
00961       break;
00962     }
00963     
00964     //check if the current point has an adc value greater than the
00965     //last required point
00966     //and whether a point has been found yet
00967     if (*adc>lastGcPointAdc && !pointFound){
00968         
00969       //set control variable
00970       pointFound=true;
00971 
00972       //interpolate in pmt adc space (y-y2)*m+x2;
00973       Double_t m=(*ph-*(ph-1))/(*adc-*(adc-1));
00974       lastPh=this->Interpolate(lastGcPointAdc,*adc,m,*ph);
00975       
00976       //calculate gradient in pin adc space
00977       m=(*pin-*(pin-1))/(*ph-*(ph-1));
00978       lastPin=this->Interpolate(lastPh,*ph,m,*pin);
00979 
00980       if (MsgService::Instance()->IsActive("LITuning_LastGc",
00981                                            Msg::kDebug)){
00982         MSG("LITuning_LastGc",Msg::kInfo)
00983           <<"("<<pb<<":"<<led<<")"
00984           <<" Highest GC point found"
00985           <<" ("<<counter<<"/"<<adcVector.size()<<")"
00986           <<", Required Point="<<lastGcPointAdc<<endl;
00987         this->PrintPhPinMsg(adc,ph,pin,lastPh,lastPin);
00988       }
00989 
00990       //jump out of the loop when point is found
00991       break;
00992     }
00993     
00994     //go to the next point
00995     ph++;
00996     adc++;
00997     pin++; 
00998   }
00999 
01000   //check on success of finding point
01001   if (firstPointTooHigh){
01002     this->InterpolateAboveOrBelow(kGcUnknown,
01003                                   adcVector.begin()+1,
01004                                   phVector.begin()+1,
01005                                   pinVector.begin()+1,led,pb,
01006                                   lastGcPointAdc,lastPh,lastPin);
01007     //set control variable
01008     pointFound=true;
01009   }
01010   else if (!pointFound){//i.e. last data point was too low
01011     this->InterpolateAboveOrBelow(kGcUnknown,
01012                                   adcVector.end()-1,phVector.end()-1,
01013                                   pinVector.end()-1,led,pb,
01014                                   lastGcPointAdc,lastPh,lastPin);
01015     //set control variable
01016     pointFound=true;
01017   }
01018 
01019   //need to check if the pulse height was set to the maximum
01020   //because if it was then the pin value might be way to high
01021   //and mess up the linear with pin adc tuning
01022   //Need to correct the pin value when ph is the maximum
01023   if (lastPh==fMaxPossPh){
01024     //get iterators to the end of the vector
01025     ph=phVector.end()-1;
01026     adc=adcVector.end()-1;
01027     pin=pinVector.end()-1;
01028     
01029 
01030     MSG("LITuning_LastGc",Msg::kWarning)
01031       <<endl
01032       <<"("<<pb<<":"<<led<<")"
01033       <<" Looking for last GC point but PH has been set to max possible"
01034       <<endl
01035       <<"lastGcPointAdc="<<static_cast<Int_t>(lastGcPointAdc)
01036       <<", fLastGcPointAdc="<<static_cast<Int_t>(fLastGcPointAdc)
01037       <<", Difference="
01038       <<static_cast<Int_t>(fLastGcPointAdc-lastGcPointAdc)
01039       <<endl;
01040     this->PrintPhPinMsg(adc,ph,pin,lastPh,lastPin);
01041 
01042     //interpolate in pmt adc space (y-y2)*m+x2;
01043     Double_t m=(*adc-*(adc-1))/(*ph-*(ph-1));
01044     lastGcPointAdc=this->Interpolate(lastPh,*ph,m,*adc);
01045       
01046     //calculate gradient in pin adc space
01047     m=(*pin-*(pin-1))/(*ph-*(ph-1));
01048     lastPin=this->Interpolate(lastPh,*ph,m,*pin);
01049 
01050     //correct the values if needed
01051     this->CorrectInterpValues(adc,ph,pin,led,pb,lastGcPointAdc,
01052                               lastPh,lastPin);
01053 
01054     MSG("LITuning_LastGc",Msg::kWarning)
01055       <<endl
01056       <<"("<<pb<<":"<<led<<")"
01057       <<" After interpolation and potential correction:"
01058       <<"lastGcPointAdc="<<static_cast<Int_t>(lastGcPointAdc)
01059       <<endl;
01060     this->PrintPhPinMsg(adc,ph,pin,lastPh,lastPin);
01061   }
01062 
01063   MSG("LITuning",Msg::kVerbose)
01064     <<"CalcLastGcPoint method finished"<<endl;
01065 }
01066 
01067 //......................................................................
01068 
01069 Int_t LITuning::GoodPin(vector<LIRun>::iterator currentGc)
01070 {
01076 
01077   MSG("LITuning",Msg::kDebug)<<"Running GoodPin method..."<<endl;
01078   
01079   //get the two maximum pin values for the input gain curve  
01080   Double_t maxPin1=currentGc->GetMaxPin(1);
01081   Double_t maxPin2=currentGc->GetMaxPin(2);
01082 
01083   Int_t led=currentGc->GetLed();
01084   Int_t pb=currentGc->GetPb();
01085 
01086   Double_t avPin1dPINdPH=this->CalcAv_dPINdPH(currentGc,1);
01087   Double_t avPin2dPINdPH=this->CalcAv_dPINdPH(currentGc,2);
01088   
01089   if (MsgService::Instance()->IsActive("LITuning_Pin",Msg::kDebug)){
01090     MSG("LITuning_Pin", Msg::kInfo)
01091       <<"("<<pb<<":"<<led<<")"
01092       <<" Av gradient Pin1 = "<<avPin1dPINdPH
01093       <<", Av gradient Pin2 = "<<avPin2dPINdPH
01094       <<endl;
01095   }
01096 
01097   Bool_t pin1dPINdPHIsOk=false;
01098   Bool_t pin2dPINdPHIsOk=false;
01099   Bool_t pin1RangeIsOk=false;
01100   Bool_t pin2RangeIsOk=false;
01101 
01102   //work out why the different pins are good or bad
01103   if (maxPin1>fPinLowestMaxHG && maxPin1<fPinHighestMaxHG){
01104     pin1RangeIsOk=true;
01105   }
01106   if (maxPin2>fPinLowestMaxLG && maxPin2<fPinHighestMaxLG){
01107     pin2RangeIsOk=true;
01108   }
01109   if (avPin1dPINdPH>fMinHGdPINdPH){
01110     pin1dPINdPHIsOk=true;
01111   }
01112   if (avPin2dPINdPH>fMinLGdPINdPH){
01113     pin2dPINdPHIsOk=true;
01114   }
01115   
01116   if (MsgService::Instance()->IsActive("LITuning_Pin",Msg::kDebug)){
01117     MSG("LITuning_Pin",Msg::kInfo)
01118       <<"("<<pb<<":"<<led<<")"
01119       <<" Good/Bad: Pin1 range="<<pin1RangeIsOk
01120       <<", gradient="<<pin1dPINdPHIsOk
01121       <<endl<<"                  Pin2 range="<<pin2RangeIsOk
01122       <<", gradient="<<pin2dPINdPHIsOk<<endl
01123       <<"        maxPin1="<<maxPin1
01124       <<", maxPin2="<<maxPin2
01125       <<", avPin1dPINdPH="<<avPin1dPINdPH
01126       <<", avPin2dPINdPH="<<avPin2dPINdPH<<endl;
01127   }
01128 
01129   //for neardet, always return low gain pin first for the time being
01130   if (currentGc->GetDetector()==Detector::kNear
01131       && pin2RangeIsOk && pin2dPINdPHIsOk){
01132     MSG("LITuning_Pin",Msg::kDebug)
01133       <<"("<<pb<<":"<<led<<")"
01134       <<" It's ND, using second pin in calculations"<<endl;
01135     return 2;
01136   }
01137 
01138 
01139   //if pin1 good
01140   if (pin1RangeIsOk && pin1dPINdPHIsOk){
01141     MSG("LITuning_Pin",Msg::kDebug)
01142       <<"("<<pb<<":"<<led<<")"
01143       <<" Using first pin in calculations"<<endl;
01144     return 1;
01145   }
01146 
01147   //if pin2 good
01148   if (pin2RangeIsOk && pin2dPINdPHIsOk){
01149     MSG("LITuning_Pin",Msg::kDebug)
01150       <<"("<<pb<<":"<<led<<")"
01151       <<" Pin1 is bad, using second pin in calculations"<<endl;
01152     return 2;
01153   }
01154 
01155   //both have range and gradient bad to get this far
01156 
01157   //if both too high
01158   if (maxPin1>fPinHighestMaxHG && maxPin2>fPinHighestMaxLG){
01159     //print all details if not already done so
01160     if (!MsgService::Instance()->IsActive("LITuning_Pin",Msg::kDebug)){
01161       MSG("LITuning_Pin",Msg::kInfo)
01162         <<"("<<pb<<":"<<led<<")"
01163         <<" Good/Bad: Pin1 range="<<pin1RangeIsOk
01164         <<", gradient="<<pin1dPINdPHIsOk
01165         <<endl<<"                  Pin2 range="<<pin2RangeIsOk
01166         <<", gradient="<<pin2dPINdPHIsOk<<endl
01167         <<"        maxPin1="<<maxPin1
01168         <<", maxPin2="<<maxPin2
01169         <<", avPin1dPINdPH="<<avPin1dPINdPH
01170         <<", avPin2dPINdPH="<<avPin2dPINdPH<<endl;
01171     }
01172     MSG("LITuning_Pin",Msg::kWarning)
01173       <<endl<<"("<<pb<<":"<<led<<")"
01174       <<" Both Pin1 and pin2 are too high"
01175       <<endl<<"Selecting the lower of the two with good gradient"<<endl;
01176 
01177     if (maxPin1<maxPin2 && pin1dPINdPHIsOk){
01178       return 1;
01179     }
01180     else if (maxPin2<maxPin1 && pin2dPINdPHIsOk){
01181       return 2;
01182     }
01183   }
01184 
01185   if (!MsgService::Instance()->IsActive("LITuning_Pin",Msg::kDebug)){
01186     MSG("LITuning_Pin",Msg::kInfo)
01187       <<"("<<pb<<":"<<led<<")"
01188       <<" Good/Bad: Pin1 range="<<pin1RangeIsOk
01189       <<", gradient="<<pin1dPINdPHIsOk
01190       <<endl<<"                  Pin2 range="<<pin2RangeIsOk
01191       <<", gradient="<<pin2dPINdPHIsOk<<endl
01192       <<"        maxPin1="<<maxPin1
01193       <<", maxPin2="<<maxPin2
01194       <<", avPin1dPINdPH="<<avPin1dPINdPH
01195       <<", avPin2dPINdPH="<<avPin2dPINdPH<<endl;
01196   }
01197 
01198   //if you get this far print out a mesage anyway
01199   MSG("LITuning_Pin",Msg::kError)
01200     <<"("<<pb<<":"<<led<<")"<<" ** Both pins appear bad **"<<endl;
01201 
01202   MSG("LITuning",Msg::kDebug)<<"GoodPin method finished"<<endl;
01203   return 0;
01204 }
01205 /*
01206 
01207 //early simple algorithm results for 17661
01208 box06led01#I=62,96,136,195,254,300,343,383,423,462;
01209 box06led02#I=43,405,625,844,1023,1023,1023,1023,1023,1023;
01210 box06led03#I=60,97,157,233,308,380,449,518,587,656;
01211 box06led04#I=64,116,181,246,308,366,422,476,529,580;
01212 box06led05#I=67,103,142,187,233,279,329,375,420,456;
01213 box06led06#I=63,100,147,202,256,313,367,418,464,509;
01214 box06led07#I=63,104,157,212,264,310,351,385,418,445;
01215 box06led08#I=63,99,139,187,236,287,338,387,434,478;
01216 box06led09#I=63,101,149,202,253,301,347,394,438,480;
01217 
01218 //before not allowing zero adc points to be used when interp
01219 box06led10#I=29,87,127,180,239,287,332,375,416,458;
01220 //after (57 is a much more realistic value from looking by eye)
01221 box06led10#I=57,95,150,224,284,339,391,442,494,545;
01222 //wohoooooooo
01223 
01224 box06led11#I=18,84,129,178,226,268,306,343,377,411;
01225 box06led12#I=62,88,115,148,184,218,252,287,322,358;
01226 box06led13#I=63,85,112,143,175,211,250,292,333,367;
01227 box06led14#I=63,172,240,279,310,341,371,401,431,461;
01228 
01229 //before vetoing pin because of bad gradient:
01230 box06led15#I=58,67,74,81,87,93,99,105,112,470;
01231 //after 
01232 box06led15#I=58,90,132,182,234,293,347,390,431,470;
01233 //wohoooooooo
01234 
01235 box06led16#I=61,89,122,166,209,249,288,327,363,399;
01236 box06led17#I=66,116,181,249,312,371,427,482,536,589;
01237 box06led18#I=62,101,151,207,263,316,368,419,470,521;
01238 box06led19#I=65,126,191,255,315,374,431,485,538,591;
01239 box06led20#I=63,104,150,201,249,296,341,387,433,478;
01240 
01242 //after selecting last point based on pmt adc / ph gradient
01243 //in preference to the fixed value
01244 //and other changes inserted in above
01246 box06led01#I=62,105,169,247,307,361,413,463,514,564;
01247 box06led02#I=43,183,296,385,459,526,593,659,726,794;
01248 box06led03#I=60,101,171,255,336,413,489,563,639,715;
01249 box06led04#I=64,114,177,241,301,358,413,466,517,567;
01250 box06led05#I=67,116,174,236,300,365,425,473,520,567;
01251 box06led06#I=63,118,196,275,356,429,494,560,624,688;
01252 box06led07#I=63,126,205,279,343,390,434,472,511,549;
01253 box06led08#I=63,108,165,227,292,356,419,474,528,581;
01254 box06led09#I=63,123,201,275,345,414,477,532,583,632;
01255 box06led10#I=57,95,150,224,284,339,391,442,494,545;
01256 box06led11#I=52,109,182,249,308,361,412,457,500,540;
01257 box06led12#I=62,96,136,183,229,274,321,368,415,456;
01258 box06led13#I=63,92,129,169,214,265,317,364,406,444;
01259 box06led14#I=63,210,275,320,364,408,451,494,539,584;
01260 box06led15#I=60,100,159,223,298,362,416,466,515,564;
01261 box06led16#I=61,105,169,234,293,351,406,454,500,543;
01262 box06led17#I=66,128,208,286,358,426,491,555,618,680;
01263 box06led18#I=62,108,171,238,302,364,424,484,545,606;
01264 box06led19#I=65,139,217,291,362,431,496,559,623,687;
01265 box06led20#I=63,109,165,223,277,329,382,434,486,534;
01266 
01267 */
01268 //......................................................................
01269 
01270 void LITuning::CalculateDriftPoints()
01271 {
01272   MSG("LITuning", Msg::kInfo) 
01273     <<"Running CalculateDriftPoints method..."<<endl;
01274 
01275   //get iterators to the gain curves and drift points
01276   vector<LIRun>::iterator gcData;
01277   gcData=fGainCurve->begin();
01278   vector<LIRun>::iterator dpTuned;
01279   //note can't get begin() before vector contains any elements
01280   //so get end()-1 for dpTuned below 
01281 
01282   MSG("LITuning_TuneDp",Msg::kDebug)
01283     <<"Starting the loop over all input data gain curves"<<endl;
01284     
01285   //loop over all the gain curves
01286   while (gcData!=fGainCurve->end()){
01287 
01288     if (!this->DataIsOk(gcData,2)){
01289       gcData++;
01290       continue;
01291     }
01292 
01293     //get iterators to the vectors of gain curve points
01294     vector<Double_t> phVector;
01295     vector<Double_t>::iterator ph;
01296     phVector=gcData->GetPh();
01297     ph=phVector.begin();
01298     vector<Double_t> adcVector;
01299     vector<Double_t>::iterator adc;
01300     adcVector=gcData->GetAdc();
01301     adc=adcVector.begin();
01302 
01303     //get the pulserbox and led associated with real data gain curve
01304     Int_t pulserBox=gcData->GetPb();
01305     Int_t led=gcData->GetLed();
01306 
01307     MSG("LITuning_TuneDp",Msg::kDebug)
01308       <<"("<<pulserBox<<":"<<led<<") First point has ph="<<*ph
01309       <<", adc="<<*adc<<endl;
01310 
01311     //add another DP to vector to hold tuned drift points
01312     fBestDp.push_back(LIRun(pulserBox,led,LIRun::kDriftPoint));
01313     //get iterator to the newest (last) element
01314     dpTuned=fBestDp.end()-1;
01315     MSG("LITuning_TuneDp",Msg::kDebug)
01316       <<"("<<pulserBox<<":"<<led<<") Created DP"<<endl;
01317 
01318     //check that the first adc is not too high
01319     if (*adc>fIdealAdc){  
01320       //if there is not enough data at low pulse heights
01321       //it is better to set too high than too low
01322       //since the led might not have turned on at low PH
01323       dpTuned->AddPoint(*ph,*adc);
01324       
01325       MSG("LITuning_TuneDp",Msg::kInfo)
01326         <<"("<<pulserBox<<":"<<led<<") DP"
01327         <<" Not enough points at low PHs"
01328         <<" for DP. Pulse Height set to lowest point taken"
01329         <<endl<<"PH="<<*ph<<", ideal ADC="<<fIdealAdc
01330         <<", actual adc="<<*adc
01331         <<endl;
01332       //once it's found then continue to the next GC
01333       gcData++;
01334       continue;
01335     }
01336     //iterate to take you to the second point
01337     ph++;
01338     adc++;
01339 
01340     MSG("LITuning_TuneDp",Msg::kDebug)
01341       <<"Starting loop over the given gain curve"<<endl;
01342     
01343     //loop over the points 2 -> end
01344     while(ph!=gcData->GetPh().end()){
01345       
01346       if (*adc>fIdealAdc){
01347         //interpolate to find the best PH
01348         Double_t m=(*ph-*(ph-1))/(*adc-*(adc-1));
01349         Double_t bestPhInterp=this->Interpolate(fIdealAdc,*adc,m,*ph);
01350         //(fIdealAdc-*adc)*
01351         //((*ph-*(ph-1))/(*adc-*(adc-1)))+*ph;
01352        
01353         if (bestPhInterp<0){ 
01354           MSG("LITuning_TuneDp",Msg::kWarning)
01355             <<endl<<"("<<pulserBox<<":"<<led<<") DP"
01356             <<" Interpolated point is negative ("
01357             <<bestPhInterp<<"). Setting to one"
01358             <<", ideal="<<fIdealAdc
01359             <<endl<<"       Lower point: adc="<<*(adc-1)
01360             <<", PH="<<*(ph-1)
01361             <<endl<<"       Upper point: adc="<<*adc
01362             <<", PH="<<*ph<<endl<<endl;
01363           
01364           //set to 0 if negative
01365           //this should never happen!!
01366           bestPhInterp=0;
01367         }
01368         else{
01369           MSG("LITuning_TuneDp",Msg::kInfo)
01370             <<"("<<pulserBox<<":"<<led<<") DP"
01371             <<" Interpolated point found, fIdealAdc="<<fIdealAdc
01372             <<endl<<"       Lower point: adc="<<*(adc-1)
01373             <<", PH="<<*(ph-1)
01374             <<endl<<"       Upper point: adc="<<*adc
01375             <<", PH="<<*ph<<"  Best Ph="<<bestPhInterp
01376             <<endl;
01377         }
01378 
01379         //set the interpolated DP
01380         dpTuned->AddPoint(bestPhInterp,fIdealAdc);
01381         
01382         //once point is found then stop loop    
01383         MSG("LITuning_TuneDp",Msg::kDebug)
01384           <<"("<<pulserBox<<":"<<led
01385           <<") Point found. Breaking out of loop"<<endl;
01386         break;
01387       }
01388       
01389       //iterate the gain curve point
01390       adc++;
01391       ph++;
01392       MSG("LITuning_TuneDp",Msg::kVerbose)
01393         <<"("<<pulserBox<<":"<<led<<") Iterated to next ph"<<endl;
01394     }//end of while
01395 
01396     //check if a DP was found and print a message
01397     if (*adc>10 && ph==gcData->GetPh().end() &&
01398         dpTuned->GetPh().empty()){
01399       MSG("LITuning_TuneDp",Msg::kInfo)
01400         <<"("<<pulserBox<<":"<<led<<") DP"
01401         <<" Not enough points at high PHs"
01402         <<" for DP, ideal ADC="<<fIdealAdc
01403         <<", PH="<<*ph<<", adc="<<*adc
01404         <<endl;
01405     }
01406     
01407     //iterate to next gain curve
01408     MSG("LITuning_TuneDp",Msg::kDebug)
01409       <<"("<<pulserBox<<":"<<led<<") Iterated to next dp"<<endl;
01410     gcData++;
01411   }
01412 
01413   MSG("LITuning_TuneDp",Msg::kDebug)
01414     <<"Finished the loop over all input data gain curves"<<endl;
01415     
01416   MSG("LITuning",Msg::kInfo) 
01417     <<"CalculateDriftPoints method finished"<<endl;
01418 }
01419 
01420 //......................................................................
01421 
01422 void LITuning::InterpolateAboveOrBelow(EGcTuningType tuningType,
01423                                        vector<Double_t>::iterator adc,
01424                                        vector<Double_t>::iterator ph,
01425                                        vector<Double_t>::iterator pin,
01426                                        Int_t led,Int_t pb,
01427                                        Double_t& interpAdc,
01428                                        Double_t& interpPh,
01429                                        Double_t& interpPin)
01430 {
01431   MSG("LITuning",Msg::kVerbose) 
01432     <<"Running InterpolateAboveOrBelow method..."<<endl;
01433 
01436 
01437   if (tuningType!=kGcLinearInPmtAdc && tuningType!=kGcLinearInPinAdc &&
01438       tuningType!=kGcUnknown){
01439     MSG("LITuning",Msg::kFatal)
01440       <<"Tuning type = "<<tuningType<<" not defined."<<endl
01441       <<"Will exit programme here."<<endl;
01442     exit(0);
01443   }
01444   
01445   //get iterators to the last points in the vectors
01446   //vector<Double_t>::iterator ph=phVector.end()-1;
01447   //vector<Double_t>::iterator adc=adcVector.end()-1;
01448   //vector<Double_t>::iterator pin=pinVector.end()-1;
01449 
01450   //check the tuning type since it dictates whether to
01451   //interpolate in pin or pmt adc space
01452   if (tuningType==kGcUnknown){
01453     //interpolate in pmt adc space (y-y2)*m+x2;
01454     Double_t m=(*ph-*(ph-1))/(*adc-*(adc-1));
01455     interpPh=this->Interpolate(interpAdc,*adc,m,*ph);
01456     
01457     //work out the pin value at the interpolated ph
01458     //calculate gradient in pin adc space
01459     m=(*pin-*(pin-1))/(*ph-*(ph-1));
01460     interpPin=this->Interpolate(interpPh,*ph,m,*pin);
01461   }
01462   else if (tuningType==kGcLinearInPmtAdc){
01463     //interpolate in pmt adc space (y-y2)*m+x2;
01464     Double_t m=(*ph-*(ph-1))/(*adc-*(adc-1));
01465     interpPh=this->Interpolate(interpAdc,*adc,m,*ph);    
01466 
01467     //work out the pin value at the interpolated ph
01468     //calculate gradient in pin adc space
01469     m=(*pin-*(pin-1))/(*ph-*(ph-1));
01470     interpPin=this->Interpolate(interpPh,*ph,m,*pin);
01471   }
01472   else if (tuningType==kGcLinearInPinAdc){
01473     //interpolate in pin space (y-y2)*m+x2;
01474     Double_t m=(*ph-*(ph-1))/(*pin-*(pin-1));
01475     interpPh=this->Interpolate(interpPin,*pin,m,*ph);
01476 
01477     //work out the pmt adc value at the interpolated ph
01478     //calculate gradient in pmt space 
01479     m=(*adc-*(adc-1))/(*ph-*(ph-1));
01480     interpAdc=this->Interpolate(interpPh,*ph,m,*adc);
01481   }
01482 
01483   Bool_t valuesCorrected=false;
01484 
01485   if (interpPh<fMinPossPh || interpPin<fMinPossPin ||
01486       interpPin>fMaxPossPin || interpPh>fMaxPossPh){
01487     this->CorrectInterpValues(adc,ph,pin,led,pb,interpAdc,
01488                               interpPh,interpPin);
01489     valuesCorrected=true;
01490   }
01491 
01492   if (valuesCorrected) {
01493     fS="Interpolated values were out of range and corrected ";
01494     fS+=" to be within allowed min/max";
01495   }
01496   else {
01497     fS="Interpolated values stayed within allowed min/max";
01498   }
01499   
01500   if (MsgService::Instance()->IsActive("LITuning",
01501                                        Msg::kDebug)){
01502     MSG("LITuning",Msg::kInfo)
01503       <<endl
01504       <<"("<<pb<<":"<<led<<")"
01505       <<" Looking for GC point."
01506       <<" Interpolated above/below data"
01507       <<endl<<fS<<endl
01508       <<"PMT ADC="<<interpAdc<<endl;
01509     this->PrintPhPinMsg(adc,ph,pin,interpPh,interpPin);
01510   }
01511 
01512   MSG("LITuning",Msg::kVerbose) 
01513     <<"InterpolateAboveOrBelow method finished"<<endl;
01514 }
01515 
01516 //......................................................................
01517 
01518 void LITuning::CorrectInterpValues(vector<Double_t>::iterator adc,
01519                                    vector<Double_t>::iterator ph,
01520                                    vector<Double_t>::iterator pin,
01521                                    Int_t led,Int_t pb,
01522                                    Double_t interpAdc,
01523                                    Double_t& interpPh,
01524                                    Double_t& interpPin)
01525 {
01526   MSG("LITuning",Msg::kVerbose) 
01527     <<"Running CorrectInterpValues method..."<<endl;
01528 
01529   //check points are above minimum
01530   if (interpPh<fMinPossPh || interpPin<fMinPossPin){
01531     MSG("LITuning_TuneHl",Msg::kWarning)
01532       <<endl
01533       <<"("<<pb<<":"<<led<<")"
01534       <<" Looking for GC point."
01535       <<" Interpolated but overshot allowed minimum"
01536       <<endl
01537       <<"PMT ADC="<<interpAdc<<endl;
01538     this->PrintPhPinMsg(adc,ph,pin,interpPh,interpPin);
01539 
01540     MSG("LITuning_TuneHl",Msg::kWarning)
01541       <<endl
01542       <<"After setting overshoot points to minimum:"<<endl;
01543     //set points to minimum if required
01544     if (interpPh<fMinPossPh) interpPh=fMinPossPh;
01545     if (interpPin<fMinPossPin) interpPin=fMinPossPin;
01546     //print out their new values
01547     this->PrintPhPinMsg(adc,ph,pin,interpPh,interpPin);
01548   }
01549 
01550   //check points are below maximum
01551   if (interpPin>fMaxPossPin || interpPh>fMaxPossPh){
01552     MSG("LITuning_TuneHl",Msg::kWarning)
01553       <<endl
01554       <<"("<<pb<<":"<<led<<")"
01555       <<" Looking for GC point."
01556       <<" Interpolated but overshot allowed maximum"
01557       <<endl
01558       <<"PMT ADC="<<interpAdc<<endl;
01559     this->PrintPhPinMsg(adc,ph,pin,interpPh,interpPin);
01560 
01561     MSG("LITuning_TuneHl",Msg::kWarning)
01562       <<endl
01563       <<"After setting overshoot points to maximum:"<<endl;
01564     //set points to maximum if required
01565     if (interpPh>fMaxPossPh) interpPh=fMaxPossPh;
01566     if (interpPin>fMaxPossPin) interpPin=fMaxPossPin;
01567     //print out their new values
01568     this->PrintPhPinMsg(adc,ph,pin,interpPh,interpPin);
01569   }
01570   
01571   MSG("LITuning",Msg::kVerbose) 
01572     <<"CorrectInterpValues method finished"<<endl;
01573 }
01574 
01575 //......................................................................
01576 
01577 Double_t LITuning::Interpolate(Double_t y,Double_t y2,Double_t m,
01578                                Double_t x2)
01579 {
01580   MSG("LITuning",Msg::kVerbose) 
01581     <<"Running Interpolate method..."<<endl;
01582     
01583   //interpolation formula
01584   Double_t x=(y-y2)*m+x2;
01585 
01586   MSG("LITuning",Msg::kVerbose) 
01587     <<"Interpolate method finished"<<endl;
01588   return x;
01589 }
01590 
01591 //......................................................................
01592 
01593 Bool_t LITuning::DataIsOk(vector<LIRun>::iterator gcData,
01594                           Int_t minNumPoints,Int_t maxAllowedAdc)
01595 {
01596   MSG("LITuning",Msg::kVerbose) 
01597     <<"Running DataIsOk method..."<<endl;
01598     
01599   Bool_t sizeOk=false;
01600   Bool_t adcRangeOk=false;
01601 
01602   Int_t phSize=gcData->GetPh().size();
01603   Int_t adcSize=gcData->GetAdc().size();
01604 
01605   //DO NOT use a gain curve with less than minNumPoints points
01606   if (phSize>=minNumPoints && adcSize>=minNumPoints &&
01607       phSize==adcSize) sizeOk=true;
01608 
01609   //check the range of the adc values
01610   //this is no good for ND
01611   //hack alert!!!!
01612   maxAllowedAdc=0;//just for unused parameter warning
01613   //if (gcData->GetMaxAdc()<maxAllowedAdc && gcData->GetMaxAdc()>=1 && 
01614   //  gcData->GetMinAdc()<maxAllowedAdc && 
01615   //  gcData->GetMinAdc()>=0) adcRangeOk=true; 
01616 
01617   //check the range of the adc values
01618   if (gcData->GetMaxAdc()>=1 && gcData->GetMinAdc()>=0) adcRangeOk=true;
01619 
01620   MSG("LITuning",Msg::kDebug) 
01621     <<"DataIsOk: max ADC="<<gcData->GetMaxAdc()
01622     <<", min ADC="<<gcData->GetMinAdc()
01623     <<", PH size="<<phSize<<", ADC size="<<adcSize
01624     <<endl;
01625 
01626   MSG("LITuning",Msg::kVerbose) 
01627     <<"DataIsOk method finished"<<endl;
01628   return sizeOk*adcRangeOk;//only ok if both ok
01629 }
01630 
01631 //......................................................................
01632 
01633 void LITuning::GcLinearInPmtAdc(vector<LIRun>::iterator gcData,
01634                                 Int_t goodPin,
01635                                 vector<LIRun>::iterator& gcTuned,
01636                                 Double_t firstPh,Double_t lastPh,
01637                                 Double_t firstPin,Double_t lastPin)
01638 {
01639   MSG("LITuning",Msg::kVerbose)
01640     <<"Running GcLinearInPmtAdc method..."<<endl;
01641 
01642   //get iterators to the vectors of gain curve points
01643   vector<Double_t> phVector;
01644   vector<Double_t>::iterator ph;
01645   phVector=gcData->GetPh();
01646   ph=phVector.begin();
01647   vector<Double_t> adcVector;
01648   vector<Double_t>::iterator adc;
01649   adcVector=gcData->GetAdc();
01650   adc=adcVector.begin();
01651   vector<Double_t>pinVector;
01652   vector<Double_t>::iterator pin;
01653   pinVector=gcData->GetPin(goodPin);
01654   pin=pinVector.begin();
01655 
01656   //get the pulserbox and led associated with real data gain curve
01657   Int_t pb=gcData->GetPb();
01658   Int_t led=gcData->GetLed();
01659 
01660   //set the first point as it has already been found
01661   gcTuned->AddPoint(firstPh,fFirstGcPointAdc,firstPin);
01662 
01663   //loop to find gain curve points (second through to last but one)
01664   for (Int_t g=1;g<fNumGainPoints-1;g++){
01665     //calculate the required adc for this point
01666     Double_t adcSeparation=(fLastGcPointAdc-fFirstGcPointAdc)/
01667       (fNumGainPoints-1);
01668     Double_t reqAdc=fFirstGcPointAdc+g*adcSeparation;
01669       
01670     if (reqAdc<fMinPossAdc || reqAdc>fMaxPossAdc){
01671       MSG("LITuning_TuneGc",Msg::kFatal)
01672         <<endl<<"("<<pb<<":"<<led<<") GC g="<<g+1
01673         <<" Aborted finding gain curve point, reqAdc="<<reqAdc
01674         <<", adcSeparation="<<adcSeparation<<endl;
01675       continue;
01676     }
01677       
01678     if (MsgService::Instance()->IsActive("LITuning_TuneGc",
01679                                          Msg::kDebug)){
01680       MSG("LITuning_TuneGc",Msg::kInfo)
01681         <<endl<<"Gain Curve point "<<g+1<<" ("<<pb<<":"<<led
01682         <<") reqAdc="<<reqAdc<<", sep="<<adcSeparation<<endl;
01683     }
01684 
01685     //reset all the variables for this loop
01686     Bool_t pointFound=false;
01687     Bool_t firstPointTooHigh=false;
01688     Int_t counter=0;//already done one point
01689     ph=phVector.begin();
01690     adc=adcVector.begin();
01691     Double_t interpPh=-1;
01692     Double_t pinAtReqAdc=-1;
01693 
01694     //loop over the points
01695     while(ph!=phVector.end()){
01696       //counter
01697       counter++;
01698 
01699       //check if the first data point has an adc value greater than
01700       //the last required point
01701       if (*adc>reqAdc && adc==adcVector.begin()){
01702             
01703         //set control variables
01704         pointFound=false;
01705         firstPointTooHigh=true;
01706           
01707         //jump out of the loop
01708         break;
01709       }
01710     
01711       //check if the current point has an adc value greater than the
01712       //required point
01713       //and whether a point has been found yet
01714       if (*adc>reqAdc && !pointFound){
01715         
01716         //set control variable
01717         pointFound=true;
01718 
01719         //interpolate in pmt adc space (y-y2)*m+x2;
01720         Double_t m=(*ph-*(ph-1))/(*adc-*(adc-1));
01721         interpPh=this->Interpolate(reqAdc,*adc,m,*ph);
01722       
01723         if (MsgService::Instance()->IsActive("LITuning_TuneGc",
01724                                              Msg::kDebug)){
01725           MSG("LITuning_TuneGc",Msg::kInfo)
01726             <<"("<<pb<<":"<<led<<")"
01727             <<" GC point "<<g+1<<" found"
01728             <<" ("<<counter<<"/"<<adcVector.size()<<")"
01729             <<", Required Point="<<reqAdc<<endl;
01730           this->PrintPhMsg(adc,ph,interpPh);
01731         }
01732 
01733         //jump out of the loop when point is found
01734         break;
01735       }
01736     
01737       //go to the next point
01738       ph++;
01739       adc++;
01740       pin++;
01741     }
01742 
01743     //check on success of finding point
01744     if (firstPointTooHigh){
01745       this->InterpolateAboveOrBelow(kGcLinearInPmtAdc,
01746                                     adcVector.begin()+1,
01747                                     phVector.begin()+1,
01748                                     pinVector.begin()+1,led,pb,
01749                                     reqAdc,interpPh,pinAtReqAdc);
01750       //set control variable
01751       pointFound=true;
01752     }
01753     else if (!pointFound){//i.e. last data point was too low
01754       this->InterpolateAboveOrBelow(kGcLinearInPmtAdc,
01755                                     adcVector.end()-1,phVector.end()-1,
01756                                     pinVector.end()-1,led,pb,
01757                                     reqAdc,interpPh,pinAtReqAdc);
01758       //set control variable
01759       pointFound=true;
01760     }
01761       
01762     //add the point to the tuned GC
01763     if (pointFound) gcTuned->AddPoint(interpPh,reqAdc,pinAtReqAdc);
01764     else MSG("LITuning_TuneGc",Msg::kWarning)<<"No GC Point found"
01765                                              <<endl;
01766   }//end of for
01767 
01768   //set the last point as it has already been found
01769   gcTuned->AddPoint(lastPh,fLastGcPointAdc,lastPin);
01770 
01771   MSG("LITuning",Msg::kVerbose) 
01772     <<"GcLinearInPmtAdc method finished"<<endl;
01773 }
01774 
01775 //......................................................................
01776 
01777 void LITuning::GcLinearInPinAdc(vector<LIRun>::iterator gcData,
01778                                 Int_t goodPin,
01779                                 vector<LIRun>::iterator& gcTuned,
01780                                 Double_t firstPh,Double_t lastPh,
01781                                 Double_t firstPin,Double_t lastPin)
01782 {
01783   MSG("LITuning",Msg::kVerbose) 
01784     <<"Running GcLinearInPinAdc method..."<<endl;
01785 
01786   //get iterators to the vectors of gain curve points
01787   vector<Double_t> phVector;
01788   vector<Double_t>::iterator ph;
01789   phVector=gcData->GetPh();
01790   ph=phVector.begin();
01791   vector<Double_t> adcVector;
01792   vector<Double_t>::iterator adc;
01793   adcVector=gcData->GetAdc();
01794   adc=adcVector.begin();
01795   vector<Double_t>pinVector;
01796   vector<Double_t>::iterator pin;
01797   pinVector=gcData->GetPin(goodPin);
01798   pin=pinVector.begin();
01799 
01800   //get the pulserbox and led associated with real data gain curve
01801   Int_t pb=gcData->GetPb();
01802   Int_t led=gcData->GetLed();
01803 
01804   //set the first point as it has already been found
01805   gcTuned->AddPoint(firstPh,fFirstGcPointAdc,firstPin);
01806 
01807   //loop to find gain curve points (second through to last but one)
01808   for (Int_t g=1;g<fNumGainPoints-1;g++){
01809     //calculate the required pin for this point
01810     Double_t pinSeparation=(lastPin-firstPin)/(fNumGainPoints-1);
01811     Double_t reqPin=firstPin+g*pinSeparation;
01812     
01813     if (reqPin<fMinPossPin || reqPin>fMaxPossPin){
01814       MSG("LITuning_TuneGc",Msg::kFatal)
01815         <<endl<<"("<<pb<<":"<<led<<") GC g="<<g+1
01816         <<" Aborted finding gain curve point, reqPin="<<reqPin
01817         <<", pinSeparation="<<pinSeparation<<endl;
01818       continue;
01819     }
01820     if (MsgService::Instance()->IsActive("LITuning_TuneGc",
01821                                          Msg::kDebug)){
01822       MSG("LITuning_TuneGc",Msg::kInfo)
01823         <<endl<<"Gain Curve point "<<g+1<<" ("<<pb<<":"<<led
01824         <<") reqPin="<<reqPin<<", sep="<<pinSeparation<<endl;
01825       if (MsgService::Instance()->IsActive("LITuning_TuneGc",
01826                                            Msg::kVerbose)){
01827         this->PrintFirstLastMsg(firstPh,lastPh,firstPin,lastPin);
01828       }
01829     }
01830 
01831     //reset all the variables for this loop
01832     Bool_t pointFound=false;
01833     Bool_t firstPointTooHigh=false;
01834     Int_t counter=0;//already done one point
01835     adc=adcVector.begin();
01836     ph=phVector.begin();
01837     pin=pinVector.begin();
01838     Double_t interpPh=-1;
01839     Double_t adcAtReqPin=-1;
01840     
01841     //loop over the points
01842     while(ph!=phVector.end()){
01843       //counter
01844       counter++;
01845       
01846       //check if the first data point has an pin value greater than
01847       //the last required point
01848       if (*pin>reqPin && pin==pinVector.begin()){
01849         
01850         //set control variables
01851         pointFound=false;
01852         firstPointTooHigh=true;
01853           
01854         //jump out of the loop
01855         break;
01856       }
01857     
01858       //check if the current point has an pin value greater than the
01859       //required point
01860       //and whether a point has been found yet
01861       if (*pin>reqPin && !pointFound){
01862         
01863         //set control variable
01864         pointFound=true;
01865 
01866         //interpolate in pin space (y-y2)*m+x2;
01867         Double_t m=(*ph-*(ph-1))/(*pin-*(pin-1));
01868         interpPh=this->Interpolate(reqPin,*pin,m,*ph);
01869         
01870         //calculate gradient in pmt space 
01871         m=(*adc-*(adc-1))/(*ph-*(ph-1));
01872         //interpolate in pmt space (y-y2)*m+x2;
01873         adcAtReqPin=this->Interpolate(interpPh,*ph,m,*adc);
01874      
01875         if (MsgService::Instance()->IsActive("LITuning_TuneGc",
01876                                              Msg::kDebug)){
01877           MSG("LITuning_TuneGc",Msg::kInfo)
01878             <<"("<<pb<<":"<<led<<")"
01879             <<" GC point "<<g+1<<" found"
01880             <<" ("<<counter<<"/"<<pinVector.size()<<")"
01881             <<", Required PIN ADC="<<reqPin<<endl;
01882           this->PrintPinMsg(pin,ph,adcAtReqPin,interpPh);
01883         }
01884           
01885         //jump out of the loop when point is found
01886         break;
01887       }
01888     
01889       //go to the next point
01890       ph++;
01891       pin++;
01892       adc++;
01893     }
01894 
01895     //check on success of finding point
01896     if (firstPointTooHigh){
01897       this->InterpolateAboveOrBelow(kGcLinearInPinAdc,
01898                                     adcVector.begin()+1,//was pinVector?
01899                                     phVector.begin()+1,
01900                                     pinVector.begin()+1,led,pb,
01901                                     adcAtReqPin,interpPh,reqPin);
01902       //set control variable
01903       pointFound=true;
01904     }
01905     else if (!pointFound){//i.e. last data point was too low
01906       this->InterpolateAboveOrBelow(kGcLinearInPinAdc,
01907                                     adcVector.end()-1,phVector.end()-1,
01908                                     pinVector.end()-1,led,pb,
01909                                     adcAtReqPin,interpPh,reqPin);
01910       //set control variable
01911       pointFound=true;
01912     }
01913       
01914     //add the point to the tuned GC
01915     if (pointFound) gcTuned->AddPoint(interpPh,adcAtReqPin,reqPin);
01916     else MSG("LITuning_TuneGc",Msg::kWarning)<<"No GC point found"
01917                                              <<endl;
01918 
01919   }//end of for
01920 
01921   //set the last point as it has already been found
01922   gcTuned->AddPoint(lastPh,fLastGcPointAdc,lastPin);
01923 
01924   MSG("LITuning",Msg::kVerbose) 
01925     <<"GcLinearInPinAdc method finished"<<endl;
01926 }
01927 
01928 //......................................................................
01929 
01930 void LITuning::CalculateGainCurve(EGcTuningType tuningType)
01931 {
01932   MSG("LITuning", Msg::kInfo) 
01933     <<"Running CalculateGainCurve method..."<<endl;
01934 
01935   if (tuningType!=kGcLinearInPmtAdc && tuningType!=kGcLinearInPinAdc){
01936     MSG("LITuning_TuneGc",Msg::kFatal)
01937       <<"Tuning type = "<<tuningType<<" not defined."<<endl
01938       <<"Will exit programme here."<<endl;
01939     exit(0);
01940   }
01941   
01942   //get iterators to the gain curve
01943   vector<LIRun>::iterator gcData;
01944   gcData=fGainCurve->begin();
01945   vector<LIRun>::iterator gcTuned;
01946   //note can't get begin() before vector contains any elements
01947   //so get end()-1 for gcTuned below 
01948 
01950   //loop over all the gain curves for the different pulser boxes
01951   //and leds
01953   while (gcData!=fGainCurve->end()){
01954 
01955     //get the pulserbox and led associated with real data gain curve
01956     Int_t pulserBox=gcData->GetPb();
01957     Int_t led=gcData->GetLed();
01958 
01959     if (led!=-1 && pulserBox!=-1){
01960       if (MsgService::Instance()->IsActive("LITuning_TuneGc",
01961                                            Msg::kDebug)){
01962         MSG("LITuning_TuneGc", Msg::kInfo)
01963           <<endl<<"("<<pulserBox<<":"<<led
01964           <<") **** Starting GC tuning for this led... **** "
01965           <<endl<<endl;
01966       }
01967     }
01968 
01969     if (!this->DataIsOk(gcData)){
01970       MSG("LITuning_TuneGc", Msg::kInfo) 
01971         <<"This gain curve data ("<<pulserBox<<":"<<led<<") is not "
01972         <<"consistent for calcuations"<<endl
01973         <<"Either it has less than the minimum number of points or"
01974         <<" the data is nonsense"<<endl;
01975       gcData++;
01976       continue;
01977     }
01978 
01979     //get iterators to the vectors of gain curve points
01980     vector<Double_t> phVector;
01981     vector<Double_t>::iterator ph;
01982     phVector=gcData->GetPh();
01983     ph=phVector.begin();
01984     vector<Double_t> adcVector;
01985     vector<Double_t>::iterator adc;
01986     adcVector=gcData->GetAdc();
01987     adc=adcVector.begin();
01988     vector<Double_t>pinVector;
01989     vector<Double_t>::iterator pin;
01990     Int_t goodPin=this->GoodPin(gcData);
01991     if (goodPin==1 || goodPin==2){
01992       pinVector=gcData->GetPin(goodPin);
01993       pin=pinVector.begin();
01994     }
01995     else {
01996       MSG("LITuning_TuneGc", Msg::kWarning)
01997         <<endl 
01998         <<"This gain curve ("<<pulserBox<<":"<<led<<") does not have "
01999         <<"a good pin diode associated with it (goodPin="<<goodPin<<")"
02000         <<endl;
02001       
02002       //set pin iterator to point to pulse height!!!
02003       //pin=ph;
02004       //don't like this, best to skip
02005 
02006       //find out the first and last points before continuing
02007       
02008       //variables for first and last points
02009       Double_t firstPh=-1;
02010       Double_t firstPin=-1;
02011       Double_t lastPh=-1;
02012       Double_t lastPin=-1;
02013       //get the first and last gain curve points
02014       this->CalcFirstGcPoint(gcData,1,firstPh,firstPin);
02015       this->CalcLastGcPoint(gcData,1,lastPh,lastPin);
02016       
02017       MSG("LITuning_TuneGc", Msg::kWarning)
02018         <<"("<<pulserBox<<":"<<led<<") Skipping this LED"<<endl
02019         <<"Calcuated first and last points anyway:"<<endl
02020         <<"first Ph="<<firstPh<<", last Ph="<<lastPh<<endl
02021         <<"first Pin="<<firstPin<<", last Pin="<<lastPin<<endl<<endl;
02022 
02023       gcData++;
02024       continue;
02025     }
02026     
02027     MSG("LITuning_TuneGc",Msg::kDebug)
02028       <<"("<<pulserBox<<":"<<led<<"), ph="<<*ph<<", adc="<<*adc
02029       <<", good pin="<<goodPin<<endl;
02030 
02031     //variables to hold the ph and pin values to find GC points between
02032     Double_t firstPh=-1;
02033     Double_t firstPin=-1;
02034     Double_t lastPh=-1;
02035     Double_t lastPin=-1;
02036 
02037     //get the first and last gain curve points
02038     this->CalcFirstGcPoint(gcData,goodPin,firstPh,firstPin);
02039     this->CalcLastGcPoint(gcData,goodPin,lastPh,lastPin);
02040     
02041     if (MsgService::Instance()->IsActive("LITuning_TuneGc",
02042                                          Msg::kDebug)){
02043       this->PrintFirstLastMsg(firstPh,lastPh,firstPin,lastPin);
02044     }
02045 
02046     //add another GC to vector to hold tuned drift points
02047     fBestGc.push_back(LIRun(pulserBox,led,LIRun::kGainCurve));
02048     //get iterator to the newest (last) element
02049     gcTuned=fBestGc.end()-1;
02050 
02052     //Run the tuning algorithm on this particular pulser box and
02053     //led to generate the points
02055     if (tuningType==kGcLinearInPmtAdc){
02056       this->GcLinearInPmtAdc(gcData,goodPin,gcTuned,firstPh,lastPh,
02057                              firstPin,lastPin);
02058     }
02059     else if (tuningType==kGcLinearInPinAdc){
02060       this->GcLinearInPinAdc(gcData,goodPin,gcTuned,firstPh,lastPh,
02061                              firstPin,lastPin);
02062     }
02063 
02064     MSG("LITuning_TuneGc",Msg::kDebug)
02065       <<"("<<pulserBox<<":"<<led<<") Created tuned GC Point"<<endl;
02066     
02067     gcData++;
02068   }
02069 
02070   MSG("LITuning",Msg::kInfo) 
02071     <<"CalculateGainCurve method finished"<<endl;
02072 }
02073 
02074 //......................................................................
02075 
02076 Int_t LITuning::PrintLIConfig(LIRun::ELIRunType liRun)
02077 {
02078   MSG("LITuning",Msg::kDebug) 
02079     <<"Running PrintLIConfig method..."<<endl;
02080 
02081   vector<LIRun>::iterator tunedRun;
02082   vector<LIRun>::iterator tunedRunEnd;
02083 
02084   //select appropriate vectors depending if the run to 
02085   //be printed is a GC or a DP
02086   if (liRun==LIRun::kGainCurve){
02087     if (fBestGc.empty()){
02088       MSG("LITuning",Msg::kWarning)
02089         <<"There is nothing to print, no tuned values have been"
02090         <<" computed for a gain curve"<<endl;
02091       return 0;
02092     }
02093     //select the tuned gain curve
02094     tunedRun=fBestGc.begin();
02095     tunedRunEnd=fBestGc.end();
02096     MSG("LITuning",Msg::kInfo)<<endl<<"<fullCalib>"<<endl;
02097   }
02098   else if (liRun==LIRun::kDriftPoint){
02099     if (fBestDp.empty()){
02100       MSG("LITuning",Msg::kWarning)
02101         <<"There is nothing to print, no tuned values have been"
02102         <<" computed for a drift point"<<endl;
02103       return 0;
02104     }
02105     //select the tuned drift points
02106     tunedRun=fBestDp.begin();
02107     tunedRunEnd=fBestDp.end();
02108     MSG("LITuning",Msg::kInfo)<<endl<<"<driftCalib>"<<endl;
02109   }
02110   
02111   //variable to hold the last pulser box
02112   Int_t lastPulserBox=-1;
02113 
02114   //loop and print out the list of LI run pulse heights 
02115   //in the desired format
02116   while (tunedRun!=tunedRunEnd){
02117 
02118     //get iterators to the vectors of li run points
02119     vector<Double_t> phVector;
02120     vector<Double_t>::iterator ph;
02121     phVector=tunedRun->GetPh();
02122     ph=phVector.begin();
02123 
02124     //check that there is a point present
02125     if (phVector.empty()){
02126       MSG("LITuning",Msg::kWarning)
02127         <<"("<<tunedRun->GetPb()<<":"<<tunedRun->GetLed()
02128         <<") DP is empty"<<endl;
02129       tunedRun++;
02130       continue;
02131     }
02132     else{
02133       //leave a line between pulser boxes
02134       if (tunedRun->GetPb()!=lastPulserBox){
02135         MSG("LITuning",Msg::kInfo)<<endl;
02136       }
02137     }
02138 
02139     //keep a record of last pulser box
02140     lastPulserBox=tunedRun->GetPb();
02141 
02142     //print only on debug
02143     if (MsgService::Instance()->IsActive("LITuning",Msg::kDebug)){
02144       tunedRun->PrintAll();
02145     }
02146 
02147     string sBox="";
02148     sBox=Form("%d",tunedRun->GetPb());
02149     if (tunedRun->GetPb()<10) sBox="0"+sBox;
02150     
02151     string sLed="";
02152     sLed=Form("%d",tunedRun->GetLed());
02153     if (tunedRun->GetLed()<10) sLed="0"+sLed;
02154     
02155     //form the base string
02156     fS="box"+sBox+"led"+sLed+"#I=";
02157 
02158     //loop over all the points in the vector (1 or more)
02159     while(ph!=phVector.end()){
02160 
02161       MSG("LITuning",Msg::kVerbose)
02162         <<"Looping over tuned points"<<endl;
02163 
02164       //round up pulse height
02165       Double_t rem=0;
02166       Double_t iph=0;
02167       rem=modf(*ph,&iph);
02168       if (rem>=0.5) iph++;//round up
02169 
02170       string sPh="";
02171       if (iph<1e6){
02172         sPh=Form("%d",static_cast<Int_t>(iph));
02173       }
02174       else{
02175         sPh="Really high PH!";
02176       }
02177 
02178       MSG("LITuning",Msg::kVerbose)
02179         <<"iph="<<iph
02180         <<", sPh="<<sPh<<endl;
02181 
02182       fS+=sPh;
02183       if (ph<phVector.end()-1) fS+=",";
02184       //iterate the next point
02185       ph++;
02186     }
02187     fS+=";";
02188     //print out the string in the required format
02189     MSG("LITuning",Msg::kInfo)<<fS<<endl; 
02190 
02191     //iterate the li run that you are printing out
02192     tunedRun++;
02193   }
02194 
02195   //print out end tag
02196   if (liRun==LIRun::kGainCurve){
02197     MSG("LITuning",Msg::kInfo)<<endl<<"</fullCalib>"<<endl;
02198   }
02199   else if (liRun==LIRun::kDriftPoint){
02200     MSG("LITuning",Msg::kInfo)<<endl<<"</driftCalib>"<<endl;
02201   }
02202   
02203   //This is the format under which the parameters are specified
02204   //in the config file
02205 
02206   //Label under which we specify LI sequence for drift calib:
02207   //<driftCalib>
02208   //box00led01#I=400;
02209   //box00led02#I=440;
02210   //box00led03#I=510;
02211   //[etc., etc.]
02212   //box15led20#I=390;
02213   //</driftCalib>
02214   
02215   //Label under which we specify LI sequence for gain-curve calib:
02216   //<fullCalib>
02217   //box00led01#I=100,200,300,400,500,600,700,800,900,1000;
02218   //box00led02#I=110,220,330,440,550,660,770,880,990,1023;
02219   //[etc., etc.]
02220   //box15led20#I=98,196,294,392,490,588,686,784,882,980;
02221   //</fullCalib>
02222   
02223   MSG("LITuning",Msg::kDebug) 
02224     <<"PrintLIConfig method finished"<<endl;
02225   return 1;
02226 }
02227 
02228 //......................................................................
02229 
02230 void LITuning::PrintLedCheckGrid(LIRun::ELIRunType liRun,
02231                                  Int_t firstPb,Int_t lastPb,
02232                                  Int_t firstLed,Int_t lastLed)
02233 {
02234   MSG("LITuning",Msg::kDebug) 
02235     <<"Running PrintLedCheckGrid method..."<<endl;
02236  
02237   vector<LIRun>::iterator tunedRun;
02238   vector<LIRun>::iterator tunedRunEnd;
02239 
02240   Int_t totalNumPbs=lastPb-firstPb+1;
02241   Int_t numLedsPerPb=lastLed-firstLed+1;
02242   
02243   //select appropriate vectors depending if the run to 
02244   //be checked is a GC or a DP
02245   if (liRun==LIRun::kGainCurve){
02246     if (fBestGc.empty()){
02247       MSG("LITuning",Msg::kWarning)
02248         <<"There is nothing to print, no tuned values have been"
02249         <<" computed for a gain curve"<<endl;
02250     }
02251     //select the tuned gain curve
02252     tunedRun=fBestGc.begin();
02253     tunedRunEnd=fBestGc.end();
02254   }
02255   else if (liRun==LIRun::kDriftPoint){
02256     if (fBestDp.empty()){
02257       MSG("LITuning",Msg::kWarning)
02258         <<"There is nothing to print, no tuned values have been"
02259         <<" computed for a drift point"<<endl;
02260     }
02261     //select the tuned drift points
02262     tunedRun=fBestDp.begin();
02263     tunedRunEnd=fBestDp.end();
02264   }
02265   
02266   //vector to hold which leds were tuned
02267   vector<Int_t> totalLISystem(totalNumPbs*numLedsPerPb,0);
02268 
02269   //loop over tuned leds
02270   while (tunedRun!=tunedRunEnd){
02271 
02272     //get iterator to the vector of li run points
02273     vector<Double_t> phVector;
02274     phVector=tunedRun->GetPh();
02275 
02276     //check that there is a point present
02277     if (phVector.empty()){
02278       MSG("LITuning",Msg::kWarning)
02279         <<"("<<tunedRun->GetPb()<<":"<<tunedRun->GetLed()
02280         <<") DP is empty"<<endl;
02281       tunedRun++;
02282       continue;
02283     }
02284 
02285     Int_t pb=tunedRun->GetPb();
02286     Int_t led=tunedRun->GetLed();
02287     Int_t ledIndex=pb*numLedsPerPb+led-1;
02288 
02289     if (pb<=lastPb && led<=lastLed &&
02290         pb>=firstPb && led>=firstLed){
02291       totalLISystem[ledIndex]++;
02292     }
02293     else{
02294       MSG("LITuning",Msg::kInfo)
02295         <<"Pulser box and or led are out of expected range:"
02296         <<" PB="<<pb<<", LED="<<led<<endl;
02297     }
02298     tunedRun++;
02299   }
02300   
02301   //variable to hold the output string
02302   string sDataProcessed="";
02303 
02304   //loop over whole li system
02305   for (Int_t pb=firstPb;pb<=lastPb;pb++){
02306     for (Int_t led=firstLed;led<=lastLed;led++){
02307       Int_t ledIndex=pb*numLedsPerPb+led-1;
02308       MSG("LITuning",Msg::kVerbose)
02309         <<"PB="<<pb<<", LED="<<led<<endl;
02310       
02311       string sBox="";
02312       sBox=Form("%d",pb);
02313       if (pb<10) sBox="0"+sBox;
02314       
02315       string sLed="";
02316       sLed=Form("%d",led);
02317       if (led<10) sLed="0"+sLed;
02318       
02319       string sTotalLISystem=Form("%d",totalLISystem[ledIndex]);
02320       static Int_t lastPulserBox=-1;
02321 
02322       if (pb!=lastPulserBox){
02323         MSG("LITuning",Msg::kDebug)
02324           <<"New PB="<<pb<<", LED="<<led<<endl;
02325         
02326         //add prefix to each line in string
02327         if (pb==firstPb){
02328           sDataProcessed+="PB "+sBox+" LEDs: ";
02329         }
02330         else{
02331           sDataProcessed+="\nPB "+sBox+" LEDs: ";
02332         }
02333       }
02334       //keep a record of last pulser box
02335       lastPulserBox=pb;
02336 
02337       //add whether point was tuned      
02338       sDataProcessed+=sTotalLISystem;
02339       
02340       //add comma separations
02341       if (led!=lastLed){
02342         sDataProcessed+=",";
02343       }
02344       
02345       //add spaces every five leds
02346       if (led%5==0){
02347         sDataProcessed+=" ";
02348       }
02349     }
02350   }
02351 
02352   string sLIRunType="non-specified type";
02353   if (liRun==LIRun::kGainCurve){
02354     sLIRunType="Gain Curve";
02355   }
02356   else if (liRun==LIRun::kDriftPoint){
02357     sLIRunType="Drift Point";
02358   }
02359 
02360   //print string
02361   MSG("LITuning",Msg::kInfo)
02362     <<endl<<"Of the "<<totalNumPbs*numLedsPerPb
02363     <<" leds the following were tuned for a "<<sLIRunType<<endl
02364     <<sDataProcessed<<endl;
02365   
02366   MSG("LITuning",Msg::kDebug) 
02367     <<"Finished PrintLedCheckGrid method"<<endl;
02368 }
02369 
02370 //......................................................................
02371 
02372 Bool_t LITuning::GetTunedDpGraphs(TGraph*& gAdcVsLed,TGraph*& gPhVsLed,
02373                                   TGraph*& gPinVsLed,
02374                                   Int_t numLedsPerPb)
02375 {
02376   MSG("LITuning",Msg::kInfo) 
02377     <<"Running GetTunedDpGraphs method..."<<endl;
02378 
02379   //check if a gain curve has been calculated
02380   if (fBestDp.empty()){
02381     MSG("LITuning",Msg::kWarning)
02382       <<"There is nothing to print, no tuned values have been"
02383       <<" computed for a drift point"<<endl;
02384     return false;
02385   }
02386 
02387   vector<LIRun>::iterator tunedRun;
02388   vector<LIRun>::iterator tunedRunEnd;
02389  
02390   //select the tuned gain curve
02391   tunedRun=fBestDp.begin();
02392   tunedRunEnd=fBestDp.end();
02393   
02394   vector<Double_t> phVector;
02395   vector<Double_t> pinVector;
02396   vector<Double_t> adcVector;
02397   vector<Double_t> ledIndexVector;
02398 
02400   //loop over tuned DPs and fill vectors
02402   while (tunedRun!=tunedRunEnd){
02403 
02404     //get the pulserbox and led 
02405     Int_t pulserBox=tunedRun->GetPb();
02406     Int_t led=tunedRun->GetLed();
02407     //calculate the ledIndex
02408     Int_t ledIndex=pulserBox*numLedsPerPb+led-1;
02409 
02410     phVector.push_back(tunedRun->GetPh(0));
02411     pinVector.push_back(tunedRun->GetPin(2,0));//pin2
02412     adcVector.push_back(tunedRun->GetAdc(0));
02413     ledIndexVector.push_back(ledIndex);
02414 
02415    //print only on debug
02416     if (MsgService::Instance()->IsActive("LITuning",Msg::kDebug)){
02417       tunedRun->PrintAll();
02418     }
02419 
02420     //iterate the li run that you are looking at
02421     tunedRun++;
02422   }
02423 
02424   MSG("LITuning",Msg::kDebug) 
02425     <<"Making graphs..."<<endl;
02426   gAdcVsLed=this->TGraphVect(ledIndexVector,adcVector);
02427   gPhVsLed=this->TGraphVect(ledIndexVector,phVector);
02428   gPinVsLed=this->TGraphVect(ledIndexVector,pinVector);
02429     
02431   //do pmt adc graph
02433   fS="Theoretical Tuned PMT ADC of LEDs";
02434   gAdcVsLed->SetTitle(fS.c_str());
02435   gAdcVsLed->SetFillColor(0);
02436   gAdcVsLed->SetMinimum(-2);
02437 
02439   //do ph graph
02441   fS="Tuned Pulse Height of LEDs";
02442   gPhVsLed->SetTitle(fS.c_str());
02443   gPhVsLed->SetFillColor(0);
02444   gPhVsLed->SetMinimum(-2);
02445 
02447   //do pin adc graph
02449   fS="PIN ADC at Tuned Drift Point Light Levels";
02450   gPinVsLed->SetTitle(fS.c_str());
02451   gPinVsLed->SetFillColor(0);
02452   gPinVsLed->SetMinimum(-2);
02453 
02454   MSG("LITuning",Msg::kDebug) 
02455     <<"Finished GetTunedDpGraphs method"<<endl;
02456   return true;
02457 }
02458 
02459 //......................................................................
02460 
02461 Bool_t LITuning::GetDataGcGraphs(vector<TGraph*>& gAdcVsPh,
02462                                  vector<TGraph*>& gAdcFVsPh,
02463                                  vector<TGraph*>& gPinVsPh,
02464                                  vector<TGraph*>& gPin2VsPh,
02465                                  vector<TGraphAsymmErrors*>& 
02466                                  gAdcErrVsPh,
02467                                  vector<TGraphAsymmErrors*>& 
02468                                  gAdcFErrVsPh)
02469 {
02470   MSG("LITuning",Msg::kInfo) 
02471     <<"Running GetDataGcGraphs method..."<<endl;
02472 
02473   //check if data has been input
02474   if (!fGainCurve){//check that it's not a null pointer
02475     MSG("LITuning",Msg::kWarning)
02476       <<"There is nothing to print, no data has been input"<<endl;
02477     return false;
02478   }
02479 
02480   //get iterators for the histos
02481   vector<TGraph*>::iterator gAdcVsPhIter;
02482   vector<TGraph*>::iterator gAdcFVsPhIter;
02483   vector<TGraph*>::iterator gPinVsPhIter;
02484   vector<TGraph*>::iterator gPin2VsPhIter;
02485   vector<TGraphAsymmErrors*>::iterator gAdcErrVsPhIter;
02486   vector<TGraphAsymmErrors*>::iterator gAdcFErrVsPhIter;
02487 
02488   vector<LIRun>::iterator gcData;
02489   vector<LIRun>::iterator gcDataEnd;
02490   
02491   //select the tuned gain curve
02492   gcData=fGainCurve->begin();
02493   gcDataEnd=fGainCurve->end();
02494 
02496   //loop over input data and create graphs
02498   while (gcData!=gcDataEnd){
02499 
02500     //get iterators to the vectors of li run points
02501     vector<Double_t> phVector;
02502     phVector=gcData->GetPh();
02503     vector<Double_t> pinVector;
02504     pinVector=gcData->GetPin(1);
02505     vector<Double_t> pin2Vector;
02506     pin2Vector=gcData->GetPin(2);
02507     vector<Double_t> adcVector;
02508     adcVector=gcData->GetAdc();
02509     vector<Double_t> adcLowVector;
02510     adcLowVector=gcData->GetAdcLow();
02511     vector<Double_t> adcHighVector;
02512     adcHighVector=gcData->GetAdcHigh();
02513     vector<Double_t> adcFLowVector;
02514     adcFLowVector=gcData->GetAdcLowF();
02515     vector<Double_t> adcFHighVector;
02516     adcFHighVector=gcData->GetAdcHighF();
02517     vector<Double_t> adcFVector;
02518     adcFVector=gcData->GetAdcF();
02519 
02520     //get the pulserbox and led 
02521     Int_t pulserBox=gcData->GetPb();
02522     Int_t led=gcData->GetLed();
02523     Detector::Detector_t detectorType=gcData->GetDetector();
02524 
02525     //check that there is a point present
02526     if (phVector.empty()){
02527       MSG("LITuning",Msg::kDebug)
02528         <<"("<<pulserBox<<":"<<led<<") Input data vectors are empty."
02529         <<" Skipping this point..."
02530         <<endl;
02531       gcData++;
02532       continue;
02533     }
02534 
02535     string sPb=Form("%d",pulserBox);
02536     string sLed=Form("%d",led);
02537     string sEndBit=", Pulser Box "+sPb+", LED "+sLed;
02538     MSG("LITuning",Msg::kVerbose) 
02539       <<"("<<pulserBox<<":"<<led<<") Making graphs..."<<endl;
02540     gAdcVsPh.push_back(this->TGraphVect(phVector,adcVector));
02541     gAdcFVsPh.push_back(this->TGraphVect(phVector,adcFVector));
02542     gPinVsPh.push_back(this->TGraphVect(phVector,pinVector));
02543     gPin2VsPh.push_back(this->TGraphVect(phVector,pin2Vector));
02544     gAdcErrVsPh.push_back
02545       (this->TGraphAsymmErrorsVectEY(phVector,adcVector,adcLowVector,
02546                                      adcHighVector));
02547     gAdcFErrVsPh.push_back
02548       (this->TGraphAsymmErrorsVectEY(phVector,adcFVector,adcFLowVector,
02549                                      adcFHighVector));
02550     
02551     gAdcVsPhIter=gAdcVsPh.end()-1;
02552     gAdcFVsPhIter=gAdcFVsPh.end()-1;
02553     gPinVsPhIter=gPinVsPh.end()-1;
02554     gPin2VsPhIter=gPin2VsPh.end()-1;
02555     gAdcErrVsPhIter=gAdcErrVsPh.end()-1;
02556     gAdcFErrVsPhIter=gAdcFErrVsPh.end()-1;
02557 
02559     //do pmt adc graph
02561     fS="Response of PMTs to LI Pulse Height"+sEndBit; 
02562     (*gAdcVsPhIter)->SetTitle(fS.c_str());
02563     (*gAdcVsPhIter)->SetFillColor(0);
02564     (*gAdcVsPhIter)->SetMinimum(-2);
02565     if (detectorType==Detector::kFar){
02566       (*gAdcVsPhIter)->SetMaximum(15000);
02567     }
02568     else if (detectorType==Detector::kNear){
02569       Double_t maxAdc=gcData->GetMaxAdc();
02570       if (maxAdc>30000){
02571         (*gAdcVsPhIter)->SetMaximum(maxAdc+0.1*maxAdc);
02572       }
02573       else{
02574         (*gAdcVsPhIter)->SetMaximum(30000);
02575       }
02576     }
02577     else if (detectorType==Detector::kCalDet){
02578       //don't set max!
02579     }
02580     else if (detectorType==Detector::kUnknown){
02581       //don't set max!
02582     }
02583     else {
02584       MSG("LITuning",Msg::kDebug)
02585         <<"("<<pulserBox<<":"<<led<<") Detector Type not supported."
02586         <<"Detector Type=";
02587       Detector::AsString(detectorType);
02588       cout<<endl;
02589     }
02590 
02592     //do far end of strip pmt adc graph
02594     fS="Response of 'Far End of Strip PMTs' to LI Pulse Height"+
02595       sEndBit; 
02596     (*gAdcFVsPhIter)->SetTitle(fS.c_str());
02597     (*gAdcFVsPhIter)->SetFillColor(0);
02598     (*gAdcFVsPhIter)->SetMinimum(-2);
02599     if (detectorType==Detector::kFar){
02600       (*gAdcFVsPhIter)->SetMaximum(15000);
02601     }
02602     else if (detectorType==Detector::kNear){
02603       Double_t maxAdcF=gcData->GetMaxAdcF();
02604       if (maxAdcF>30000){
02605         (*gAdcFVsPhIter)->SetMaximum(maxAdcF+0.1*maxAdcF);
02606       }
02607       else{
02608         (*gAdcFVsPhIter)->SetMaximum(30000);
02609       }
02610     }
02611     else if (detectorType==Detector::kCalDet){
02612       //don't set max!
02613     }
02614     else if (detectorType==Detector::kUnknown){
02615       //don't set max!
02616     }
02617     else {
02618       MSG("LITuning",Msg::kDebug)
02619         <<"("<<pulserBox<<":"<<led<<") Detector Type not supported."
02620         <<"Detector Type=";
02621       Detector::AsString(detectorType);
02622       cout<<endl;
02623     }
02624 
02626     //do pin graph
02628     fS="Response of PIN to LI Pulse Height"+sEndBit; 
02629     (*gPinVsPhIter)->SetTitle(fS.c_str());
02630     (*gPinVsPhIter)->SetFillColor(0);
02631     (*gPinVsPhIter)->SetMinimum(-2);
02632     if (detectorType==Detector::kFar){
02633       (*gPinVsPhIter)->SetMaximum(12500);
02634     }
02635     else if (detectorType==Detector::kNear){
02636       Double_t maxPin=gcData->GetMaxPin();
02637       if (maxPin>30000){
02638         (*gPinVsPhIter)->SetMaximum(maxPin+0.1*maxPin);
02639       }
02640       else{
02641         (*gPinVsPhIter)->SetMaximum(30000);
02642       }
02643     }
02644     else if (detectorType==Detector::kCalDet){
02645       //don't set max!
02646     }
02647     else if (detectorType==Detector::kUnknown){
02648       //don't set max!
02649     }
02650     else {
02651       MSG("LITuning",Msg::kDebug)
02652         <<"("<<pulserBox<<":"<<led<<") Detector Type not supported."
02653         <<"Detector Type=";
02654       Detector::AsString(detectorType);
02655       cout<<endl;
02656     }
02657 
02659     //do pin2 graph
02661     fS="Response of Low Gain PIN to LI Pulse Height"+sEndBit; 
02662     (*gPin2VsPhIter)->SetTitle(fS.c_str());
02663     (*gPin2VsPhIter)->SetFillColor(0);
02664     (*gPin2VsPhIter)->SetMinimum(-2);
02665     if (detectorType==Detector::kFar){
02666       (*gPin2VsPhIter)->SetMaximum(12500);
02667     }
02668     else if (detectorType==Detector::kNear){
02669       Double_t maxPin=gcData->GetMaxPin();
02670       if (maxPin>30000){
02671         (*gPin2VsPhIter)->SetMaximum(maxPin+0.1*maxPin);
02672       }
02673       else{
02674         (*gPin2VsPhIter)->SetMaximum(30000);
02675       }
02676     }
02677     else if (detectorType==Detector::kCalDet){
02678       //don't set max!
02679     }
02680     else if (detectorType==Detector::kUnknown){
02681       //don't set max!
02682     }
02683     else {
02684       MSG("LITuning",Msg::kDebug)
02685         <<"("<<pulserBox<<":"<<led<<") Detector Type not supported."
02686         <<"Detector Type=";
02687       Detector::AsString(detectorType);
02688       cout<<endl;
02689     }
02690 
02692     //do adcErr graph
02694     fS="Response of PMTs to LI Pulse Height (Error is 90% range)"+
02695       sEndBit; 
02696     (*gAdcErrVsPhIter)->SetTitle(fS.c_str());
02697     (*gAdcErrVsPhIter)->SetFillColor(0);
02698     if (detectorType==Detector::kFar){
02699       (*gAdcErrVsPhIter)->SetMaximum(15000);
02700     }
02701     else if (detectorType==Detector::kNear){
02702       Double_t maxAdc=gcData->GetMaxAdc();
02703       if (maxAdc>30000){
02704         (*gAdcErrVsPhIter)->SetMaximum(maxAdc+0.1*maxAdc);
02705       }
02706       else{
02707         (*gAdcErrVsPhIter)->SetMaximum(30000);
02708       }
02709     }
02710     else if (detectorType==Detector::kCalDet){
02711       //don't set max!
02712     }
02713     else if (detectorType==Detector::kUnknown){
02714       //don't set max!
02715     }
02716     else {
02717       MSG("LITuning",Msg::kDebug)
02718         <<"("<<pulserBox<<":"<<led<<") Detector Type not supported."
02719         <<"Detector Type=";
02720       Detector::AsString(detectorType);
02721       cout<<endl;
02722     }
02723 
02725     //do adcErr graph for far end of strip
02727     fS="Response of PMTs to LI Pulse Height (Error is 90% range)"+
02728       sEndBit; 
02729     (*gAdcFErrVsPhIter)->SetTitle(fS.c_str());
02730     (*gAdcFErrVsPhIter)->SetFillColor(0);
02731     if (detectorType==Detector::kFar){
02732       (*gAdcFErrVsPhIter)->SetMaximum(15000);
02733     }
02734     else if (detectorType==Detector::kNear){
02735       Double_t maxAdcF=gcData->GetMaxAdcF();
02736       if (maxAdcF>30000){
02737         (*gAdcFErrVsPhIter)->SetMaximum(maxAdcF+0.1*maxAdcF);
02738       }
02739       else{
02740         (*gAdcFErrVsPhIter)->SetMaximum(30000);
02741       }
02742     }
02743     else if (detectorType==Detector::kCalDet){
02744       //don't set max!
02745     }
02746     else if (detectorType==Detector::kUnknown){
02747       //don't set max!
02748     }
02749     else {
02750       MSG("LITuning",Msg::kDebug)
02751         <<"("<<pulserBox<<":"<<led<<") Detector Type not supported."
02752         <<"Detector Type=";
02753       Detector::AsString(detectorType);
02754       cout<<endl;
02755     }
02756 
02757     //print only on debug
02758     if (MsgService::Instance()->IsActive("LITuning",Msg::kDebug)){
02759       gcData->PrintAll();
02760     }
02761 
02762     //iterate the li run that you are looking at
02763     gcData++;
02764   }
02765 
02766   MSG("LITuning",Msg::kDebug) 
02767     <<"Finished GetDataGcGraphs method"<<endl;
02768   return true;
02769 }
02770 
02771 //......................................................................
02772 
02773 Bool_t LITuning::GetTunedGcPlots(vector<TH2F*>& hGcAdc,
02774                                  vector<TH2F*>& hGcPin,
02775                                  vector<TH2F*>& hGcPh,
02776                                  Int_t firstLed,Int_t lastLed)
02777 {
02778   MSG("LITuning",Msg::kInfo) 
02779     <<"Running GetTunedGcPlots method..."<<endl;
02780 
02781   //check if a gain curve has been calculated
02782   if (fBestGc.empty()){
02783     MSG("LITuning",Msg::kWarning)
02784       <<"There is nothing to print, no tuned values have been"
02785       <<" computed for a gain curve"<<endl;
02786     return false;
02787   }
02788 
02789   //get iterators for the histos
02790   vector<TH2F*>::iterator hGcAdcIter;
02791   vector<TH2F*>::iterator hGcPinIter;
02792   vector<TH2F*>::iterator hGcPhIter;
02793 
02794   vector<LIRun>::iterator tunedRun;
02795   vector<LIRun>::iterator tunedRunEnd;
02796  
02797   //select the tuned gain curve
02798   tunedRun=fBestGc.begin();
02799   tunedRunEnd=fBestGc.end();
02800   
02801   //variable to hold the last pulser box
02802   Int_t lastPulserBox=-1;
02803 
02805   //loop over tuned GCs and create the histos
02807   while (tunedRun!=tunedRunEnd){
02808 
02809     //get iterators to the vectors of li run points
02810     vector<Double_t> phVector;
02811     vector<Double_t>::iterator ph;
02812     phVector=tunedRun->GetPh();
02813     ph=phVector.begin();
02814     vector<Double_t> pinVector;
02815     vector<Double_t>::iterator pin;
02816     pinVector=tunedRun->GetPin(1);
02817     pin=pinVector.begin();
02818     vector<Double_t> adcVector;
02819     vector<Double_t>::iterator adc;
02820     adcVector=tunedRun->GetAdc();
02821     adc=adcVector.begin();
02822 
02823     //get the pulserbox and led 
02824     Int_t pulserBox=tunedRun->GetPb();
02825     Int_t led=tunedRun->GetLed();
02826 
02827     //check that there is a point present
02828     if (phVector.empty()){
02829       MSG("LITuning",Msg::kInfo)
02830         <<"("<<pulserBox<<":"<<led<<") Tuned vectors are empty"<<endl;
02831       tunedRun++;
02832       continue;
02833     }
02834 
02835     Int_t xMax=lastLed+1;
02836     Int_t xMin=firstLed-1;
02837     Int_t numXbins=xMax-xMin;
02838 
02839     if (pulserBox!=lastPulserBox){
02840       MSG("LITuning",Msg::kDebug)<<"Next PB..."<<endl;
02841       string sPb=Form("%d",pulserBox);
02842       fS="Gain Curve Points in PMT ADCs, Pulser Box "+sPb; 
02843       hGcAdc.push_back(new TH2F(fS.c_str(),fS.c_str(),
02844                                 numXbins,xMin,xMax,200,0,15000));
02845       fS="Gain Curve Points in PIN ADCs, Pulser Box "+sPb; 
02846       hGcPin.push_back(new TH2F(fS.c_str(),fS.c_str(),
02847                                 numXbins,xMin,xMax,200,0,9000));
02848       fS="Gain Curve PHs, Pulser Box "+sPb; 
02849       hGcPh.push_back(new TH2F(fS.c_str(),fS.c_str(),
02850                                numXbins,xMin,xMax,200,0,1050));
02851 
02852       hGcAdcIter=hGcAdc.end()-1;
02853       hGcPinIter=hGcPin.end()-1;
02854       hGcPhIter=hGcPh.end()-1;
02855 
02856       (*hGcAdcIter)->GetXaxis()->SetTitle("LED");
02857       (*hGcAdcIter)->GetXaxis()->CenterTitle();
02858       (*hGcAdcIter)->GetYaxis()->SetTitle("PMT ADCs");
02859       (*hGcAdcIter)->GetYaxis()->CenterTitle();
02860       (*hGcAdcIter)->SetFillColor(0);
02861       (*hGcAdcIter)->SetBit(TH1::kCanRebin);
02862       
02863       (*hGcPinIter)->GetXaxis()->SetTitle("LED");
02864       (*hGcPinIter)->GetXaxis()->CenterTitle();
02865       (*hGcPinIter)->GetYaxis()->SetTitle("PIN ADCs");
02866       (*hGcPinIter)->GetYaxis()->CenterTitle();
02867       (*hGcPinIter)->SetFillColor(0);
02868       (*hGcPinIter)->SetBit(TH1::kCanRebin);
02869       
02870       (*hGcPhIter)->GetXaxis()->SetTitle("LED");
02871       (*hGcPhIter)->GetXaxis()->CenterTitle();
02872       (*hGcPhIter)->GetYaxis()->SetTitle("Pulse Height");
02873       (*hGcPhIter)->GetYaxis()->CenterTitle();
02874       (*hGcPhIter)->SetFillColor(0);
02875       (*hGcPhIter)->SetBit(TH1::kCanRebin);
02876     }
02877     //keep a record of last pulser box
02878     lastPulserBox=pulserBox;
02879 
02880     //print only on debug
02881     if (MsgService::Instance()->IsActive("LITuning",Msg::kDebug)){
02882       tunedRun->PrintAll();
02883     }
02884 
02885     //loop over all the points in the vector (1 or more)
02886     while(ph!=phVector.end()){
02887 
02888       MSG("LITuning",Msg::kVerbose)
02889         <<"Looping over tuned points"<<endl;
02890 
02891       (*hGcPinIter)->Fill(led,*pin);
02892       (*hGcAdcIter)->Fill(led,*adc);
02893       (*hGcPhIter)->Fill(led,*ph);
02894       
02895       adc++;
02896       pin++;
02897       ph++;
02898     }
02899 
02900     //iterate the li run that you are looking at
02901     tunedRun++;
02902   }
02903 
02904   MSG("LITuning",Msg::kDebug) 
02905     <<"GetTunedGcPlots method finished"<<endl;
02906   return true;
02907 }
02908 
02909 //......................................................................
02910 
02911 void LITuning::PrintAll()
02912 {
02913   MSG("LITuning",Msg::kInfo) 
02914     <<"Running PrintAll method..."<<endl;
02915 
02916   //create iterators
02917   vector<LIRun>::iterator run;
02918   vector<LIRun>::iterator runEnd;
02919 
02920   MSG("LITuning",Msg::kDebug) 
02921     <<"Getting iterators to input gain curve"<<endl;
02922   //get the begining and end of the vector of gain curves
02923   run=fGainCurve->begin();
02924   runEnd=fGainCurve->end();
02925   MSG("LITuning",Msg::kDebug)
02926     <<"Got iterators to input gain curve"<<endl;
02927   
02928   //loop and print out the data stored in the LIRun objects
02929   while (run!=runEnd){
02930     //print out the info stored in the object
02931     run->PrintAll();
02932     //iterate the li run that you are printing out
02933     run++;
02934   }
02935   
02936   MSG("LITuning",Msg::kInfo) 
02937     <<"PrintAll method finished"<<endl;
02938 }
02939 
02940 //......................................................................

Generated on Mon Feb 15 11:06:53 2010 for loon by  doxygen 1.3.9.1