All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups
hybridRecoProcessor.cc
Go to the documentation of this file.
1 #include "hybridRecoProcessor.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 
17 #include <UTIL/LCRelationNavigator.h>
18 
19 #include <TFile.h>
20 #include <TH2F.h>
21 #include <TMath.h>
22 #include <TVector3.h>
23 #include "TLorentzVector.h"
24 
25 #include <marlin/Global.h>
26 
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>
34 
35 #include <UTIL/CellIDDecoder.h>
36 
37 // ----- include for verbosity dependend logging ---------
38 #include "marlin/VerbosityLevels.h"
39 
40 // needed for uint
41 #include <sys/types.h>
42 
43 using namespace lcio ;
44 using namespace marlin ;
45 
47 
48 
49 hybridRecoProcessor::hybridRecoProcessor() : Processor("hybridRecoProcessor") {
50  // modify processor description
51  _description = "hybridRecoProcessor does whatever it does ..." ;
52 
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);
60 
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);
68 
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);
76 
77 
78  registerProcessorParameter( "virtualCellsDefault",
79  "number of virtual cells per strip (used if info not found in gear file)",
81  int(1) );
82 
83  registerProcessorParameter( "saveIntersectionCollection",
84  "save collection with strip interactions?",
86  false);
87 
88  registerProcessorParameter( "saveCheckRootHistograms",
89  "save root file with debugging histograms?",
90  _makePlots,
91  false);
92 
93 }
94 
95 
97 
98  _fout=NULL;
99 
100  _symmetry=-999;
101  _stripLength=999;
102  _stripWidth=999;
103  _cellSize=999;
104  _nVirtual=999;
105 
106  if (_makePlots) { // define output root file and some histograms to put in it
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());
109 
110  h_phiThetaMC = new TH2F("MCphiTheta", "MCphiTheta", 100, -2*TMath::Pi(), 2*TMath::Pi(), 100, -2*TMath::Pi(), 2*TMath::Pi());
111 
112  h_stripDist_intercept = new TH1F("dist_in","dist_in",100,0,2);
113  h_stripDist_nointercept = new TH1F("dist_no","dist_no",100,0,2);
114 
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);;
119 
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);
126  }
127 
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);
136  }
137  }
138  }
139  }
140 
141  return;
142 }
143 
144 void hybridRecoProcessor::processRunHeader( LCRunHeader* /*run*/) {
145  return;
146 }
147 
149 
150  // read gear information about strip sizes
151 
152  streamlog_out ( DEBUG )<< "hello from hybridRecoProcessor::setupGeometry" << endl;
153 
154  const gear::CalorimeterParameters& pEcalBarrel = Global::GEAR->getEcalBarrelParameters();
155  const gear::LayerLayout& ecalBarrelLayout = pEcalBarrel.getLayerLayout();
156  const gear::GearParameters& pMokka = Global::GEAR->getGearParameters("MokkaParameters");
157 
158 
159  // number of virtual cells in ECAL scint strips
160  // this is the number of virtual cells used in Mokka: it's just used to calculate the true strip size
161  // from the gear file information. (in the case of >1 virtual cells in the simulation, the cell size in the gear
162  // file is that of the virtual cell, not of the whole strip
163  int nMokkaVirtualCells = 1;
164  try {
165  // first try to get from ECAL barrel section of gear file (it's here for "latest" Mokka versions)
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) {
169  try {
170  // otherwise look in the mokka parameters section
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;
175  assert(0);
176  }
177  streamlog_out (MESSAGE) << "taking number of Mokka virtual cells from Mokka section of gear file: " << nVirtualMokkaS << " " << nMokkaVirtualCells << endl;
178  } catch(gear::UnknownParameterException &e2) {
179  // if still not found, use default from processor parameter
180  nMokkaVirtualCells = _ecalStrip_default_nVirt;
181  streamlog_out (WARNING) << "taking number of Mokka virtual cells from steering file (not found in gear file): " << nMokkaVirtualCells << endl;
182  }
183  }
184 
185 
186  // this part assumes that all strips in the calo have the same size, as do all cells
187  // (there may be a mix of strips and cells)
188  for(int i=0; i<ecalBarrelLayout.getNLayers(); i++){
189  float size0 = ecalBarrelLayout.getCellSize0(i);
190  float size1 = ecalBarrelLayout.getCellSize1(i);
191 
192  // the gear file has size of virtual strips. we need to convert to the whole strip length
193  // if (i%2==0) size1*=_nSimVirt;
194  // else size0*=_nSimVirt;
195  if (i%2==0) size1*=nMokkaVirtualCells;
196  else size0*=nMokkaVirtualCells;
197 
198  streamlog_out ( DEBUG ) << "layer " << i << " " << size0 << " " << size1 << " " << min(size0, size1)/max(size0, size1) << endl;
199 
200  _stripAspectRatio = max(size0, size1)/min(size0, size1);
201 
202  if ( _stripAspectRatio > 1.5 ) { // it's a strip
203  _stripLength = max(size0, size1);
204  _stripWidth = min(size0, size1);
205  break;
206  } else { // a cell
207  _cellSize = size0;
208  }
209  }
210 
211  _symmetry = pEcalBarrel.getSymmetryOrder();
212 
213  streamlog_out ( DEBUG ) << "strip length = " << _stripLength << " width " << _stripWidth << " aspect ratio " << _stripAspectRatio << " cell size " << _cellSize << " ; symmetry = " << _symmetry << endl;
214 
215  // this is the number of virtual cells we will split the strip into
216  // it's completely unrelated to the number of virtual cells used in the Mokka simulation.
218 
219  return;
220 }
221 
222 
223 void hybridRecoProcessor::processEvent( LCEvent * evt ) {
224 
225  if (_symmetry<0) setupGeometry();
226 
227  if (_makePlots) {
228  // first fill some simple MC histos
229  float phi=-999;
230  float theta=-999;
231  try {
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]);
236  h_phiThetaMC->Fill(mom.Phi(), mom.Theta());
237  phi = mom.Phi();
238  theta = mom.Theta();
239  }
240  }
241  catch(DataNotAvailableException &e) {};
242  }
243 
244  if ( _stripAspectRatio<2.0 ) {
245  streamlog_out ( WARNING ) << " -- not a long enough strip, not worth splitting -- length, width, aspect ratio: " <<
246  _stripLength << " " << _stripWidth << " " << _stripAspectRatio << ", doing nothing" << endl;
247  return;
248  }
249 
250  std::pair < TVector3, TVector3 > stripEnds;
251  std::vector <std::string> * toSplit;
252  std::vector <std::string> * stripSplitter;
253  int orientation;
254 
255  std::map < IMPL::LCCollectionVec*, std::string > outputcolls;
256 
257  if (_saveIntersections) {
258  intersectionHits = new IMPL::LCCollectionVec( LCIO::CALORIMETERHIT );
259  intersectionHits->setFlag(intersectionHits->getFlag()|( 1 << LCIO::RCHBIT_LONG)); // store position
260 
261  stripEndsTransCol = new IMPL::LCCollectionVec( LCIO::CALORIMETERHIT );
262  stripEndsTransCol->setFlag(stripEndsTransCol->getFlag()|( 1 << LCIO::RCHBIT_LONG)); // store position
263 
264  stripEndsLongCol = new IMPL::LCCollectionVec( LCIO::CALORIMETERHIT );
265  stripEndsLongCol->setFlag(stripEndsLongCol->getFlag()|( 1 << LCIO::RCHBIT_LONG)); // store position
266  }
267 
268  for (int icol=0; icol<2; icol++) { // loop over longitudinal and transverse strip collections
269  switch (icol) {
270  case 0:
271  orientation = TRANSVERSE;
272  toSplit = &_ecalCollectionsTranStrips;
273  stripSplitter = &_ecalCollectionsLongStrips;
274  break;
275  case 1:
276  orientation = LONGITUDINAL;
277  toSplit = &_ecalCollectionsLongStrips;
278  stripSplitter = &_ecalCollectionsTranStrips;
279  break;
280  default:
281  streamlog_out ( ERROR ) << "ERROR crazy stuff!!! abandoning event..." << endl;
282  return;
283  }
284 
285  for (uint i=0; i<toSplit->size(); i++) { // loop over collections of this type (long/trans)
286  try {
287  LCCollection * col = evt->getCollection( toSplit->at(i).c_str() );
288  if (!col) continue;
289 
290  const std::string layerCodingString(col->getParameters().getStringVal(LCIO::CellIDEncoding));
291 
292  // is this a barrel or endcap collection?
293  TString name = toSplit->at(i);
294  bool barrel(true);
295  if (name.Contains("Barrel") || name.Contains("barrel")) {
296  barrel = true;
297  } else if (name.Contains("Endcap") || name.Contains("endcap")) {
298  barrel = false;
299  } else {
300  streamlog_out ( ERROR ) << "WARNING: cannot tell if collection is for barrel or endcap..." << name << endl;
301  }
302 
303  // make new collections for split and unsplit strips
304  IMPL::LCCollectionVec* splitStripHits = new IMPL::LCCollectionVec( LCIO::CALORIMETERHIT );
305  splitStripHits->setFlag(splitStripHits->getFlag()|( 1 << LCIO::RCHBIT_LONG)); // store position
306  splitStripHits->parameters().setValue(LCIO::CellIDEncoding, layerCodingString);
307 
308  IMPL::LCCollectionVec* unSplitStripHits = new IMPL::LCCollectionVec( LCIO::CALORIMETERHIT );
309  unSplitStripHits->setSubset();
310  unSplitStripHits->parameters().setValue(LCIO::CellIDEncoding, layerCodingString);
311 
312  // get the cellid decoder for this collection
313  CellIDDecoder<CalorimeterHit> id( col ) ;
314  _decoder = &id;
315 
316  // loop over the collection's hits
317  int nelem = col->getNumberOfElements();
318  for (int j=0; j < nelem; ++j) {
319  CalorimeterHit * hit = dynamic_cast<CalorimeterHit*>(col->getElementAt(j) );
320  if (!hit) {
321  streamlog_out ( ERROR ) << "ERROR null hit in collection " << toSplit->at(i).c_str() << " " << j << endl;
322  continue;
323  }
324  // split the hits
325  std::vector <CalorimeterHit*> splitHits = getVirtualHits(evt, hit, orientation, barrel);
326 
327  // add (new) hits to collections
328  if (splitHits.size()==0) { // not split, add original hit
329  unSplitStripHits->addElement(hit);
330  } else { // split was split, add the virtual hits
331  for (uint hh=0; hh<splitHits.size(); hh++) {
332  splitStripHits->addElement(splitHits[hh]);
333  }
334  }
335 
336  } // loop over hits in collection
337 
338  if (splitStripHits->getNumberOfElements()>0)
339  outputcolls[splitStripHits] = toSplit->at(i) + "Split";
340  if (unSplitStripHits->getNumberOfElements()>0)
341  outputcolls[unSplitStripHits] = toSplit->at(i) + "UnSplit";
342 
343  } catch(DataNotAvailableException &e) {};
344  } // loop over collections
345  } // long/trans loop
346 
347  std::map < IMPL::LCCollectionVec*, std::string >::iterator ii;
348 
349  // add the new collections to the event
350  for (ii=outputcolls.begin(); ii!=outputcolls.end(); ii++) {
351  evt->addCollection(ii->first, ii->second);
352  }
353 
354  if (_saveIntersections) {
355  evt->addCollection(intersectionHits,"stripIntersections");
356  evt->addCollection(stripEndsTransCol,"stripEndsT");
357  evt->addCollection(stripEndsLongCol, "stripEndsL");
358  }
359 
360  return;
361 }
362 
363 std::vector <CalorimeterHit*> hybridRecoProcessor::getVirtualHits(LCEvent* evt, CalorimeterHit* hit, int orientation, bool barrel ) {
364 
365  // this splits the strip into zero or more hits along its length
366  // by looking at nearby hits with different orientation (trans/long or square)
367 
368  int ieb=!barrel;
369 
370  int layer = (*_decoder)(hit)["K-1"];
371  int module = (*_decoder)(hit)["M"];
372  int stave = (*_decoder)(hit)["S-1"];
373 
374  TVector3 pp;
375  pp.SetXYZ( hit->getPosition()[0], hit->getPosition()[1], hit->getPosition()[2]);
376 
377  if (_makePlots) {
378  h_stavemodule[ieb]->Fill(stave, module);
379  h_layer[ieb] ->Fill(layer);
380 
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);
387 
388  h_cth_phi[ieb][stave][module]->Fill(pp.CosTheta(), pp.Phi());
389  h_XY[ieb][stave][module]->Fill(pp.X(), pp.Y());
390  }
391 
392  std::vector <CalorimeterHit*> newhits;
393 
394  // get the ends of this strip
395  std::pair < TVector3, TVector3 > stripEnds = getStripEnds(hit, orientation, barrel);
396  TVector3 stripDir = stripEnds.first - stripEnds.second;
397 
398  if (_saveIntersections) {
399  // make new collection with a hit at each end of a strip
400  // for debugging purposes
401  float pp[3];
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);
408 
409  if (orientation==TRANSVERSE) stripEndsTransCol->addElement(interhit);
410  else if (orientation==LONGITUDINAL) stripEndsLongCol->addElement(interhit);
411 
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);
418 
419  if (orientation==TRANSVERSE) stripEndsTransCol->addElement(interhit);
420  else if (orientation==LONGITUDINAL) stripEndsLongCol->addElement(interhit);
421  }
422 
423  // decide which collections to use to split the strip
424  int splitterOrientation;
425  std::vector <std::string> * splitterCols;
426  if ( orientation==TRANSVERSE ) {
427  splitterOrientation = LONGITUDINAL;
428  splitterCols = &_ecalCollectionsLongStrips;
429  } else if ( orientation==LONGITUDINAL ) {
430  splitterOrientation = TRANSVERSE;
431  splitterCols = &_ecalCollectionsTranStrips;
432  } else {
433  streamlog_out ( DEBUG ) << "no need to split this orientation";
434  return newhits;
435  }
436 
437  std::map <int, float> virtEnergy;
438  int nSplitters(0);
439 
440  // loop over splitter cols, find nearby hits
441  for (int jj=0; jj<2; jj++) { // strips, cells
442 
443  std::vector <std::string> * splitter = jj==0 ? splitterCols : &_ecalCollectionsCells;
444 
445  for (uint i=0; i<splitter->size(); i++) {
446  try {
447  LCCollection * col = evt->getCollection( splitter->at(i).c_str() );
448  if (!col) continue;
449 
450  CellIDDecoder<CalorimeterHit> id( col ) ;
451  _decoder2 = &id;
452 
453  int nelem = col->getNumberOfElements();
454 
455  for (int j=0; j < nelem; ++j) {
456  CalorimeterHit * hit2 = dynamic_cast<CalorimeterHit*>(col->getElementAt(j) );
457  if (!hit2) {
458  streamlog_out ( ERROR ) << "ERROR null hit2 in collection " << splitter->at(i).c_str() << " " << j << endl;
459  continue;
460  }
461 
462  int layer2 = (*_decoder)(hit2)["K-1"];
463  int module2 = (*_decoder)(hit2)["M"];
464  int stave2 = (*_decoder)(hit2)["S-1"];
465 
466  int dlayer = abs(layer2-layer);
467  int dstave = abs(stave2-stave);
468  int dmodule = abs(module2-module);
469 
470  // are the two hits close enough to look at further?
471 
472  // if hits in same module and same stave, require that only one layer difference
473  if (dmodule==0 && dstave==0 && dlayer>1) continue;
474 
475  if (barrel) {
476  dstave = min( dstave, _symmetry-dstave);
477  if ( dstave==0 && dmodule>1 ) continue; // allow same stave and +- 1 module
478  if ( dmodule==0 && dstave>1 ) continue; // or same module +- 1 stave
479  if ( dstave==0 && dlayer>1) continue; // if in same stave, require dlayer==1
480  } else { // endcap
481  dstave = min( dstave, 4-dstave);
482  if (dmodule!=0) continue; // different endcap
483  if (dstave>1) continue; // more than 1 stave (=quarter endcap) apart
484  if (dlayer>1) continue; // more than 1 layer apart
485  }
486 
487  // simple distance check for remaining hit pairs
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) );
491 
492  if (dist>2*_stripLength) continue;
493 
494  // for remaining hits, check if they overlap
495  TVector3 stripDir2(0,0,0);
496  if (jj==0) { //strip
497  std::pair < TVector3, TVector3 > stripEnds2 = getStripEnds(hit2, splitterOrientation, barrel);
498  stripDir2 = stripEnds2.first - stripEnds2.second;
499  } // leave 0 for cell
500 
501  // check if strips intersect
502  TVector3 intercept = stripIntersect(hit, stripDir, hit2, stripDir2);
503  if (_makePlots) {
504  if (intercept.Mag()>0) h_stripDist_intercept ->Fill(dist/_stripLength);
505  else h_stripDist_nointercept->Fill(dist/_stripLength);
506  }
507  if (intercept.Mag()>0) { // intercept found, calculate in which virtual cell
508  nSplitters++;
509  float frac(-1);
510  for (int i=0; i<3; i++) {
511  float dx = stripEnds.second[i] - stripEnds.first[i];
512  if (fabs(dx)>0.1) {
513  frac = (intercept[i]-stripEnds.first[i])/dx;
514  break;
515  }
516  }
517 
518  if (frac>=0.0 && frac<=1.0) {
519  int segment = int(frac*_nVirtual);
520  if (segment>=0 && segment<_nVirtual) {
521  if (virtEnergy.find(segment)!=virtEnergy.end()) {
522  virtEnergy[segment] += hit2->getEnergy();
523  } else {
524  virtEnergy[segment] = hit2->getEnergy();
525  }
526 
527  if (_saveIntersections) {
528  CalorimeterHitImpl* interhit = new CalorimeterHitImpl();
529  float pos[3];
530  pos[0] = intercept.X();
531  pos[1] = intercept.Y();
532  pos[2] = intercept.Z();
533  interhit->setPosition( pos );
534  interhit->setEnergy(0.1);
535  intersectionHits->addElement(interhit);
536  }
537 
538  } else {
539  streamlog_out ( WARNING ) << "strange segment " << segment << " frac = " << frac << " nvirt = " << _nVirtual << endl;
540  }
541  } else {
542  streamlog_out ( WARNING ) << "strange frac " << frac << endl;
543  }
544 
545  }
546  }
547  } catch(DataNotAvailableException &e) {};
548  }
549  }
550 
551 
552  // now create the virtual cells, and assign energy
553  std::map <int, float>::iterator it;
554  float totenergy(0);
555  for (it=virtEnergy.begin(); it!=virtEnergy.end(); it++) {
556  totenergy+=it->second;
557  }
558  for (it=virtEnergy.begin(); it!=virtEnergy.end(); it++) {
559  // energy of hit
560  float energy = hit->getEnergy()*it->second/totenergy;
561  // position of hit
562  TVector3 virtualCentre = stripEnds.second-stripEnds.first;
563  virtualCentre*= (it->first + 0.5)/_nVirtual;
564  virtualCentre += stripEnds.first;
565  // make the new hit
566  CalorimeterHitImpl* newhit = new CalorimeterHitImpl();
567 
568  float pos[3];
569  pos[0] = virtualCentre.X();
570  pos[1] = virtualCentre.Y();
571  pos[2] = virtualCentre.Z();
572 
573  newhit->setType(hit->getType());
574  newhit->setPosition( pos );
575  newhit->setEnergy(energy);
576 
577  newhit->setCellID0(hit->getCellID0());
578  newhit->setCellID1(hit->getCellID1());
579 
580  newhits.push_back(newhit);
581 
582  }
583 
584  return newhits;
585 }
586 
587 
588 std::pair < TVector3, TVector3 > hybridRecoProcessor::getStripEnds(CalorimeterHit* hit, int orientation, bool barrel) {
589  // calculate the positions of the strip ends
590 
591  TVector3 stripcentre(hit->getPosition()[0], hit->getPosition()[1], hit->getPosition()[2]);
592  TVector3 stripend1(stripcentre);
593  TVector3 stripend2(stripcentre);
594 
595  int stave = (*_decoder)(hit)["S-1"];
596 
597  if (barrel) {
598  if (orientation == TRANSVERSE) { // transverse, along z axis in barrel region
599  stripend1.SetZ(stripcentre.Z() - _stripLength/2.);
600  stripend2.SetZ(stripcentre.Z() + _stripLength/2.);
601  } else if (orientation == LONGITUDINAL) { // longitudinal, along x-y in barrel
602  if (_makePlots) {
603  h_phiModuleCheck->Fill(1.0*stave+0.5, stripcentre.Phi());
604  }
605  float phiRotAngle = stave*2.*TMath::Pi()/_symmetry;
606  TVector3 stripHalfVec(_stripLength/2.,0,0);
607  stripHalfVec.RotateZ(phiRotAngle);
608  stripend1-=stripHalfVec;
609  stripend2+=stripHalfVec;
610  }
611  } else { // endcap
612  // is the slab horizontal?
613  bool horizontalSlab = stave%2==1;
614  // are the strips in the slab horizontal?
615  bool horizontalStrip(true);
616  if (horizontalSlab) {
617  if (orientation == LONGITUDINAL) horizontalStrip=true;
618  else if (orientation == TRANSVERSE) horizontalStrip=false;
619  } else {
620  if (orientation == LONGITUDINAL) horizontalStrip=false;
621  else if (orientation == TRANSVERSE) horizontalStrip=true;
622  }
623 
624  if (horizontalStrip) {
625  stripend1.SetX(stripcentre.X() - _stripLength/2.);
626  stripend2.SetX(stripcentre.X() + _stripLength/2.);
627  } else {
628  stripend1.SetY(stripcentre.Y() - _stripLength/2.);
629  stripend2.SetY(stripcentre.Y() + _stripLength/2.);
630  }
631 
632  }
633 
634  std::pair < TVector3, TVector3 > output (stripend1, stripend2);
635 
636  return output;
637 }
638 
639 
640 void hybridRecoProcessor::check( LCEvent * /*evt*/ ) {
641  // nothing to check here - could be used to fill checkplots in reconstruction processor
642 }
643 
645  streamlog_out ( MESSAGE ) << "hybridRecoProcessor::end() " << name() << std::endl ;
646  if (_makePlots && _fout) {
647  _fout->Write(0);
648  _fout->Close();
649  }
650 
651 }
652 
653 TVector3 hybridRecoProcessor::stripIntersect(CalorimeterHit* hit0, TVector3 axis0, CalorimeterHit* hit1, TVector3 axis1) {
654  // find intercept of hit1 with hit0
655  // hit0 must be a strip
656  // hit1 can be an orthogonal strip, or a cell
657  // axis0,1 are direction of strip
658 
659  // centre position of cell/strip
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] );
663 
664  // direction of strip long axis
665  // 0,0,0 for square cell
666  TVector3 stripDir[2];
667  stripDir[0]=axis0;
668  stripDir[1]=axis1;
669 
670  // deal with cell case
671  // define it's direction as perpendicular to strip and vector cell centre to origin
672  bool isStrip[2];
673  for (int i=0; i<2; i++) {
674  if (stripDir[i].Mag()>1e-10) {
675  isStrip[i]=true;
676  } else {
677  isStrip[i]=false;
678  stripDir[i] = stripDir[1-i].Cross(stripCentre[i]);
679  }
680  // ensure dir is normalised
681  stripDir[i]*=1./stripDir[i].Mag();
682  }
683 
684  if (!isStrip[0]) streamlog_out ( ERROR ) << "ERROR from hybridRecoProcessor::stripIntersect, first hit should be a strip" << endl;
685 
686  TVector3 p[2][2]; // ends of strips
687  for (int j=0; j<2; j++) {
688  for (int i=0; i<2; i++) {
689  float ll = isStrip[j] ? _stripLength : _stripWidth*1.1; // inflate a little for cells
690  p[j][i] = stripCentre[j]-TMath::Power(-1, i)*0.5*ll*stripDir[j];
691  }
692  }
693 
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();
698  pNorm[j][i]=p[j][i];
699  pNorm[j][i]*=1./mm;
700  }
701  }
702 
703 
704  TVector3 inPlane[2]; // difference between points: line inside plane
705  for (int j=0; j<2; j++) {
706  inPlane[j]=p[j][0]-p[j][1];
707  }
708 
709  // vector normal to both lines (this is normal to the plane we're interested in)
710  TVector3 normal = inPlane[0].Cross(inPlane[1]);
711  float mag = normal.Mag();
712  normal*=1./mag;
713 
714  // point on line [0]
715  TVector3 point(p[0][0]+p[0][1]); point*=0.5;
716 
717  // calculate the projected positions of ends of [1] on
718  // the plane which contains "point" with normal "normal"
719  TVector3 qPrime[2];
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];
723  }
724 
725  // find the intersection of lines qPrime and p (they are in same plane)
726  TVector3 a(p[0][1]-p[0][0]);
727  TVector3 b(qPrime[1]-qPrime[0]);
728  TVector3 c(qPrime[0]-p[0][0]);
729 
730  float factor = (c.Cross(b)).Dot(a.Cross(b))/((a.Cross(b)).Mag2());
731 
732  TVector3 x = p[0][0] + a*factor;
733 
734  // check that two lines really intercept
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];
740  if (d0*d1>1e-10) {
741  intersect = false;
742  }
743  }
744  }
745 
746  if (intersect) return x;
747  else return TVector3(0,0,0);
748 }
CellIDDecoder< CalorimeterHit > * _decoder2
static const float mm
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
static const float e
std::vector< LCCollection * > LCCollectionVec
Definition: SiStripClus.h:55
CellIDDecoder< CalorimeterHit > * _decoder
virtual void end()
Called after data processing for clean up.
TH2F * h_XY[2][10][10]
IMPL::LCCollectionVec * intersectionHits
IMPL::LCCollectionVec * stripEndsTransCol
virtual void check(LCEvent *evt)
virtual void processEvent(LCEvent *evt)
Called for every event - the working horse.