00001
00002
00003 #include "TkrRecon/RecNtupleAlg.h"
00004
00005 #include "geometry/Ray.h"
00006 #include "geometry/Plane.h"
00007 #include "geometry/Intersection.h"
00008 #include "geometry/Point.h"
00009 #include "geometry/Vector.h"
00010
00011 #include <algorithm>
00012 inline static double sqr(double x) {return x*x;}
00013 using namespace std;
00014
00015 static const AlgFactory<RecNtupleAlg> Factory;
00016 const IAlgFactory& RecNtupleAlgFactory = Factory;
00017
00018
00019
00020 RecNtupleAlg::RecNtupleAlg(const std::string& name, ISvcLocator* pSvcLocator) :
00021 Algorithm(name, pSvcLocator)
00022
00023 {
00024 declareProperty("tupleName", m_tupleName="");
00025 }
00026
00027
00028 StatusCode RecNtupleAlg::initialize()
00029
00030 {
00031 StatusCode sc = StatusCode::SUCCESS;
00032
00033 MsgStream log(msgSvc(), name());
00034 log << MSG::INFO << "initialize" << endreq;
00035
00036
00038
00039
00040
00041 sc = serviceLocator()->getService("ntupleWriterSvc",
00042 IID_INTupleWriterSvc, reinterpret_cast<IInterface*&>( ntupleWriteSvc));
00043
00044 if( sc.isFailure() )
00045 {
00046 log << MSG::ERROR << "RecNtupleAlg failed to get the ntupleWriterSvc" << endreq;
00047 return sc;
00048 }
00049
00050
00051 sc = serviceLocator()->getService("TkrGeometrySvc",
00052 IID_ITkrGeometrySvc, reinterpret_cast<IInterface*&>( pGeometry));
00053
00054 if( sc.isFailure() )
00055 {
00056 log << MSG::ERROR << "RecNtupleAlg failed to get the TkrGeometrySvc" << endreq;
00057 return sc;
00058 }
00059
00060 return sc;
00061 }
00062
00063
00064
00065
00066 StatusCode RecNtupleAlg::execute()
00067
00068 {
00070 StatusCode sc = StatusCode::SUCCESS;
00071
00072
00073 RecTupleValues nTuple;
00074
00075
00076 ICsIClusterList* pCalClusters = SmartDataPtr<ICsIClusterList>(eventSvc(),"/Event/CalRecon/CsIClusterList");
00077 SiClusters* pSiClusters = SmartDataPtr<SiClusters>(eventSvc(),"/Event/TkrRecon/SiClusters");
00078 SiRecObjs* pSiRecObjs = SmartDataPtr<SiRecObjs>(eventSvc(),"/Event/TkrRecon/SiRecObjs");
00079
00080 if ((sc = nTuple.calcTupleValues(pCalClusters, pSiClusters, pSiRecObjs, pGeometry)).isFailure()) return sc;
00081
00082 return nTuple.fillTupleValues(ntupleWriteSvc, m_tupleName.c_str());
00083 }
00084
00085 StatusCode RecNtupleAlg::finalize()
00086
00087 {
00088 StatusCode sc = StatusCode::SUCCESS;
00089
00090 return sc;
00091 }
00092
00093
00094
00095
00096
00097
00098 RecTupleValues::RecTupleValues()
00099
00100 {
00101
00102 Rec_Tkr_SkirtX = -9999.;
00103 Rec_Tkr_SkirtY = -9999.;
00104
00105
00106 Rec_Conv_Twr_Dist = 0;
00107 Rec_Fit_xV = 0;
00108 Rec_Fit_yV = 0;
00109
00110 Rec_Active_Dist = 0;
00111
00112 Rec_fst_Hit_Count = 0;
00113 Rec_Surplus_Hit_Ratio = 0;
00114 Rec_Outside_Hit_Ratio = 0;
00115 Rec_showerHits1 = 0;
00116 Rec_showerHits2 = 0;
00117 Rec_Sum_Hits = 0;
00118
00119 Rec_CsI_Energy = 0.3;
00120 Rec_CsI_Corr_Energy = 0;
00121 };
00122
00123
00124 StatusCode RecTupleValues::calcTupleValues(ICsIClusterList* pCalClusters, SiClusters* pSiClusters, SiRecObjs* pRecObjs, ITkrGeometrySvc* pGeom)
00125
00126 {
00127 StatusCode sc = StatusCode::SUCCESS;
00128
00129
00130 if (pRecObjs)
00131 {
00132 unsigned int ngammas = pRecObjs->numGammas();
00133
00134 if (ngammas == 0) return sc;
00135
00136
00137 if (pCalClusters)
00138 {
00139 ICsICluster* pCalClus = pCalClusters->Cluster(0);
00140 Rec_CsI_Energy = pCalClus->energySum() / 1000;
00141 if (Rec_CsI_Energy < 0.001) Rec_CsI_Energy = 0.3;
00142 }
00143
00144
00145 GFgamma* pGamma = pRecObjs->Gamma(0);
00146
00147
00148 if (pGamma->empty()) return sc;
00149
00150
00151 calcSkirtVars(pGamma);
00152 calcTowerBoundaries(pGamma, pGeom);
00153 calcActiveDistance(pGamma, pGeom);
00154 calcExtraHits(pSiClusters, pGamma, pGeom);
00155
00156
00157 calcEnergyCorrection(pGamma);
00158 }
00159
00160 return sc;
00161 }
00162
00163
00164 StatusCode RecTupleValues::fillTupleValues(INTupleWriterSvc* pSvc, const char* pName)
00165
00166 {
00167 StatusCode sc = StatusCode::SUCCESS;
00168
00169 if (pSvc)
00170 {
00171 if ((sc = pSvc->addItem(pName, "REC_Tkr_SkirtX", Rec_Tkr_SkirtX )).isFailure()) return sc;
00172 if ((sc = pSvc->addItem(pName, "REC_Tkr_SkirtY", Rec_Tkr_SkirtY )).isFailure()) return sc;
00173 if ((sc = pSvc->addItem(pName, "REC_Conv_Twr_Dist", Rec_Conv_Twr_Dist )).isFailure()) return sc;
00174 if ((sc = pSvc->addItem(pName, "REC_Fit_xV", Rec_Fit_xV )).isFailure()) return sc;
00175 if ((sc = pSvc->addItem(pName, "REC_Fit_yV", Rec_Fit_yV )).isFailure()) return sc;
00176 if ((sc = pSvc->addItem(pName, "REC_Active_Dist", Rec_Active_Dist )).isFailure()) return sc;
00177 if ((sc = pSvc->addItem(pName, "REC_fst_Hit_Count", Rec_fst_Hit_Count )).isFailure()) return sc;
00178 if ((sc = pSvc->addItem(pName, "REC_Surplus_Hit_Ratio", Rec_Surplus_Hit_Ratio)).isFailure()) return sc;
00179 if ((sc = pSvc->addItem(pName, "REC_Outside_Hit_Ratio", Rec_Outside_Hit_Ratio)).isFailure()) return sc;
00180 if ((sc = pSvc->addItem(pName, "REC_showerHits1", Rec_showerHits1 )).isFailure()) return sc;
00181 if ((sc = pSvc->addItem(pName, "REC_showerHits2", Rec_showerHits2 )).isFailure()) return sc;
00182 if ((sc = pSvc->addItem(pName, "REC_Sum_Hits", Rec_Sum_Hits )).isFailure()) return sc;
00183 if ((sc = pSvc->addItem(pName, "REC_CsI_Corr_Energy", Rec_CsI_Corr_Energy )).isFailure()) return sc;
00184 }
00185
00186 return sc;
00187 }
00188
00189
00190
00191 void RecTupleValues::calcSkirtVars(GFgamma* pGamma)
00192
00193 {
00194 GFtrack* pBestX = pGamma->getXpair()->getBest();
00195 GFtrack* pBestY = pGamma->getYpair()->getBest();
00196
00197 double lastHitX = 0.;
00198 double lastHitXZ = 0.;
00199 double lastHitY = 0.;
00200 double lastHitYZ = 0.;
00201
00202 double lastSlpX = 1.;
00203 double lastSlpY = 1.;
00204
00205
00206 if (!pBestX->empty())
00207 {
00208 int nHits = pBestX->numDataPoints();
00209 KalHit lastHit = pBestX->kplanelist[nHits-1].getHit(KalHit::FIT);
00210
00211 lastHitX = lastHit.getPar().getPosition();
00212 lastSlpX = lastHit.getPar().getSlope();
00213 lastHitXZ = pBestX->kplanelist[nHits-1].getZPlane();
00214 }
00215
00216
00217 if (!pBestY->empty())
00218 {
00219 int nHits = pBestY->numDataPoints();
00220 KalHit lastHit = pBestY->kplanelist[nHits-1].getHit(KalHit::FIT);
00221
00222 lastHitY = lastHit.getPar().getPosition();
00223 lastSlpY = lastHit.getPar().getSlope();
00224 lastHitYZ = pBestY->kplanelist[nHits-1].getZPlane();
00225 }
00226
00227
00228 Point skirt(0., 0., -14.8751);
00229 Vector normalVec(0., 0., 1.);
00230 Plane p(skirt, normalVec);
00231
00232
00233 Vector dir = Vector(lastSlpX, 0., 1.).unit();
00234 Point lastHit(lastHitX, 0., lastHitXZ);
00235 Ray r(lastHit, dir);
00236 Intersection intersectX(r, p);
00237
00238
00239
00240
00241
00242
00243 double dist = intersectX.distance(100., 1);
00244
00245 if (dist < FLT_MAX)
00246 {
00247 Point pos = r.position(dist);
00248 Rec_Tkr_SkirtX = pos.x();
00249 }
00250
00251
00252 dir = Vector(0., lastSlpY, 1.).unit();
00253 lastHit = Point(0., lastHitY, lastHitYZ);
00254 r = Ray(lastHit, dir);
00255 Intersection intersectY(r, p);
00256
00257
00258
00259
00260
00261
00262 dist = intersectY.distance(100., 1);
00263
00264
00265 if (dist < FLT_MAX)
00266 {
00267 Point pos = r.position(dist);
00268 Rec_Tkr_SkirtY = pos.y();
00269 }
00270
00271 return;
00272 }
00273
00274
00275 void RecTupleValues::calcTowerBoundaries(GFgamma* pGamma, ITkrGeometrySvc* pGeom)
00276
00277 {
00278 Point vertex = pGamma->getFirstHit();
00279 double x_ist = vertex.x();
00280 double y_ist = vertex.y();
00281
00282 double tower_width = pGeom->towerPitch();
00283 double num_2 = pGeom->numXTowers()/2.;
00284
00285 Rec_Fit_xV = fmod((x_ist + tower_width*num_2), tower_width);
00286 Rec_Fit_xV = Rec_Fit_xV - tower_width*.5;
00287 Rec_Fit_yV = fmod((y_ist + tower_width*num_2), tower_width);
00288 Rec_Fit_yV = Rec_Fit_yV - tower_width*.5;
00289
00290 Rec_Fit_xV = fabs(Rec_Fit_xV);
00291 Rec_Fit_yV = fabs(Rec_Fit_yV);
00292
00293 Rec_Conv_Twr_Dist = (Rec_Fit_xV > Rec_Fit_yV) ? Rec_Fit_xV : Rec_Fit_yV;
00294
00295 return;
00296 }
00297
00298
00299
00300 void RecTupleValues::calcActiveDistance(GFgamma* pGamma, ITkrGeometrySvc* pGeom)
00301
00302 {
00303 Rec_Active_Dist = -20.;
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348 return;
00349 }
00350
00351
00352
00353 void RecTupleValues::calcExtraHits(SiClusters* pSiClusters, GFgamma* pGamma, ITkrGeometrySvc* pGeom)
00354
00355 {
00356
00357 double norma = 1.;
00358
00359
00360 double CsICorrEnergy = Rec_CsI_Energy;
00361
00362
00363 Point x0 = pGamma->vertex();
00364 Vector t0 = pGamma->direction();
00365
00366 Point x1 = GFdata::doVertex(pGamma->getBest(SiCluster::X)->ray(),
00367 pGamma->getBest(SiCluster::Y)->ray());
00368 Vector t1 = GFdata::doDirection(pGamma->getBest(SiCluster::X)->direction(),
00369 pGamma->getBest(SiCluster::Y)->direction());
00370
00371
00372 int firstLayer = pGamma->firstLayer();
00373 Point firstHit = pGamma->vertex();
00374
00375 int diffXY = pGamma->getXpair()->firstLayer()-pGamma->getYpair()->firstLayer();
00376 double dz = pGamma->getBest(SiCluster::X)->vertex().z()
00377 - pGamma->getBest(SiCluster::Y)->vertex().z();
00378
00379 double hitRadFact = fabs(t0.z()) + sqrt(1. - t0.z()*t0.z())/fabs(t0.z());
00380
00381 if(hitRadFact > 3.) hitRadFact = 3.;
00382
00383 int ipln = pGeom->numPlanes() - firstLayer;
00384 double radLenEff = (pGeom->pbRadLen(max(0,ipln-1)) + 2.*pGeom->siThickness()/9.36 +.003)/fabs(t1.z());
00385 double thetaCone = .014/(CsICorrEnergy/2.)*sqrt(radLenEff)*(1.+.038*log(radLenEff));
00386 double minSprd = 5.* thetaCone * pGeom->trayHeight();
00387 double dltSprd = minSprd;
00388 double norm = sqrt(t0.x()*t0.x() + t0.y()*t0.y());
00389 double xFact = 1.,
00390 yFact = 1.;
00391
00392 if(norm > 10000.*FLT_MIN) {
00393 xFact = 1. + (hitRadFact - 1.)*fabs(t0.x())/norm;
00394 yFact = 1. + (hitRadFact - 1.)*fabs(t0.y())/norm;
00395 }
00396
00397 double dltX = dltSprd*xFact;
00398 double dltY = dltSprd*yFact;
00399
00400
00401 Rec_fst_Hit_Count = pSiClusters->numberOfHitsNear(firstLayer, dltX, dltY, firstHit);
00402
00403
00404 if(Rec_fst_Hit_Count == 3 && diffXY == 0) {
00405 SiCluster::view far_axis = SiCluster::X;
00406 double dR = dltX;
00407 if (dz>0) {
00408 far_axis = SiCluster::Y;
00409 dR = dltY;
00410 }
00411 int ihit_second = pSiClusters->numberOfHitsNear(far_axis, firstLayer, dltX, firstHit);
00412 if (ihit_second == 2) Rec_fst_Hit_Count -=.5;
00413 }
00414 if(Rec_fst_Hit_Count == 1 && diffXY == 0) {
00415 SiCluster::view far_axis = SiCluster::X;
00416 double dR = dltX;
00417 if (dz>0) {
00418 far_axis = SiCluster::Y;
00419 dR = dltY;
00420 }
00421 int ihit_second = pSiClusters->numberOfHitsNear(far_axis, firstLayer, dltX, firstHit);
00422 if (ihit_second == 1) Rec_fst_Hit_Count -=.5;
00423 }
00424
00425
00426 double deltaS = pGeom->trayHeight()/fabs(t0.z());
00427 double disp = deltaS;
00428 int lastLayer = (int)(4+2.*log(CsICorrEnergy/.01) + firstLayer);
00429 if(lastLayer > pGeom->numPlanes()) lastLayer = pGeom->numPlanes();
00430
00431 Rec_Sum_Hits = pSiClusters->numberOfHitsNear(firstLayer, .5*dltX, .5*dltY, firstHit);
00432
00433 Rec_showerHits1 = Rec_Sum_Hits;
00434 Rec_showerHits2 = 0;
00435
00436 if(firstLayer > 11) {
00437 Rec_showerHits1 = 0;
00438 Rec_showerHits2 = Rec_Sum_Hits;
00439 }
00440
00441 if(Rec_Sum_Hits < 2.) Rec_Sum_Hits = 2.;
00442 if(lastLayer - firstLayer < 5 && lastLayer == pGeom->numPlanes()) Rec_Sum_Hits +=.5;
00443 double outHits = 0;
00444
00445 xFact *= sqrt(t0.z() *t0.z() + t0.x()*t0.x());
00446 yFact *= sqrt(t0.z() *t0.z() + t0.y()*t0.y());
00447
00448 int i;
00449 for(i=firstLayer+1; i<pGeom->numPlanes(); i++) {
00450 ipln = pGeom->numPlanes() - i;
00451 radLenEff = (pGeom->pbRadLen(max(0,ipln-1)) + 2.*pGeom->siThickness()/9.36 +.003)/fabs(t1.z());
00452 double thetaMS = .014/(CsICorrEnergy/2.)*sqrt(radLenEff)*(1.+.038*log(radLenEff));
00453 double s_total = (i-firstLayer) * deltaS;
00454 double xSprd = thetaMS * s_total * xFact * 2.021;
00455 double ySprd = thetaMS * s_total * yFact * 2.021;
00456 Point trkHit((Point)(disp*t0 + x0));
00457 if (xSprd > 50) xSprd = 50.;
00458 if (ySprd > 50) ySprd = 50.;
00459 double nearHits = pSiClusters->numberOfHitsNear(i, xSprd, ySprd, trkHit);
00460
00461 if(i< 12) Rec_showerHits1 += nearHits;
00462 else Rec_showerHits2 += nearHits;
00463
00464 if( i < lastLayer) {
00465 Rec_Sum_Hits += nearHits;
00466 outHits += pSiClusters->numberOfHitsNear(i, 50., 50., trkHit) - nearHits;
00467 }
00468 disp += deltaS;
00469 }
00470
00471 norma = lastLayer - firstLayer;
00472
00473 Rec_Surplus_Hit_Ratio = Rec_Sum_Hits / norma;
00474 Rec_Outside_Hit_Ratio = outHits / norma;
00475
00476 return;
00477 }
00478
00479
00480
00481 void RecTupleValues::calcEnergyCorrection(GFgamma* pGamma)
00482
00483 {
00484 Rec_CsI_Corr_Energy = Rec_CsI_Energy;
00485
00486 if (Rec_Conv_Twr_Dist > 0)
00487 {
00488 GFtrack* _Xbest = pGamma->getXpair()->getBest();
00489 GFtrack* _Ybest = pGamma->getYpair()->getBest();
00490 Vector t0 = pGamma->direction();
00491
00492
00493 double hit_energy = 0.0003*Rec_showerHits1 + .0013*Rec_showerHits2;
00494 double num_Layers_Crossed = _Xbest->numDataPoints()+ _Xbest->numGaps();
00495
00496 if(_Xbest->numDataPoints() < _Ybest->numDataPoints())
00497 num_Layers_Crossed = _Ybest->numDataPoints()+ _Ybest->numGaps();
00498
00499 double x_ing_energy = .0016*num_Layers_Crossed;
00500 double edg_corr = (Rec_Conv_Twr_Dist < 10.) ? 1 : .68 + (.069 - .0036* Rec_Conv_Twr_Dist )*Rec_Conv_Twr_Dist;
00501 double trk_energy = hit_energy + x_ing_energy;
00502
00503 trk_energy /= (fabs(t0.z()) > .2) ? fabs(t0.z()) : .2;
00504 Rec_CsI_Corr_Energy = (Rec_CsI_Energy + trk_energy)/edg_corr;
00505 }
00506
00507 return;
00508 }
00509
00510
00511