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.;
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
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
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
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109 short UtilMisc::IType(const AtmosEvent *event) {
00110 if(event->NScintHits == 0) return(kData);
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);
00116 if(TMath::Abs(event->MCInfo.IDnu)==16) return(kNuTauCC);
00117 if(TMath::Abs(event->MCInfo.IDnu)==14) return(kNuMuCC);
00118 if(TMath::Abs(event->MCInfo.IDnu)==12) return(kNuECC);
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
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
00176 for (i=0; i<4; i++) {
00177 if(fabs(CosL[i]) < 1.e-6) continue;
00178 Wall = CosL[i] > 0.0 ? 4.0 : -4.0;
00179 int j = i<2 ? i+2 : i-2;
00180
00181
00182
00183
00184 OProj = VtxL[j] + (CosL[j]/CosL[i])*(Wall-VtxL[i]);
00185 if(fabs(OProj) > HalfSideL) continue;
00186
00187
00188 ZProj = VtxZ + (CosZ/CosL[i])*(Wall-VtxL[i]);
00189 break;
00190 }
00191
00192
00193
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
00198 if(CosZ<0.0 && VtxSM==1) {
00199 DetVtx[2] = SM1EdgesZ[0];
00200 Side = 8;
00201 }
00202
00203 else if(CosZ>0.0 && VtxSM==1) {
00204 DetVtx[2] = SM1EdgesZ[1];
00205 Side = 9;
00206 }
00207
00208 else if(CosZ<0.0 && VtxSM==2) {
00209 DetVtx[2] = SM2EdgesZ[0];
00210 Side = 10;
00211 }
00212
00213 else if(CosZ>0.0 && VtxSM==2) {
00214 DetVtx[2] = SM2EdgesZ[1];
00215 Side = 11;
00216 }
00217
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
00230 case 0:
00231 DetVtx[0] = C45 * (OProj - Wall);
00232 DetVtx[1] = C45 * (OProj + Wall);
00233 break;
00234
00235 case 1:
00236 DetVtx[1] = Wall;
00237 DetVtx[0] = OProj;
00238 break;
00239
00240 case 2:
00241 DetVtx[0] = C45 * (Wall - OProj);
00242 DetVtx[1] = C45 * (Wall + OProj);
00243 break;
00244
00245 case 3:
00246 DetVtx[1] = OProj;
00247 DetVtx[0] = Wall;
00248 break;
00249
00250 default:
00251 MSG("UtilMisc", Msg::kError) << "WTF, puking on shoes" << endl;
00252 assert(false);
00253 break;
00254 }
00255 }
00256 return Side;
00257 }