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

UtilMisc.cxx

Go to the documentation of this file.
00001 #include <cassert>
00002 #include <string>
00003 #include <sstream>
00004 
00005 #include "TMath.h"
00006 #include <cmath>
00007 
00008 #include "MessageService/MsgService.h"
00009 
00010 #include "AtNuEvent/AtmosEvent.h"
00011 #include "AtNuEvent/AtmosScintHit.h"
00012 #include "AtNuEvent/AtmosStrip.h"
00013 #include "AtNuEvent/AtmosMC.h"
00014 
00015 
00016 #include "AtNuUtils/UtilMisc.h"
00017 
00018 CVSID("$Id: UtilMisc.cxx,v 1.5 2008/04/04 21:50:46 bspeak Exp $");
00019 
00020 const double C45 = TMath::Sqrt(2.) / 2.; //Cosine of 45 degrees
00021 
00022 const double SinSq2Th = 0.95;
00023 const double SinSq2ThHi = 1.0;
00024 const double SinSq2ThLo = 0.9;
00025 
00026 const double DMSq = 0.0021;
00027 const double DMSqHi = 0.003;
00028 const double DMSqLo = 0.0015;
00029 
00030 const double REarth = 6371.0;
00031 const double RMine = 6360.0;
00032 
00033 double UtilMisc::OscProb(const AtmosMC &MCInfo, double *sigma) {
00034 
00035   //To start, only concern with numu CC events
00036   if (MCInfo.IDact!=1 || TMath::Abs(MCInfo.IDnu)!=14) {
00037     if(sigma) *sigma = 0.0;
00038     return(0.0);
00039   }
00040 
00041   double NuEnergy = TMath::Abs(MCInfo.Enu);
00042 
00043   //Use cosy as the zenith angle
00044   double NuMomentum = TMath::Sqrt((MCInfo.PnuX * MCInfo.PnuX) + 
00045     (MCInfo.PnuY * MCInfo.PnuY) + (MCInfo.PnuZ * MCInfo.PnuZ));
00046 
00047   double NuCosY = MCInfo.PnuY / NuMomentum;
00048 
00049   return UtilMisc::OscProb(NuCosY,NuEnergy,sigma);
00050 }
00051 
00052 double UtilMisc::OscProb(double CosY, double NuE, double *sigma) {
00053   MSG("Util",Msg::kVerbose) << "UtilMisc::OscProb" << endl;
00054   double NuL = (REarth*REarth) - (RMine*RMine)*(1.0-(CosY*CosY));
00055   NuL = -1.0*RMine*CosY + TMath::Sqrt(NuL);
00056 
00057   double OscFact = TMath::Sin(1.27 * DMSq * NuL / NuE);
00058   OscFact = OscFact * OscFact * SinSq2Th;
00059 
00060   if (sigma) {
00061     double OscHi = TMath::Sin(1.27 * DMSqHi * NuL / NuE);
00062     OscHi = OscHi * OscHi;
00063     double OscLo = TMath::Sin(1.27 * DMSqLo * NuL / NuE);
00064     OscLo = OscLo * OscLo;
00065 
00066     double OscFactHi = SinSq2ThHi * TMath::Max(OscHi,OscLo);
00067     double OscFactLo = SinSq2ThLo * TMath::Min(OscHi,OscLo);
00068 
00069     *sigma = TMath::Abs(OscFactHi - OscFactLo) / 2.0;
00070     OscFact = (OscFactHi + OscFactLo) / 2.0;
00071   }
00072 
00073   return(OscFact);
00074 }
00075 
00076 bool UtilMisc::IdIsChargedLepton(int Id) {
00077   if(TMath::Abs(Id) == 11) return true;
00078   if(TMath::Abs(Id) == 13) return true;
00079   if(TMath::Abs(Id) == 15) return true;
00080   return false;
00081 }
00082 
00083 bool UtilMisc::IdIsNeutralLepton(int Id) {
00084   if(TMath::Abs(Id) == 12) return true;
00085   if(TMath::Abs(Id) == 14) return true;
00086   if(TMath::Abs(Id) == 16) return true;
00087   return false;
00088 }
00089 
00090 bool UtilMisc::IdIsNeutrino(int Id) {
00091   return UtilMisc::IdIsNeutralLepton(Id);
00092 }
00093 
00094 bool UtilMisc::IdIsLepton(int Id) {
00095   return UtilMisc::IdIsChargedLepton(Id) ||
00096          UtilMisc::IdIsNeutralLepton(Id);
00097 }
00098 
00099 /* IType defines an index type used through out where:
00100  * IType = 0(kNuECC) : nu_e CC
00101  *       = 1(kNuMuCC) : nu_mu CC
00102  *       = 2(kNuTauCC) : nu_tau CC
00103  *       = 3(kNuNC) : nu NC
00104  *       = 4(kCRMu) : CR muon
00105  *       = 5(kCRNeutron) : CR muon induced neutron
00106  *       = 6(kMCOther) : MC other
00107  *       = 7(kData) : Data
00108  */
00109 short UtilMisc::IType(const AtmosEvent *event) {
00110   if(event->NScintHits == 0) return(kData);//No ScintHits recorded, must be data
00111   if(event->MCInfo.IDnu == 0) {
00112     if(event->MCInfo.Emu == 0.) return kCRNeutron;
00113     return(kCRMu);
00114   }
00115   if(event->MCInfo.IDact == 0) return(kNuNC);//nu NC
00116   if(TMath::Abs(event->MCInfo.IDnu)==16) return(kNuTauCC);//nu_tau CC, call it NC
00117   if(TMath::Abs(event->MCInfo.IDnu)==14) return(kNuMuCC);//nu_mu CC
00118   if(TMath::Abs(event->MCInfo.IDnu)==12) return(kNuECC);//nue CC
00119   return(kMCOther);
00120 
00121   MSG("UtilMisc",Msg::kSynopsis) << "What is this with IDnu = " << event->MCInfo.IDnu
00122          << " and IDact = " << event->MCInfo.IDact << endl;
00123   MSG("UtilMisc",Msg::kWarning) << "This event fails classifaction: " << event->Run
00124          << ", " << event->SubRun << ", " << event->Snarl << endl;
00125   return (-1);
00126 }
00127 
00128 void UtilMisc::ReportEvent(const AtmosEvent *event) {
00129   MSG("Util",Msg::kSynopsis) << event->Run << "-" << event->SubRun << "-" << event->Snarl
00130          << endl;
00131 }
00132 
00133 std::string UtilMisc::EventAsString(const AtmosEvent *event) {
00134   std::ostringstream oss;
00135   oss << event->Run << "-" << event->SubRun << "-" << event->Snarl;
00136   return oss.str();
00137 }
00138 
00139 static const double SM1EdgesZ[2] = { 0.00, 14.75};
00140 static const double SM2EdgesZ[2] = {15.96, 29.94};
00141 static const double HalfSideL = 4. / (1. + sqrt(2.));
00142 
00143 short UtilMisc::DetectorWall(double *Vtx, double *Cos, double *DetVtx) {
00144   if(!Vtx || !Cos || !DetVtx) return(-1);
00145   const double VtxX = Vtx[0];
00146   const double VtxY = Vtx[1];
00147   const double VtxU = C45 * (Vtx[1] + Vtx[0]);
00148   const double VtxV = C45 * (Vtx[1] - Vtx[0]);
00149   const double VtxL[4] = {VtxV, VtxY, VtxU, VtxX};
00150 
00151   const double VtxZ = Vtx[2];
00152   const int VtxSM = 1 + (int)(VtxZ/15.);
00153 
00154   //For uncontained vertex, set Wall to Vtx and return -1;
00155   if (TMath::Abs(VtxU) > 4.0 || TMath::Abs(VtxV) > 4.0 ||
00156       TMath::Abs(VtxX) > 4.0 || TMath::Abs(VtxY) > 4.0 ||
00157       VtxZ < SM1EdgesZ[0] || VtxZ > SM2EdgesZ[1] ||
00158       (SM1EdgesZ[1] < VtxZ && VtxZ < SM2EdgesZ[0])) {
00159     for (int i=0; i<3; i++)  DetVtx[i] = Vtx[i];
00160     return -1;
00161   }
00162 
00163   const double CosX = Cos[0];
00164   const double CosY = Cos[1];
00165   const double CosZ = Cos[2];
00166   const double CosU = C45 * (Cos[1] + Cos[0]);
00167   const double CosV = C45 * (Cos[1] - Cos[0]);
00168   const double CosL[4] = {CosV,CosY,CosU,CosX};
00169 
00170   DetVtx[0] = 0.; DetVtx[1] = 0.; DetVtx[2] = 0.;
00171 
00172   double ZProj(0.), OProj(0.), Wall(0.);
00173   int Side(-1);
00174   int i(0);
00175   //loop over each octagonal edge pair (0=V, 1=Y, 2=U, 3=X)
00176   for (i=0; i<4; i++) {
00177     if(fabs(CosL[i]) < 1.e-6) continue;//DirCos can't be small
00178     Wall = CosL[i] > 0.0 ? 4.0 : -4.0;//Pointing up or down
00179     int j = i<2 ? i+2 : i-2;//Find the orthogonal coordinate index
00180 
00181     //OProj is the coordinate in the orthogonal 'j' coordinate where the
00182     //vertex points back to in the 'i' coordinate, if it sits outside of
00183     //the halflength of an octagonal side, move along
00184     OProj = VtxL[j] + (CosL[j]/CosL[i])*(Wall-VtxL[i]);
00185     if(fabs(OProj) > HalfSideL) continue;
00186 
00187     //Calculated the ZProj for the case that gets to this point
00188     ZProj = VtxZ + (CosZ/CosL[i])*(Wall-VtxL[i]);
00189     break;
00190   }
00191 
00192   //Firt examine the cases where the projection would land on the edge
00193   //of one of the super modules
00194   if ((i>3) || (ZProj<SM1EdgesZ[0]) || (ZProj>SM2EdgesZ[1]) ||
00195       (ZProj>SM1EdgesZ[1] && VtxZ < SM1EdgesZ[1]) ||
00196       (ZProj<SM2EdgesZ[0] && VtxZ > SM2EdgesZ[0])) {
00197     //Low Z edge of SM1
00198     if(CosZ<0.0 && VtxSM==1) {
00199       DetVtx[2] = SM1EdgesZ[0];
00200       Side = 8;
00201     }
00202     //High Z edge of SM1
00203     else if(CosZ>0.0 && VtxSM==1) {
00204       DetVtx[2] = SM1EdgesZ[1];
00205       Side = 9;
00206     }
00207     //Low Z edge of SM2
00208     else if(CosZ<0.0 && VtxSM==2) {
00209       DetVtx[2] = SM2EdgesZ[0];
00210       Side = 10;
00211     }
00212     //High Z edge of SM2
00213     else if(CosZ>0.0 && VtxSM==2) {
00214       DetVtx[2] = SM2EdgesZ[1];
00215       Side = 11;
00216     }
00217     //WTF edge of WTF, should crash and make a core dump
00218     else {
00219       MSG("UtilMisc", Msg::kError) << "WTF, puking on shoes" << endl;
00220       assert(false);
00221     }
00222     DetVtx[0] = VtxX + (CosX/CosZ)*(DetVtx[2]-VtxZ);
00223     DetVtx[1] = VtxY + (CosY/CosZ)*(DetVtx[2]-VtxZ);
00224   }
00225   else {
00226     DetVtx[2] = ZProj;
00227     Side = CosL[i] > 0.0 ? i : i+4;
00228     switch(i) {
00229      //Detector Vertex on V edge
00230      case 0:
00231       DetVtx[0] = C45 * (OProj - Wall);
00232       DetVtx[1] = C45 * (OProj + Wall);
00233       break;
00234      //Detector Vertex on Y edge
00235      case 1:
00236       DetVtx[1] = Wall;
00237       DetVtx[0] = OProj;
00238       break;
00239      //Detector Vertex on U edge
00240      case 2:
00241       DetVtx[0] = C45 * (Wall - OProj);
00242       DetVtx[1] = C45 * (Wall + OProj);
00243       break;
00244      //Detector Vertex on X edge
00245      case 3:
00246       DetVtx[1] = OProj;
00247       DetVtx[0] = Wall;
00248       break;
00249      //Detector Vertex on WTF edge, should crash and make a core dump
00250      default:
00251       MSG("UtilMisc", Msg::kError) << "WTF, puking on shoes" << endl;
00252       assert(false);
00253       break;
00254     }
00255   }
00256   return Side;
00257 }

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