73 : _use_e (defs.get_bool (
"use_e")),
74 _e_com (defs.get_float (
"e_com")),
75 _ignore_met (defs.get_bool (
"ignore_met")),
76 _chisq_constrainer_args (defs)
178 int obj_index (
int i)
265 s <<
"Constraints: (e_com = " << c.
_args.
e_com() <<
") ";
274 s <<
"Mass constraint:\n";
299 void adjust_fourvecs (Fourvec_Event& ev,
311 int nobjs = ev.nobjs ();
312 for (
int i=0;
i < nobjs;
i++) {
313 const FE_Obj&
obj = ev.obj (
i);
366 if (obj.muon_p) e = 1/
e;
372 double xx = e*e - obj.mass*obj.mass;
384 if (obj.muon_p) p = 1/
p;
387 e = (obj.mass == 0 ? p :
sqrt (obj.mass*obj.mass + p*p));
393 if (fabs (eta) > 50) {
395 eta = eta > 0 ? 50 : -50;
397 double exp_eta =
exp (eta);
398 double iexp_eta = 1/exp_eta;
399 double sin_theta = 2 / (exp_eta + iexp_eta);
400 double cos_theta = (exp_eta - iexp_eta) / (exp_eta + iexp_eta);
404 p * sin_theta *
sin (phi),
426 void set_p_eta_phi_vec (
const FE_Obj& obj,
445 c(ndx +
p_offs) = obj.p.vect().mag();
449 c(ndx +
eta_offs) = obj.p.pseudoRapidity();
462 Matrix error_matrix (
double p_sig,
510 void pack_event (
const Fourvec_Event& ev,
535 int nobjs = ev.nobjs ();
537 int n_measured_vars = nobjs * 3;
539 n_measured_vars += 2;
542 G_i =
Matrix (n_measured_vars, n_measured_vars, 0);
545 for (
int i=0;
i<nobjs;
i++) {
546 const FE_Obj& obj = ev.obj (
i);
547 int this_index = obj_index (
i);
548 set_p_eta_phi_vec (obj, xm, this_index, use_e_flag);
549 G_i.sub (this_index, this_index, error_matrix (obj.p_error,
557 int kt_ndx = obj_index (nobjs);
558 xm (kt_ndx+
x_offs) = ev.kt().x();
559 xm (kt_ndx+
y_offs) = ev.kt().y();
562 G_i(kt_ndx+
x_offs, kt_ndx+
x_offs) = ev.kt_x_error() * ev.kt_x_error();
563 G_i(kt_ndx+
y_offs, kt_ndx+
y_offs) = ev.kt_y_error() * ev.kt_y_error();
569 if (ev.has_neutrino()) {
570 ym(
nu_z) = ev.nu().z();
595 void unpack_event (Fourvec_Event& ev,
615 for (
int j=0;
j<ev.nobjs();
j++) {
616 const FE_Obj& obj = ev.obj (
j);
617 ev.set_obj_p (
j, get_p_eta_phi_vec (x, obj_index (
j), obj, use_e_flag));
623 int kt_ndx = obj_index (ev.nobjs());
626 if (ev.has_neutrino()) {
678 double dot_and_gradient (
const Fourvec& v1,
703 double dot = v1 * v2;
705 double p1 = v1.vect().mag();
706 double p2 = v2.vect().mag();
709 double pt1 = v1.vect().perp();
710 double pt2 = v2.vect().perp();
714 if (p1 == 0 || p2 == 0 || e1 == 0 || e2 == 0 || pt1 == 0 || pt2 == 0) {
722 v1_x[
p_offs] = (dot - v1.m2() * e2 /
e1) / p1;
723 v2_x[
p_offs] = (dot - v2.m2() * e1 /
e2) / p2;
730 v1_x[
phi_offs] = v1(1)*v2(0) - v1(0)*v2(1);
733 double fac = v1(0)*v2(0) + v1(1)*v2(1);
734 v1_x[
eta_offs] = pt1*v2(2) - v1(2)/pt1 * fac;
735 v2_x[
eta_offs] = pt2*v1(2) - v2(2)/pt2 * fac;
762 void addin_obj_gradient (
int constraint_no,
785 Bx(base_index +
p_offs, constraint_no) += sign * grad[
p_offs];
818 void addin_nu_gradient (
int constraint_no,
874 void addin_gradient (
const Fourvec_Event& ev,
901 if (obj_no >= ev.nobjs()) {
902 assert (obj_no == ev.nobjs());
903 addin_nu_gradient (constraint_no, sign, obj_index (obj_no), grad, Bx, By);
906 addin_obj_gradient (constraint_no, sign, obj_index (obj_no), grad, Bx);
940 void addin_gradients (
const Fourvec_Event& ev,
944 const double igrad[],
946 const double jgrad[],
970 addin_gradient (ev, constraint_no, sign, i, igrad, Bx, By);
971 addin_gradient (ev, constraint_no, sign, j, jgrad, Bx, By);
987 void add_mass_terms (
const Fourvec_Event& ev,
1003 F(
i+1) += constraints[
i].sum_mass_terms (ev);
1040 bool calculate_mass_constraints (
const Fourvec_Event& ev,
1041 const Pair_Table&
pt,
1042 const vector<Constraint>& constraints,
1069 int npairs = pt.npairs ();
1070 for (
int p=0; p < npairs; p++) {
1071 const Objpair& objpair = pt.get_pair (p);
1072 int i = objpair.i();
1073 int j = objpair.j();
1074 double igrad[3], jgrad[3];
1075 bool badflag =
false;
1076 double dot = dot_and_gradient (ev.obj (i).p,
1086 if (objpair.for_constraint (
k)) {
1087 F(
k+1) += objpair.for_constraint (
k) *
dot;
1088 addin_gradients (ev,
k+1, objpair.for_constraint (
k),
1089 i, igrad,
j, jgrad, Bx, By);
1094 add_mass_terms (ev, constraints, F);
1121 void add_nuterm (
unsigned ndx,
1143 double cot_theta = v.pz() / v.vect().perp();
1145 for (
int j=1; j<=Bx.num_col(); j++) {
1146 double dxnu = Bx(kt_ndx+
x_offs, j);
1147 double dynu = Bx(kt_ndx+
y_offs, j);
1149 if (dxnu != 0 || dynu != 0) {
1150 double fac = 1 / v.vect().mag();
1152 fac = v.e() * fac * fac;
1153 Bx(ndx +
p_offs, j) -= (px*dxnu + py*dynu) * fac;
1154 Bx(ndx +
phi_offs, j) += py*dxnu - px*dynu;
1155 Bx(ndx +
eta_offs, j) -= (px*dxnu + py*dynu) * cot_theta;
1184 void convert_neutrino (
const Fourvec_Event& ev,
1205 int nconstraints = Bx.num_col ();
1210 double pnu2 = nu.vect().mag2();
double pnu =
sqrt (pnu2);
1211 double ptnu2 = nu.vect().perp2();
double ptnu =
sqrt (ptnu2);
1215 double thfac = nu.z()/pnu2/ptnu;
1217 fac[0][0] = nu(0)/pnu; fac[0][1] = nu(1)/pnu; fac[0][2] = nu(2)/pnu;
1218 fac[1][0] = - nu(1)/ptnu2; fac[1][1] = nu(0)/ptnu2; fac[1][2] = 0;
1219 fac[2][0] = nu(0)*thfac; fac[2][1] = nu(1)*thfac; fac[2][2] = -ptnu/pnu2;
1221 int kt_ndx = obj_index (ev.nobjs());
1222 for (
int j=1; j<=nconstraints; j++) {
1223 double tmp1 = fac[0][0]*Bx(kt_ndx+
x_offs,j) +
1224 fac[1][0]*Bx(kt_ndx+
y_offs,j) +
1225 fac[2][0]*By(
nu_z,j);
1227 fac[1][1]*Bx(kt_ndx+
y_offs,j) +
1228 fac[2][1]*By(
nu_z,j);
1229 By(
nu_z,j) = fac[0][2]*Bx(kt_ndx+
x_offs,j) + fac[2][2]*By(
nu_z,j);
1231 Bx(kt_ndx+
x_offs,j) = tmp1;
1235 for (
int j=0; j<ev.nobjs(); j++) {
1236 add_nuterm (obj_index (j), ev.obj(j).p, Bx, use_e_flag, kt_ndx);
1261 void calculate_kt_constraints (
const Fourvec_Event& ev,
1281 int base = F.num_col() - 2;
1282 int nobjs = ev.nobjs();
1283 for (
int j=0; j<nobjs; j++) {
1284 const Fourvec& obj = ev.obj (j).p;
1287 int ndx = obj_index (j);
1288 double p = obj.vect().mag();
1289 double cot_theta = obj.z() / obj.vect().perp();
1300 Bx(ndx +
p_offs, base+1) *= obj.e() /
p;
1301 Bx(ndx +
p_offs, base+2) *= obj.e() /
p;
1305 int kt_ndx = obj_index (nobjs);
1306 Bx(kt_ndx+
x_offs, base+1) = -1;
1307 Bx(kt_ndx+
y_offs, base+2) = -1;
1309 F(base+1) =
tmp(0) - ev.kt().x ();
1310 F(base+2) =
tmp(1) - ev.kt().y ();
1327 void ddtheta_to_ddeta (
int i,
double cos_theta,
Matrix& Bx)
1341 double sin_theta =
sqrt (1 - cos_theta * cos_theta);
1342 for (
int j=1; j<=Bx.num_col(); j++)
1343 Bx(i,j) *= - sin_theta;
1384 const vector<Constraint>& constraints,
1434 const vector<Constraint>& constraints,
1448 _constraints (constraints),
1450 _pt (constraints, ev)
1484 Bx =
Matrix (Bx.num_row(), Bx.num_col(), 0);
1485 By =
Matrix (By.num_row(), By.num_col(), 0);
1488 const double p_eps = 1e-10;
1490 if (_ev.has_neutrino() && _ev.nu().z() > _args.e_com()) {
1494 int nobjs = _ev.nobjs ();
1497 for (
int j=0; j<nobjs; j++) {
1498 if (_ev.obj(j).p.perp() <= p_eps || _ev.obj(j).p.e() <= p_eps) {
1503 if (! calculate_mass_constraints (_ev, _pt, _constraints, _args.use_e(),
1507 if (_ev.has_neutrino())
1508 convert_neutrino (_ev, _args.use_e(), Bx, By);
1509 else if (!_args.ignore_met())
1512 calculate_kt_constraints (_ev, _args.use_e(),
F, Bx);
1516 for (
int j=0; j<nobjs; j++) {
1517 ddtheta_to_ddeta (obj_index (j) +
eta_offs,
1518 _ev.obj(j).p.cosTheta(),
1523 for (
int j=0; j<nobjs; j++) {
1524 const FE_Obj& obj = _ev.obj (j);
1527 double pmu2 = obj.
p.vect().mag2();
1528 int ndx = obj_index (j) +
p_offs;
1529 for (
int k=1;
k<=Bx.num_col();
k++)
1530 Bx(ndx,
k) = - Bx(ndx,
k) * pmu2;
1590 const double p_eps = 1e-10;
1591 const double eta_max = 10;
1594 for (
int j=0; j<nobjs; j++)
1595 if (
x(obj_index (j) +
p_offs) < p_eps ||
1596 fabs(
x(obj_index (j) +
eta_offs)) > eta_max) {
1632 double calculate_sigm (
const Matrix& Q,
1648 double sig2 =
scalar (Bx.T() * Q * Bx);
1650 if (By.num_row() > 0) {
1651 sig2 +=
scalar (By.T() * R * By);
1652 sig2 += 2 *
scalar (Bx.T() * S * By);
1682 void calculate_mass (Fourvec_Event& ev,
1683 const vector<Constraint>& mass_constraint,
1684 const Fourvec_Constrainer_Args& args,
1709 if (mass_constraint.size () == 0) {
1716 int n_measured_vars = ev.nobjs()*3 + 2;
1717 int n_unmeasured_vars = 0;
1718 if (ev.has_neutrino ()) n_unmeasured_vars = 1;
1721 Matrix Bx (n_measured_vars, 1);
1722 Matrix By (n_unmeasured_vars, 1);
1724 Fourvec_Constraint_Calculator cc (ev, mass_constraint, args);
1725 cc.calculate_constraints (F, Bx, By);
1730 m =
sqrt (
F(1) * 2);
1745 sigm = calculate_sigm (Q, R, S, Bx, By);
1781 int nobjs = ev.
nobjs ();
1782 int n_measured_vars = nobjs * 3;
1783 int n_unmeasured_vars = 0;
1787 n_measured_vars += 2;
1790 n_unmeasured_vars = 1;
1795 Matrix G_i (n_measured_vars, n_measured_vars);
1812 double chisq = fitter.fit (cc,
1813 xm, x, ym, y, G_i, Y,
1817 unpack_event (ev, x, y,
_args.
use_e (), use_kt);
Define an abstract interface for getting parameter settings.
Represent a mass constraint equation. Mass constraints come in two varieties, either saying that the ...
void adjust_e_for_mass(Fourvec &v, double mass)
Adjust the energy component of four-vector v (leaving the three-vector part unchanged) so that the fo...
Represent an event for kinematic fitting as a collection of four-momenta. Each object is represented ...
Sin< T >::type sin(const T &t)
Fourvec_Constrainer(const Fourvec_Constrainer_Args &args)
Constructor.
CLHEP::HepVector Column_Vector
Concrete realization of the Constraint_Calculator class. Evaluate constraints at the point described ...
Define matrix types for the HitFit package, and supply a few additional operations.
int nobjs() const
Return the number of objects in the event not including any neutrinos.
Abstract base class for evaluating constraints. Users derive from this class and implement the eval()...
Fourvec_Constrainer_Args(const Defaults &defs)
Constructor, initialize from a Defaults object.
bool calculate_constraints(Row_Vector &F, Matrix &Bx, Matrix &By) const
Calculate the constraint functions and gradients.
virtual ~Fourvec_Constraint_Calculator()
Cos< T >::type cos(const T &t)
Minimize a subject to a set of constraints. Based on the SQUAW algorithm.
Minimize a subject to a set of constraints, based on the SQUAW algorithm.
CLHEP::HepLorentzVector Fourvec
Typedef for a HepLorentzVector.
const Chisq_Constrainer_Args & chisq_constrainer_args() const
Hold on to parameters for the Chisq_Constrainer class.
const Fourvec_Constrainer_Args _args
void adjust_p_for_mass(Fourvec &v, double mass)
Adjust the three-vector part of v, leaving the energy unchanged,.
std::vector< Constraint > _mass_constraint
Fourvec_Constraint_Calculator(Fourvec_Event &ev, const vector< Constraint > &constraints, const Fourvec_Constrainer_Args &args)
Constructor.
CLHEP::HepDiagMatrix Diagonal_Matrix
A lookup table to speed up constraint evaluation using Fourvec_Constrainer.
virtual bool eval(const Column_Vector &x, const Column_Vector &y, Row_Vector &F, Matrix &Bx, Matrix &By) override
Evaluate constraints at the point described by x and y (well-measured and poorly-measured variables...
std::vector< std::vector< double > > tmp
Chisq_Constrainer_Args _chisq_constrainer_args
std::vector< Constraint > _constraints
T dot(const Basic3DVector &v) const
Scalar product, or "dot" product, with a vector of same type.
double constrain(Fourvec_Event &ev, double &m, double &sigm, Column_Vector &pullx, Column_Vector &pully)
Do a constrained fit for event ev. Returns the requested mass and its uncertainty in m and sigm...
Define an interface for getting parameter settings.
std::ostream & operator<<(std::ostream &s, const Constraint_Intermed &ci)
Output stream operator, print the content of this Constraint_Intermed to an output stream...
const Fourvec_Constrainer_Args & _args
Do a kinematic fit for a set of four-vectors, given a set of mass constraints.
void mass_constraint(std::string s)
Specify a combination of objects that will be returned by the constrain() method as mass...
Represent a single object in a Fourvec_Event, this is just a dumb data container. Each object in a Fo...
static uInt32 F(BLOWFISH_CTX *ctx, uInt32 x)
const vector< Constraint > & _constraints
void add_constraint(std::string s)
Specify an additional constraint s for the problem. The format for s is described in the class descri...
Do a kinematic fit for a set of four-momenta, given a set of mass constraints.
A lookup table to speed up constraint evaluation.
Row-vector class. CLHEP doesn't have a row-vector class, so HitFit uses its own. This is only a simpl...
Hold on to parameters for the Fourvec_Constrainer class.
double scalar(const CLHEP::HepGenMatrix &m)
Return the matrix as a scalar. Raise an assertion if the matris is not .
Represent an event for kinematic fitting as a collection of four-momenta.
bool has_neutrino() const
Return TRUE is this event contains a neutrino, otherwise returns FALSE.