All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups
DDStripSplitter.cc
Go to the documentation of this file.
1 #include "DDStripSplitter.h"
2 #include <iostream>
3 #include <map>
4 
5 using std::endl;
6 
7 #include <EVENT/LCCollection.h>
8 #include <EVENT/MCParticle.h>
9 #include <EVENT/ReconstructedParticle.h>
10 
11 #include <EVENT/SimCalorimeterHit.h>
12 
13 #include "CalorimeterHitType.h"
14 
15 #include "IMPL/CalorimeterHitImpl.h"
16 #include <IMPL/LCRelationImpl.h>
17 
18 #include <UTIL/LCRelationNavigator.h>
19 
20 #include <marlin/Global.h>
21 #include <marlin/Exceptions.h>
22 
23 #include "DD4hep/DetectorSelector.h"
24 #include "DD4hep/DetType.h"
25 #include "DD4hep/Detector.h"
26 
27 #include <UTIL/CellIDDecoder.h>
28 
29 // ----- include for verbosity dependend logging ---------
30 #include "marlin/VerbosityLevels.h"
31 
32 // needed for uint
33 #include <sys/types.h>
34 
35 #include "streamlog/streamlog.h"
36 
37 #define RELATIONFROMTYPESTR "FromType"
38 #define RELATIONTOTYPESTR "ToType"
39 
40 
41 using namespace lcio ;
42 using namespace marlin ;
43 
45 
46 
47 DDStripSplitter::DDStripSplitter() : Processor("DDStripSplitter") {
48  // modify processor description
49  _description = "DDStripSplitter applies SSA to a strip-based calorimeter ..." ;
50 
51  registerInputCollection( LCIO::CALORIMETERHIT,
52  "ECALcollection_evenLayers",
53  "Name of the ECAL collection in even layers",
55  std::string("ECalBarrelScEvenCollectionRec") );
56 
57  registerInputCollection( LCIO::CALORIMETERHIT,
58  "ECALcollection_oddLayers",
59  "Name of the ECAL collection in odd layers",
61  std::string("ECalBarrelScOddCollectionRec") );
62 
63  registerInputCollection( LCIO::LCRELATION,
64  "LCRelations_evenLayers",
65  "name of the relation collection for even layer hits",
67  std::string("ECalBarrelScHitsEvenRecRelations") );
68 
69  registerInputCollection( LCIO::LCRELATION,
70  "LCRelations_oddLayers",
71  "name of the relation collection for odd layer hits",
73  std::string("ECalBarrelScHitsOddRecRelations") );
74 
75  registerInputCollection( LCIO::MCPARTICLE,
76  "MCParticleCollection",
77  "name of MCParticle collection (used for some plots)",
79  std::string("MCParticle") );
80 
81  registerProcessorParameter( "splitEcalCollection",
82  "name of output collection containing split hits",
84  std::string("ECalBarrelSplitCollection") );
85 
86  registerProcessorParameter( "unsplitEcalCollection",
87  "name of output collection containing unsplit hits",
89  std::string("ECalBarrelUnSplitCollection") );
90 
91  registerProcessorParameter( "splitEcalRelCol",
92  "name of relation collection for split hits",
94  std::string("ECalBarrelSplitRelations") );
95 
96  registerProcessorParameter( "stripIntersecCollName",
97  "name of (optional) output collection containing strip intersections",
99  std::string("stripIntersections") );
100 
101  registerProcessorParameter( "evenStripEndsCollName",
102  "name of (optional) output collection containing ends of strips in even layers",
104  std::string("stripEndsEven") );
105 
106  registerProcessorParameter( "oddStripEndsCollName",
107  "name of (optional) output collection containing ends of strips in odd layers",
109  std::string("stripEndsOdd") );
110 
111  registerProcessorParameter( "virtualCellsDefault",
112  "number of virtual cells per strip (used if info not found in gear file)",
114  int(1) );
115 
116  registerProcessorParameter( "saveIntersectionCollection",
117  "save collection with strip interactions?",
119  false);
120 
121  registerProcessorParameter( "isBarrelHits",
122  "are hits in these collections in the barrel (true) or endcap (false) ?",
123  _isBarrel,
124  true);
125 
126  // code for layer info for cellID decoder
127  registerProcessorParameter("CellIDLayerString" ,
128  "name of the part of the cellID that holds the layer" ,
130  std::string("layer")
131  );
132  registerProcessorParameter("CellIDModuleString" ,
133  "name of the part of the cellID that holds the module" ,
135  std::string("module")
136  );
137  registerProcessorParameter("CellIDStaveString" ,
138  "name of the part of the cellID that holds the stave" ,
140  std::string("stave")
141  );
142 
143 
144 }
145 
146 
148 
149  _symmetry=-999;
150  _cellSize=999;
151  _nVirtual=999;
153  _flag_rel.setBit(LCIO::LCREL_WEIGHTED); // for the hit relations
154 
155  return;
156 }
157 
158 void DDStripSplitter::processRunHeader( LCRunHeader* /*run*/) {
159  return;
160 }
161 
162 
163 
165 
166 
167  unsigned int includeFlag(0);
168  unsigned int excludeFlag(0);
169 
170  if ( _isBarrel ) {
171  includeFlag = ( dd4hep::DetType::CALORIMETER | dd4hep::DetType::ELECTROMAGNETIC | dd4hep::DetType::BARREL);
172  } else {
173  includeFlag = ( dd4hep::DetType::CALORIMETER | dd4hep::DetType::ELECTROMAGNETIC | dd4hep::DetType::ENDCAP);
174  }
175  excludeFlag = ( dd4hep::DetType::AUXILIARY | dd4hep::DetType::FORWARD );
176 
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 ;
181 
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() << ", " ;
188  }
189  throw marlin::StopProcessingException(this);
190  }
191 
192  int ical=0;
193  _caloGeomData = theDetectors.at(ical).extension<dd4hep::rec::LayeredCalorimeterData>();
194  if ( ! _caloGeomData ) {
195  streamlog_out ( WARNING ) << "could not get calorimeter geometry information!" << endl;
196  throw marlin::StopProcessingException(this);
197  }
198  _symmetry = _caloGeomData->inner_symmetry;
199  _stripLength = _caloGeomData->layers[0].cellSize0;
200  _stripWidth = _caloGeomData->layers[0].cellSize1;
201 
202  // check that layer 1 is orthogonal to this one
203  float lay1_strSize0 = _caloGeomData->layers[1].cellSize0;
204  float lay1_strSize1 = _caloGeomData->layers[1].cellSize1;
205  if ( fabs(lay1_strSize0-_stripWidth)/_stripWidth > 0.05 || fabs(lay1_strSize1-_stripLength)/_stripLength > 0.05 ) {
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;
209  }
210  throw marlin::StopProcessingException(this);
211  }
212 
213  _evenIsTransverse = 0;
214  if ( _stripLength<_stripWidth ) {
215  _evenIsTransverse = 1;
216  float temp = _stripLength;
218  _stripWidth=temp;
219  }
222 
223  // convert from cm to mm (dd4hep units -> lcio units...)
224  _stripLength*=10;
225  _stripWidth*=10;
226 
227  streamlog_out( DEBUG ) << "strip length, width = " << _stripLength << " " << _stripWidth << " mm " << endl;
228  if ( _stripAspectRatio < 2. ) {
229  streamlog_out( ERROR ) << "this strip is very short: probably not worth using the strip splitter!" << endl;
230  throw marlin::StopProcessingException(this);
231  }
232 
233  return;
234 }
235 
236 
237 void DDStripSplitter::processEvent( LCEvent * evt ) {
238 
239  if (_symmetry<0) setupGeometry();
240 
241  if ( _stripAspectRatio<2.0 ) {
242  streamlog_out ( WARNING ) << " -- not a long enough strip, not worth splitting -- length, width, aspect ratio: " <<
243  _stripLength << " " << _stripWidth << " " << _stripAspectRatio << ", doing nothing" << endl;
244  return;
245  }
246 
247  std::pair < TVector3, TVector3 > stripEnds;
248  std::string toSplit;
249  std::string toSplitRel;
250  int orientation;
251 
252  // std::map < IMPL::LCCollectionVec*, std::string > outputcolls;
253 
254  if (_saveIntersections) {
255  intersectionHits = new IMPL::LCCollectionVec( LCIO::CALORIMETERHIT );
256  intersectionHits->setFlag(intersectionHits->getFlag()|( 1 << LCIO::RCHBIT_LONG)); // store position
257 
258  stripEndsEvenCol = new IMPL::LCCollectionVec( LCIO::CALORIMETERHIT );
259  stripEndsEvenCol->setFlag(stripEndsEvenCol->getFlag()|( 1 << LCIO::RCHBIT_LONG)); // store position
260 
261  stripEndsOddCol = new IMPL::LCCollectionVec( LCIO::CALORIMETERHIT );
262  stripEndsOddCol->setFlag(stripEndsOddCol->getFlag()|( 1 << LCIO::RCHBIT_LONG)); // store position
263  }
264 
265  IMPL::LCCollectionVec* splitStripHits = new IMPL::LCCollectionVec( LCIO::CALORIMETERHIT );
266  splitStripHits->setFlag(splitStripHits->getFlag()|( 1 << LCIO::RCHBIT_LONG)); // store position
267  IMPL::LCCollectionVec* unSplitStripHits = new IMPL::LCCollectionVec( LCIO::CALORIMETERHIT );
268  unSplitStripHits->setSubset();
269 
270  LCCollectionVec *splitRelCol = new LCCollectionVec(LCIO::LCRELATION);
271  splitRelCol->setFlag(_flag_rel.getFlag());
272  splitRelCol->parameters().setValue( RELATIONFROMTYPESTR , LCIO::CALORIMETERHIT ) ;
273  splitRelCol->parameters().setValue( RELATIONTOTYPESTR , LCIO::SIMCALORIMETERHIT ) ;
274 
275  for (int icol=0; icol<2; icol++) { // loop over strip collections in even and odd layers (assumed to have perpendicular orientations)
276  switch (icol) {
277  case 0:
278  if ( _evenIsTransverse==1 ) {
279  orientation = TRANSVERSE;
280  } else if ( _evenIsTransverse==0 ) {
281  orientation = LONGITUDINAL;
282  } else {
283  streamlog_out( ERROR) << "strip orientation undefined!!" << endl;
284  throw marlin::StopProcessingException(this);
285  }
286  toSplit = _ecalCollectionEvenLayers;
287  toSplitRel = _inputRelationsColEven;
288  break;
289  case 1:
290  if ( _evenIsTransverse==1 ) {
291  orientation = LONGITUDINAL;
292  } else if ( _evenIsTransverse==0 ) {
293  orientation = TRANSVERSE;
294  } else {
295  streamlog_out( ERROR ) << "strip orientation undefined!!" << endl;
296  throw marlin::StopProcessingException(this);
297  }
298  toSplit = _ecalCollectionOddLayers;
299  toSplitRel = _inputRelationsColOdd;
300  break;
301  default:
302  streamlog_out ( ERROR ) << "crazy stuff!!! abandoning event..." << endl;
303  throw marlin::StopProcessingException(this);
304  return;
305  }
306 
307  try {
308  LCCollection * col = evt->getCollection( toSplit.c_str() );
309  if (!col) continue;
310 
311  LCCollection * colrel = evt->getCollection( toSplitRel.c_str() );
312  if (!colrel) continue;
313  LCRelationNavigator navi(colrel);
314 
315  const std::string layerCodingString(col->getParameters().getStringVal(LCIO::CellIDEncoding));
316  // set up cellid encoding for new collections
317  splitStripHits->parameters().setValue(LCIO::CellIDEncoding, layerCodingString);
318  unSplitStripHits->parameters().setValue(LCIO::CellIDEncoding, layerCodingString);
319 
320  // get the cellid decoder for this collection
321  CellIDDecoder<CalorimeterHit> id( col ) ;
322  _decoder = &id;
323 
324  // loop over the collection's hits
325  int nelem = col->getNumberOfElements();
326  for (int j=0; j < nelem; ++j) {
327  CalorimeterHit * hit = dynamic_cast<CalorimeterHit*>(col->getElementAt(j) );
328  if (!hit) {
329  streamlog_out ( ERROR ) << "ERROR null hit in collection " << toSplit.c_str() << " " << j << endl;
330  throw marlin::StopProcessingException(this);
331  continue;
332  }
333  // split the hits
334  std::vector <CalorimeterHit*> splitHits = getVirtualHits(evt, hit, orientation, _isBarrel); // assume the first one (should be only one)
335 
336  // find the corresponding simhit (for the relations)
337  SimCalorimeterHit* simhit = (SimCalorimeterHit*) navi.getRelatedToObjects(hit)[0];
338 
339  // add (new) hits to collections
340  if (splitHits.size()==0) { // not split, add original hit
341  unSplitStripHits->addElement(hit);
342  splitRelCol->addElement( new LCRelationImpl(hit,simhit,1.0) );
343  } else { // split was split, add the virtual hits
344  for (uint hh=0; hh<splitHits.size(); hh++) {
345  splitStripHits->addElement(splitHits[hh]);
346  float weight = 1.;
347  splitRelCol->addElement( new LCRelationImpl(splitHits[hh],simhit,weight) );
348  }
349  }
350  } // loop over hits in collection
351  } catch(DataNotAvailableException &e) {};
352  } // long/trans loop
353 
354  // add the new collections to the event
355  evt->addCollection( splitStripHits, _splitEcalCollection );
356  evt->addCollection( unSplitStripHits, _unsplitEcalCollection );
357  evt->addCollection( splitRelCol, _splitEcalRelCol );
358 
359  if (_saveIntersections) {
360  evt->addCollection(intersectionHits,_stripIntersecCollName);
361  evt->addCollection(stripEndsEvenCol,_evenStripEndsCollName);
362  evt->addCollection(stripEndsOddCol, _oddStripEndsCollName);
363  }
364 
365  return;
366 }
367 
368 std::vector <CalorimeterHit*> DDStripSplitter::getVirtualHits(LCEvent* evt, CalorimeterHit* hit, int orientation, bool barrel ) {
369 
370  // this splits the strip into zero or more hits along its length
371  // by looking at nearby hits with different orientation (trans/long or square)
372 
373  int layer = (*_decoder)(hit)[_cellIDLayerString];
374  int module = (*_decoder)(hit)[_cellIDModuleString];
375  int stave = (*_decoder)(hit)[_cellIDStaveString];
376 
377  TVector3 pp;
378  pp.SetXYZ( hit->getPosition()[0], hit->getPosition()[1], hit->getPosition()[2]);
379 
380  std::vector <CalorimeterHit*> newhits;
381 
382  // get the ends of this strip
383  std::pair < TVector3, TVector3 > stripEnds = getStripEnds(hit, orientation, barrel);
384  TVector3 stripDir = stripEnds.first - stripEnds.second;
385 
386  if (_saveIntersections) {
387  // make new collection with a hit at each end of a strip
388  // for debugging purposes
389  float ppp[3];
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);
396 
397  if ( layer%2 == 0 ) stripEndsEvenCol->addElement(interhit);
398  else stripEndsOddCol->addElement(interhit);
399 
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);
406 
407  if ( layer%2 == 0 ) stripEndsEvenCol->addElement(interhit);
408  else stripEndsOddCol->addElement(interhit);
409  }
410 
411  // decide which collections to use to split the strip
412  int splitterOrientation;
413  std::string splitterCol;
414  if ( layer%2 == 0 ) {
415  splitterCol = _ecalCollectionOddLayers;
416  splitterOrientation = _evenIsTransverse ? LONGITUDINAL : TRANSVERSE ;
417  } else {
418  splitterCol = _ecalCollectionEvenLayers;
419  splitterOrientation = _evenIsTransverse ? TRANSVERSE : LONGITUDINAL ;
420  }
421 
422  std::map <int, float> virtEnergy;
423  int nSplitters(0);
424 
425  // loop over splitter cols, find nearby hits
426  for (int jj=0; jj<2; jj++) { // strips, cells
427 
428  try {
429  LCCollection * col = evt->getCollection( splitterCol.c_str() );
430  if (!col) continue;
431 
432  CellIDDecoder<CalorimeterHit> id( col ) ;
433  _decoder2 = &id;
434 
435  int nelem = col->getNumberOfElements();
436 
437  for (int j=0; j < nelem; ++j) {
438  CalorimeterHit * hit2 = dynamic_cast<CalorimeterHit*>(col->getElementAt(j) );
439  if (!hit2) {
440  streamlog_out ( ERROR ) << "ERROR null hit2 in collection " << splitterCol << " " << j << endl;
441  throw marlin::StopProcessingException(this);
442  continue;
443  }
444  int layer2 = (*_decoder)(hit2)[_cellIDLayerString];
445  int module2 = (*_decoder)(hit2)[_cellIDModuleString];
446  int stave2 = (*_decoder)(hit2)[_cellIDStaveString];
447 
448  int dlayer = abs(layer2-layer);
449  int dstave = abs(stave2-stave);
450  int dmodule = abs(module2-module);
451 
452  // are the two hits close enough to look at further?
453 
454  // if hits in same module and same stave, require that only one layer difference
455  if (dmodule==0 && dstave==0 && dlayer>1) continue;
456 
457  if (barrel) {
458  dstave = min( dstave, _symmetry-dstave);
459  if ( dstave==0 && dmodule>1 ) continue; // allow same stave and +- 1 module
460  if ( dmodule==0 && dstave>1 ) continue; // or same module +- 1 stave
461  if ( dstave==0 && dlayer>1) continue; // if in same stave, require dlayer==1
462  } else { // endcap
463  dstave = min( dstave, 4-dstave);
464  if (dmodule!=0) continue; // different endcap
465  if (dstave>1) continue; // more than 1 stave (=quarter endcap) apart
466  if (dlayer>1) continue; // more than 1 layer apart
467  }
468 
469  // simple distance check for remaining hit pairs
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) );
473 
474  if (dist>2*_stripLength) continue;
475 
476  // for remaining hits, check if they overlap
477  TVector3 stripDir2(0,0,0);
478  if (jj==0) { //strip
479  std::pair < TVector3, TVector3 > stripEnds2 = getStripEnds(hit2, splitterOrientation, barrel);
480  stripDir2 = stripEnds2.first - stripEnds2.second;
481  } // leave 0 for cell
482 
483  // check if strips intersect
484  TVector3 intercept = stripIntersect(hit, stripDir, hit2, stripDir2);
485  if (intercept.Mag()>0) { // intercept found, calculate in which virtual cell
486  nSplitters++;
487  float frac(-1);
488  for (int ii=0; ii<3; ii++) {
489  float dx = stripEnds.second[ii] - stripEnds.first[ii];
490  if (fabs(dx)>0.1) {
491  frac = (intercept[ii]-stripEnds.first[ii])/dx;
492  break;
493  }
494  }
495 
496  if (frac>=0.0 && frac<=1.0) {
497  int segment = int(frac*_nVirtual);
498  if (segment>=0 && segment<_nVirtual) {
499  if (virtEnergy.find(segment)!=virtEnergy.end()) {
500  virtEnergy[segment] += hit2->getEnergy();
501  } else {
502  virtEnergy[segment] = hit2->getEnergy();
503  }
504 
505  if (_saveIntersections) {
506  CalorimeterHitImpl* interhit = new CalorimeterHitImpl();
507  float pos[3];
508  pos[0] = intercept.X();
509  pos[1] = intercept.Y();
510  pos[2] = intercept.Z();
511  interhit->setPosition( pos );
512  interhit->setEnergy(0.1);
513  intersectionHits->addElement(interhit);
514  }
515 
516  } else {
517  streamlog_out ( WARNING ) << "strange segment " << segment << " frac = " << frac << " nvirt = " << _nVirtual << endl;
518  }
519  } else {
520  streamlog_out ( WARNING ) << "strange frac " << frac << endl;
521  }
522 
523  }
524  }
525  } catch(DataNotAvailableException &e) {};
526  }
527 
528 
529  // now create the virtual cells, and assign energy
530  std::map <int, float>::iterator it;
531  float totenergy(0);
532  for (it=virtEnergy.begin(); it!=virtEnergy.end(); it++) {
533  totenergy+=it->second;
534  }
535  for (it=virtEnergy.begin(); it!=virtEnergy.end(); it++) {
536  // energy of hit
537  float energy = hit->getEnergy()*it->second/totenergy;
538  // position of hit
539  TVector3 virtualCentre = stripEnds.second-stripEnds.first;
540  virtualCentre*= (it->first + 0.5)/_nVirtual;
541  virtualCentre += stripEnds.first;
542  // make the new hit
543  CalorimeterHitImpl* newhit = new CalorimeterHitImpl();
544 
545  float pos[3];
546  pos[0] = virtualCentre.X();
547  pos[1] = virtualCentre.Y();
548  pos[2] = virtualCentre.Z();
549 
550  newhit->setType(hit->getType());
551  newhit->setPosition( pos );
552  newhit->setEnergy(energy);
553 
554  newhit->setCellID0(hit->getCellID0());
555  newhit->setCellID1(hit->getCellID1());
556 
557  newhits.push_back(newhit);
558 
559  }
560 
561  return newhits;
562 }
563 
564 
565 std::pair < TVector3, TVector3 > DDStripSplitter::getStripEnds(CalorimeterHit* hit, int orientation, bool barrel) {
566  // calculate the positions of the strip ends
567 
568  TVector3 stripcentre(hit->getPosition()[0], hit->getPosition()[1], hit->getPosition()[2]);
569  TVector3 stripend1(stripcentre);
570  TVector3 stripend2(stripcentre);
571 
572  int stave = (*_decoder)(hit)[_cellIDStaveString];
573 
574  if (barrel) {
575  if (orientation == TRANSVERSE) { // transverse, along z axis in barrel region
576  stripend1.SetZ(stripcentre.Z() - _stripLength/2.);
577  stripend2.SetZ(stripcentre.Z() + _stripLength/2.);
578  } else if (orientation == LONGITUDINAL) { // longitudinal, along x-y in barrel
579  float phiRotAngle = (stave-1)*2.*TMath::Pi()/_symmetry; // for new ILD models (dd4hep based)
580  TVector3 stripHalfVec(_stripLength/2.,0,0);
581  stripHalfVec.RotateZ(phiRotAngle - TMath::Pi()/2.);
582  stripend1-=stripHalfVec;
583  stripend2+=stripHalfVec;
584  }
585  } else { // endcap
586  // is the slab horizontal?
587  bool horizontalSlab = stave%2==1;
588  // are the strips in the slab horizontal?
589  bool horizontalStrip(true);
590  if (horizontalSlab) {
591  if (orientation == LONGITUDINAL) horizontalStrip=false;
592  else if (orientation == TRANSVERSE) horizontalStrip=true;
593  } else {
594  if (orientation == LONGITUDINAL) horizontalStrip=true;
595  else if (orientation == TRANSVERSE) horizontalStrip=false;
596  }
597 
598  if (horizontalStrip) {
599  stripend1.SetX(stripcentre.X() - _stripLength/2.);
600  stripend2.SetX(stripcentre.X() + _stripLength/2.);
601  } else {
602  stripend1.SetY(stripcentre.Y() - _stripLength/2.);
603  stripend2.SetY(stripcentre.Y() + _stripLength/2.);
604  }
605 
606  }
607 
608  std::pair < TVector3, TVector3 > output (stripend1, stripend2);
609 
610  return output;
611 }
612 
613 
614 void DDStripSplitter::check( LCEvent * /*evt*/ ) {
615  // nothing to check here - could be used to fill checkplots in reconstruction processor
616 }
617 
619  streamlog_out ( MESSAGE ) << "DDStripSplitter::end() " << name() << std::endl ;
620 }
621 
622 TVector3 DDStripSplitter::stripIntersect(CalorimeterHit* hit0, TVector3 axis0, CalorimeterHit* hit1, TVector3 axis1) {
623  // find intercept of hit1 with hit0
624  // hit0 must be a strip
625  // hit1 can be an orthogonal strip, or a cell
626  // axis0,1 are direction of strip
627 
628  // centre position of cell/strip
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] );
632 
633  // direction of strip long axis
634  // 0,0,0 for square cell
635  TVector3 stripDir[2];
636  stripDir[0]=axis0;
637  stripDir[1]=axis1;
638 
639  // deal with cell case
640  // define it's direction as perpendicular to strip and vector cell centre to origin
641  bool isStrip[2];
642  for (int i=0; i<2; i++) {
643  if (stripDir[i].Mag()>1e-10) {
644  isStrip[i]=true;
645  } else {
646  isStrip[i]=false;
647  stripDir[i] = stripDir[1-i].Cross(stripCentre[i]);
648  }
649  // ensure dir is normalised
650  stripDir[i]*=1./stripDir[i].Mag();
651  }
652 
653  if (!isStrip[0]) {
654  streamlog_out ( ERROR ) << "ERROR from DDStripSplitter::stripIntersect, first hit should be a strip" << endl;
655  throw marlin::StopProcessingException(this);
656  }
657 
658  TVector3 p[2][2]; // ends of strips
659  for (int j=0; j<2; j++) {
660  for (int i=0; i<2; i++) {
661  float ll = isStrip[j] ? _stripLength : _stripWidth*1.1; // inflate a little for cells
662  p[j][i] = stripCentre[j]-TMath::Power(-1, i)*0.5*ll*stripDir[j];
663  }
664  }
665 
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();
670  pNorm[j][i]=p[j][i];
671  pNorm[j][i]*=1./mm;
672  }
673  }
674 
675 
676  TVector3 inPlane[2]; // difference between points: line inside plane
677  for (int j=0; j<2; j++) {
678  inPlane[j]=p[j][0]-p[j][1];
679  }
680 
681  // vector normal to both lines (this is normal to the plane we're interested in)
682  TVector3 normal = inPlane[0].Cross(inPlane[1]);
683  float mag = normal.Mag();
684  normal*=1./mag;
685 
686  // point on line [0]
687  TVector3 point(p[0][0]+p[0][1]); point*=0.5;
688 
689  // calculate the projected positions of ends of [1] on
690  // the plane which contains "point" with normal "normal"
691  TVector3 qPrime[2];
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];
695  }
696 
697  // find the intersection of lines qPrime and p (they are in same plane)
698  TVector3 a(p[0][1]-p[0][0]);
699  TVector3 b(qPrime[1]-qPrime[0]);
700  TVector3 c(qPrime[0]-p[0][0]);
701 
702  float factor = (c.Cross(b)).Dot(a.Cross(b))/((a.Cross(b)).Mag2());
703 
704  TVector3 x = p[0][0] + a*factor;
705 
706  // check that two lines really intercept
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];
712  if (d0*d1>1e-10) {
713  intersect = false;
714  }
715  }
716  }
717 
718  if (intersect) return x;
719  else return TVector3(0,0,0);
720 }
virtual void setupGeometry()
static const float mm
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
LCFlagImpl _flag_rel
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
static const float e
std::vector< LCCollection * > LCCollectionVec
Definition: SiStripClus.h:55
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)
#define RELATIONTOTYPESTR
IMPL::LCCollectionVec * stripEndsEvenCol