23 #include <TDatabasePDG.h>
24 #include <TParticlePDG.h>
32 const double chargedPionMass =
33 TDatabasePDG::Instance()->GetParticle(211)->Mass();
40 double computeW2FromXQ2M(
double x,
double Q2,
double m) {
42 return std::pow(m, 2.) + (1. - x) * Q2 / x;
50 double bounded(
double x,
double minimum,
double maximum) {
51 return std::max(minimum, std::min(x, maximum));
65 struct EnergyFromMomentumAndId :
public std::unary_function<const Particle*,
67 double operator()(
const Particle* p)
const {
72 double energy(p->
GetE());
78 TParticlePDG* pdg = p->
Id().
Info();
80 if (pdg && p->
Id() != 0) {
85 mass = chargedPionMass;
88 energy = sqrt(pow(p->
GetP(), 2.) + pow(mass, 2.));
105 class MeasuredParticle {
109 throw std::invalid_argument(
"MeasuredParticle given NULL pointer");
111 ParticleMC* measured =
new ParticleMC;
113 measured->SetId(CalculateId(particle));
115 TParticlePDG* pdg = measured->Id().Info();
117 measured->SetM(pdg->Mass());
119 std::pair<double, double> ep =
120 CalculateEnergyMomentum(particle, pdg->Mass());
121 TLorentzVector vec(0., 0., ep.second, ep.first);
123 vec.SetPhi(particle->
GetPhi());
124 measured->Set4Vector(vec);
135 TParticlePDG* pdg = particle->
Id().
Info();
137 if (pdg && particle->
Id() != 0) {
139 }
else if (particle->
GetP() > 0.) {
162 static std::pair<double, double> CalculateEnergyMomentum(
165 int id = CalculateId(particle);
166 TParticlePDG* pdg = TDatabasePDG::Instance()->GetParticle(
id);
176 std::pair<double, double> ep(0., 0.);
177 if (particle->
GetP() > 0.) {
178 ep.first = sqrt(pow(particle->
GetP(), 2.) + pow(mass, 2.));
179 ep.second = particle->
GetP();
180 }
else if (particle->
GetE() > 0.) {
181 ep.first = particle->
GetE();
182 ep.second = sqrt(pow(particle->
GetE(), 2.) - pow(mass, 2.));
193 struct EnergyMomentum4Vector :
public std::unary_function<const Particle*,
195 TLorentzVector operator()(
const Particle* p)
const {
201 ep.SetE(EnergyFromMomentumAndId()(p));
210 struct EMinusPz :
public std::unary_function<const Particle*, double> {
211 double operator()(
const Particle* p)
const {
212 TLorentzVector fourMomentum(0., 0., 0., 0.);
214 fourMomentum = EnergyMomentum4Vector()(p);
216 return fourMomentum.E() - fourMomentum.Pz();
233 double Q2,
double W2)
260 std::auto_ptr<const VirtualParticle> scattered(
261 MeasuredParticle::Create(mBeams.at(3)));
265 if (scattered->GetTheta() > 0. && scattered->GetP() > 0.) {
266 const TLorentzVector& l = mBeams.at(0)->Get4Vector();
267 const TLorentzVector& h = mBeams.at(1)->Get4Vector();
271 double Q2 = 2. * l.E() * scattered->GetE() *
272 (1. + cos(scattered->GetTheta()));
273 kin->mQ2 = std::max(0., Q2);
276 double gamma = mBeams.at(1)->GetE() / mBeams.at(1)->GetM();
277 double beta = mBeams.at(1)->GetP() / mBeams.at(1)->GetE();
278 double ELeptonInNucl = gamma * (l.P() - beta * l.Pz());
279 double ELeptonOutNucl = gamma *
280 (scattered->GetP() - beta * scattered->GetPz());
281 kin->mNu = std::max(0., ELeptonInNucl - ELeptonOutNucl);
286 const TLorentzVector q = l - scattered->Get4Vector();
287 double y = (q.Dot(h)) / (l.Dot(h));
288 kin->mY = bounded(y, 0., 1.);
290 double cme = (l + h).M2();
291 double x = kin->mQ2 / kin->mY / cme;
292 kin->mX = bounded(x, 0., 1.);
293 kin->mW2 = computeW2FromXQ2M(kin->mX, kin->mQ2, h.M());
296 catch(std::invalid_argument& except) {
298 std::cerr <<
"No lepton for kinematic calculations" << std::endl;
305 JacquetBlondelComputer::~JacquetBlondelComputer() {
307 typedef std::vector<const VirtualParticle*>::iterator Iter;
322 std::vector<const erhic::VirtualParticle*>
final;
326 std::transform(
final.begin(),
final.end(), std::back_inserter(
mParticles),
327 std::ptr_fun(&MeasuredParticle::Create));
335 kin->mY = ComputeY();
336 kin->mQ2 = ComputeQSquared();
337 kin->mX = ComputeX();
338 kin->mW2 = computeW2FromXQ2M(kin->mX, kin->mQ2,
345 Double_t JacquetBlondelComputer::ComputeY()
const {
350 if (hadron && lepton) {
354 std::back_inserter(E),
356 const double sumEh = std::accumulate(E.begin(), E.end(), 0.);
358 std::list<double> pz;
360 std::back_inserter(pz),
362 const double sumPzh = std::accumulate(pz.begin(), pz.end(), 0.);
366 y = (hadron->GetE() * sumEh -
367 hadron->GetPz() * sumPzh -
368 pow(hadron->GetM(), 2.)) /
369 (lepton->GetE() * hadron->GetE() - lepton->GetPz() * hadron->GetPz());
372 return bounded(y, 0., 1.);
379 Double_t JacquetBlondelComputer::ComputeQSquared()
const {
385 std::list<double> px;
388 std::back_inserter(px),
391 std::list<double> py;
394 std::back_inserter(py),
396 double sumPx = std::accumulate(px.begin(), px.end(), 0.);
397 double sumPy = std::accumulate(py.begin(), py.end(), 0.);
398 double y = ComputeY();
400 Q2 = (pow(sumPx, 2.) + pow(sumPy, 2.)) / (1. - y);
403 return std::max(0., Q2);
409 Double_t JacquetBlondelComputer::ComputeX()
const {
414 if (hadron && lepton) {
415 double y = ComputeY();
416 double s = (hadron->Get4Vector() + lepton->Get4Vector()).M2();
419 x = ComputeQSquared() / y / s;
422 return bounded(x, 0., 1.);
427 DoubleAngleComputer::~DoubleAngleComputer() {
429 typedef std::vector<const VirtualParticle*>::iterator Iter;
430 for (Iter i = mParticles.begin(); i != mParticles.end(); ++i) {
444 std::vector<const erhic::VirtualParticle*>
final;
448 std::transform(
final.begin(),
final.end(), std::back_inserter(mParticles),
449 std::ptr_fun(&MeasuredParticle::Create));
458 kin->mQ2 = ComputeQSquared();
459 kin->mX = ComputeX();
460 kin->mY = ComputeY();
462 kin->mW2 = computeW2FromXQ2M(kin->mX, kin->mQ2,
481 std::list<TLorentzVector> hadrons;
482 std::transform(mParticles.begin(),
484 std::back_inserter(hadrons),
486 TLorentzVector h = std::accumulate(hadrons.begin(),
488 TLorentzVector(0., 0., 0., 0.));
489 mAngle = 2. * TMath::ATan((h.E() - h.Pz()) / h.Pt());
496 Double_t DoubleAngleComputer::ComputeY()
const {
500 double theta = scattered->
GetTheta();
502 double denominator = tan(theta / 2.) + tan(gamma / 2.);
503 if (denominator > 0.) {
504 y = tan(gamma / 2.) / denominator;
508 return bounded(y, 0., 1.);
513 Double_t DoubleAngleComputer::ComputeQSquared()
const {
515 const VirtualParticle* lepton = mEvent.
BeamLepton();
517 if (lepton && scattered) {
518 double theta = scattered->
GetTheta();
520 double denominator = tan(theta / 2.) + tan(gamma / 2.);
521 if (denominator > 0.) {
522 Q2 = 4. * pow(lepton->GetE(), 2.) / tan(theta / 2.) / denominator;
526 return std::max(0., Q2);
531 Double_t DoubleAngleComputer::ComputeX()
const {
533 const VirtualParticle* lepton = mEvent.
BeamLepton();
534 const VirtualParticle* hadron = mEvent.
BeamHadron();
535 if (lepton && hadron) {
536 double s = (lepton->Get4Vector() + hadron->Get4Vector()).M2();
537 double y = ComputeY();
538 if (s > 0. && y > 0.) {
539 x = ComputeQSquared() / y / s;
543 return bounded(x, 0., 1.);
virtual Double_t GetPhi() const =0
virtual Double_t GetP() const =0
DoubleAngleComputer(const EventDis &)
virtual Double_t GetM() const =0
virtual Double_t GetE() const =0
virtual Double_t GetPz() const =0
LeptonKinematicsComputer(const EventDis &)
Double_t mAngle
Caches the quark angle.
virtual TLorentzVector Get4Vector() const
virtual Double_t GetPy() const =0
virtual Double_t GetP() const
virtual Double_t GetPx() const =0
const EventDis & mEvent
The event for which kinematics are being calculated.
virtual const VirtualParticle * BeamLepton() const =0
virtual void HadronicFinalState(ParticlePtrList &) const
JacquetBlondelComputer(const EventDis &)
std::vector< const VirtualParticle * > mParticles
Array of final-state particles used in computing kinematics.
virtual Double_t ComputeQuarkAngle() const
virtual const VirtualParticle * ScatteredLepton() const =0
virtual TLorentzVector Get4Vector() const =0
TParticlePDG * Info() const
virtual Pid Id() const =0
virtual Double_t GetTheta() const =0
virtual Double_t GetE() const
virtual const VirtualParticle * BeamHadron() const =0
Abstract base class for a general particle.
virtual const VirtualParticle * ExchangeBoson() const =0