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"
16 #include <IMPL/LCRelationImpl.h>
18 #include <UTIL/LCRelationNavigator.h>
20 #include <marlin/Global.h>
21 #include <marlin/Exceptions.h>
23 #include "DD4hep/DetectorSelector.h"
24 #include "DD4hep/DetType.h"
25 #include "DD4hep/Detector.h"
27 #include <UTIL/CellIDDecoder.h>
30 #include "marlin/VerbosityLevels.h"
33 #include <sys/types.h>
35 #include "streamlog/streamlog.h"
37 #define RELATIONFROMTYPESTR "FromType"
38 #define RELATIONTOTYPESTR "ToType"
41 using namespace lcio ;
42 using namespace marlin ;
49 _description =
"DDStripSplitter applies SSA to a strip-based calorimeter ..." ;
51 registerInputCollection( LCIO::CALORIMETERHIT,
52 "ECALcollection_evenLayers",
53 "Name of the ECAL collection in even layers",
55 std::string(
"ECalBarrelScEvenCollectionRec") );
57 registerInputCollection( LCIO::CALORIMETERHIT,
58 "ECALcollection_oddLayers",
59 "Name of the ECAL collection in odd layers",
61 std::string(
"ECalBarrelScOddCollectionRec") );
63 registerInputCollection( LCIO::LCRELATION,
64 "LCRelations_evenLayers",
65 "name of the relation collection for even layer hits",
67 std::string(
"ECalBarrelScHitsEvenRecRelations") );
69 registerInputCollection( LCIO::LCRELATION,
70 "LCRelations_oddLayers",
71 "name of the relation collection for odd layer hits",
73 std::string(
"ECalBarrelScHitsOddRecRelations") );
75 registerInputCollection( LCIO::MCPARTICLE,
76 "MCParticleCollection",
77 "name of MCParticle collection (used for some plots)",
79 std::string(
"MCParticle") );
81 registerProcessorParameter(
"splitEcalCollection",
82 "name of output collection containing split hits",
84 std::string(
"ECalBarrelSplitCollection") );
86 registerProcessorParameter(
"unsplitEcalCollection",
87 "name of output collection containing unsplit hits",
89 std::string(
"ECalBarrelUnSplitCollection") );
91 registerProcessorParameter(
"splitEcalRelCol",
92 "name of relation collection for split hits",
94 std::string(
"ECalBarrelSplitRelations") );
96 registerProcessorParameter(
"stripIntersecCollName",
97 "name of (optional) output collection containing strip intersections",
99 std::string(
"stripIntersections") );
101 registerProcessorParameter(
"evenStripEndsCollName",
102 "name of (optional) output collection containing ends of strips in even layers",
104 std::string(
"stripEndsEven") );
106 registerProcessorParameter(
"oddStripEndsCollName",
107 "name of (optional) output collection containing ends of strips in odd layers",
109 std::string(
"stripEndsOdd") );
111 registerProcessorParameter(
"virtualCellsDefault",
112 "number of virtual cells per strip (used if info not found in gear file)",
116 registerProcessorParameter(
"saveIntersectionCollection",
117 "save collection with strip interactions?",
121 registerProcessorParameter(
"isBarrelHits",
122 "are hits in these collections in the barrel (true) or endcap (false) ?",
127 registerProcessorParameter(
"CellIDLayerString" ,
128 "name of the part of the cellID that holds the layer" ,
132 registerProcessorParameter(
"CellIDModuleString" ,
133 "name of the part of the cellID that holds the module" ,
135 std::string(
"module")
137 registerProcessorParameter(
"CellIDStaveString" ,
138 "name of the part of the cellID that holds the stave" ,
167 unsigned int includeFlag(0);
168 unsigned int excludeFlag(0);
171 includeFlag = ( dd4hep::DetType::CALORIMETER | dd4hep::DetType::ELECTROMAGNETIC | dd4hep::DetType::BARREL);
173 includeFlag = ( dd4hep::DetType::CALORIMETER | dd4hep::DetType::ELECTROMAGNETIC | dd4hep::DetType::ENDCAP);
175 excludeFlag = ( dd4hep::DetType::AUXILIARY | dd4hep::DetType::FORWARD );
177 dd4hep::Detector & lcdd = dd4hep::Detector::getInstance();
178 const std::vector< dd4hep::DetElement>& theDetectors = dd4hep::DetectorSelector(lcdd).detectors( includeFlag, excludeFlag ) ;
179 streamlog_out( DEBUG2 ) <<
" getExtension : includeFlag: " << dd4hep::DetType( includeFlag ) <<
" excludeFlag: " << dd4hep::DetType( excludeFlag )
180 <<
" found : " << theDetectors.size() <<
" - first det: " << theDetectors.at(0).name() << std::endl ;
182 if( theDetectors.size() != 1 ){
183 std::stringstream es ;
184 streamlog_out (ERROR) <<
" getExtension: selection is not unique (or empty) includeFlag: " << dd4hep::DetType( includeFlag ) <<
" excludeFlag: " << dd4hep::DetType( excludeFlag )
185 <<
" --- found detectors : " ;
186 for(
unsigned i=0, N= theDetectors.size(); i<N ; ++i ){
187 streamlog_out (ERROR) << theDetectors.at(i).name() <<
", " ;
189 throw marlin::StopProcessingException(
this);
193 _caloGeomData = theDetectors.at(ical).extension<dd4hep::rec::LayeredCalorimeterData>();
195 streamlog_out ( WARNING ) <<
"could not get calorimeter geometry information!" << endl;
196 throw marlin::StopProcessingException(
this);
206 streamlog_out( ERROR ) <<
"doesn't look like a basic strip-based calo?? don't know how to deal with this geometry!" << endl;
207 for (
size_t ilay = 0 ; ilay<
_caloGeomData->layers.size(); ilay++ ) {
208 streamlog_out( MESSAGE ) <<
"strip size in layer " << ilay <<
" : " <<
_caloGeomData->layers[ilay].cellSize0 <<
" " <<
_caloGeomData->layers[ilay].cellSize1 << endl;
210 throw marlin::StopProcessingException(
this);
229 streamlog_out( ERROR ) <<
"this strip is very short: probably not worth using the strip splitter!" << endl;
230 throw marlin::StopProcessingException(
this);
242 streamlog_out ( WARNING ) <<
" -- not a long enough strip, not worth splitting -- length, width, aspect ratio: " <<
247 std::pair < TVector3, TVector3 > stripEnds;
249 std::string toSplitRel;
266 splitStripHits->setFlag(splitStripHits->getFlag()|( 1 << LCIO::RCHBIT_LONG));
268 unSplitStripHits->setSubset();
271 splitRelCol->setFlag(
_flag_rel.getFlag());
273 splitRelCol->parameters().setValue(
RELATIONTOTYPESTR , LCIO::SIMCALORIMETERHIT ) ;
275 for (
int icol=0; icol<2; icol++) {
283 streamlog_out( ERROR) <<
"strip orientation undefined!!" << endl;
284 throw marlin::StopProcessingException(
this);
295 streamlog_out( ERROR ) <<
"strip orientation undefined!!" << endl;
296 throw marlin::StopProcessingException(
this);
302 streamlog_out ( ERROR ) <<
"crazy stuff!!! abandoning event..." << endl;
303 throw marlin::StopProcessingException(
this);
308 LCCollection * col = evt->getCollection( toSplit.c_str() );
311 LCCollection * colrel = evt->getCollection( toSplitRel.c_str() );
312 if (!colrel)
continue;
313 LCRelationNavigator navi(colrel);
315 const std::string layerCodingString(col->getParameters().getStringVal(LCIO::CellIDEncoding));
317 splitStripHits->parameters().setValue(LCIO::CellIDEncoding, layerCodingString);
318 unSplitStripHits->parameters().setValue(LCIO::CellIDEncoding, layerCodingString);
321 CellIDDecoder<CalorimeterHit> id( col ) ;
325 int nelem = col->getNumberOfElements();
326 for (
int j=0; j < nelem; ++j) {
327 CalorimeterHit * hit =
dynamic_cast<CalorimeterHit*
>(col->getElementAt(j) );
329 streamlog_out ( ERROR ) <<
"ERROR null hit in collection " << toSplit.c_str() <<
" " << j << endl;
330 throw marlin::StopProcessingException(
this);
337 SimCalorimeterHit* simhit = (SimCalorimeterHit*) navi.getRelatedToObjects(hit)[0];
340 if (splitHits.size()==0) {
341 unSplitStripHits->addElement(hit);
342 splitRelCol->addElement(
new LCRelationImpl(hit,simhit,1.0) );
344 for (uint hh=0; hh<splitHits.size(); hh++) {
345 splitStripHits->addElement(splitHits[hh]);
347 splitRelCol->addElement(
new LCRelationImpl(splitHits[hh],simhit,weight) );
351 }
catch(DataNotAvailableException &
e) {};
378 pp.SetXYZ( hit->getPosition()[0], hit->getPosition()[1], hit->getPosition()[2]);
380 std::vector <CalorimeterHit*> newhits;
383 std::pair < TVector3, TVector3 > stripEnds =
getStripEnds(hit, orientation, barrel);
384 TVector3 stripDir = stripEnds.first - stripEnds.second;
390 ppp[0] = stripEnds.first.X();
391 ppp[1] = stripEnds.first.Y();
392 ppp[2] = stripEnds.first.Z();
393 CalorimeterHitImpl* interhit =
new CalorimeterHitImpl();
394 interhit->setPosition( ppp );
395 interhit->setEnergy(0.03);
400 ppp[0] = stripEnds.second.X();
401 ppp[1] = stripEnds.second.Y();
402 ppp[2] = stripEnds.second.Z();
403 interhit =
new CalorimeterHitImpl();
404 interhit->setPosition( ppp );
405 interhit->setEnergy(0.03);
412 int splitterOrientation;
413 std::string splitterCol;
414 if ( layer%2 == 0 ) {
422 std::map <int, float> virtEnergy;
426 for (
int jj=0; jj<2; jj++) {
429 LCCollection * col = evt->getCollection( splitterCol.c_str() );
432 CellIDDecoder<CalorimeterHit> id( col ) ;
435 int nelem = col->getNumberOfElements();
437 for (
int j=0; j < nelem; ++j) {
438 CalorimeterHit * hit2 =
dynamic_cast<CalorimeterHit*
>(col->getElementAt(j) );
440 streamlog_out ( ERROR ) <<
"ERROR null hit2 in collection " << splitterCol <<
" " << j << endl;
441 throw marlin::StopProcessingException(
this);
448 int dlayer = abs(layer2-layer);
449 int dstave = abs(stave2-stave);
450 int dmodule = abs(module2-module);
455 if (dmodule==0 && dstave==0 && dlayer>1)
continue;
459 if ( dstave==0 && dmodule>1 )
continue;
460 if ( dmodule==0 && dstave>1 )
continue;
461 if ( dstave==0 && dlayer>1)
continue;
463 dstave = min( dstave, 4-dstave);
464 if (dmodule!=0)
continue;
465 if (dstave>1)
continue;
466 if (dlayer>1)
continue;
470 float dist = sqrt( pow(hit2->getPosition()[0] - hit->getPosition()[0], 2) +
471 pow(hit2->getPosition()[1] - hit->getPosition()[1], 2) +
472 pow(hit2->getPosition()[2] - hit->getPosition()[2], 2) );
477 TVector3 stripDir2(0,0,0);
479 std::pair < TVector3, TVector3 > stripEnds2 =
getStripEnds(hit2, splitterOrientation, barrel);
480 stripDir2 = stripEnds2.first - stripEnds2.second;
484 TVector3 intercept =
stripIntersect(hit, stripDir, hit2, stripDir2);
485 if (intercept.Mag()>0) {
488 for (
int ii=0; ii<3; ii++) {
489 float dx = stripEnds.second[ii] - stripEnds.first[ii];
491 frac = (intercept[ii]-stripEnds.first[ii])/dx;
496 if (frac>=0.0 && frac<=1.0) {
498 if (segment>=0 && segment<_nVirtual) {
499 if (virtEnergy.find(segment)!=virtEnergy.end()) {
500 virtEnergy[segment] += hit2->getEnergy();
502 virtEnergy[segment] = hit2->getEnergy();
506 CalorimeterHitImpl* interhit =
new CalorimeterHitImpl();
508 pos[0] = intercept.X();
509 pos[1] = intercept.Y();
510 pos[2] = intercept.Z();
511 interhit->setPosition( pos );
512 interhit->setEnergy(0.1);
517 streamlog_out ( WARNING ) <<
"strange segment " << segment <<
" frac = " << frac <<
" nvirt = " << _nVirtual << endl;
520 streamlog_out ( WARNING ) <<
"strange frac " << frac << endl;
525 }
catch(DataNotAvailableException &
e) {};
530 std::map <int, float>::iterator it;
532 for (it=virtEnergy.begin(); it!=virtEnergy.end(); it++) {
533 totenergy+=it->second;
535 for (it=virtEnergy.begin(); it!=virtEnergy.end(); it++) {
537 float energy = hit->getEnergy()*it->second/totenergy;
539 TVector3 virtualCentre = stripEnds.second-stripEnds.first;
540 virtualCentre*= (it->first + 0.5)/
_nVirtual;
541 virtualCentre += stripEnds.first;
543 CalorimeterHitImpl* newhit =
new CalorimeterHitImpl();
546 pos[0] = virtualCentre.X();
547 pos[1] = virtualCentre.Y();
548 pos[2] = virtualCentre.Z();
550 newhit->setType(hit->getType());
551 newhit->setPosition( pos );
552 newhit->setEnergy(energy);
554 newhit->setCellID0(hit->getCellID0());
555 newhit->setCellID1(hit->getCellID1());
557 newhits.push_back(newhit);
568 TVector3 stripcentre(hit->getPosition()[0], hit->getPosition()[1], hit->getPosition()[2]);
569 TVector3 stripend1(stripcentre);
570 TVector3 stripend2(stripcentre);
579 float phiRotAngle = (stave-1)*2.*TMath::Pi()/
_symmetry;
581 stripHalfVec.RotateZ(phiRotAngle - TMath::Pi()/2.);
582 stripend1-=stripHalfVec;
583 stripend2+=stripHalfVec;
587 bool horizontalSlab = stave%2==1;
589 bool horizontalStrip(
true);
590 if (horizontalSlab) {
592 else if (orientation ==
TRANSVERSE) horizontalStrip=
true;
595 else if (orientation ==
TRANSVERSE) horizontalStrip=
false;
598 if (horizontalStrip) {
608 std::pair < TVector3, TVector3 > output (stripend1, stripend2);
619 streamlog_out ( MESSAGE ) <<
"DDStripSplitter::end() " << name() << std::endl ;
629 TVector3 stripCentre[2];
630 stripCentre[0].SetXYZ( hit0->getPosition()[0], hit0->getPosition()[1], hit0->getPosition()[2] );
631 stripCentre[1].SetXYZ( hit1->getPosition()[0], hit1->getPosition()[1], hit1->getPosition()[2] );
635 TVector3 stripDir[2];
642 for (
int i=0; i<2; i++) {
643 if (stripDir[i].Mag()>1
e-10) {
647 stripDir[i] = stripDir[1-i].Cross(stripCentre[i]);
650 stripDir[i]*=1./stripDir[i].Mag();
654 streamlog_out ( ERROR ) <<
"ERROR from DDStripSplitter::stripIntersect, first hit should be a strip" << endl;
655 throw marlin::StopProcessingException(
this);
659 for (
int j=0; j<2; j++) {
660 for (
int i=0; i<2; i++) {
662 p[j][i] = stripCentre[j]-TMath::Power(-1, i)*0.5*ll*stripDir[j];
666 TVector3 pNorm[2][2];
667 for (
int j=0; j<2; j++) {
668 for (
int i=0; i<2; i++) {
669 float mm = p[j][i].Mag();
677 for (
int j=0; j<2; j++) {
678 inPlane[j]=p[j][0]-p[j][1];
682 TVector3 normal = inPlane[0].Cross(inPlane[1]);
683 float mag = normal.Mag();
687 TVector3 point(p[0][0]+p[0][1]); point*=0.5;
692 for (
int i=0; i<2; i++) {
693 float d = ((point - p[1][i]).Dot(normal))/(pNorm[1][i].Dot(normal));
694 qPrime[i] = p[1][i] + d*pNorm[1][i];
698 TVector3 a(p[0][1]-p[0][0]);
699 TVector3 b(qPrime[1]-qPrime[0]);
700 TVector3 c(qPrime[0]-p[0][0]);
702 float factor = (c.Cross(b)).Dot(a.Cross(b))/((a.Cross(b)).Mag2());
704 TVector3 x = p[0][0] + a*factor;
707 bool intersect =
true;
708 for (
int ii=0; ii<2; ii++) {
709 for (
int j=0; j<3; j++) {
710 float d0 = ii==0 ? x[j]-p[0][0][j] : x[j]-qPrime[0][j];
711 float d1 = ii==0 ? x[j]-p[0][1][j] : x[j]-qPrime[1][j];
718 if (intersect)
return x;
719 else return TVector3(0,0,0);
virtual void setupGeometry()
virtual void init()
Called at the begin of the job before anything is read.
virtual void end()
Called after data processing for clean up.
#define RELATIONFROMTYPESTR
std::string _oddStripEndsCollName
std::string _splitEcalCollection
CellIDDecoder< CalorimeterHit > * _decoder
std::string _cellIDStaveString
std::string _ecalCollectionOddLayers
std::string _inputRelationsColOdd
std::string _evenStripEndsCollName
IMPL::LCCollectionVec * stripEndsOddCol
virtual void processEvent(LCEvent *evt)
Called for every event - the working horse.
virtual void processRunHeader(LCRunHeader *run)
Called for every run.
virtual void check(LCEvent *evt)
IMPL::LCCollectionVec * intersectionHits
std::string _cellIDModuleString
DDStripSplitter aDDStripSplitter
std::string _ecalCollectionEvenLayers
std::string _splitEcalRelCol
std::string _mcParticleCollectionName
Input collection name.
dd4hep::rec::LayeredCalorimeterData * _caloGeomData
CellIDDecoder< CalorimeterHit > * _decoder2
std::pair< TVector3, TVector3 > getStripEnds(CalorimeterHit *hit, int orientation, bool barrel)
std::string _cellIDLayerString
std::string _stripIntersecCollName
std::vector< LCCollection * > LCCollectionVec
std::string _inputRelationsColEven
std::string _unsplitEcalCollection
std::vector< CalorimeterHit * > getVirtualHits(LCEvent *evt, CalorimeterHit *hit, int orientation, bool barrel)
TVector3 stripIntersect(CalorimeterHit *hit0, TVector3 axis0, CalorimeterHit *hit1, TVector3 axis1)
int _ecalStrip_default_nVirt
#define RELATIONTOTYPESTR
IMPL::LCCollectionVec * stripEndsEvenCol