All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups
ThrustReconstruction.cc
Go to the documentation of this file.
1 #include "ThrustReconstruction.h"
2 #include <iostream>
3 #include <fstream>
4 #include <vector>
5 
6 // #include <CLHEP/Vector/ThreeVector.h>
7 // #include <CLHEP/Random/RanluxEngine.h>
8 
9 #include <EVENT/LCCollection.h>
10 #include <EVENT/LCIO.h>
11 #include <EVENT/MCParticle.h>
12 #include <IMPL/LCCollectionVec.h>
13 #include <IMPL/ReconstructedParticleImpl.h>
14 #include <IMPL/LCTOOLS.h>
15 
16 
17 using namespace lcio ;
18 using namespace marlin ;
19 using namespace std ;
20 
21 
23 
24 
26  : Processor("ThrustReconstruction") {
27 
28  // modify processor description
29  _description = "Calculates thrust axis and thrust value of event using different algorithms" ;
30 
31  // register steering parameters:
32  // name, description, class-variable, default value
33 
34  registerInputCollection( LCIO::RECONSTRUCTEDPARTICLE,
35  "inputCollectionName" ,
36  "Name of collection of reconstructed particles used for thrust reconstruction" ,
38  std::string("SelectedReconstructedParticle") ) ;
39 
40  registerProcessorParameter( "typeOfThrustFinder" ,
41  "Type of thrust reconstruction algorithm to be used:\n#\t1 : Tasso algorithm\n#\t2 : JetSet algorithm" ,
42  _typeOfThrustFinder , 2 ) ;
43 
44 }
45 
47  _min = 2; _max = 0;
48  // usually a good idea to
49  printParameters() ;
50 
51  // config ranlux
52  filename = "Ranlux.coonf";
53  ifstream rndcfgfile( filename.c_str() );
54  if (!rndcfgfile)
55  {
56  long int ss=1234;
57  myrnd.setSeeds(&ss,4);
58  myrnd.showStatus();
59  }
60  else
61  {
62  rndcfgfile.close();
63  myrnd.restoreStatus(filename.c_str());
64  myrnd.showStatus();
65  } // if file not exist
66 
67 }
68 
69 void ThrustReconstruction::processRunHeader( LCRunHeader* /*run*/) {
70  // run->parameters().setValue("thrust",12300321);
71 }
72 
73 void ThrustReconstruction::processEvent( LCEvent * evt ) {
74 
75  // get pointer to collection vec of input particles
76  _inParVec = evt->getCollection(_inputCollectionName) ;
77 
78  if (_inParVec->getTypeName()!=LCIO::RECONSTRUCTEDPARTICLE)
79  {
80  std::stringstream errorMsg;
81  errorMsg << "\nProcessor: ThrustReconstruction \n" <<
82  "Collection is of wrong type (" << _inParVec->getTypeName() <<
83  "). Processor requires collection tpye " << LCIO::RECONSTRUCTEDPARTICLE
84  << "\n" ;
85  throw Exception(errorMsg.str());
86  }
87 
88  // Clear Vector of Hep3Vectors, to hold only momenta of this event.
89  if (!_partMom.empty()) _partMom.clear();
90 
91  for (int n=0;n<_inParVec->getNumberOfElements() ;n++)
92  {
93  ReconstructedParticle* aPart = dynamic_cast<ReconstructedParticle*>( _inParVec->getElementAt(n) );
94  if ( aPart == NULL )
95  throw Exception( std::string("Particle in ReconstructedParticle collection is not ReconstructedParticle") );
96 
97  const double* partMom = aPart->getMomentum();
98  _partMom.push_back( Hep3Vector(partMom[0], partMom[1], partMom[2]) );
99  } // for n
100 
101  // Reset the Class variables for Output
103  _majorThrustValue = -1;
104  _minorThrustValue = -1;
105  _principleThrustAxis.set(0,0,0);
106  _majorThrustAxis.set(0,0,0);
107  _minorThrustAxis.set(0,0,0);
108 
109  // Switch to the desired type of thrust finder
110  if (_typeOfThrustFinder == 1)
111  {
112  TassoThrust();
113  }
114  else if (_partMom.size()<=1)
115  {
116  TassoThrust();
117  }
118  else if (_typeOfThrustFinder == 2)
119  {
120  JetsetThrust();
121  }
122  // ###write
123  // evt->parameters().setValue("thrust",_principleThrustValue);
124 
125  FloatVec thrax;
126 
127  thrax.clear();
128  thrax.push_back(_principleThrustAxis.x());
129  thrax.push_back(_principleThrustAxis.y());
130  thrax.push_back(_principleThrustAxis.z());
131 
132  _inParVec->parameters().setValue("principleThrustValue",_principleThrustValue);
133  _inParVec->parameters().setValues("principleThrustAxis",thrax);
134 
135  if (_typeOfThrustFinder == 2)
136  {
137  thrax.clear();
138  thrax.push_back(_majorThrustAxis.x());
139  thrax.push_back(_majorThrustAxis.y());
140  thrax.push_back(_majorThrustAxis.z());
141 
142  _inParVec->parameters().setValue("majorThrustValue",_majorThrustValue);
143  _inParVec->parameters().setValues("majorThrustAxis",thrax);
144 
145  thrax.clear();
146  thrax.push_back(_minorThrustAxis.x());
147  thrax.push_back(_minorThrustAxis.y());
148  thrax.push_back(_minorThrustAxis.z());
149 
150  _inParVec->parameters().setValue("minorThrustValue",_minorThrustValue);
151  _inParVec->parameters().setValues("minorThrustAxis",thrax);
152 
153  float Oblateness;
154  Oblateness = _majorThrustValue - _minorThrustValue;
155  _inParVec->parameters().setValue("Oblateness",Oblateness);
156  if ( (_majorThrustValue < 0) || (_minorThrustValue < 0) )
157  {
158  _inParVec->parameters().setValue("Oblateness",-1);
159  }
160  }
161 
162  streamlog_out( DEBUG4 ) << " thrust: " << _principleThrustValue << " TV: " << _principleThrustAxis << endl;
163  streamlog_out( DEBUG4 ) << " major: " << _majorThrustValue << " TV: " << _majorThrustAxis << endl;
164  streamlog_out( DEBUG4 ) << " minor: " << _minorThrustValue << " TV: " << _minorThrustAxis << endl;
165 
168 }
169 
171 
172  // cout << "max, min: " << _max << " " << _min << endl;
173 
174  myrnd.saveStatus( filename.c_str() );
175 }
176 
178  int ThrustError = 0;
179  Hep3Vector tvec;
180 
181  // No particle in Event: Error
182  if (_inParVec->getNumberOfElements()<=0)
183  {
184  ThrustError = -1;
186  _principleThrustAxis.set(0,0,0);
187  }
188  // only one Particle in Event: Thrust direction = direction of particle
189  else if (_inParVec->getNumberOfElements()==1)
190  {
193  }
194  else
195  {
196  Hep3Vector ptm, ptot, pt;
197  std::vector<Hep3Vector> pc;
198  float sp,u, pp, tmax, t;
199 
200  sp = 0;
201  for (int i=0;i < _inParVec->getNumberOfElements();i++)
202  {
203  pp = _partMom[i].mag();
204  sp += pp;
205  ptot += _partMom[i];
206  } // for i
207  // ###
208  for (int m = 0; m <= 2; m++ )
209  ptot[m] *= 0.5;
210  tmax = 0;
211  for (int k = 1; k < _inParVec->getNumberOfElements(); k++)
212  {
213  for (int j = 0; j <= k-1;j++)
214  {
215  // cross product
216  tvec = _partMom[j].cross(_partMom[k]);
217  pt = -1 * ptot;
218  for (int l = 0; l < _inParVec->getNumberOfElements(); l++)
219  {
220  if (l==k) continue;
221  if (l==j) continue;
222  u = _partMom[l] * tvec;
223  if (u<0) continue;
224  pt += _partMom[l];
225  } // for l
226 
227  while(!pc.empty())
228  {
229  pc.pop_back();
230  }
231  // note: the order is important!!!
232  pc.push_back(pt);
233  pc.push_back(pt + _partMom[k]);
234  pc.push_back(pt + _partMom[j]);
235  pc.push_back(pc[2] + _partMom[k]);
236  for (int m = 0; m <= 3; m++ )
237  {
238  t = pc[m].mag2();
239  if (t <= tmax) continue;
240  tmax = t;
241  ptm = pc[m];
242  } // for m
243  } // for j
244  } // for k
245  _principleThrustValue = 2 * sqrt(tmax) / sp;
246  tvec = ptm;
247  } // end else
248 
249  // Normalization of thrust vector
250  double ax = 0;
251  ax = tvec.mag();
252  if (ax != 0)
253  {
254  ax = 1/ax;
255  _principleThrustAxis = ax * tvec;
256  }
257  else
258  {
259  ThrustError = -1;
261  _principleThrustAxis.set(0,0,0);
262  }
263  return ThrustError;
264 }
265 
267  const int nwork=11,iFastMax = 4,iGood=2;
268  const float dConv=0.0001; // 0.0001
269  int sgn;
270  double theta=0,phi=0;
271  double thp,thps,tds,tmax,dOblateness;
272  vector<Hep3Vector> TAxes(3),Fast(iFastMax+1),Workv(nwork);
273  vector<double> Workf(nwork),dThrust(3);
274  Hep3Vector tdi,tpr,mytest;
275 
276  tmax = 0;
277  for ( unsigned int i=0; i < _partMom.size(); i++)
278  tmax += _partMom[i].mag();
279 
280  // pass = 0: find thrust axis
281  // pass = 1: find major axis
282  for ( int pass=0; pass <= 1; pass++ )
283  {
284  if ( pass == 1 )
285  {
286  phi = TAxes[0].phi();
287  theta = TAxes[0].theta();
288  for ( unsigned int i = 0;i < _partMom.size(); i++)
289  {
290  _partMom[i].rotateZ(-phi);
291  _partMom[i].rotateY(-theta);
292  }
293  TAxes[0].set(0,0,1);
294  } // if pass == 1
295 
296  // Find the ifast highest momentum particles and
297  // put the highest in Fast[0], next in Fast[1],....Fast[iFast-1].
298  // Fast[iFast] is just a workspace.
299 
300  for ( unsigned int i = 0; i < Fast.size(); i++ )
301  Fast[i].set(0,0,0);
302 
303  for ( unsigned int i = 0; i < _partMom.size(); i++ )
304  {
305  for ( int ifast = iFastMax -1; ifast >= 0 ; ifast-- )
306  {
307  if (_partMom[i].mag2() > Fast[ifast].mag2() )
308  {
309  Fast[ifast + 1] = Fast[ifast];
310  if (ifast == 0) Fast[ifast] = _partMom[i];
311  }
312  else
313  {
314  Fast[ifast + 1] = _partMom[i];
315  break;
316  } // if p>p_fast
317  } // for ifast
318  } // for i
319 
320  // Find axis with highest thrust (case 0)/ highest major (case 1).
321 
322  for ( unsigned int iw = 0; iw < Workv.size(); iw++ )
323  {
324  Workf[iw] = 0.;
325  }
326  int p = (int) min( iFastMax,_partMom.size() ) - 1 ;
327  int nc = 1 << p;
328  for ( int n = 0; n < nc; n++ )
329  {
330  tdi.set(0,0,0);
331  for (int i = 0; i < min(iFastMax,nc) ; i++)
332  {
333  if ( (1 << (i+1)) * ( (n + (1<<i)) / (1<<(i+1)) ) >= n+1) //i+1
334  { sgn = -1;} else {sgn = 1;}
335  tdi += sgn*Fast[i];
336  if (pass==1) tdi.setZ(0);
337  } // for i
338  tds = tdi.mag2();
339  for ( int iw = (int) min(n,9); iw >= 0; iw-- )
340  {
341  if (tds > Workf[iw])
342  {
343  Workf[iw+1] = Workf[iw];
344  Workv[iw+1] = Workv[iw];
345  if (iw == 0)
346  { Workv[iw] = tdi; Workf[iw] = tds;}
347  }
348  else // if tds
349  {
350  Workv[iw+1] = tdi;
351  Workf[iw+1] = tds;
352  } // if tds
353  } // for iw
354  } // for n
355 
356  // Iterate direction of axis until stable maximum.
357 
358  dThrust[pass] = 0;
359  int nagree = 0;
360  for ( int iw = 0; iw < min(nc,10) && nagree < iGood; iw++ )
361  {
362  thp = 0;
363  thps = -99999.;
364  while ( thp > thps + dConv )
365  {
366  thps = thp;
367  if ( thp <= 1E-10 )
368  { tdi = Workv[iw]; } else { tdi=tpr; }
369  tpr.set(0,0,0);
370  for ( unsigned int i = 0; i < _partMom.size(); i++ )
371  {
372  sgn = (int) sign(1,tdi.dot(_partMom[i]));
373  tpr += sgn*_partMom[i];
374  if (pass == 1) { tpr.setZ(0); } // ###
375  } // for i
376  thp = tpr.mag()/tmax;
377  } // while
378  // Save good axis. Try new initial axis until enough
379  // tries agree.
380  if ( thp < dThrust[pass] - dConv ) continue;
381  if ( thp > dThrust[pass] + dConv )
382  {
383  nagree = 0;
384  // if (myrnd.flat() > 0.49999)
385  // {sgn = 1;} else {sgn=-1;}
386  sgn = 1;
387  TAxes[pass] = sgn*tpr/(tmax*thp);
388  dThrust[pass] = thp;
389  } // if thp
390  nagree++;
391  } // for iw (2)
392  } // for pass ...
393 
394  // Find minor axis and value by orthogonality.
395  if (myrnd.flat() > 0.49999)
396  {sgn = 1;} else {sgn=-1;}
397  TAxes[2].set( -sgn*TAxes[1].y(), sgn*TAxes[1].x(), 0);
398  thp = 0.;
399  for ( unsigned int i = 0; i < _partMom.size(); i++ )
400  {
401  thp += fabs(TAxes[2].dot(_partMom[i]) );
402  } // for i
403  dThrust[2] = thp/tmax;
404 
405  // Rotate back to original coordinate system.
406  for ( unsigned int i = 0;i < TAxes.size(); i++)
407  {
408  TAxes[i].rotateY(theta);
409  TAxes[i].rotateZ(phi);
410  }
411  dOblateness = dThrust[1] - dThrust[2];
412 
413  _principleThrustValue = dThrust[0];
414  _majorThrustValue = dThrust[1];
415  _minorThrustValue = dThrust[2];
416  _principleThrustAxis = TAxes[0];
417  _majorThrustAxis = TAxes[1];
418  _minorThrustAxis = TAxes[2];
419 
420 
421  return 0;
422 }
423 
424 //______________________________________________________________
425 // helper function to get sign of b
426 double ThrustReconstruction::sign(double a, double b)
427 {
428  if ( b < 0 )
429  { return -fabs(a); } else { return fabs(a); }
430 }
431 //______________________________________________________________
432 double ThrustReconstruction::min(double a, double b)
433 {
434  if ( a < b )
435  { return a; } else { return b; }
436 }
437 //______________________________________________________________
std::vector< Hep3Vector > _partMom
static const float m
Thrust processor for marlin.
virtual void init()
Called at the begin of the job before anything is read.
static const float k
ThrustReconstruction aThrustReconstruction
virtual void processRunHeader(LCRunHeader *run)
Called for every run.
double min(double a, double b)
std::string _inputCollectionName
Input collection name.
double sign(double a, double b)
virtual void end()
Called after data processing for clean up.
virtual void processEvent(LCEvent *evt)
Called for every event - the working horse.
T sgn(T n)