source: HiSusy/trunk/Delphes-3.0.0/modules/ParticlePropagator.cc @ 1

Last change on this file since 1 was 1, checked in by zerwas, 11 years ago

first import of structure, PYTHIA8 and DELPHES

File size: 7.6 KB
Line 
1
2/** \class ParticlePropagator
3 *
4 *  Propagates charged and neutral particles
5 *  from a given vertex to a cylinder defined by its radius,
6 *  its half-length, centered at (0,0,0) and with its axis
7 *  oriented along the z-axis.
8 *
9 *  $Date: 2012-11-18 15:57:08 +0100 (Sun, 18 Nov 2012) $
10 *  $Revision: 814 $
11 *
12 *
13 *  \author P. Demin - UCL, Louvain-la-Neuve
14 *
15 */
16
17#include "modules/ParticlePropagator.h"
18
19#include "classes/DelphesClasses.h"
20#include "classes/DelphesFactory.h"
21#include "classes/DelphesFormula.h"
22
23#include "ExRootAnalysis/ExRootResult.h"
24#include "ExRootAnalysis/ExRootFilter.h"
25#include "ExRootAnalysis/ExRootClassifier.h"
26
27#include "TMath.h"
28#include "TString.h"
29#include "TFormula.h"
30#include "TRandom3.h"
31#include "TObjArray.h"
32#include "TDatabasePDG.h"
33#include "TLorentzVector.h"
34
35#include <algorithm> 
36#include <stdexcept>
37#include <iostream>
38#include <sstream>
39
40using namespace std;
41
42//------------------------------------------------------------------------------
43
44ParticlePropagator::ParticlePropagator() :
45  fItInputArray(0)
46{
47}
48
49//------------------------------------------------------------------------------
50
51ParticlePropagator::~ParticlePropagator()
52{
53}
54
55//------------------------------------------------------------------------------
56
57void ParticlePropagator::Init()
58{
59  fRadius = GetDouble("Radius", 1.0);
60  fRadius2 = fRadius*fRadius;
61  fHalfLength = GetDouble("HalfLength", 3.0);
62  fBz = GetDouble("Bz", 0.0);
63  if(fRadius < 1.0E-2)
64  { 
65    cout << "ERROR: magnetic field radius is too low\n";
66    return;
67  }
68  if(fHalfLength < 1.0E-2)
69  {
70    cout << "ERROR: magnetic field length is too low\n";
71    return;
72  }
73
74  // import array with output from filter/classifier module
75
76  fInputArray = ImportArray(GetString("InputArray", "Delphes/candidates"));
77  fItInputArray = fInputArray->MakeIterator();
78
79  // create output arrays
80
81  fOutputArray = ExportArray(GetString("OutputArray", "candidates"));
82  fTrackOutputArray = ExportArray(GetString("TrackOutputArray", "tracks"));
83}
84
85//------------------------------------------------------------------------------
86
87void ParticlePropagator::Finish()
88{
89  if(fItInputArray) delete fItInputArray;
90}
91
92//------------------------------------------------------------------------------
93
94void ParticlePropagator::Process()
95{
96  Candidate *candidate, *mother;
97  TLorentzVector candidatePosition, candidateMomentum;
98  Double_t px, py, pz, pt, pt2, e, m, q;
99  Double_t px_t, py_t, pz_t, pt_t, p_t, e_t;
100  Double_t x, y, z, t, r, phi;
101  Double_t x_c, y_c, r_c, phi_c, phi_0;
102  Double_t x_t, y_t, z_t, r_t;
103  Double_t t1, t2, t3, t4, t5, t6;
104  Double_t t_z, t_r, t_ra, t_rb;
105  Double_t tmp, discr, discr2;
106  Double_t delta, gammam, omega, asinrho;
107 
108  const Double_t c_light = 2.99792458E8;
109   
110  fItInputArray->Reset();
111  while((candidate = static_cast<Candidate*>(fItInputArray->Next())))
112  {
113    candidatePosition = candidate->Position;
114    candidateMomentum = candidate->Momentum;
115    x = candidatePosition.X()*1.0E-3;
116    y = candidatePosition.Y()*1.0E-3;
117    z = candidatePosition.Z()*1.0E-3;
118    m = candidate->Mass;
119    q = candidate->Charge;
120
121    // check that particle position is inside the cylinder
122    if(TMath::Hypot(x, y) > fRadius || TMath::Abs(z) > fHalfLength)
123    {
124      continue;
125    }
126
127    px = candidateMomentum.Px();
128    py = candidateMomentum.Py();
129    pz = candidateMomentum.Pz();
130    pt = candidateMomentum.Pt();
131    pt2 = candidateMomentum.Perp2();
132    e = candidateMomentum.E();
133
134    if(pt2 < 1.0E-9)
135    {
136      continue;
137    }
138
139    if(TMath::Abs(q) < 1.0E-9 || TMath::Abs(fBz) < 1.0E-9)
140    {
141      // solve pt2*t^2 + 2*(px*x + py*y)*t + (fRadius2 - x*x - y*y) = 0
142      tmp = px*y - py*x;
143      discr2 = pt2*fRadius2 - tmp*tmp;
144     
145      if(discr2 < 0)
146      {
147        // no solutions
148        continue;
149      }
150
151      tmp = px*x + py*y;
152      discr = TMath::Sqrt(discr2);
153      t1 = (-tmp + discr)/pt2;
154      t2 = (-tmp - discr)/pt2;
155      t = (t1 < 0) ? t2 : t1; 
156
157      z_t = z + pz*t;
158      if(TMath::Abs(z_t) > fHalfLength)
159      {
160        t3 = (+fHalfLength - z) / pz;
161        t4 = (-fHalfLength - z) / pz;
162        t = (t3 < 0) ? t4 : t3; 
163      }
164
165      x_t = x + px*t;
166      y_t = y + py*t;
167      z_t = z + pz*t;
168
169      mother = candidate;
170      candidate = static_cast<Candidate*>(candidate->Clone());
171
172      candidate->Position.SetXYZT(x_t*1.0E3, y_t*1.0E3, z_t*1.0E3, 0.0);
173
174      candidate->Momentum = candidateMomentum;
175      candidate->Mother = mother;
176     
177      fOutputArray->Add(candidate);
178      if(TMath::Abs(q) > 1.0E-9) fTrackOutputArray->Add(candidate);
179    }
180    else
181    {
182
183      // 1.  initial transverse momentum p_{T0} : Part->pt
184      //     initial transverse momentum direction \phi_0 = -atan(p_X0/p_Y0)
185      //     relativistic gamma : gamma = E/mc² ; gammam = gamma \times m
186      //     giration frequency \omega = q/(gamma m) fBz
187      //     helix radius r = p_T0 / (omega gamma m)
188
189      gammam = e*1.0E9 / (c_light*c_light);      // gammam in [eV/c²]
190      omega = q * fBz / (gammam);                // omega is here in [ 89875518 / s] 
191      r = pt / (q * fBz) * 1.0E9/c_light;        // in [m] 
192
193      phi_0 = TMath::ATan2(py, px); // [rad] in [-pi; pi]
194
195      // 2. helix axis coordinates
196      x_c = x + r*TMath::Sin(phi_0);
197      y_c = y - r*TMath::Cos(phi_0);
198      r_c = TMath::Hypot(x_c, y_c);
199      phi_c = TMath::ATan2(y_c, x_c);
200      phi = phi_c;
201      if(x_c < 0.0) phi += TMath::Pi();
202
203      // 3. time evaluation t = TMath::Min(t_r, t_z)
204      //    t_r : time to exit from the sides
205      //    t_z : time to exit from the front or the back
206      t_r = 0.0; // in [ns]
207      int sign_pz = (pz > 0.0) ? 1 : -1;
208      if(pz == 0.0) t_z = 1.0E99;
209      else t_z = gammam / (pz*1.0E9/c_light) * (-z + fHalfLength*sign_pz);
210
211      if(r_c + TMath::Abs(r)  < fRadius)
212      {
213        // helix does not cross the cylinder sides
214        t = t_z;
215      }
216      else
217      {
218        asinrho = TMath::ASin( (fRadius*fRadius - r_c*r_c - r*r) / (2*TMath::Abs(r)*r_c)  );
219        delta = phi_0 - phi;
220        if(delta <-TMath::Pi()) delta += 2*TMath::Pi();
221        if(delta > TMath::Pi()) delta -= 2*TMath::Pi();
222        t1 = (delta + asinrho) / omega;
223        t2 = (delta + TMath::Pi() - asinrho) / omega;
224        t3 = (delta + TMath::Pi() + asinrho) / omega;
225        t4 = (delta - asinrho) / omega;
226        t5 = (delta - TMath::Pi() - asinrho) / omega;
227        t6 = (delta - TMath::Pi() + asinrho) / omega;
228
229        if(t1 < 0) t1 = 1.0E99;
230        if(t2 < 0) t2 = 1.0E99;
231        if(t3 < 0) t3 = 1.0E99;
232        if(t4 < 0) t4 = 1.0E99;
233        if(t5 < 0) t5 = 1.0E99;
234        if(t6 < 0) t6 = 1.0E99;
235
236        t_ra = TMath::Min(t1, TMath::Min(t2, t3));
237        t_rb = TMath::Min(t4, TMath::Min(t5, t6));
238        t_r = TMath::Min(t_ra, t_rb);
239        t = TMath::Min(t_r, t_z); 
240      }
241
242      // 4. position in terms of x(t), y(t), z(t)
243      x_t = x_c + r * TMath::Sin(omega * t - phi_0);
244      y_t = y_c + r * TMath::Cos(omega * t - phi_0);
245      z_t = z + pz*1.0E9 / c_light / gammam * t;
246      r_t = TMath::Hypot(x_t, y_t);
247
248      if(r_t > 0.0)
249      {
250        mother = candidate;
251        candidate = static_cast<Candidate*>(candidate->Clone());
252
253        candidate->Position.SetXYZT(x_t*1.0E3, y_t*1.0E3, z_t*1.0E3, 0.0);
254
255        px_t = pt * TMath::Cos(phi_0 - omega*t); 
256        py_t = pt * TMath::Sin(phi_0 - omega*t);
257        pz_t = pz;
258
259        pt_t = TMath::Hypot(px_t, py_t);
260        p_t = TMath::Hypot(pt_t, pz_t);
261        e_t = TMath::Hypot(m, p_t);
262
263        candidate->Momentum.SetPxPyPzE(px_t, py_t, pz_t, e_t);
264        candidate->Mother = mother;
265       
266        fOutputArray->Add(candidate);
267        fTrackOutputArray->Add(candidate);
268      }
269    }
270  }
271}
272
273//------------------------------------------------------------------------------
Note: See TracBrowser for help on using the repository browser.