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

NuExtraction.cxx

Go to the documentation of this file.
00001 
00002 
00003 // Coded by Jeff Hartnell Jul/2005       
00004 //                                                                    
00005 // Contact: j.j.hartnell@rl.ac.uk
00007 
00008 #include <set>
00009 #include <cmath>
00010 
00011 #include "TClonesArray.h"
00012 #include "TH2F.h"
00013 #include "TMath.h"
00014 #include "TVector3.h"
00015 
00016 #include "BeamDataUtil/BDSpillAccessor.h"
00017 #include "BeamDataUtil/BMSpillAna.h"
00018 #include "DcsUser/CoilTools.h"
00019 #include "DataUtil/DataQualDB.h"
00020 #include "DataUtil/EnergyCorrections.h"
00021 #include "MessageService/MsgFormat.h"
00022 #include "CandFitTrackSA/Ntp/NtpFitSARecord.h"
00023 #include "CandFitTrackSA/Ntp/NtpFitSAPlane.h"
00024 #include "CandFitTrackSA/Ntp/NtpFitSA.h"
00025 #include "CandNtupleSR/NtpSREvent.h"
00026 #include "CandNtupleSR/NtpSRShower.h"
00027 #include "CandNtupleSR/NtpSRStrip.h"
00028 #include "CandNtupleSR/NtpSRTimeStatus.h"
00029 #include "CandNtupleSR/NtpSRTrack.h"
00030 #include "StandardNtuple/NtpStRecord.h"
00031 
00032 #include "SpillTiming/SpillTimeFinder.h"
00033 #include "SpillTiming/SpillServerMonFinder.h"
00034 #include "RunQuality/DbuFarRunQuality.h"
00035 #include "RunQuality/DbuNearRunQuality.h"
00036 
00037 #include "NtupleUtils/LISieve.h"
00038 #include "NtupleUtils/NuLibrary.h"
00039 #include "NtupleUtils/NuEvent.h"
00040 #include "NtupleUtils/NuExtraction.h"
00041 #include "NtupleUtils/NuMCEvent.h"
00042 
00043 // for the NC analysis
00044 #include "AnalysisNtuples/Module/CondensedNtpModule.h"
00045 #include "AnalysisNtuples/Module/ANtpRecoNtpManipulator.h"
00046 #include "AnalysisNtuples/Module/ANtpInfoObjectFillerNC.h"
00047 #include "AnalysisNtuples/ANtpEventInfoNC.h"
00048 #include "AnalysisNtuples/ANtpTrackInfoNC.h"
00049 #include "AnalysisNtuples/ANtpShowerInfoNC.h"
00050 #include "AnalysisNtuples/ANtpTruthInfoBeam.h"
00051 #include "AnalysisNtuples/ANtpBeamInfo.h"
00052 #include "AstroUtil/AstTime.h"
00053 
00054 using std::endl;
00055 using std::cout;
00056 using std::map;
00057 using std::vector;
00058 
00059 namespace EnergyCorrections {}
00060 using namespace EnergyCorrections;
00061 
00062 CVSID("$Id: NuExtraction.cxx,v 1.67 2010/01/25 13:17:43 evansj Exp $");
00063 
00064 //......................................................................
00065 
00066 NuExtraction::NuExtraction()
00067 {
00068   MSG("NuExtraction",Msg::kDebug)
00069     <<"Running NuExtraction Constructor..."<<endl;
00070 
00071 
00072   MSG("NuExtraction",Msg::kDebug)
00073     <<"Finished NuExtraction Constructor"<<endl;
00074 }
00075 
00076 //......................................................................
00077 
00078 NuExtraction::~NuExtraction()
00079 {
00080   MSG("NuExtraction",Msg::kDebug)
00081     <<"Running NuExtraction Destructor..."<<endl;
00082   
00083 
00084   MSG("NuExtraction",Msg::kDebug)
00085     <<"Finished NuExtraction Destructor"<<endl;
00086 }
00087 
00088 //......................................................................
00089 
00090 void NuExtraction::ExtractBasicInfo(const NtpStRecord& ntp,
00091                                     const NtpSREvent& evt,
00092                                     NuEvent& nu) const
00093 {
00095 
00096   //get the run, snarl, etc info
00097   this->ExtractGeneralInfo(ntp,nu);
00098   //get info from the evt
00099   this->ExtractEvtInfo(evt,nu);
00100   //extract trk info (needed to get best track info)
00101   this->ExtractTrkInfo(ntp,evt,nu);
00102   //extract shw info
00103   this->ExtractShwInfo(ntp,evt,nu);     
00104 }
00105 
00106 //......................................................................
00107 
00108 void NuExtraction::ExtractAuxiliaryInfo(const NtpStRecord& ntp,
00109                                         const NtpSREvent& evt,
00110                                         const NtpFitSARecord* pntpSA,
00111                                         NuEvent& nu) const
00112 {
00113   //extract a bunch of supplementary information needed for analysis
00114   
00115   //get the SA fitter information if it is available
00116   this->ExtractSAFitInfo(pntpSA,nu);
00117   //get the timing info
00118   this->ExtractMinMaxEvtTimes(ntp,evt,nu);
00119   this->ExtractTimeToNearestSpill(nu);
00120   //get the data quality
00121   this->ExtractDataQuality(nu);
00122   this->ExtractLITags(ntp,nu);
00123   this->ExtractBeamInfoDB(nu);//done per snarl but do here as safer
00124   this->ExtractAdditionalDSTVariables(nu);
00125 }
00126 
00127 //......................................................................
00128 
00129 void NuExtraction::ExtractGeneralInfo(const NtpStRecord& ntp,
00130                                       NuEvent& nu) const
00131 {
00132   const RecCandHeader& rec=ntp.GetHeader();
00133 
00134   nu.run=rec.GetRun();
00135   nu.subRun=rec.GetSubRun();
00136   nu.runType=rec.GetRunType();
00137   nu.errorCode=rec.GetErrorCode();
00138   nu.snarl=rec.GetSnarl();
00139   nu.trigSrc=rec.GetTrigSrc();
00140   nu.timeFrame=rec.GetTimeFrame();
00141   nu.remoteSpillType=rec.GetRemoteSpillType();
00142 
00143   nu.detector=rec.GetVldContext().GetDetector();
00144   nu.simFlag=rec.GetVldContext().GetSimFlag();
00145   nu.timeSec=rec.GetVldContext().GetTimeStamp().GetSec();
00146   nu.timeNanoSec=rec.GetVldContext().GetTimeStamp().GetNanoSec();
00147   nu.timeSeconds=rec.GetVldContext().GetTimeStamp().GetSeconds();
00148   
00149   const NtpSREventSummary& evthdr=ntp.evthdr;
00150   nu.trigtime=evthdr.trigtime;
00151   nu.planeEvtHdrBeg=evthdr.plane.beg;
00152   nu.planeEvtHdrEnd=evthdr.plane.end;
00153   nu.snarlPulseHeight=evthdr.ph.sigcor;
00154 
00155   //a hack to correct the trigger bit of the cosmic MC in the ND
00156   if (nu.simFlag==SimFlag::kMC && nu.detector==Detector::kNear) {
00157     //the cosmic MC doesn't have any entries
00158     TClonesArray& mcTca=*ntp.mc;
00159     if (mcTca.GetEntries()==0){ 
00160       MAXMSG("MeuAnalysis",Msg::kWarning,5)
00161         <<"Performing hack to correct the fTrigSrc of"
00162         <<" ND cosmic MC, was="
00163         <<nu.trigSrc<<", setting to 4"<<endl;
00164       nu.trigSrc=4;//a plane trigger
00165     }
00166   }
00167 }
00168 
00169 //......................................................................
00170 
00171 void NuExtraction::ExtractSAFitInfo(const NtpFitSARecord* pntpSA,
00172                                     NuEvent& nu) const
00173 {
00174   if (!pntpSA) {
00175     MAXMSG("MeuAnalysis",Msg::kDebug,5)
00176       <<"ExtractSAFitInfo: no NtpFitSARecord"<<endl;
00177     return;
00178   }
00179 
00180   //get a reference
00181   const NtpFitSARecord& ntpSA=*pntpSA;
00182   const TClonesArray& fitsaTca=(*ntpSA.fitsa);
00183 
00184   //get an instance of the code library
00185   const NuLibrary& lib=NuLibrary::Instance();
00186   
00187   if (nu.trkIndex1>=0) {
00188     const NtpFitSA& fitsa=
00189       *(dynamic_cast<NtpFitSA*>(fitsaTca[nu.trkIndex1]));
00190     
00191     nu.trkfitpassSA1=fitsa.fit.pass;
00192     nu.trkvtxdcoszSA1=fitsa.fit.dcosz; 
00193     nu.chargeSA1=lib.reco.GetTrackCharge(fitsa.fit.qp, nu.hornIsReverse);
00194     nu.qpSA1=fitsa.fit.qp;
00195     nu.sigqpSA1=fitsa.fit.eqp;
00196     nu.chi2SA1=fitsa.fit.chi2;
00197     nu.ndofSA1=fitsa.fit.ndf;
00198     nu.probSA1=TMath::Prob(fitsa.fit.chi2,fitsa.fit.ndf);
00199     TVector3 xyz=lib.reco.uvz2xyz(fitsa.fit.u,fitsa.fit.v,fitsa.fit.z,
00200                                   lib.reco.GetVldContext(nu));
00201     nu.xTrkVtxSA1=xyz.X();
00202     nu.yTrkVtxSA1=xyz.Y();
00203     nu.zTrkVtxSA1=fitsa.fit.z;
00204     nu.uTrkVtxSA1=fitsa.fit.u;
00205     nu.vTrkVtxSA1=fitsa.fit.v;
00206   }
00207 
00208   if (nu.trkIndex2>=0) {
00209     const NtpFitSA& fitsa=
00210       *(dynamic_cast<NtpFitSA*>(fitsaTca[nu.trkIndex2]));
00211     
00212     nu.trkfitpassSA2=fitsa.fit.pass;
00213     nu.trkvtxdcoszSA2=fitsa.fit.dcosz; 
00214     nu.chargeSA2=lib.reco.GetTrackCharge(fitsa.fit.qp, nu.hornIsReverse);
00215     nu.qpSA2=fitsa.fit.qp;
00216     nu.sigqpSA2=fitsa.fit.eqp;
00217     nu.chi2SA2=fitsa.fit.chi2;
00218     nu.ndofSA2=fitsa.fit.ndf;
00219     nu.probSA2=TMath::Prob(fitsa.fit.chi2,fitsa.fit.ndf);
00220     TVector3 xyz=lib.reco.uvz2xyz(fitsa.fit.u,fitsa.fit.v,fitsa.fit.z,
00221                                   lib.reco.GetVldContext(nu));
00222     nu.xTrkVtxSA2=xyz.X();
00223     nu.yTrkVtxSA2=xyz.Y();
00224     nu.zTrkVtxSA2=fitsa.fit.z;
00225     nu.uTrkVtxSA2=fitsa.fit.u;
00226     nu.vTrkVtxSA2=fitsa.fit.v;
00227   }
00228 
00229   if (nu.trkIndex3>=0) {
00230     const NtpFitSA& fitsa=
00231       *(dynamic_cast<NtpFitSA*>(fitsaTca[nu.trkIndex3]));
00232     
00233     nu.trkfitpassSA3=fitsa.fit.pass;
00234     nu.trkvtxdcoszSA3=fitsa.fit.dcosz; 
00235     nu.chargeSA3=lib.reco.GetTrackCharge(fitsa.fit.qp, nu.hornIsReverse);
00236     nu.qpSA3=fitsa.fit.qp;
00237     nu.sigqpSA3=fitsa.fit.eqp;
00238     nu.chi2SA3=fitsa.fit.chi2;
00239     nu.ndofSA3=fitsa.fit.ndf;
00240     nu.probSA3=TMath::Prob(fitsa.fit.chi2,fitsa.fit.ndf);
00241     TVector3 xyz=lib.reco.uvz2xyz(fitsa.fit.u,fitsa.fit.v,fitsa.fit.z,
00242                                   lib.reco.GetVldContext(nu));
00243     nu.xTrkVtxSA3=xyz.X();
00244     nu.yTrkVtxSA3=xyz.Y();
00245     nu.zTrkVtxSA3=fitsa.fit.z;
00246     nu.uTrkVtxSA3=fitsa.fit.u;
00247     nu.vTrkVtxSA3=fitsa.fit.v;
00248   }
00249 
00250   //copy across the variables for the best track
00251   lib.reco.SetBestTrkSAFit(nu);
00252 }
00253 /*
00254   MAXMSG("MeuAnalysis",Msg::kInfo,500)
00255     <<"nu.ntrk="<<nu.ntrk
00256     <<" ntrk="<<ntpSA.ntrack
00257     <<", nu.planeTrkBeg="<<nu.planeTrkBeg
00258     <<", nu.planeTrkEnd="<<nu.planeTrkEnd
00259     <<endl;
00260 
00261   MAXMSG("MeuAnalysis",Msg::kInfo,500)
00262     <<"nu.trkIndex="<<nu.trkIndex<<endl;
00263 
00264   for (Int_t i=0;i<ntpSA.ntrack;i++) {      
00265     const NtpFitSA& fitsa=
00266       *(dynamic_cast<NtpFitSA*>(fitsaTca[i]));
00267     
00268     MAXMSG("MeuAnalysis",Msg::kInfo,500)
00269       <<"i="<<i
00270       <<", pln.begin="<<fitsa.plane.begin
00271       <<", pln.end="<<fitsa.plane.end
00272       <<"SA: pass="<<fitsa.fit.pass
00273       <<", qp="<<fitsa.fit.qp
00274       <<endl;
00275   }
00276   
00277   if (nu.trkIndex<0) {
00278     MAXMSG("MeuAnalysis",Msg::kWarning,50)
00279       <<"ExtractSAFitInfo: nu.trkIndex="<<nu.trkIndex<<endl;
00280   }
00281 
00282 
00283     MAXMSG("MeuAnalysis",Msg::kInfo,500)
00284       <<"SR: pass="<<nu.trkfitpass
00285       <<", qp="<<nu.qp
00286       <<", eqp="<<nu.sigqp
00287       <<", chi2="<<nu.chi2
00288       <<", ndof="<<nu.ndof
00289       <<", prob="<<nu.prob
00290       <<endl
00291       <<"SA: pass="<<fitsa.fit.pass
00292       <<", qp="<<fitsa.fit.qp
00293       <<", eqp="<<fitsa.fit.eqp
00294       <<", chi2="<<fitsa.fit.chi2
00295       <<", ndof="<<fitsa.fit.ndf
00296       <<", prob="<<TMath::Prob(fitsa.fit.chi2,fitsa.fit.ndf)
00297       <<endl;
00298       //chargeSA
00299   */
00300 
00301 //......................................................................
00302 
00303 void NuExtraction::ExtractCoilInfo(NuEvent& nu) const
00304 {
00305   //return if not data
00306   if (nu.simFlag!=SimFlag::kData) {
00307     MAXMSG("NuExtraction",Msg::kInfo,1)
00308       <<"Not extracting Coil info for simFlag="<<nu.simFlag<<endl;
00309     //set these to be the most likely values
00310     nu.coilIsOk=true;
00311     int fieldNo = NuUtilities::GetDigit(nu.run, 5);
00312     if (fieldNo == 1 || fieldNo == 3) {
00313       MAXMSG("NuExtraction",Msg::kInfo,1)
00314       << "Found field id #" << fieldNo << ", setting coil current to forward."
00315       <<endl;            
00316       nu.coilIsReverse=false;
00317     }
00318     else if (fieldNo == 2 || fieldNo == 4) {
00319       MAXMSG("NuExtraction",Msg::kInfo,1)
00320       << "Found field id #" << fieldNo << ", setting coil current to reverse."
00321       <<endl;                  
00322       nu.coilIsReverse=true;
00323     }
00324     else {
00325       MAXMSG("NuExtraction",Msg::kWarning,1)
00326       << "Don't recognize field id #" << fieldNo << ", only 1, 2, 3, 4 are allowed values.  Assuming field is forward."
00327       <<endl;      
00328       nu.coilIsReverse=false;
00329     }
00330     return;
00331   }
00332   
00333   //check whether to use the database
00334   if (!nu.useDBForDataQuality) {//use data quality flag
00335     MAXMSG("NuExtraction",Msg::kWarning,1)
00336       <<"Not extracting CoilCurrent (flag set to not query database)"
00337       <<endl;
00338     //leave values as current (for re-reconstruction case)
00339     return;
00340   }
00341 
00342   //get an instance of the code library
00343   const NuLibrary& lib=NuLibrary::Instance();
00344   VldContext vc=lib.reco.GetVldContext(nu);
00345   
00346   //extract the information about the coil using CoilTools
00347   //this is much faster than using the database
00348   nu.coilIsOk=CoilTools::IsOK(vc);
00349   nu.coilIsReverse=CoilTools::IsReverse(vc);
00350   
00351   //get the coil current here too
00352   this->ExtractCoilCurrent(nu);
00353 }
00354 
00355 //......................................................................
00356 
00357 void NuExtraction::ExtractCoilCurrent(NuEvent& nu) const
00358 {
00359   //return if not data
00360   if (nu.simFlag!=SimFlag::kData) {
00361     MAXMSG("NuExtraction",Msg::kInfo,1)
00362       <<"Not extracting CoilCurrent for simFlag="<<nu.simFlag<<endl;
00363     return;
00364   }
00365   
00366   //check whether to use the database
00367   if (!nu.useDBForDataQuality) {//use data quality flag
00368     MAXMSG("NuExtraction",Msg::kWarning,1)
00369       <<"Not extracting CoilCurrent (flag set to not query database)"
00370       <<endl;
00371     //leave values as they are (for re-reconstruction case)
00372     return;
00373   }
00374 
00375   //get an instance of the code library
00376   const NuLibrary& lib=NuLibrary::Instance();
00377 
00378   //get vc
00379   VldContext vc=lib.reco.GetVldContext(nu);
00380 
00381   //get the current, depending on detector
00382   if (nu.detector==Detector::kNear) {
00383     const Dcs_Mag_Near* magnear=CoilTools::Instance().GetMagNear(vc);
00384     if (magnear) nu.coilCurrent=magnear->GetCurrent();
00385     else {
00386       MAXMSG("NuExtraction",Msg::kWarning,10)
00387         <<"No rows in Dcs_Mag_Near DB table for VldContext="<<vc
00388         <<" setting coilCurrent=0"<<endl;
00389       nu.coilCurrent=0;//set to default value
00390     }
00391   } 
00392   else if (nu.detector==Detector::kFar) {
00393     const BfldDbiCoilState* coilstate1=
00394       CoilTools::Instance().GetCoilState(vc,1);
00395     const BfldDbiCoilState* coilstate2=
00396       CoilTools::Instance().GetCoilState(vc,2);
00397     //ahh, two values, one slot ... take average
00398     if (coilstate1 && coilstate2) {
00399       nu.coilCurrent=0.5*(coilstate1->GetCurrent()+
00400                           coilstate2->GetCurrent());
00401     } 
00402     else {
00403       MAXMSG("NuExtraction",Msg::kInfo,10)
00404         <<"Insufficient rows in BfldDbiCoilState DB table, VldContext="
00405         <<vc<<" setting coilCurrent=0"<<endl;
00406       nu.coilCurrent=0;//set to default value
00407     }
00408   }
00409   else cout<<"Ahhh, det="<<nu.detector<<endl;
00410   
00411   //The old slow way:
00412   //DbiResultPtr<Dcs_Mag_Near> ptr(vc);
00413   //if(ptr.GetNumRows()){
00414   //const Dcs_Mag_Near* row=ptr.GetRow(0);
00415   //nu.coilCurrent=row->GetCurrent();
00416   //}
00417   //else {
00418   //MAXMSG("NuExtraction",Msg::kInfo,10)
00419   //  <<"No rows in Dcs_Mag_Near DB table for VldContext="<<vc
00420   //  <<" setting coilCurrent=0"<<endl;
00421   //nu.coilCurrent=0;//set to default value
00422   //}
00423 
00424   MAXMSG("NuExtraction",Msg::kInfo,10)
00425     <<"Extracted CoilCurrent="<<nu.coilCurrent<<endl;
00426 }
00427 
00428 //......................................................................
00429 
00430 void NuExtraction::ExtractLITags(const NtpStRecord& ntp,NuEvent& nu) const
00431 {
00433   
00434   //get an event header
00435   const NtpSREventSummary& evthdr=ntp.evthdr;      
00436   
00437   //get an instance of the code library
00438   const NuLibrary& lib=NuLibrary::Instance();
00439 
00440   //extract all the possible LI variables
00441   nu.litime=evthdr.litime;
00442   nu.isLI=LISieve::IsLI(ntp);
00443   nu.litag=lib.reco.FDRCBoundary(nu);
00444 }
00445 
00446 //......................................................................
00447 
00448 void NuExtraction::ExtractBeamInfoDB(NuEvent& nu) const
00449 {
00450   //check if data
00451   if (nu.simFlag!=SimFlag::kData) {
00452     MAXMSG("NuExtraction",Msg::kInfo,1)
00453       <<"Not extracting BeamInfoDB for simFlag="<<nu.simFlag
00454       <<endl;
00455     return;
00456   }
00457 
00458   //check whether to use the database
00459   if (!nu.useDBForBeamInfo) {
00460     MAXMSG("NuExtraction",Msg::kWarning,1)
00461       <<"Not extracting BeamInfoDB (flag set to not query database)"
00462       <<endl;
00463     //leave values as current (for re-reconstruction case)
00464     return;
00465   }
00466 
00467   MAXMSG("NuExtraction",Msg::kInfo,1)
00468     <<"Extracting BeamInfoDB for simFlag="<<nu.simFlag
00469     <<", detector="<<nu.detector<<endl;
00470 
00471   //do it per snarl (especially for the ND)
00472   MAXMSG("NuExtraction",Msg::kWarning,1)
00473     <<"ExtractBeamInfoDB: this needs to be sorted out properly"<<endl;
00474 
00475   //get an instance of the code library
00476   const NuLibrary& lib=NuLibrary::Instance();
00477   
00478   //get the event time stamp
00479   VldContext vc=lib.reco.GetVldContext(nu);
00480   VldTimeStamp vts=vc.GetTimeStamp();
00481   
00482   //get a spill accessor
00483   BDSpillAccessor &sa = BDSpillAccessor::Get();
00484   const BeamMonSpill *bs = sa.LoadSpill(vts);
00485 
00486   //now determine if good beam
00487   Bool_t goodBeam=false;
00488   BMSpillAna bmana;
00489   bmana.UseDatabaseCuts();
00490   bmana.SetSpill(*bs);
00491 
00492   //set the time difference to determine if spill is in time
00493   VldTimeStamp delta_vts=vts-bs->SpillTime();
00494   bmana.SetTimeDiff(delta_vts.GetSeconds());
00495   
00496   //determine whether to select
00497   if(bmana.SelectSpill()) goodBeam=true;
00498   else goodBeam=false;
00499   
00500   //store the variable
00501   nu.goodBeam=goodBeam;
00502   
00503   // Extract run period for data from VldContext
00504   static VldTimeStamp* vtsRunIEnd = new VldTimeStamp(2006,4,1,0,0,0);
00505   static VldTimeStamp* vtsRunIIEnd = new VldTimeStamp(2007,8,1,0,0,0);
00506   static VldTimeStamp* vtsRunIIIEnd = new VldTimeStamp(2009,8,1,0,0,0);
00507   static VldTimeStamp* beginRHC = new VldTimeStamp(2009,9,29,0,0,0);
00508   static VldTimeStamp* endRHC = new VldTimeStamp(2010,3,1,0,0,0);
00509   
00510   MAXMSG("NuExtraction",Msg::kInfo, 1) << "beginRHC=" << beginRHC->AsString() << ", endRHC=" << endRHC->AsString() << endl;
00511   
00512   //store the beam variables (these are junk if the spill is not in time)
00513   nu.hornCur=bs->fHornCur;
00514   nu.beamTypeDB=bs->BeamType();
00515   nu.potDB=bs->fTortgt;
00516 
00517   if(vts.GetDate()<vtsRunIEnd->GetDate()) nu.runPeriod = 1;
00518   else if(vts.GetDate()<vtsRunIIEnd->GetDate()) nu.runPeriod = 2;
00519   else if(vts.GetDate()<vtsRunIIIEnd->GetDate()) nu.runPeriod = 3;
00520   else nu.runPeriod = 4;
00521   
00522   // Check for RHC
00523   if (vts.GetDate() >= beginRHC->GetDate() && 
00524       vts.GetDate() < endRHC->GetDate()  ) {
00525     MAXMSG("NuExtraction",Msg::kInfo, 10) << "Found RHC date: " << vts.AsString() << endl;
00526     nu.hornIsReverse =  true;
00527     nu.hornCur *= -1;
00528     if (nu.beamTypeDB == BeamType::kL010z185i) {
00529       nu.beamTypeDB = BeamType::kL010z185i_rev;
00530     }
00531     else {
00532       MAXMSG("NuExtraction",Msg::kInfo, 50) << "RHC event has non-rev beamtype: " 
00533       << BeamType::AsString(static_cast<BeamType::BeamType_t>(nu.beamTypeDB)) 
00534       << " (" << nu.beamTypeDB << ")" << endl;
00535     }
00536   }
00537   else {
00538     MAXMSG("NuExtraction",Msg::kInfo, 10) << "Found FHC date: " << vts.AsString() << endl;
00539     nu.hornIsReverse = false;
00540   }
00541   
00542   
00543   MAXMSG("NuExtraction",Msg::kInfo,10)
00544   <<"Extracting BeamInfoDB found" 
00545   <<  " goodBeam=" << nu.goodBeam
00546   << ", hornCur=" << nu.hornCur
00547   << ", beamTypeDB=" << nu.beamTypeDB
00548   << ", potDB=" << nu.potDB
00549   << ", hornIsReverse="<< (nu.hornIsReverse?"Yes":"No")
00550   << ", runPeriod=" << nu.runPeriod
00551   << endl;
00552   
00553   
00554   
00555   //other possibilities
00556   //Float_t hbw=bs->fProfWidX*1000.;//make it in mm
00557   //Float_t vbw=bs->fProfWidY*1000.;//make it in mm
00558   //Float_t hpos1=bs->fTargProfX*1000.;//make it in mm
00559   //Float_t vpos1=bs->fTargProfY*1000.;//make it in mm
00560   //BeamType::BeamType_t beamType=bs->BeamType();
00561   //Bool_t horn_on = bs->GetStatusBits().horn_on;
00562   //Bool_t target_in = bs->GetStatusBits().target_in;
00563 }
00564 
00565 //......................................................................
00566 
00567 void NuExtraction::ExtractTimeToNearestSpill(NuEvent& nu) const
00568 {
00569   //check if data
00570   if (nu.simFlag!=SimFlag::kData) {
00571     MAXMSG("NuExtraction",Msg::kInfo,1)
00572       <<"Not extracting TimeToNearestSpill for simFlag="<<nu.simFlag
00573       <<endl;
00574     //set a default value
00575     nu.timeToNearestSpill=-999999;
00576     return;
00577   }
00578 
00579   //check if the far detector
00580   if (nu.detector!=Detector::kFar) {
00581     MAXMSG("NuExtraction",Msg::kInfo,1)
00582       <<"Not extracting TimeToNearestSpill for detector="<<nu.detector
00583       <<endl;
00584     //set a default value
00585     nu.timeToNearestSpill=-999999;
00586     return;
00587   }
00588 
00589   //check whether to use the database
00590   if (!nu.useDBForSpillTiming) {
00591     MAXMSG("NuExtraction",Msg::kWarning,1)
00592       <<"Not extracting TimeToNearestSpill"
00593       <<" (flag set to not query database)"
00594       <<", nu.timeToNearestSpill="<<nu.timeToNearestSpill
00595       <<endl;
00596     //leave as current value (for re-reconstruction case)
00597     return;
00598   }
00599  
00600   MAXMSG("NuExtraction",Msg::kInfo,1)
00601     <<"Extracting TimeToNearestSpill for simFlag="<<nu.simFlag
00602     <<", detector="<<nu.detector<<endl;
00603   SpillTimeFinder& spillFinder=SpillTimeFinder::Instance();
00604   
00605   //get an instance of the code library
00606   const NuLibrary& lib=NuLibrary::Instance();
00607 
00608   VldContext vc=lib.reco.GetVldContext(nu);
00609   nu.timeToNearestSpill=spillFinder.GetTimeToNearestSpill(vc);
00610 
00611   VldTimeStamp nearestspill = spillFinder.GetTimeOfNearestSpill(vc);
00612   nu.nearestSpillSec = nearestspill.GetSec();
00613   nu.nearestSpillNanosec = nearestspill.GetNanoSec();
00614 }
00615 
00616 //......................................................................
00617 
00618 void NuExtraction::ExtractDataQuality(NuEvent& nu) const
00619 {  
00620   //return if not data
00621   if (nu.simFlag!=SimFlag::kData) {
00622     MAXMSG("NuExtraction",Msg::kInfo,1)
00623       <<"Not extracting Data Quality info for simFlag="<<nu.simFlag<<endl;
00624     //set these to be the most likely values
00625     nu.isGoodDataQuality = 1;
00626     nu.isGoodDataQualityRUN = 1;
00627     nu.isGoodDataQualityCOIL = 1;
00628     nu.isGoodDataQualityHV = 1;
00629     nu.isGoodDataQualityGPS = 1;
00630     return;
00631   }
00632 
00633   //check whether to use the database
00634   if (!nu.useDBForDataQuality) {
00635     MAXMSG("NuExtraction",Msg::kWarning,1)
00636       <<"Not extracting DataQuality"
00637       <<" (flag set to not query database)"
00638       <<", isGoodDataQuality="<<nu.isGoodDataQuality
00639       <<endl;
00640     //nu.isGoodDataQuality=leave as current value
00641     return;
00642   }
00643     
00644   // get validity context from ntuple record
00645   //const RecCandHeader* ntpHeader = &(ntp.GetHeader());
00646   //VldContext cx = ntpHeader->GetVldContext();
00647   //get an instance of the code library
00648   const NuLibrary& lib=NuLibrary::Instance();
00649   VldContext cx = lib.reco.GetVldContext(nu);
00650   
00651   // check data quality
00652   // ==================
00653   // run DataUtil methods
00654 
00655   nu.isGoodDataQuality = DataUtil::IsGoodData(cx);
00656   nu.isGoodDataQualityRUN = DataUtil::IsGoodDataRUN(cx);
00657   nu.isGoodDataQualityCOIL = DataUtil::IsGoodDataCOIL(cx);
00658   nu.isGoodDataQualityHV = DataUtil::IsGoodDataHV(cx);
00659   nu.isGoodDataQualityGPS = DataUtil::IsGoodDataGPS(cx);
00660 
00661   // extract run quality variables
00662   // =============================
00663 
00664   // far detector - search DbuFarRunQuality table
00665   if( cx.GetDetector() == Detector::kFar ) {   
00666     // perform database query
00667     DbiResultPtr<DbuFarRunQuality> farquery("DBUFARRUNQUALITY",cx,0);
00668 
00669     if( farquery.GetNumRows()>0 ){
00670       const DbuFarRunQuality* rowptr = farquery.GetRow(0);
00671       nu.numActiveCrates = rowptr->GetCrateMask();
00672       nu.numTimeFrames = rowptr->GetTimeFrames();
00673       nu.numGoodSnarls = rowptr->GetGoodSnarls();
00674       nu.snarlRateMedian = rowptr->GetMedianSnarlRate();
00675       nu.snarlRateMax = rowptr->GetMaxSnarlRate();
00676     }
00677   }
00678 
00679   // near detector
00680   if( cx.GetDetector() == Detector::kNear ) {
00681     //perform database query
00682     DbiResultPtr<DbuNearRunQuality> nearquery("DBUNEARRUNQUALITY",cx,0);
00683     
00684     if( nearquery.GetNumRows()>0 ){
00685       const DbuNearRunQuality* rowptr = nearquery.GetRow(0);
00686       nu.numActiveCrates = 8 - rowptr->GetColdCrates();
00687       nu.numTimeFrames = rowptr->GetSubrunLength();
00688       nu.numGoodSnarls = rowptr->GetTriggersSpill();
00689       nu.snarlRateMedian = rowptr->GetSnarlRateMedian();
00690       nu.snarlRateMax = rowptr->GetSnarlRateMax();
00691     }
00692   }
00693 
00694 
00695   // extract gps data
00696   // ================
00697   // use SpillServerMonFinder to access nearest spill monitoring block,
00698   // only necessary for far detector
00699   if( cx.GetDetector() == Detector::kFar ) {
00700   
00701     SpillServerMonFinder& spillFinder = SpillServerMonFinder::Instance();
00702     const SpillServerMon& nearestSpill = spillFinder.GetNearestSpill(cx);
00703     VldTimeStamp dt = nearestSpill.GetSpillTime()-cx.GetTimeStamp();
00704 
00705     nu.deltaSecToSpillGPS = dt.GetSec();
00706     nu.deltaNanoSecToSpillGPS = dt.GetNanoSec();
00707     nu.gpsError = nearestSpill.GetSpillTimeError();
00708     nu.gpsSpillType = nearestSpill.GetSpillType();
00709   }  
00710 
00711   // coil currents
00712   // =============
00713   // set this information in ExtractCoilInfo() method
00714 }
00715 
00716 //......................................................................
00717 
00718 void NuExtraction::ExtractTrkInfo(const NtpStRecord& ntp,
00719                                   const NtpSREvent& evt,
00720                                   NuEvent& nu) const
00721 {
00722   Msg::LogLevel_t logLevel=Msg::kDebug;  
00723   
00724   MAXMSG("NuExtraction",logLevel,200)
00725     <<"evt="<<evt.index<<", trks="<<evt.ntrack
00726     <<", shws="<<evt.nshower<<endl;
00727   
00728   //extract the trk info
00729   this->ExtractPrimaryTrkInfo(ntp,evt,nu);
00730   this->ExtractSecondTrkInfo(ntp,evt,nu);
00731   this->ExtractThirdTrkInfo(ntp,evt,nu);
00732 }
00733 
00734 //......................................................................
00735 
00736 void NuExtraction::ExtractTrkShwInfo(const NtpStRecord& ntp,
00737                                const NtpSREvent& evt,
00738                                NuEvent& nu) const
00739 {
00740   Msg::LogLevel_t logLevel=Msg::kDebug;  
00741   
00742   MAXMSG("NuExtraction",logLevel,200)
00743     <<"evt="<<evt.index<<", trks="<<evt.ntrack
00744     <<", shws="<<evt.nshower<<endl;
00745   
00746   //extract the trk info
00747   this->ExtractTrkInfo(ntp,evt,nu);
00748   
00749   //extract the shower info (does 1-3)
00750   this->ExtractShwInfo(ntp,evt,nu);
00751 }
00752 
00753 //......................................................................
00754 
00755 void NuExtraction::ExtractEvtInfo(const NtpSREvent& evt,
00756                             NuEvent& nu) const
00757 {
00759     
00760   nu.evt=evt.index;
00761   nu.slc=evt.slc;
00762   nu.ndigitEvt=evt.ndigit;
00763   nu.nstripEvt=evt.nstrip;
00764   nu.nshw=evt.nshower;
00765   nu.ntrk=evt.ntrack;
00766   nu.primshw=evt.primshw;
00767   nu.primtrk=evt.primtrk;
00768   nu.rawPhEvt=evt.ph.raw;
00769   nu.evtphsigcor=evt.ph.sigcor;
00770   nu.evtphsigmap=evt.ph.sigmap;
00771   nu.planeEvtN=evt.plane.n;
00772   nu.planeEvtNu=evt.plane.nu;
00773   nu.planeEvtNv=evt.plane.nv;
00774 
00775   nu.xEvtVtx=evt.vtx.x;
00776   nu.yEvtVtx=evt.vtx.y;
00777   nu.zEvtVtx=evt.vtx.z;
00778   nu.uEvtVtx=evt.vtx.u;
00779   nu.vEvtVtx=evt.vtx.v;
00780   nu.planeEvtVtx=evt.vtx.plane;
00781   nu.planeEvtBeg=evt.plane.beg;
00782   nu.planeEvtBegu=evt.plane.begu;
00783   nu.planeEvtBegv=evt.plane.begv;
00784   
00785   nu.xEvtEnd=evt.end.x;
00786   nu.yEvtEnd=evt.end.y;
00787   nu.zEvtEnd=evt.end.z;
00788   nu.uEvtEnd=evt.end.u;
00789   nu.vEvtEnd=evt.end.v;
00790   nu.planeEvtEnd=evt.plane.end;
00791   nu.planeEvtEndu=evt.plane.endu;
00792   nu.planeEvtEndv=evt.plane.endv;
00793 }
00794 
00795 //......................................................................
00796 
00797 void NuExtraction::ExtractShwInfo(const NtpStRecord& ntp,
00798                             const NtpSREvent& evt,
00799                             NuEvent& nu) const
00800 {
00801   //get an instance of the code library
00802   const NuLibrary& lib=NuLibrary::Instance();
00803 
00804   //get pointer to shower
00805   const NtpSRShower* pshw=lib.reco.GetShowerWithIndexX(ntp,evt,0);
00806   nu.shwExists1=false;
00807   //check if shower exists
00808   if (pshw) {
00809     //get a reference
00810     const NtpSRShower& shw=*pshw;
00811     //fill the variable(s)
00812     nu.shwExists1=true;
00813     nu.ndigitShw1=shw.ndigit;
00814     nu.nstripShw1=shw.nstrip;
00815     nu.nplaneShw1=shw.plane.n;
00816     nu.shwEnCor1=lib.reco.GetShowerEnergyCor(shw.shwph.linCCgev,CandShowerHandle::kCC,nu);
00817     nu.shwEnNoCor1=shw.shwph.linCCgev;//has to go first
00818     nu.shwEnLinCCCor1=lib.reco.GetShowerEnergyCor(shw.shwph.linCCgev,CandShowerHandle::kCC,nu);
00819     nu.shwEnLinCCNoCor1=shw.shwph.linCCgev;
00820     nu.shwEnLinNCCor1=lib.reco.GetShowerEnergyCor(shw.shwph.linNCgev,CandShowerHandle::kNC,nu);
00821     nu.shwEnLinNCNoCor1=shw.shwph.linNCgev;
00822     nu.shwEnWtCCCor1=lib.reco.GetShowerEnergyCor(shw.shwph.wtCCgev,CandShowerHandle::kWtCC,nu);
00823     nu.shwEnWtCCNoCor1=shw.shwph.wtCCgev;
00824     nu.shwEnWtNCCor1=lib.reco.GetShowerEnergyCor(shw.shwph.wtNCgev,CandShowerHandle::kWtNC,nu);
00825     nu.shwEnWtNCNoCor1=shw.shwph.wtNCgev;
00826 
00827     nu.shwEnMip1=shw.ph.mip;//Note: shw.ph.gev=shw.shwph.wtCCgev
00828     nu.planeShwBeg1=shw.plane.beg;
00829     nu.planeShwEnd1=shw.plane.end;
00830     nu.planeShwMax1=lib.reco.GetShwMaxPlane(ntp, shw);
00831     nu.xShwVtx1=shw.vtx.x;
00832     nu.yShwVtx1=shw.vtx.y;
00833     nu.zShwVtx1=shw.vtx.z;
00834   }
00835   
00836   pshw=lib.reco.GetShowerWithIndexX(ntp,evt,1);
00837   nu.shwExists2=false;
00838   //check if shower exists
00839   if (pshw) {
00840     //get a reference
00841     const NtpSRShower& shw=*pshw;
00842     //fill the variable(s)
00843     nu.shwExists2=true;
00844     nu.ndigitShw2=shw.ndigit;
00845     nu.nstripShw2=shw.nstrip;
00846     nu.nplaneShw2=shw.plane.n;
00847     nu.shwEnCor2=lib.reco.GetShowerEnergyCor(shw.shwph.linCCgev,CandShowerHandle::kCC,nu);
00848     nu.shwEnNoCor2=shw.shwph.linCCgev;//shw.ph.gev=shw.shwph.wtCCgev
00849     nu.shwEnLinCCCor2=lib.reco.GetShowerEnergyCor(shw.shwph.linCCgev,CandShowerHandle::kCC,nu);
00850     nu.shwEnLinCCNoCor2=shw.shwph.linCCgev;
00851     nu.shwEnLinNCCor2=lib.reco.GetShowerEnergyCor(shw.shwph.linNCgev,CandShowerHandle::kNC,nu);
00852     nu.shwEnLinNCNoCor2=shw.shwph.linNCgev;
00853     nu.shwEnWtCCCor2=lib.reco.GetShowerEnergyCor(shw.shwph.wtCCgev,CandShowerHandle::kWtCC,nu);
00854     nu.shwEnWtCCNoCor2=shw.shwph.wtCCgev;
00855     nu.shwEnWtNCCor2=lib.reco.GetShowerEnergyCor(shw.shwph.wtNCgev,CandShowerHandle::kWtNC,nu);
00856     nu.shwEnWtNCNoCor2=shw.shwph.wtNCgev;
00857     nu.shwEnMip2=shw.ph.mip;
00858     nu.planeShwBeg2=shw.plane.beg;
00859     nu.planeShwEnd2=shw.plane.end;
00860     nu.planeShwMax2=lib.reco.GetShwMaxPlane(ntp, shw);
00861     nu.xShwVtx2=shw.vtx.x;
00862     nu.yShwVtx2=shw.vtx.y;
00863     nu.zShwVtx2=shw.vtx.z;
00864   }
00865 
00866   pshw=lib.reco.GetShowerWithIndexX(ntp,evt,2);
00867   nu.shwExists3=false;
00868   //check if shower exists
00869   if (pshw) {
00870     //get a reference
00871     const NtpSRShower& shw=*pshw;
00872     //fill the variable(s)
00873     nu.shwExists3=true;
00874     nu.ndigitShw3=shw.ndigit;
00875     nu.nstripShw3=shw.nstrip;
00876     nu.nplaneShw3=shw.plane.n;
00877     nu.shwEnCor3=lib.reco.GetShowerEnergyCor(shw.shwph.linCCgev,CandShowerHandle::kCC,nu);
00878     nu.shwEnNoCor3=shw.shwph.linCCgev;//shw.ph.gev=shw.shwph.wtCCgev
00879     nu.shwEnLinCCCor3=lib.reco.GetShowerEnergyCor(shw.shwph.linCCgev,CandShowerHandle::kCC,nu);
00880     nu.shwEnLinCCNoCor3=shw.shwph.linCCgev;
00881     nu.shwEnLinNCCor3=lib.reco.GetShowerEnergyCor(shw.shwph.linNCgev,CandShowerHandle::kNC,nu);
00882     nu.shwEnLinNCNoCor3=shw.shwph.linNCgev;
00883     nu.shwEnWtCCCor3=lib.reco.GetShowerEnergyCor(shw.shwph.wtCCgev,CandShowerHandle::kWtCC,nu);
00884     nu.shwEnWtCCNoCor3=shw.shwph.wtCCgev;
00885     nu.shwEnWtNCCor3=lib.reco.GetShowerEnergyCor(shw.shwph.wtNCgev,CandShowerHandle::kWtNC,nu);
00886     nu.shwEnWtNCNoCor3=shw.shwph.wtNCgev;
00887     nu.shwEnMip3=shw.ph.mip;
00888     nu.planeShwBeg3=shw.plane.beg;
00889     nu.planeShwEnd3=shw.plane.end;
00890     nu.planeShwMax3=lib.reco.GetShwMaxPlane(ntp, shw);
00891     nu.xShwVtx3=shw.vtx.x;
00892     nu.yShwVtx3=shw.vtx.y;
00893     nu.zShwVtx3=shw.vtx.z;
00894   }
00895 
00896 
00897   pshw=lib.reco.GetShowerWithIndexX(ntp,evt,3);
00898   nu.shwExists4=false;
00899   //check if shower exists
00900   if (pshw) {
00901     //get a reference
00902     const NtpSRShower& shw=*pshw;
00903     //fill the variable(s)
00904     nu.shwExists4=true;
00905     nu.ndigitShw4=shw.ndigit;
00906     nu.nstripShw4=shw.nstrip;
00907     nu.nplaneShw4=shw.plane.n;
00908     nu.shwEnCor4=lib.reco.GetShowerEnergyCor(shw.shwph.linCCgev,CandShowerHandle::kCC,nu);
00909     nu.shwEnNoCor4=shw.shwph.linCCgev;//shw.ph.gev=shw.shwph.wtCCgev
00910     nu.shwEnLinCCCor4=lib.reco.GetShowerEnergyCor(shw.shwph.linCCgev,CandShowerHandle::kCC,nu);
00911     nu.shwEnLinCCNoCor4=shw.shwph.linCCgev;
00912     nu.shwEnLinNCCor4=lib.reco.GetShowerEnergyCor(shw.shwph.linNCgev,CandShowerHandle::kNC,nu);
00913     nu.shwEnLinNCNoCor4=shw.shwph.linNCgev;
00914     nu.shwEnWtCCCor4=lib.reco.GetShowerEnergyCor(shw.shwph.wtCCgev,CandShowerHandle::kWtCC,nu);
00915     nu.shwEnWtCCNoCor4=shw.shwph.wtCCgev;
00916     nu.shwEnWtNCCor4=lib.reco.GetShowerEnergyCor(shw.shwph.wtNCgev,CandShowerHandle::kWtNC,nu);
00917     nu.shwEnWtNCNoCor4=shw.shwph.wtNCgev;
00918     nu.shwEnMip4=shw.ph.mip;
00919     nu.planeShwBeg4=shw.plane.beg;
00920     nu.planeShwEnd4=shw.plane.end;
00921     nu.planeShwMax4=lib.reco.GetShwMaxPlane(ntp, shw);
00922     nu.xShwVtx4=shw.vtx.x;
00923     nu.yShwVtx4=shw.vtx.y;
00924     nu.zShwVtx4=shw.vtx.z;
00925   }
00926 
00927   pshw=lib.reco.GetShowerWithIndexX(ntp,evt,4);
00928   nu.shwExists5=false;
00929   //check if shower exists
00930   if (pshw) {
00931     //get a reference
00932     const NtpSRShower& shw=*pshw;
00933     //fill the variable(s)
00934     nu.shwExists5=true;
00935     nu.ndigitShw5=shw.ndigit;
00936     nu.nstripShw5=shw.nstrip;
00937     nu.nplaneShw5=shw.plane.n;
00938     nu.shwEnCor5=lib.reco.GetShowerEnergyCor(shw.shwph.linCCgev,CandShowerHandle::kCC,nu);
00939     nu.shwEnNoCor5=shw.shwph.linCCgev;//shw.ph.gev=shw.shwph.wtCCgev
00940     nu.shwEnLinCCCor5=lib.reco.GetShowerEnergyCor(shw.shwph.linCCgev,CandShowerHandle::kCC,nu);
00941     nu.shwEnLinCCNoCor5=shw.shwph.linCCgev;
00942     nu.shwEnLinNCCor5=lib.reco.GetShowerEnergyCor(shw.shwph.linNCgev,CandShowerHandle::kNC,nu);
00943     nu.shwEnLinNCNoCor5=shw.shwph.linNCgev;
00944     nu.shwEnWtCCCor5=lib.reco.GetShowerEnergyCor(shw.shwph.wtCCgev,CandShowerHandle::kWtCC,nu);
00945     nu.shwEnWtCCNoCor5=shw.shwph.wtCCgev;
00946     nu.shwEnWtNCCor5=lib.reco.GetShowerEnergyCor(shw.shwph.wtNCgev,CandShowerHandle::kWtNC,nu);
00947     nu.shwEnWtNCNoCor5=shw.shwph.wtNCgev;
00948     nu.shwEnMip5=shw.ph.mip;
00949     nu.planeShwBeg5=shw.plane.beg;
00950     nu.planeShwEnd5=shw.plane.end;
00951     nu.planeShwMax5=lib.reco.GetShwMaxPlane(ntp, shw);
00952     nu.xShwVtx5=shw.vtx.x;
00953     nu.yShwVtx5=shw.vtx.y;
00954     nu.zShwVtx5=shw.vtx.z;
00955   }
00956 
00957 /*
00958   pshw=lib.reco.GetShowerWithIndexX(ntp,evt,5);
00959   nu.shwExists6=false;
00960   //check if shower exists
00961   if (pshw) {
00962     //get a reference
00963     const NtpSRShower& shw=*pshw;
00964     //fill the variable(s)
00965     nu.shwExists6=true;
00966     nu.shwEnCor6=lib.reco.GetShowerEnergyCor(shw.shwph.linCCgev,CandShowerHandle::kCC,nu);
00967     nu.shwEnNoCor6=shw.shwph.linCCgev;//shw.ph.gev=shw.shwph.wtCCgev
00968     nu.shwEnMip6=shw.ph.mip;
00969     nu.planeShwBeg6=shw.plane.beg;
00970     nu.planeShwEnd6=shw.plane.end;
00971     nu.xShwVtx6=shw.vtx.x;
00972     nu.yShwVtx6=shw.vtx.y;
00973     nu.zShwVtx6=shw.vtx.z;
00974   }
00975 
00976   pshw=lib.reco.GetShowerWithIndexX(ntp,evt,6);
00977   nu.shwExists7=false;
00978   //check if shower exists
00979   if (pshw) {
00980     //get a reference
00981     const NtpSRShower& shw=*pshw;
00982     //fill the variable(s)
00983     nu.shwExists7=true;
00984     nu.shwEnCor7=lib.reco.GetShowerEnergyCor(shw.shwph.linCCgev,CandShowerHandle::kCC,nu);
00985     nu.shwEnNoCor7=shw.shwph.linCCgev;//shw.ph.gev=shw.shwph.wtCCgev
00986     nu.shwEnMip7=shw.ph.mip;
00987     nu.planeShwBeg7=shw.plane.beg;
00988     nu.planeShwEnd7=shw.plane.end;
00989     nu.xShwVtx7=shw.vtx.x;
00990     nu.yShwVtx7=shw.vtx.y;
00991     nu.zShwVtx7=shw.vtx.z;
00992   }
00993 */
00994 }
00995 
00996 //......................................................................
00997 
00998 void NuExtraction::ExtractPrimaryTrkInfo(const NtpStRecord& ntp,
00999                                          const NtpSREvent& evt,
01000                                          NuEvent& nu) const
01001 {
01002   //get an instance of the code library
01003   const NuLibrary& lib=NuLibrary::Instance();
01004 
01005   //get pointer to primary trk
01006   const NtpSRTrack* ptrk=lib.reco.GetTrackWithIndexX(ntp,evt,0);
01007   
01008   //set this to default to no track exists
01009   nu.trkExists1=false;
01010 
01011   //check if track exists
01012   if (ptrk) {
01013     //get a reference
01014     const NtpSRTrack& trk=*ptrk;
01015     
01016     nu.trkExists1=true;
01017     nu.trkIndex1=trk.index;
01018     nu.ndigitTrk1=trk.ndigit;
01019     nu.nstripTrk1=trk.nstrip;
01020     nu.trkEnCorRange1=lib.reco.GetTrackEnergyFromRangeCor
01021       (trk.momentum.range,nu);
01022     nu.trkEnCorCurv1=lib.reco.GetTrackEnergyFromCurvCor
01023       (trk.momentum.qp,nu);
01024     nu.trkShwEnNear1 = lib.reco.GetShowerEnergyNearTrack(ntp, trk,
01025                                                          &nu.trkShwEnNearDW1);
01026     nu.trkMomentumRange1=trk.momentum.range;
01027     nu.containedTrk1=trk.contained;
01028     nu.trkfitpass1=trk.fit.pass;
01029     nu.trkvtxdcosz1=trk.vtx.dcosz;
01030     nu.trkvtxdcosy1=trk.vtx.dcosy;
01031     nu.trknplane1=trk.plane.n;
01032     nu.charge1=lib.reco.GetTrackCharge(trk, nu.hornIsReverse);
01033     nu.qp1=trk.momentum.qp;
01034     nu.qp_rangebiased1=trk.momentum.qp_rangebiased;
01035     nu.sigqp1=trk.momentum.eqp;
01036     if (nu.sigqp1 != 0.0) nu.qp_sigqp1= nu.qp1 / nu.sigqp1;
01037     nu.chi21=trk.fit.chi2;
01038     nu.ndof1=trk.fit.ndof;
01039     nu.qpFraction1=lib.reco.GetTrkQPFraction(trk);
01040     nu.trkVtxUVDiffPl1=trk.plane.begu-trk.plane.begv;
01041     nu.trkLength1=abs(trk.plane.end-trk.plane.beg+1);
01042     nu.planeTrkNu1=trk.plane.nu;
01043     nu.planeTrkNv1=trk.plane.nv;
01044     nu.ntrklike1=trk.plane.ntrklike;
01045     nu.trkphsigcor1=trk.ph.sigcor;
01046     nu.trkphsigmap1=trk.ph.sigmap;
01047     nu.trkIdMC1 = lib.reco.GetTrueTrackId(ntp,trk);
01048     
01049     //majority curvature is extracted in its own function
01050 
01051     nu.xTrkVtx1=trk.vtx.x;
01052     nu.yTrkVtx1=trk.vtx.y;
01053     nu.zTrkVtx1=trk.vtx.z;
01054     nu.uTrkVtx1=trk.vtx.u;
01055     nu.vTrkVtx1=trk.vtx.v;
01056     nu.planeTrkVtx1=trk.vtx.plane;
01057     nu.planeTrkBeg1=trk.plane.beg;
01058     nu.planeTrkBegu1=trk.plane.begu;
01059     nu.planeTrkBegv1=trk.plane.begv;
01060     nu.stripTrkBeg1   = lib.reco.GetTrackFirstStrip(ntp, trk);
01061     nu.stripTrkBegu1  = lib.reco.GetTrackFirstUStrip(ntp, trk);
01062     nu.stripTrkBegv1  = lib.reco.GetTrackFirstVStrip(ntp, trk);
01063     nu.stripTrkEnd1   = lib.reco.GetTrackLastStrip(ntp,trk);
01064     nu.stripTrkEndu1  = lib.reco.GetTrackLastUStrip(ntp,trk);
01065     nu.stripTrkEndv1  = lib.reco.GetTrackLastVStrip(ntp,trk);
01066     nu.stripTrkBegIsu1= lib.reco.GetTrackFirstStripIsU(ntp, trk);
01067     nu.stripTrkEndIsu1= lib.reco.GetTrackLastStripIsU(ntp, trk);
01068     nu.regionTrkVtx1 = lib.reco.GetRegion(ntp,trk.vtx);
01069     nu.edgeRegionTrkVtx1 = lib.reco.GetEdgeRegion(ntp,trk.vtx);
01070     nu.edgeRegionTrkEnd1 = lib.reco.GetEdgeRegion(ntp,trk.end);
01071     nu.phiTrkVtx1 = lib.reco.GetPhi(trk.vtx);
01072     nu.phiTrkEnd1 = lib.reco.GetPhi(trk.end);
01073     
01074     lib.reco.CalculateParallelStripInset(nu, 1);
01075     lib.reco.CalculatePerpendicularStripFlag(nu, 1);
01076     lib.reco.CalculateHorizontalVerticalStripNumber(nu, 1);
01077     
01078     nu.xTrkEnd1=trk.end.x;
01079     nu.yTrkEnd1=trk.end.y;
01080     nu.zTrkEnd1=trk.end.z;
01081     nu.uTrkEnd1=trk.end.u;
01082     nu.vTrkEnd1=trk.end.v;
01083     nu.planeTrkEnd1=trk.plane.end;
01084     nu.planeTrkEndu1=trk.plane.endu;
01085     nu.planeTrkEndv1=trk.plane.endv;
01086     
01087     nu.drTrkFidall1=trk.fidall.dr;
01088     nu.dzTrkFidall1=trk.fidall.dz;
01089     nu.drTrkFidvtx1=trk.fidvtx.dr;
01090     nu.dzTrkFidvtx1=trk.fidvtx.dz;
01091     nu.drTrkFidend1=trk.fidend.dr;
01092     nu.dzTrkFidend1=trk.fidend.dz;
01093     nu.traceTrkFidall1 = trk.fidall.trace;
01094     nu.traceTrkFidvtx1 = trk.fidvtx.trace;
01095     nu.traceTrkFidend1 = trk.fidend.trace;
01096     
01097     nu.cosPrTrkVtx1 = lib.reco.GetCosBetweenPr_Theta(trk);
01098   }
01099 }
01100 
01101 //......................................................................
01102 
01103 void NuExtraction::ExtractSecondTrkInfo(const NtpStRecord& ntp,
01104                                         const NtpSREvent& evt,
01105                                         NuEvent& nu) const
01106 {
01107   //get an instance of the code library
01108   const NuLibrary& lib=NuLibrary::Instance();
01109 
01110   //get pointer to trk
01111   const NtpSRTrack* ptrk=lib.reco.GetTrackWithIndexX(ntp,evt,1);
01112   
01113   //set this to default to no track exists
01114   nu.trkExists2=false;
01115 
01116   //check if track exists
01117   if (ptrk) {
01118     //get a reference
01119     const NtpSRTrack& trk=*ptrk;
01120     
01121     nu.trkExists2=true;
01122     nu.trkIndex2=trk.index;
01123     nu.ndigitTrk2=trk.ndigit;
01124     nu.nstripTrk2=trk.nstrip;
01125     nu.trkEnCorRange2=lib.reco.GetTrackEnergyFromRangeCor
01126       (trk.momentum.range,nu);
01127     nu.trkEnCorCurv2=lib.reco.GetTrackEnergyFromCurvCor
01128       (trk.momentum.qp,nu);
01129     nu.trkShwEnNear2 = lib.reco.GetShowerEnergyNearTrack(ntp, trk,
01130                                                          &nu.trkShwEnNearDW2);
01131     nu.trkMomentumRange2=trk.momentum.range;
01132     nu.containedTrk2=trk.contained;
01133     nu.trkfitpass2=trk.fit.pass;
01134     nu.trkvtxdcosz2=trk.vtx.dcosz;
01135     nu.trkvtxdcosy2=trk.vtx.dcosy;
01136     nu.trknplane2=trk.plane.n;
01137     nu.charge2=lib.reco.GetTrackCharge(trk, nu.hornIsReverse);
01138     nu.qp2=trk.momentum.qp;
01139     nu.qp_rangebiased2=trk.momentum.qp_rangebiased;
01140     nu.sigqp2=trk.momentum.eqp;
01141     if (nu.sigqp2 != 0.0) nu.qp_sigqp2=nu.qp2 / nu.sigqp2;
01142     nu.chi22=trk.fit.chi2;
01143     nu.ndof2=trk.fit.ndof;
01144     nu.qpFraction2=lib.reco.GetTrkQPFraction(trk);
01145     nu.trkVtxUVDiffPl2=trk.plane.begu-trk.plane.begv;
01146     nu.trkLength2=abs(trk.plane.end-trk.plane.beg+1);
01147     nu.planeTrkNu2=trk.plane.nu;
01148     nu.planeTrkNv2=trk.plane.nv;
01149     nu.ntrklike2=trk.plane.ntrklike;
01150     nu.trkphsigcor2=trk.ph.sigcor;
01151     nu.trkphsigmap2=trk.ph.sigmap;
01152     nu.trkIdMC2 = lib.reco.GetTrueTrackId(ntp,trk);
01153 
01154     //majority curvature is extracted in its own function
01155 
01156     nu.xTrkVtx2=trk.vtx.x;
01157     nu.yTrkVtx2=trk.vtx.y;
01158     nu.zTrkVtx2=trk.vtx.z;
01159     nu.uTrkVtx2=trk.vtx.u;
01160     nu.vTrkVtx2=trk.vtx.v;
01161     nu.planeTrkVtx2=trk.vtx.plane;
01162     nu.planeTrkBeg2=trk.plane.beg;
01163     nu.planeTrkBegu2=trk.plane.begu;
01164     nu.planeTrkBegv2=trk.plane.begv;
01165     nu.stripTrkBeg2   = lib.reco.GetTrackFirstStrip(ntp, trk);
01166     nu.stripTrkBegu2  = lib.reco.GetTrackFirstUStrip(ntp, trk);
01167     nu.stripTrkBegv2  = lib.reco.GetTrackFirstVStrip(ntp, trk);
01168     nu.stripTrkEnd2   = lib.reco.GetTrackLastStrip(ntp,trk);
01169     nu.stripTrkEndu2  = lib.reco.GetTrackLastUStrip(ntp,trk);
01170     nu.stripTrkEndv2  = lib.reco.GetTrackLastVStrip(ntp,trk);
01171     nu.stripTrkBegIsu2= lib.reco.GetTrackFirstStripIsU(ntp, trk);
01172     nu.stripTrkEndIsu2= lib.reco.GetTrackLastStripIsU(ntp, trk);
01173     nu.regionTrkVtx2 = lib.reco.GetRegion(ntp,trk.vtx);
01174     nu.edgeRegionTrkVtx2 = lib.reco.GetEdgeRegion(ntp,trk.vtx);
01175     nu.edgeRegionTrkEnd2 = lib.reco.GetEdgeRegion(ntp,trk.end);
01176     nu.phiTrkVtx2 = lib.reco.GetPhi(trk.vtx); //TMath::ATan2(trk.vtx.y, trk.vtx.x);
01177     nu.phiTrkEnd2 = lib.reco.GetPhi(trk.end);
01178 
01179     lib.reco.CalculateParallelStripInset(nu, 2);
01180     lib.reco.CalculatePerpendicularStripFlag(nu, 2);
01181     lib.reco.CalculateHorizontalVerticalStripNumber(nu, 2);
01182     
01183     nu.xTrkEnd2=trk.end.x;
01184     nu.yTrkEnd2=trk.end.y;
01185     nu.zTrkEnd2=trk.end.z;
01186     nu.uTrkEnd2=trk.end.u;
01187     nu.vTrkEnd2=trk.end.v;
01188     nu.planeTrkEnd2=trk.plane.end;
01189     nu.planeTrkEndu2=trk.plane.endu;
01190     nu.planeTrkEndv2=trk.plane.endv;
01191 
01192     nu.drTrkFidall2=trk.fidall.dr;
01193     nu.dzTrkFidall2=trk.fidall.dz;
01194     nu.drTrkFidvtx2=trk.fidvtx.dr;
01195     nu.dzTrkFidvtx2=trk.fidvtx.dz;
01196     nu.drTrkFidend2=trk.fidend.dr;
01197     nu.dzTrkFidend2=trk.fidend.dz;
01198     nu.traceTrkFidall2 = trk.fidall.trace;
01199     nu.traceTrkFidvtx2 = trk.fidvtx.trace;
01200     nu.traceTrkFidend2 = trk.fidend.trace;
01201     
01202     nu.cosPrTrkVtx2 = lib.reco.GetCosBetweenPr_Theta(trk);
01203     
01204   }
01205 }
01206 
01207 //......................................................................
01208 
01209 void NuExtraction::ExtractThirdTrkInfo(const NtpStRecord& ntp,
01210                                        const NtpSREvent& evt,
01211                                        NuEvent& nu) const
01212 {
01213   //get an instance of the code library
01214   const NuLibrary& lib=NuLibrary::Instance();
01215 
01216   //get pointer to trk
01217   const NtpSRTrack* ptrk=lib.reco.GetTrackWithIndexX(ntp,evt,2);
01218   
01219   //set this to default to no track exists
01220   nu.trkExists3=false;
01221 
01222   //check if track exists
01223   if (ptrk) {
01224     //get a reference
01225     const NtpSRTrack& trk=*ptrk;
01226     
01227     nu.trkExists3=true;
01228     nu.trkIndex3=trk.index;
01229     nu.ndigitTrk3=trk.ndigit;
01230     nu.nstripTrk3=trk.nstrip;
01231     nu.trkEnCorRange3=lib.reco.GetTrackEnergyFromRangeCor
01232       (trk.momentum.range,nu);
01233     nu.trkEnCorCurv3=lib.reco.GetTrackEnergyFromCurvCor
01234       (trk.momentum.qp,nu);
01235     nu.trkShwEnNear3 = lib.reco.GetShowerEnergyNearTrack(ntp, trk,
01236                                                          &nu.trkShwEnNearDW3);
01237     nu.trkMomentumRange3=trk.momentum.range;
01238     nu.containedTrk3=trk.contained;
01239     nu.trkfitpass3=trk.fit.pass;
01240     nu.trkvtxdcosz3=trk.vtx.dcosz;
01241     nu.trkvtxdcosy3=trk.vtx.dcosy;
01242     nu.trknplane3=trk.plane.n;
01243     nu.charge3=lib.reco.GetTrackCharge(trk, nu.hornIsReverse);
01244     nu.qp3=trk.momentum.qp;
01245     nu.qp_rangebiased3=trk.momentum.qp_rangebiased;
01246     nu.sigqp3=trk.momentum.eqp;
01247     if (nu.sigqp3 != 0.0) nu.qp_sigqp3=nu.qp3 / nu.sigqp3;
01248     nu.chi23=trk.fit.chi2;
01249     nu.ndof3=trk.fit.ndof;
01250     nu.qpFraction3=lib.reco.GetTrkQPFraction(trk);
01251     nu.trkVtxUVDiffPl3=trk.plane.begu-trk.plane.begv;
01252     nu.trkLength3=abs(trk.plane.end-trk.plane.beg+1);
01253     nu.planeTrkNu3=trk.plane.nu;
01254     nu.planeTrkNv3=trk.plane.nv;
01255     nu.ntrklike3=trk.plane.ntrklike;
01256     nu.trkphsigcor3=trk.ph.sigcor;
01257     nu.trkphsigmap3=trk.ph.sigmap;
01258     nu.trkIdMC3 = lib.reco.GetTrueTrackId(ntp,trk);
01259     
01260     //majority curvature is extracted in its own function
01261 
01262     nu.xTrkVtx3=trk.vtx.x;
01263     nu.yTrkVtx3=trk.vtx.y;
01264     nu.zTrkVtx3=trk.vtx.z;
01265     nu.uTrkVtx3=trk.vtx.u;
01266     nu.vTrkVtx3=trk.vtx.v;
01267     nu.planeTrkVtx3=trk.vtx.plane;
01268     nu.planeTrkBeg3=trk.plane.beg;
01269     nu.planeTrkBegu3=trk.plane.begu;
01270     nu.planeTrkBegv3=trk.plane.begv;
01271     nu.stripTrkBeg3   = lib.reco.GetTrackFirstStrip(ntp, trk);
01272     nu.stripTrkBegu3  = lib.reco.GetTrackFirstUStrip(ntp, trk);
01273     nu.stripTrkBegv3  = lib.reco.GetTrackFirstVStrip(ntp, trk);
01274     nu.stripTrkEnd3   = lib.reco.GetTrackLastStrip(ntp,trk);
01275     nu.stripTrkEndu3  = lib.reco.GetTrackLastUStrip(ntp,trk);
01276     nu.stripTrkEndv3  = lib.reco.GetTrackLastVStrip(ntp,trk);
01277     nu.stripTrkBegIsu3= lib.reco.GetTrackFirstStripIsU(ntp, trk);
01278     nu.stripTrkEndIsu3= lib.reco.GetTrackLastStripIsU(ntp, trk);
01279     nu.regionTrkVtx3 = lib.reco.GetRegion(ntp, trk.vtx);
01280     nu.edgeRegionTrkVtx3 = lib.reco.GetEdgeRegion(ntp,trk.vtx);
01281     nu.edgeRegionTrkEnd3 = lib.reco.GetEdgeRegion(ntp,trk.end);
01282     nu.phiTrkVtx3 = lib.reco.GetPhi(trk.vtx);
01283     nu.phiTrkEnd3 = lib.reco.GetPhi(trk.end);
01284 
01285     lib.reco.CalculateParallelStripInset(nu, 3);
01286     lib.reco.CalculatePerpendicularStripFlag(nu, 3);
01287     lib.reco.CalculateHorizontalVerticalStripNumber(nu, 3);
01288     
01289     nu.xTrkEnd3=trk.end.x;
01290     nu.yTrkEnd3=trk.end.y;
01291     nu.zTrkEnd3=trk.end.z;
01292     nu.uTrkEnd3=trk.end.u;
01293     nu.vTrkEnd3=trk.end.v;
01294     nu.planeTrkEnd3=trk.plane.end;
01295     nu.planeTrkEndu3=trk.plane.endu;
01296     nu.planeTrkEndv3=trk.plane.endv;
01297 
01298     nu.drTrkFidall3=trk.fidall.dr;
01299     nu.dzTrkFidall3=trk.fidall.dz;
01300     nu.drTrkFidvtx3=trk.fidvtx.dr;
01301     nu.dzTrkFidvtx3=trk.fidvtx.dz;
01302     nu.drTrkFidend3=trk.fidend.dr;
01303     nu.dzTrkFidend3=trk.fidend.dz;
01304     nu.traceTrkFidall3 = trk.fidall.trace;
01305     nu.traceTrkFidvtx3 = trk.fidvtx.trace;
01306     nu.traceTrkFidend3 = trk.fidend.trace;
01307     
01308     nu.cosPrTrkVtx3 = lib.reco.GetCosBetweenPr_Theta(trk);
01309   }
01310 }
01311 
01312 //......................................................................
01313 
01314 void NuExtraction::ExtractMajorityCurvature(const NtpStRecord& ntp,
01315                                             const NtpSREvent& evt,
01316                                             NuEvent& nu) const
01317 {
01318   //check if a track exists
01319   if (nu.ntrk<=0) {
01320     MAXMSG("NuReco",Msg::kInfo,3)
01321       <<"ExtractMajorityCurvature: no tracks so nothing to do"
01322       <<", ntrk="<<nu.ntrk<<endl;
01323     nu.trkExists=false;
01324     return;
01325   }
01326 
01327   //check if flag is set to not calc maj curv
01328   if (!nu.calcMajCurv) {
01329     MAXMSG("NuReco",Msg::kWarning,1)
01330       <<"ExtractMajorityCurvature: flag set to calcMajCurv="
01331       <<nu.calcMajCurv<<endl;
01332     return;
01333   }
01334   
01335   //get an instance of the code library
01336   const NuLibrary& lib=NuLibrary::Instance();
01337   
01338   //get pointer to 1st trk
01339   const NtpSRTrack* ptrk=lib.reco.GetTrackWithIndexX(ntp,evt,0);
01340   
01341   //check if track exists
01342   if (ptrk) {
01343     //get a reference
01344     const NtpSRTrack& trk=*ptrk;
01345     
01346     //get an instance of the code library
01347     const NuLibrary& lib=NuLibrary::Instance();
01348     const MajCInfo majCInfo=lib.majC.CurvatureImproved(&trk);
01349     nu.jitter1=majCInfo.jitter;
01350     nu.jPID1=majCInfo.jPID;
01351     nu.majC1=majCInfo.majC;
01352     //nu.majCRatio1=majCInfo.majCRatio;
01353     //nu.rms1=majCInfo.rms;
01354     //nu.simpleMajC1=majCInfo.simpleMajC;
01355     nu.smoothMajC1=majCInfo.smoothMajC;
01356     //nu.sqJitter1=majCInfo.sqJitter;
01357     //nu.totWidth1=majCInfo.totWidth;
01358   }
01359 
01360   //get pointer to 2nd trk
01361   ptrk=lib.reco.GetTrackWithIndexX(ntp,evt,1);
01362   
01363   //check if track exists
01364   if (ptrk) {
01365     //get a reference
01366     const NtpSRTrack& trk=*ptrk;
01367     
01368     //get an instance of the code library
01369     const NuLibrary& lib=NuLibrary::Instance();
01370     const MajCInfo majCInfo=lib.majC.CurvatureImproved(&trk);
01371     nu.jitter2=majCInfo.jitter;
01372     nu.jPID2=majCInfo.jPID;
01373     nu.majC2=majCInfo.majC;
01374     //nu.majCRatio2=majCInfo.majCRatio;
01375     //nu.rms2=majCInfo.rms;
01376     //nu.simpleMajC2=majCInfo.simpleMajC;
01377     nu.smoothMajC2=majCInfo.smoothMajC;
01378     //nu.sqJitter2=majCInfo.sqJitter;
01379     //nu.totWidth2=majCInfo.totWidth;
01380   }
01381 
01383   //get pointer to 3rd trk
01384   ptrk=lib.reco.GetTrackWithIndexX(ntp,evt,2);
01385   
01386   //check if track exists
01387   if (ptrk) {
01388     //get a reference
01389     const NtpSRTrack& trk=*ptrk;
01390     
01391     //get an instance of the code library
01392     const NuLibrary& lib=NuLibrary::Instance();
01393     const MajCInfo majCInfo=lib.majC.CurvatureImproved(&trk);
01394     nu.jitter3=majCInfo.jitter;
01395     nu.jPID3=majCInfo.jPID;
01396     nu.majC3=majCInfo.majC;
01397     //nu.majCRatio3=majCInfo.majCRatio;
01398     //nu.rms3=majCInfo.rms;
01399     //nu.simpleMajC3=majCInfo.simpleMajC;
01400     nu.smoothMajC3=majCInfo.smoothMajC;
01401     //nu.sqJitter3=majCInfo.sqJitter;
01402     //nu.totWidth3=majCInfo.totWidth;
01403   }
01404 
01405   //copy across the MajCurv variables for the best track
01406   lib.reco.SetBestTrkMajorityCurvature(nu);
01407 }
01408 
01409 //......................................................................
01410 
01411 void NuExtraction::ExtractAdditionalDSTVariables(NuEvent& /*nu*/) const
01412 {
01413 
01415 /*
01416   //get an instance of the code library
01417   const NuLibrary& lib=NuLibrary::Instance();
01418 
01419   //set fiducial volume variables useful for DST interactive use  
01420   if (nu.detector==Detector::kNear) {
01421     nu.fvnmb=lib.cuts.IsInFidVolNDNuMuBar
01422       (nu.xTrkVtx,nu.yTrkVtx,nu.zTrkVtx);
01423     nu.fvpitt=lib.cuts.IsInFidVolPitt
01424       (nu.xTrkVtx,nu.yTrkVtx,nu.zTrkVtx,nu.uTrkVtx,nu.vTrkVtx);
01425     nu.fvcc=lib.cuts.IsInFidVolNDCC0250Std
01426       (nu.xTrkVtx,nu.yTrkVtx,nu.zTrkVtx);
01427   }
01428   else if (nu.detector==Detector::kFar) {
01429     nu.fvcc=lib.cuts.IsInFidVolFDCC0250Std
01430       (nu.planeTrkVtx,nu.rTrkVtx);
01431     //just set these other two to the std CC one
01432     //there are no specialised FD fid vols yet
01433     nu.fvnmb=nu.fvcc;
01434     nu.fvpitt=nu.fvcc;
01435   }
01436   else {
01437     cout<<"Ahhhh, det="<<nu.detector<<endl;
01438   }
01439 */
01440 
01441 }
01442 
01443 //......................................................................
01444 
01445 void NuExtraction::ExtractMinMaxEvtTimes(const NtpStRecord& ntp,
01446                                          const NtpSREvent& evt,
01447                                          NuEvent& nu) const
01448 {
01449   //get a multiset to hold all the strip times
01450   multiset<Double_t> times;
01451   const TClonesArray& stpTca=(*ntp.stp);
01452 
01453   Double_t timemax=-1.e10;
01454   Double_t timemin=1.e10;
01455 
01456   MsgFormat ffmt("%9.9f");
01457 
01458   //Extract the crate t0:
01459 
01460   NtpSRTimeStatus timeStatus = ntp.timestatus;
01461   nu.crateT0 = timeStatus.crate_t0_ns * Munits::ns;
01462   //  cout << "Extracted crate t0: " << nu.crateT0 << endl;
01463 
01464 /*
01465   Double_t snarlTime=(nu.timeNanoSec*(Munits::ns));
01466   if (snarlTime>0.999999981 && snarlTime<0.999999983) {
01467     const Int_t numStps=stpTca.GetEntriesFast();
01468     Int_t counter=0;
01469     //loop over strips in snarl
01470     for (Int_t i=0;i<numStps;++i) {
01471       const NtpSRStrip* pstp=
01472         dynamic_cast<NtpSRStrip*>(stpTca[i]);
01473       const NtpSRStrip& stp=(*pstp);
01474       
01475       if (stp.time1>0.000029999) {
01476         MAXMSG("NuExtraction",Msg::kInfo,10000)
01477           <<"run="<<nu.run<<", subrun="<<nu.subRun
01478           <<", snarl="<<nu.snarl<<", i="<<i
01479           <<", count="<<counter<<", evt="<<nu.evt
01480           <<", ind="<<stp.index<<", s,pl="<<stp.strip<<","<<stp.plane
01481           <<endl
01482           <<"  t1="<<ffmt(stp.time1)
01483           <<", snlTime="<<ffmt(snarlTime)
01484           <<", raw="<<stp.ph1.raw
01485           <<", sigC="<<stp.ph1.sigcor
01486           <<endl;
01487       }
01488       counter++;
01489     }
01490   }
01491 */
01492 
01493   MAXMSG("NuExtraction",Msg::kDebug,200)
01494     <<"evt.nstrip="<<evt.nstrip<<endl;
01495   for (Int_t i=0;i<evt.nstrip;i++) {        
01496     //check for bug where strip index is -1
01497     if (evt.stp[i]<0) {
01498       MAXMSG("MeuCuts",Msg::kInfo,50)
01499         <<"Skipping strip with evt.stp[i]="<<evt.stp[i]<<endl;
01500       continue;
01501     }
01502     
01503     const NtpSRStrip& stp=
01504       *(dynamic_cast<NtpSRStrip*>(stpTca[evt.stp[i]]));
01505 
01506     Double_t snarlTime=(nu.timeNanoSec*(Munits::ns));
01507     Double_t striptime=-999;
01508 
01509     //get the min/max time
01510     //code from MadTVAnalysis
01511     if (nu.detector==Detector::kNear) {
01512       if (nu.simFlag==SimFlag::kMC &&
01513           snarlTime>0.999999981 && snarlTime<0.999999983) {
01514         MAXMSG("NuExtraction",Msg::kWarning,1)
01515           <<"Deal with odd times: setting fNanoSec to zero, snarlTime="
01516           <<ffmt(snarlTime)<<endl;
01517         snarlTime=0;
01518       }
01519       
01520       //get the time relative to the snarl time
01521       striptime=stp.time1-snarlTime;
01522 
01523       //check if min/max
01524       if(striptime<=timemin && striptime!=-999) timemin=striptime;
01525       if(striptime>=timemax) timemax=striptime;
01526     }
01527     else if (nu.detector==Detector::kFar) {
01528       //get the times relative to the snarl time
01529       Double_t striptime1=stp.time1-snarlTime;
01530       Double_t striptime0=stp.time0-snarlTime;
01531       striptime=-999;
01532       if(striptime1>0 && striptime0<0) striptime=striptime1;
01533       if(striptime0>0 && striptime1<0) striptime=striptime0;
01534       if(striptime0>0 && striptime1>0) striptime=(striptime0+
01535                                                   striptime1)/2.;
01536 
01537       //check if min/max
01538       if(striptime<=timemin && striptime!=-999) timemin=striptime;
01539       if(striptime>=timemax) timemax=striptime;
01540     }
01541     else cout<<"Ahhh, detector not known"<<endl;
01542 
01543     Double_t time=stp.time0;
01544     if (time<0 || time>1) time=stp.time1;
01545     
01546     if (time>0 && time<=1) {
01547       times.insert(time);
01548     }
01549     //else just don't put the time in the map - clearly rubbish
01550     if (nu.detector==Detector::kNear) {
01551       MAXMSG("NuExtraction",Msg::kDebug,1000)
01552         <<"i="<<stp.index<<", s="<<stp.strip<<", t1="<<ffmt(stp.time1)
01553         <<", tmn="<<ffmt(timemin)<<", tmx="<<ffmt(timemax)
01554         <<", snlTime="<<ffmt(snarlTime)<<endl;
01555     }
01556     else {
01557       MAXMSG("NuExtraction",Msg::kDebug,1000)
01558         <<"i="<<stp.index<<", s="<<stp.strip
01559         <<", t0="<<ffmt(stp.time0)<<", t1="<<ffmt(stp.time1)
01560         <<", tmn="<<ffmt(timemin)<<", tmx="<<ffmt(timemax)
01561         <<", snlTime="<<ffmt(snarlTime)
01562         //<<", pl="<<stp.plane
01563         //<<", sigC="<<stp.ph1.sigcor<<", tpos="<<stp.tpos<<endl;
01564         <<endl;
01565     }
01566   }
01567   
01568   //get the median time from the map
01569   multiset<Double_t>::const_iterator it=times.begin();
01570   advance(it,times.size()/2);
01571   Double_t medianTime=*it;
01572   MAXMSG("NuExtraction",Msg::kDebug,100)
01573     <<"Median time="<<medianTime<<endl;
01574   
01575   //set the NuEvent variables
01576   nu.medianTime=medianTime;
01577   nu.timeEvtMin=timemin;
01578   nu.timeEvtMax=timemax;
01579 
01580 
01582   //sanity check and debug printout
01583   if ((timemin+nu.crateT0)<0 || (nu.run==36608 && nu.snarl==42717 && false)) {
01584     //Bad time, run=36608, snarl=42717, evt=0
01585     Double_t timemax=-1.e-10;
01586     Double_t timemin=1.e10;
01587 
01588     MAXMSG("NuExtraction",Msg::kError,1000)
01589       <<"Bad time, run="<<nu.run<<", snarl="<<nu.snarl
01590       <<", evt="<<nu.evt<<endl;
01591     for (Int_t i=0;i<evt.nstrip;i++) {
01592       //check for bug where strip index is -1
01593       if (evt.stp[i]<0) {
01594         MAXMSG("MeuCuts",Msg::kInfo,50)
01595           <<"Skipping strip with evt.stp[i]="<<evt.stp[i]<<endl;
01596         continue;
01597       }
01598       
01599       const NtpSRStrip& stp=
01600         *(dynamic_cast<NtpSRStrip*>(stpTca[evt.stp[i]]));
01601       
01602       Double_t snarlTime=(nu.timeNanoSec*(Munits::ns));
01603       Double_t striptime=-999;
01604       
01605       //get the min/max time
01606       //code from MadTVAnalysis
01607       if (nu.detector==Detector::kNear) {
01608         //get the time relative to the snarl time
01609         striptime=stp.time1-snarlTime;
01610         
01611         //check if min/max
01612         if(striptime<=timemin) timemin=striptime;
01613         if(striptime>=timemax) timemax=striptime;
01614       }
01615       else if (nu.detector==Detector::kFar) {
01616         //get the times relative to the snarl time
01617         Double_t striptime1=stp.time1-snarlTime;
01618         Double_t striptime0=stp.time0-snarlTime;
01619         striptime=-999;
01620         if(striptime1>0 && striptime0<0) striptime=striptime1;
01621         if(striptime0>0 && striptime1<0) striptime=striptime0;
01622         if(striptime0>0 && striptime1>0) striptime=(striptime0+
01623                                                     striptime1)/2.;
01624         
01625         //check if min/max
01626         if(striptime<=timemin) timemin=striptime;
01627         if(striptime>=timemax) timemax=striptime;
01628       }
01629       else cout<<"Ahhh, detector not known"<<endl;
01630       
01631       MAXMSG("NuExtraction",Msg::kInfo,1000)
01632         <<"strip="<<stp.strip
01633         <<", t0="<<ffmt(stp.time0)<<", t1="<<ffmt(stp.time1)
01634         <<", stp.index="<<stp.index
01635         <<endl
01636         <<"  tmn="<<ffmt(timemin)<<", tmx="<<ffmt(timemax)
01637         <<", stime="<<ffmt(striptime)
01638         <<", snlTime="<<ffmt(snarlTime)<<endl
01639         <<"  plane="<<stp.plane
01640         <<", ph0.raw="<<stp.ph0.raw
01641         <<", ph1.raw="<<stp.ph1.raw
01642         <<endl;
01643     }
01644   }
01645 }
01646 
01647 //......................................................................
01648 void NuExtraction::ExtractNCInfo(const NtpStRecord* pntp,
01649                    Int_t eventNb,
01650                    NuEvent& nu) const
01651 {
01652   // Protection against reset of gDirectory
01653   // The call to InitializekNN() uses another file.
01654   TDirectory *tmpd = gDirectory;
01655   MSG("NuExtraction",Msg::kDebug) << "Start ExtractNCInfo, gDirectory is : ";
01656   //gDirectory->pwd();
01657 
01658   // See AnalysisNtuple/Module/CondensedNtpModuleNC::Ana()
01659   // create the ntpManipulator object 
01660   static ANtpInfoObjectFillerNC   *InfoFiller   = new ANtpInfoObjectFillerNC();
01661   static ANtpRecoNtpManipulator *ntpManipulator = new ANtpRecoNtpManipulator();
01662   NtpStRecord            *tryRec = const_cast<NtpStRecord*>(pntp);
01663   ntpManipulator->SetRecord(tryRec);
01664   static ANtpEventInfoNC   *EventInfo  = new ANtpEventInfoNC();
01665   static ANtpTrackInfoNC   *TrackInfo  = new ANtpTrackInfoNC();
01666   static ANtpShowerInfoNC  *ShowerInfo = new ANtpShowerInfoNC();
01667   static ANtpTruthInfoBeam *TruthInfo  = new ANtpTruthInfoBeam();                                                                                             
01668 
01669   // Extract Header Info
01670   //====================
01671   // Detector - 1 near, 2 far - needed for filling the HeaderInfo
01672   Detector::Detector_t det = tryRec->GetVldContext()->GetDetector();
01673   InfoFiller->SetDetector(det);
01674   InfoFiller->SetStripArray(ntpManipulator->GetStripArray());
01675   InfoFiller->SetClusterArray(ntpManipulator->GetClusterArray());
01676   
01677   // Extract Event/Track/Shower/Truth Info
01678   //======================================
01679   //set up which flags you want to use to determine the primary shower or track
01680   //a value of 0 for a flag means it will not be used
01681   ntpManipulator->SetPrimaryTrackCriteria(0,1,0); // nplanes, length, total pulse height
01682   ntpManipulator->SetPrimaryShowerCriteria(0,1);  // nplanes, total pulse height
01683                                                                                              
01684 
01685   // Initialize kNN, only once per snarl
01686   //====================================
01687   InfoFiller->InitializekNN(ntpManipulator);
01688 
01689   // Reset the Info Objects
01690   //=======================
01691   EventInfo->Reset();
01692   TrackInfo->Reset();
01693   ShowerInfo->Reset();
01694   TruthInfo->Reset();                                                                                             
01695 
01696   // Fill event, track, shower and truth and calculate variables needed
01697   //===================================================================
01698   InfoFiller->FillInformation(eventNb, ntpManipulator, EventInfo, TrackInfo, ShowerInfo, TruthInfo);
01699   
01700   // Fill the NuEvent variables
01701   //===========================
01702   // event
01703   nu.closeTimeDeltaZ = EventInfo->closeTimeDeltaZ;
01704   nu.edgeActivityStrips = EventInfo->edgeActivityStrips;
01705   nu.edgeActivityPH = EventInfo->edgeActivityPH;
01706   nu.oppEdgeStrips = EventInfo->oppEdgeStrips;
01707   nu.oppEdgePH = EventInfo->oppEdgePH;
01708   nu.vtxMetersToCoilEvt = EventInfo->vtxMetersToCoil;
01709   nu.vtxMetersToCloseEdgeEvt = EventInfo->vtxMetersToCloseEdge;
01710   nu.minTimeSeparation = EventInfo->minTimeSeparation;                                                                                             
01711 
01712   // shower
01713   nu.transverseRMSU = ShowerInfo->transverseRMSU;
01714   nu.transverseRMSV = ShowerInfo->transverseRMSV;
01715 
01716   // track
01717   nu.dtdz = TrackInfo->dtdz;
01718   nu.endMetersToCloseEdge = TrackInfo->endMetersToCloseEdge;
01719   nu.vtxMetersToCloseEdgeTrk = TrackInfo->vtxMetersToCloseEdge;
01720   nu.vtxMetersToCoilTrk = TrackInfo->vtxMetersToCoil;
01721   nu.traceEndZ = TrackInfo->traceEndZ;                                                                                             
01722     
01723   MSG("NuExtraction",Msg::kDebug) << "End ExtractNCInfo, gDirectory is : ";
01724   gDirectory = tmpd;
01725   //gDirectory->pwd();
01726 }
01727 
01728 //......................................................................
01729 void NuExtraction::NuMCEventFromNuEvent(const NuEvent& nu,
01730                                         NuMCEvent& numc) const
01731 {
01732   //copy the info across
01733 
01735   //book keeping  quantities
01737   numc.entry=nu.entry;
01738 
01740   //snarl/run based quantities
01742   numc.run=nu.run;
01743   numc.subRun=nu.subRun;
01744   numc.snarl=nu.snarl;    
01745 
01746   numc.runPeriod=nu.runPeriod;
01747   numc.intensity=nu.intensity;
01748   numc.hornIsReverse=nu.hornIsReverse;
01749   numc.beamType=nu.beamType;
01750 
01751   numc.detector=nu.detector;
01752   numc.simFlag=nu.simFlag;
01753   numc.timeSec=nu.timeSec;
01754   numc.timeNanoSec=nu.timeNanoSec;
01755   numc.timeSeconds=nu.timeSeconds;
01756   numc.trigtime=nu.trigtime;
01757 
01758   numc.releaseType=nu.releaseType;
01759   numc.anaVersion=nu.anaVersion;
01760 
01762   //truth variables
01764   numc.energyMC=nu.energyMC;
01765 
01766   numc.neuEnMC=nu.neuEnMC;
01767   numc.neuPxMC=nu.neuPxMC;
01768   numc.neuPyMC=nu.neuPyMC;
01769   numc.neuPzMC=nu.neuPzMC;
01770 
01771   numc.mu1EnMC=nu.mu1EnMC;
01772   numc.mu1PxMC=nu.mu1PxMC;
01773   numc.mu1PyMC=nu.mu1PyMC;
01774   numc.mu1PzMC=nu.mu1PzMC;
01775 
01776   numc.tgtEnMC=nu.tgtEnMC;
01777   numc.tgtPxMC=nu.tgtPxMC;
01778   numc.tgtPyMC=nu.tgtPyMC;
01779   numc.tgtPzMC=nu.tgtPzMC;
01780 
01781   numc.zMC=nu.zMC;
01782   numc.aMC=nu.aMC;
01783   numc.nucleusMC=nu.nucleusMC;
01784   numc.initialStateMC=nu.initialStateMC;
01785   numc.hadronicFinalStateMC=nu.hadronicFinalStateMC;
01786   numc.numPreInukeFSprotMC=nu.numPreInukeFSprotMC;
01787   numc.numPreInukeFSneutMC=nu.numPreInukeFSneutMC;
01788   numc.maxMomPreInukeFSprotMC=numc.maxMomPreInukeFSprotMC;
01789   numc.maxMomPreInukeFSneutMC=numc.maxMomPreInukeFSneutMC;
01790 
01791   numc.yMC=nu.yMC;
01792   numc.y2MC=nu.y2MC;
01793   numc.xMC=nu.xMC;
01794   numc.q2MC=nu.q2MC;
01795   numc.w2MC=nu.w2MC;
01796 
01797   numc.trkEnMC=nu.trkEnMC;
01798   numc.trkEn2MC=nu.trkEn2MC;
01799   numc.shwEnMC=nu.shwEnMC;
01800   numc.shwEn2MC=nu.shwEn2MC;
01801 
01802   numc.trkEndEnMC=nu.trkEndEnMC;
01803   numc.trkStartEnMC=nu.trkStartEnMC;
01804   numc.trkContainmentMC=nu.trkContainmentMC;
01805 
01806   numc.sigma=nu.sigma;
01807   numc.iaction=nu.iaction;
01808   numc.iresonance=nu.iresonance;
01809   numc.inu=nu.inu;
01810   numc.inunoosc=nu.inunoosc;
01811   numc.itg=nu.itg;
01812     
01813   numc.vtxxMC=nu.vtxxMC;
01814   numc.vtxyMC=nu.vtxyMC;
01815   numc.vtxzMC=nu.vtxzMC;
01816   numc.vtxuMC=nu.vtxuMC;
01817   numc.vtxvMC=nu.vtxvMC;
01818   numc.planeTrkVtxMC=nu.planeTrkVtxMC;
01819   numc.rTrkVtxMC=nu.rTrkVtxMC;
01820 
01821   numc.mc=nu.mc;//copy across the index of the true event
01822 
01823   numc.Npz=nu.Npz;
01824   numc.NdxdzNea=nu.NdxdzNea;
01825   numc.NdydzNea=nu.NdydzNea;
01826   numc.NenergyN=nu.NenergyN;
01827   numc.NWtNear=nu.NWtNear;
01828   numc.NdxdzFar=nu.NdxdzFar;
01829   numc.NdydzFar=nu.NdydzFar;
01830   numc.NenergyF=nu.NenergyF;
01831   numc.NWtFar=nu.NWtFar;
01832   numc.Ndecay=nu.Ndecay;
01833   numc.Vx=nu.Vx;
01834   numc.Vy=nu.Vy;
01835   numc.Vz=nu.Vz;
01836   numc.pdPx=nu.pdPx;
01837   numc.pdPy=nu.pdPy;
01838   numc.pdPz=nu.pdPz;
01839   numc.ppdxdz=nu.ppdxdz;
01840   numc.ppdydz=nu.ppdydz;
01841   numc.pppz=nu.pppz;
01842   numc.ppenergy=nu.ppenergy;
01843   numc.ppmedium=nu.ppmedium;
01844   numc.ppvx=nu.ppvx;
01845   numc.ppvy=nu.ppvy;
01846   numc.ppvz=nu.ppvz;
01847   numc.ptype=nu.ptype;
01848   numc.Necm=nu.Necm;
01849   numc.Nimpwt=nu.Nimpwt;
01850   numc.tvx=nu.tvx;
01851   numc.tvy=nu.tvy;
01852   numc.tvz=nu.tvz;
01853   numc.tpx=nu.tpx;
01854   numc.tpy=nu.tpy;
01855   numc.tpz=nu.tpz;
01856   numc.tptype=nu.tptype;
01857   numc.tgen=nu.tgen;
01858 
01859   //copy the weights
01860   numc.rw=nu.rw;
01861   numc.fluxErr=nu.fluxErr;
01862   numc.rwActual=nu.rwActual;
01863   numc.generatorWeight=nu.generatorWeight;
01864   numc.detectorWeight=nu.detectorWeight;
01865 
01866   numc.trkEnWeight=nu.trkEnWeight;
01867   numc.shwEnWeight=nu.shwEnWeight;
01868   numc.beamWeight=nu.beamWeight;
01869   numc.fluxErrHadProdAfterTune=nu.fluxErrHadProdAfterTune;
01870   numc.fluxErrTotalErrorPreTune=nu.fluxErrTotalErrorPreTune;
01871   numc.fluxErrTotalErrorAfterTune=nu.fluxErrTotalErrorAfterTune;
01872   numc.detectorWeightNMB=nu.detectorWeightNMB;
01873   numc.detectorWeightNM=nu.detectorWeightNM;
01874 
01875   numc.trkEnWeightRunI=nu.trkEnWeightRunI;
01876   numc.shwEnWeightRunI=nu.shwEnWeightRunI;
01877   numc.beamWeightRunI=nu.beamWeightRunI;
01878   numc.fluxErrHadProdAfterTuneRunI=nu.fluxErrHadProdAfterTuneRunI;
01879   numc.fluxErrTotalErrorPreTuneRunI=nu.fluxErrTotalErrorPreTuneRunI;
01880   numc.fluxErrTotalErrorAfterTuneRunI=nu.fluxErrTotalErrorAfterTuneRunI;
01881   numc.detectorWeightNMBRunI=nu.detectorWeightNMBRunI;
01882   numc.detectorWeightNMRunI=nu.detectorWeightNMRunI;
01883 
01884   numc.trkEnWeightRunII=nu.trkEnWeightRunII;
01885   numc.shwEnWeightRunII=nu.shwEnWeightRunII;
01886   numc.beamWeightRunII=nu.beamWeightRunII;
01887   numc.fluxErrHadProdAfterTuneRunII=nu.fluxErrHadProdAfterTuneRunII;
01888   numc.fluxErrTotalErrorPreTuneRunII=nu.fluxErrTotalErrorPreTuneRunII;
01889   numc.fluxErrTotalErrorAfterTuneRunII=
01890     nu.fluxErrTotalErrorAfterTuneRunII;
01891   numc.detectorWeightNMBRunII=nu.detectorWeightNMBRunII;
01892   numc.detectorWeightNMRunII=nu.detectorWeightNMRunII;
01893   
01894   numc.InukeNwts  =  nu.InukeNwts ;
01895   numc.InukePiCExchgP  =  nu.InukePiCExchgP ;   //0  
01896   numc.InukePiCExchgN  =  nu.InukePiCExchgN ;   //1  
01897   numc.InukePiEScatP  =  nu.InukePiEScatP ;     //2  
01898   numc.InukePiEScatN  =  nu.InukePiEScatN ;     //3  
01899   numc.InukePiInEScatP  =  nu.InukePiInEScatP ;  //4  
01900   numc.InukePiInEScatN  =  nu.InukePiInEScatN ;  //5  
01901   numc.InukePiAbsorbP  =  nu.InukePiAbsorbP ;   //6  
01902   numc.InukePiAbsorbN  =  nu.InukePiAbsorbN ;   //7  
01903   numc.InukePi2PiP  =  nu.InukePi2PiP ;         //8  
01904   numc.InukePi2PiN  =  nu.InukePi2PiN ;         //9  
01905   numc.InukeNknockP  =  nu.InukeNknockP ;       //10 
01906   numc.InukeNknockN  =  nu.InukeNknockN ;       //11 
01907   numc.InukeNNPiP  =  nu.InukeNNPiP ;           //12 
01908   numc.InukeNNPiN  =  nu.InukeNNPiN ;           //13 
01909   numc.InukeFormTP  =  nu.InukeFormTP ;      //14 
01910   numc.InukeFormTN  =  nu.InukeFormTN ;      //15 
01911   numc.InukePiXsecP  =  nu.InukePiXsecP ;     //16 
01912   numc.InukePiXsecN  =  nu.InukePiXsecN ;     //17 
01913   numc.InukeNXsecP  =  nu.InukeNXsecP ;      //18 
01914   numc.InukeNXsecN  =  nu.InukeNXsecN ;      //19 
01915   numc.InukeNucrad  =  nu.InukeNucrad ;
01916   numc.InukeWrad  =  nu.InukeWrad ;
01917 }
01918 
01919 //......................................................................
01920 
01921 
01922 
01923 

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