7 #include <EVENT/LCCollection.h>
8 #include <EVENT/MCParticle.h>
9 #include <EVENT/ReconstructedParticle.h>
11 #include <EVENT/SimCalorimeterHit.h>
13 #include "CalorimeterHitType.h"
15 #include "IMPL/CalorimeterHitImpl.h"
17 #include <UTIL/LCRelationNavigator.h>
23 #include "TLorentzVector.h"
25 #include <marlin/Global.h>
27 #include <gear/GEAR.h>
28 #include <gear/GearParameters.h>
29 #include <gear/BField.h>
30 #include <gear/CalorimeterParameters.h>
31 #include <gear/TPCParameters.h>
32 #include <gear/PadRowLayout2D.h>
33 #include <gear/LayerLayout.h>
35 #include <UTIL/CellIDDecoder.h>
38 #include "marlin/VerbosityLevels.h"
41 #include <sys/types.h>
43 using namespace lcio ;
44 using namespace marlin ;
51 _description =
"hybridRecoProcessor does whatever it does ..." ;
53 std::vector <std::string> ecalCollectionsCells;
54 ecalCollectionsCells.push_back(std::string(
"ECALSiBarrel"));
55 registerInputCollections( LCIO::CALORIMETERHIT,
56 "ECALcollections_cells",
57 "Name of the ECAL cell collections",
59 ecalCollectionsCells);
61 std::vector <std::string> ecalCollectionsTranStrips;
62 ecalCollectionsTranStrips.push_back(std::string(
"ECALScTransverseBarrel"));
63 registerInputCollections( LCIO::CALORIMETERHIT,
64 "ECALcollections_tranStrips",
65 "Name of the ECAL transverse strip collections",
67 ecalCollectionsTranStrips);
69 std::vector <std::string> ecalCollectionsLongStrips;
70 ecalCollectionsLongStrips.push_back(std::string(
"ECALScLongitudinalBarrel"));
71 registerInputCollections( LCIO::CALORIMETERHIT,
72 "ECALcollections_longStrips",
73 "Name of the ECAL longitudinal strip collections",
75 ecalCollectionsLongStrips);
78 registerProcessorParameter(
"virtualCellsDefault",
79 "number of virtual cells per strip (used if info not found in gear file)",
83 registerProcessorParameter(
"saveIntersectionCollection",
84 "save collection with strip interactions?",
88 registerProcessorParameter(
"saveCheckRootHistograms",
89 "save root file with debugging histograms?",
107 _fout =
new TFile(
"hybridCheckHistos.root",
"recreate");
108 h_phiModuleCheck =
new TH2F(
"phi_HitModule",
"phi_HitModule", 20, -4, 16, 100, -2*TMath::Pi(), 2*TMath::Pi());
110 h_phiThetaMC =
new TH2F(
"MCphiTheta",
"MCphiTheta", 100, -2*TMath::Pi(), 2*TMath::Pi(), 100, -2*TMath::Pi(), 2*TMath::Pi());
115 for (
int i=0; i<2; i++) {
116 TString reg = i==0 ?
"_barrel" :
"_endcap" ;
117 h_stavemodule[i] =
new TH2F(
"stavemodule"+reg,
"stavemodule"+reg,35, 0, 35, 35,0,35);;
118 h_layer[i] =
new TH1F(
"layer"+reg,
"layer"+reg, 35,0,35);;
120 h_staveX[i] =
new TH2F(
"staveX_"+reg,
"staveX_"+reg, 100,-2000,2000,10,0,10);
121 h_staveY[i] =
new TH2F(
"staveY_"+reg,
"staveY_"+reg, 100,-2000,2000,10,0,10);
122 h_staveZ[i] =
new TH2F(
"staveZ_"+reg,
"staveZ_"+reg, 100,-5000,5000,10,0,10);
123 h_moduleX[i] =
new TH2F(
"moduleX_"+reg,
"moduleX_"+reg, 100,-2000,2000,10,0,10);
124 h_moduleY[i] =
new TH2F(
"moduleY_"+reg,
"moduleY_"+reg, 100,-2000,2000,10,0,10);
125 h_moduleZ[i] =
new TH2F(
"moduleZ_"+reg,
"moduleZ_"+reg, 100,-5000,5000,10,0,10);
128 for (
int ieb=0; ieb<2; ieb++) {
129 for (
int is=0; is<10; is++) {
130 for (
int im=0; im<10; im++) {
131 TString name = ieb==0 ?
"barrel" :
"endcap";
132 name+=
"_stave"; name+=is;
133 name+=
"_module"; name+=im;
134 h_cth_phi[ieb][is][im] =
new TH2F(name+
"_angle",name+
"_angle",100,-1,1,100,-TMath::Pi(), TMath::Pi());
135 h_XY[ieb][is][im] =
new TH2F(name+
"_xy",name+
"_xy",100,-3000,3000,100,-3000,3000);
152 streamlog_out ( DEBUG )<<
"hello from hybridRecoProcessor::setupGeometry" << endl;
154 const gear::CalorimeterParameters& pEcalBarrel = Global::GEAR->getEcalBarrelParameters();
155 const gear::LayerLayout& ecalBarrelLayout = pEcalBarrel.getLayerLayout();
156 const gear::GearParameters& pMokka = Global::GEAR->getGearParameters(
"MokkaParameters");
163 int nMokkaVirtualCells = 1;
166 nMokkaVirtualCells = pEcalBarrel.getIntVal(
"Ecal_Sc_number_of_virtual_cells");
167 streamlog_out (MESSAGE) <<
"taking number of Mokka virtual cells from calo section of gear file: " << nMokkaVirtualCells << endl;
168 }
catch(gear::UnknownParameterException &e1) {
171 std::string nVirtualMokkaS = pMokka.getStringVal(
"Ecal_Sc_number_of_virtual_cells");
172 std::stringstream convert(nVirtualMokkaS);
173 if ( !(convert >> nMokkaVirtualCells) ) {
174 streamlog_out (ERROR) <<
"could not decipher number of Mokka virtual cells! " << nVirtualMokkaS << endl;
177 streamlog_out (MESSAGE) <<
"taking number of Mokka virtual cells from Mokka section of gear file: " << nVirtualMokkaS <<
" " << nMokkaVirtualCells << endl;
178 }
catch(gear::UnknownParameterException &e2) {
181 streamlog_out (WARNING) <<
"taking number of Mokka virtual cells from steering file (not found in gear file): " << nMokkaVirtualCells << endl;
188 for(
int i=0; i<ecalBarrelLayout.getNLayers(); i++){
189 float size0 = ecalBarrelLayout.getCellSize0(i);
190 float size1 = ecalBarrelLayout.getCellSize1(i);
195 if (i%2==0) size1*=nMokkaVirtualCells;
196 else size0*=nMokkaVirtualCells;
198 streamlog_out ( DEBUG ) <<
"layer " << i <<
" " << size0 <<
" " << size1 <<
" " << min(size0, size1)/max(size0, size1) << endl;
211 _symmetry = pEcalBarrel.getSymmetryOrder();
232 LCCollection * col = evt->getCollection(
"MCParticle");
233 if (col->getNumberOfElements()>0) {
234 MCParticle * mcp =
dynamic_cast<MCParticle*
>(col->getElementAt(0) );
235 TVector3 mom(mcp->getMomentum()[0], mcp->getMomentum()[1], mcp->getMomentum()[2]);
241 catch(DataNotAvailableException &
e) {};
245 streamlog_out ( WARNING ) <<
" -- not a long enough strip, not worth splitting -- length, width, aspect ratio: " <<
250 std::pair < TVector3, TVector3 > stripEnds;
251 std::vector <std::string> * toSplit;
252 std::vector <std::string> * stripSplitter;
255 std::map < IMPL::LCCollectionVec*, std::string > outputcolls;
268 for (
int icol=0; icol<2; icol++) {
281 streamlog_out ( ERROR ) <<
"ERROR crazy stuff!!! abandoning event..." << endl;
285 for (uint i=0; i<toSplit->size(); i++) {
287 LCCollection * col = evt->getCollection( toSplit->at(i).c_str() );
290 const std::string layerCodingString(col->getParameters().getStringVal(LCIO::CellIDEncoding));
293 TString name = toSplit->at(i);
295 if (name.Contains(
"Barrel") || name.Contains(
"barrel")) {
297 }
else if (name.Contains(
"Endcap") || name.Contains(
"endcap")) {
300 streamlog_out ( ERROR ) <<
"WARNING: cannot tell if collection is for barrel or endcap..." << name << endl;
305 splitStripHits->setFlag(splitStripHits->getFlag()|( 1 << LCIO::RCHBIT_LONG));
306 splitStripHits->parameters().setValue(LCIO::CellIDEncoding, layerCodingString);
309 unSplitStripHits->setSubset();
310 unSplitStripHits->parameters().setValue(LCIO::CellIDEncoding, layerCodingString);
313 CellIDDecoder<CalorimeterHit> id( col ) ;
317 int nelem = col->getNumberOfElements();
318 for (
int j=0; j < nelem; ++j) {
319 CalorimeterHit * hit =
dynamic_cast<CalorimeterHit*
>(col->getElementAt(j) );
321 streamlog_out ( ERROR ) <<
"ERROR null hit in collection " << toSplit->at(i).c_str() <<
" " << j << endl;
325 std::vector <CalorimeterHit*> splitHits =
getVirtualHits(evt, hit, orientation, barrel);
328 if (splitHits.size()==0) {
329 unSplitStripHits->addElement(hit);
331 for (uint hh=0; hh<splitHits.size(); hh++) {
332 splitStripHits->addElement(splitHits[hh]);
338 if (splitStripHits->getNumberOfElements()>0)
339 outputcolls[splitStripHits] = toSplit->at(i) +
"Split";
340 if (unSplitStripHits->getNumberOfElements()>0)
341 outputcolls[unSplitStripHits] = toSplit->at(i) +
"UnSplit";
343 }
catch(DataNotAvailableException &
e) {};
347 std::map < IMPL::LCCollectionVec*, std::string >::iterator ii;
350 for (ii=outputcolls.begin(); ii!=outputcolls.end(); ii++) {
351 evt->addCollection(ii->first, ii->second);
370 int layer = (*_decoder)(hit)[
"K-1"];
371 int module = (*_decoder)(hit)[
"M"];
372 int stave = (*_decoder)(hit)[
"S-1"];
375 pp.SetXYZ( hit->getPosition()[0], hit->getPosition()[1], hit->getPosition()[2]);
381 h_staveX[ieb] ->Fill(hit->getPosition()[0], stave);
382 h_staveY[ieb] ->Fill(hit->getPosition()[1], stave);
383 h_staveZ[ieb] ->Fill(hit->getPosition()[2], stave);
384 h_moduleX[ieb]->Fill(hit->getPosition()[0], module);
385 h_moduleY[ieb]->Fill(hit->getPosition()[1], module);
386 h_moduleZ[ieb]->Fill(hit->getPosition()[2], module);
388 h_cth_phi[ieb][stave][module]->Fill(pp.CosTheta(), pp.Phi());
389 h_XY[ieb][stave][module]->Fill(pp.X(), pp.Y());
392 std::vector <CalorimeterHit*> newhits;
395 std::pair < TVector3, TVector3 > stripEnds =
getStripEnds(hit, orientation, barrel);
396 TVector3 stripDir = stripEnds.first - stripEnds.second;
402 pp[0] = stripEnds.first.X();
403 pp[1] = stripEnds.first.Y();
404 pp[2] = stripEnds.first.Z();
405 CalorimeterHitImpl* interhit =
new CalorimeterHitImpl();
406 interhit->setPosition( pp );
407 interhit->setEnergy(0.03);
412 pp[0] = stripEnds.second.X();
413 pp[1] = stripEnds.second.Y();
414 pp[2] = stripEnds.second.Z();
415 interhit =
new CalorimeterHitImpl();
416 interhit->setPosition( pp );
417 interhit->setEnergy(0.03);
424 int splitterOrientation;
425 std::vector <std::string> * splitterCols;
433 streamlog_out ( DEBUG ) <<
"no need to split this orientation";
437 std::map <int, float> virtEnergy;
441 for (
int jj=0; jj<2; jj++) {
445 for (uint i=0; i<splitter->size(); i++) {
447 LCCollection * col = evt->getCollection( splitter->at(i).c_str() );
450 CellIDDecoder<CalorimeterHit> id( col ) ;
453 int nelem = col->getNumberOfElements();
455 for (
int j=0; j < nelem; ++j) {
456 CalorimeterHit * hit2 =
dynamic_cast<CalorimeterHit*
>(col->getElementAt(j) );
458 streamlog_out ( ERROR ) <<
"ERROR null hit2 in collection " << splitter->at(i).c_str() <<
" " << j << endl;
462 int layer2 = (*_decoder)(hit2)[
"K-1"];
463 int module2 = (*_decoder)(hit2)[
"M"];
464 int stave2 = (*_decoder)(hit2)[
"S-1"];
466 int dlayer = abs(layer2-layer);
467 int dstave = abs(stave2-stave);
468 int dmodule = abs(module2-module);
473 if (dmodule==0 && dstave==0 && dlayer>1)
continue;
477 if ( dstave==0 && dmodule>1 )
continue;
478 if ( dmodule==0 && dstave>1 )
continue;
479 if ( dstave==0 && dlayer>1)
continue;
481 dstave = min( dstave, 4-dstave);
482 if (dmodule!=0)
continue;
483 if (dstave>1)
continue;
484 if (dlayer>1)
continue;
488 float dist = sqrt( pow(hit2->getPosition()[0] - hit->getPosition()[0], 2) +
489 pow(hit2->getPosition()[1] - hit->getPosition()[1], 2) +
490 pow(hit2->getPosition()[2] - hit->getPosition()[2], 2) );
495 TVector3 stripDir2(0,0,0);
497 std::pair < TVector3, TVector3 > stripEnds2 =
getStripEnds(hit2, splitterOrientation, barrel);
498 stripDir2 = stripEnds2.first - stripEnds2.second;
502 TVector3 intercept =
stripIntersect(hit, stripDir, hit2, stripDir2);
507 if (intercept.Mag()>0) {
510 for (
int i=0; i<3; i++) {
511 float dx = stripEnds.second[i] - stripEnds.first[i];
513 frac = (intercept[i]-stripEnds.first[i])/dx;
518 if (frac>=0.0 && frac<=1.0) {
520 if (segment>=0 && segment<_nVirtual) {
521 if (virtEnergy.find(segment)!=virtEnergy.end()) {
522 virtEnergy[segment] += hit2->getEnergy();
524 virtEnergy[segment] = hit2->getEnergy();
528 CalorimeterHitImpl* interhit =
new CalorimeterHitImpl();
530 pos[0] = intercept.X();
531 pos[1] = intercept.Y();
532 pos[2] = intercept.Z();
533 interhit->setPosition( pos );
534 interhit->setEnergy(0.1);
539 streamlog_out ( WARNING ) <<
"strange segment " << segment <<
" frac = " << frac <<
" nvirt = " << _nVirtual << endl;
542 streamlog_out ( WARNING ) <<
"strange frac " << frac << endl;
547 }
catch(DataNotAvailableException &
e) {};
553 std::map <int, float>::iterator it;
555 for (it=virtEnergy.begin(); it!=virtEnergy.end(); it++) {
556 totenergy+=it->second;
558 for (it=virtEnergy.begin(); it!=virtEnergy.end(); it++) {
560 float energy = hit->getEnergy()*it->second/totenergy;
562 TVector3 virtualCentre = stripEnds.second-stripEnds.first;
563 virtualCentre*= (it->first + 0.5)/
_nVirtual;
564 virtualCentre += stripEnds.first;
566 CalorimeterHitImpl* newhit =
new CalorimeterHitImpl();
569 pos[0] = virtualCentre.X();
570 pos[1] = virtualCentre.Y();
571 pos[2] = virtualCentre.Z();
573 newhit->setType(hit->getType());
574 newhit->setPosition( pos );
575 newhit->setEnergy(energy);
577 newhit->setCellID0(hit->getCellID0());
578 newhit->setCellID1(hit->getCellID1());
580 newhits.push_back(newhit);
591 TVector3 stripcentre(hit->getPosition()[0], hit->getPosition()[1], hit->getPosition()[2]);
592 TVector3 stripend1(stripcentre);
593 TVector3 stripend2(stripcentre);
595 int stave = (*_decoder)(hit)[
"S-1"];
605 float phiRotAngle = stave*2.*TMath::Pi()/
_symmetry;
607 stripHalfVec.RotateZ(phiRotAngle);
608 stripend1-=stripHalfVec;
609 stripend2+=stripHalfVec;
613 bool horizontalSlab = stave%2==1;
615 bool horizontalStrip(
true);
616 if (horizontalSlab) {
618 else if (orientation ==
TRANSVERSE) horizontalStrip=
false;
621 else if (orientation ==
TRANSVERSE) horizontalStrip=
true;
624 if (horizontalStrip) {
634 std::pair < TVector3, TVector3 > output (stripend1, stripend2);
645 streamlog_out ( MESSAGE ) <<
"hybridRecoProcessor::end() " << name() << std::endl ;
660 TVector3 stripCentre[2];
661 stripCentre[0].SetXYZ( hit0->getPosition()[0], hit0->getPosition()[1], hit0->getPosition()[2] );
662 stripCentre[1].SetXYZ( hit1->getPosition()[0], hit1->getPosition()[1], hit1->getPosition()[2] );
666 TVector3 stripDir[2];
673 for (
int i=0; i<2; i++) {
674 if (stripDir[i].Mag()>1
e-10) {
678 stripDir[i] = stripDir[1-i].Cross(stripCentre[i]);
681 stripDir[i]*=1./stripDir[i].Mag();
684 if (!isStrip[0]) streamlog_out ( ERROR ) <<
"ERROR from hybridRecoProcessor::stripIntersect, first hit should be a strip" << endl;
687 for (
int j=0; j<2; j++) {
688 for (
int i=0; i<2; i++) {
690 p[j][i] = stripCentre[j]-TMath::Power(-1, i)*0.5*ll*stripDir[j];
694 TVector3 pNorm[2][2];
695 for (
int j=0; j<2; j++) {
696 for (
int i=0; i<2; i++) {
697 float mm = p[j][i].Mag();
705 for (
int j=0; j<2; j++) {
706 inPlane[j]=p[j][0]-p[j][1];
710 TVector3 normal = inPlane[0].Cross(inPlane[1]);
711 float mag = normal.Mag();
715 TVector3 point(p[0][0]+p[0][1]); point*=0.5;
720 for (
int i=0; i<2; i++) {
721 float d = ((point - p[1][i]).Dot(normal))/(pNorm[1][i].Dot(normal));
722 qPrime[i] = p[1][i] + d*pNorm[1][i];
726 TVector3 a(p[0][1]-p[0][0]);
727 TVector3 b(qPrime[1]-qPrime[0]);
728 TVector3 c(qPrime[0]-p[0][0]);
730 float factor = (c.Cross(b)).Dot(a.Cross(b))/((a.Cross(b)).Mag2());
732 TVector3 x = p[0][0] + a*factor;
735 bool intersect =
true;
736 for (
int ii=0; ii<2; ii++) {
737 for (
int j=0; j<3; j++) {
738 float d0 = ii==0 ? x[j]-p[0][0][j] : x[j]-qPrime[0][j];
739 float d1 = ii==0 ? x[j]-p[0][1][j] : x[j]-qPrime[1][j];
746 if (intersect)
return x;
747 else return TVector3(0,0,0);
CellIDDecoder< CalorimeterHit > * _decoder2
IMPL::LCCollectionVec * stripEndsLongCol
std::vector< std::string > _ecalCollectionsTranStrips
virtual void setupGeometry()
std::vector< std::string > _ecalCollectionsCells
Input collection name.
TH2F * h_cth_phi[2][10][10]
hybridRecoProcessor ahybridRecoProcessor
virtual void init()
Called at the begin of the job before anything is read.
std::pair< TVector3, TVector3 > getStripEnds(CalorimeterHit *hit, int orientation, bool barrel)
TVector3 stripIntersect(CalorimeterHit *hit0, TVector3 axis0, CalorimeterHit *hit1, TVector3 axis1)
virtual void processRunHeader(LCRunHeader *run)
Called for every run.
std::vector< CalorimeterHit * > getVirtualHits(LCEvent *evt, CalorimeterHit *hit, int orientation, bool barrel)
std::vector< std::string > _ecalCollectionsLongStrips
std::vector< LCCollection * > LCCollectionVec
CellIDDecoder< CalorimeterHit > * _decoder
virtual void end()
Called after data processing for clean up.
int _ecalStrip_default_nVirt
IMPL::LCCollectionVec * intersectionHits
TH1F * h_stripDist_intercept
IMPL::LCCollectionVec * stripEndsTransCol
TH1F * h_stripDist_nointercept
virtual void check(LCEvent *evt)
virtual void processEvent(LCEvent *evt)
Called for every event - the working horse.