74 : _use_e (defs.get_bool (
"use_e")),
75 _e_com (defs.get_float (
"e_com")),
76 _ignore_met (defs.get_bool (
"ignore_met")),
77 _chisq_constrainer_args (defs)
179 int obj_index (
int i)
266 s <<
"Constraints: (e_com = " << c.
_args.
e_com() <<
") ";
275 s <<
"Mass constraint:\n";
300 void adjust_fourvecs (Fourvec_Event& ev,
312 int nobjs = ev.nobjs ();
313 for (
int i=0;
i < nobjs;
i++) {
314 const FE_Obj&
obj = ev.obj (
i);
367 if (obj.muon_p) e = 1/
e;
373 double xx = e*e - obj.mass*obj.mass;
385 if (obj.muon_p) p = 1/
p;
388 e = (obj.mass == 0 ? p :
sqrt (obj.mass*obj.mass + p*p));
394 if (fabs (eta) > 50) {
396 eta = eta > 0 ? 50 : -50;
398 double exp_eta =
exp (eta);
399 double iexp_eta = 1/exp_eta;
400 double sin_theta = 2 / (exp_eta + iexp_eta);
401 double cos_theta = (exp_eta - iexp_eta) / (exp_eta + iexp_eta);
405 p * sin_theta *
sin (phi),
427 void set_p_eta_phi_vec (
const FE_Obj& obj,
446 c(ndx +
p_offs) = obj.p.vect().mag();
450 c(ndx +
eta_offs) = obj.p.pseudoRapidity();
463 Matrix error_matrix (
double p_sig,
511 void pack_event (
const Fourvec_Event& ev,
536 int nobjs = ev.nobjs ();
538 int n_measured_vars = nobjs * 3;
540 n_measured_vars += 2;
543 G_i =
Matrix (n_measured_vars, n_measured_vars, 0);
546 for (
int i=0;
i<nobjs;
i++) {
547 const FE_Obj& obj = ev.obj (
i);
548 int this_index = obj_index (
i);
549 set_p_eta_phi_vec (obj, xm, this_index, use_e_flag);
550 G_i.sub (this_index, this_index, error_matrix (obj.p_error,
558 int kt_ndx = obj_index (nobjs);
559 xm (kt_ndx+
x_offs) = ev.kt().x();
560 xm (kt_ndx+
y_offs) = ev.kt().y();
563 G_i(kt_ndx+
x_offs, kt_ndx+
x_offs) = ev.kt_x_error() * ev.kt_x_error();
564 G_i(kt_ndx+
y_offs, kt_ndx+
y_offs) = ev.kt_y_error() * ev.kt_y_error();
570 if (ev.has_neutrino()) {
571 ym(
nu_z) = ev.nu().z();
596 void unpack_event (Fourvec_Event& ev,
616 for (
int j=0;
j<ev.nobjs();
j++) {
617 const FE_Obj& obj = ev.obj (
j);
618 ev.set_obj_p (
j, get_p_eta_phi_vec (x, obj_index (
j), obj, use_e_flag));
624 int kt_ndx = obj_index (ev.nobjs());
627 if (ev.has_neutrino()) {
679 double dot_and_gradient (
const Fourvec& v1,
704 double dot = v1 * v2;
706 double p1 = v1.vect().mag();
707 double p2 = v2.vect().mag();
710 double pt1 = v1.vect().perp();
711 double pt2 = v2.vect().perp();
715 if (p1 == 0 || p2 == 0 || e1 == 0 || e2 == 0 || pt1 == 0 || pt2 == 0) {
723 v1_x[
p_offs] = (dot - v1.m2() * e2 /
e1) / p1;
724 v2_x[
p_offs] = (dot - v2.m2() * e1 /
e2) / p2;
731 v1_x[
phi_offs] = v1(1)*v2(0) - v1(0)*v2(1);
734 double fac = v1(0)*v2(0) + v1(1)*v2(1);
735 v1_x[
eta_offs] = pt1*v2(2) - v1(2)/pt1 * fac;
736 v2_x[
eta_offs] = pt2*v1(2) - v2(2)/pt2 * fac;
763 void addin_obj_gradient (
int constraint_no,
786 Bx(base_index +
p_offs, constraint_no) += sign * grad[
p_offs];
819 void addin_nu_gradient (
int constraint_no,
875 void addin_gradient (
const Fourvec_Event& ev,
902 if (obj_no >= ev.nobjs()) {
903 assert (obj_no == ev.nobjs());
904 addin_nu_gradient (constraint_no, sign, obj_index (obj_no), grad, Bx, By);
907 addin_obj_gradient (constraint_no, sign, obj_index (obj_no), grad, Bx);
941 void addin_gradients (
const Fourvec_Event& ev,
945 const double igrad[],
947 const double jgrad[],
971 addin_gradient (ev, constraint_no, sign, i, igrad, Bx, By);
972 addin_gradient (ev, constraint_no, sign, j, jgrad, Bx, By);
988 void add_mass_terms (
const Fourvec_Event& ev,
1004 F(
i+1) += constraints[
i].sum_mass_terms (ev);
1041 bool calculate_mass_constraints (
const Fourvec_Event& ev,
1042 const Pair_Table& pt,
1043 const vector<Constraint>& constraints,
1070 int npairs = pt.npairs ();
1071 for (
int p=0; p < npairs; p++) {
1072 const Objpair& objpair = pt.get_pair (p);
1073 int i = objpair.i();
1074 int j = objpair.j();
1075 double igrad[3], jgrad[3];
1076 bool badflag =
false;
1077 double dot = dot_and_gradient (ev.obj (i).p,
1087 if (objpair.for_constraint (
k)) {
1088 F(
k+1) += objpair.for_constraint (
k) *
dot;
1089 addin_gradients (ev,
k+1, objpair.for_constraint (
k),
1090 i, igrad,
j, jgrad, Bx, By);
1095 add_mass_terms (ev, constraints, F);
1122 void add_nuterm (
unsigned ndx,
1144 double cot_theta = v.pz() / v.vect().perp();
1146 for (
int j=1; j<=Bx.num_col(); j++) {
1147 double dxnu = Bx(kt_ndx+
x_offs, j);
1148 double dynu = Bx(kt_ndx+
y_offs, j);
1150 if (dxnu != 0 || dynu != 0) {
1151 double fac = 1 / v.vect().mag();
1153 fac = v.e() * fac * fac;
1154 Bx(ndx +
p_offs, j) -= (px*dxnu + py*dynu) * fac;
1155 Bx(ndx +
phi_offs, j) += py*dxnu - px*dynu;
1156 Bx(ndx +
eta_offs, j) -= (px*dxnu + py*dynu) * cot_theta;
1185 void convert_neutrino (
const Fourvec_Event& ev,
1206 int nconstraints = Bx.num_col ();
1211 double pnu2 = nu.vect().mag2();
double pnu =
sqrt (pnu2);
1212 double ptnu2 = nu.vect().perp2();
double ptnu =
sqrt (ptnu2);
1216 double thfac = nu.z()/pnu2/ptnu;
1218 fac[0][0] = nu(0)/pnu; fac[0][1] = nu(1)/pnu; fac[0][2] = nu(2)/pnu;
1219 fac[1][0] = - nu(1)/ptnu2; fac[1][1] = nu(0)/ptnu2; fac[1][2] = 0;
1220 fac[2][0] = nu(0)*thfac; fac[2][1] = nu(1)*thfac; fac[2][2] = -ptnu/pnu2;
1222 int kt_ndx = obj_index (ev.nobjs());
1223 for (
int j=1; j<=nconstraints; j++) {
1224 double tmp1 = fac[0][0]*Bx(kt_ndx+
x_offs,j) +
1225 fac[1][0]*Bx(kt_ndx+
y_offs,j) +
1226 fac[2][0]*By(
nu_z,j);
1228 fac[1][1]*Bx(kt_ndx+
y_offs,j) +
1229 fac[2][1]*By(
nu_z,j);
1230 By(
nu_z,j) = fac[0][2]*Bx(kt_ndx+
x_offs,j) + fac[2][2]*By(
nu_z,j);
1232 Bx(kt_ndx+
x_offs,j) = tmp1;
1236 for (
int j=0; j<ev.nobjs(); j++) {
1237 add_nuterm (obj_index (j), ev.obj(j).p, Bx, use_e_flag, kt_ndx);
1262 void calculate_kt_constraints (
const Fourvec_Event& ev,
1282 int base = F.num_col() - 2;
1283 int nobjs = ev.nobjs();
1284 for (
int j=0; j<nobjs; j++) {
1285 const Fourvec& obj = ev.obj (j).p;
1288 int ndx = obj_index (j);
1289 double p = obj.vect().mag();
1290 double cot_theta = obj.z() / obj.vect().perp();
1301 Bx(ndx +
p_offs, base+1) *= obj.e() /
p;
1302 Bx(ndx +
p_offs, base+2) *= obj.e() /
p;
1306 int kt_ndx = obj_index (nobjs);
1307 Bx(kt_ndx+
x_offs, base+1) = -1;
1308 Bx(kt_ndx+
y_offs, base+2) = -1;
1310 F(base+1) =
tmp(0) - ev.kt().x ();
1311 F(base+2) =
tmp(1) - ev.kt().y ();
1328 void ddtheta_to_ddeta (
int i,
double cos_theta,
Matrix& Bx)
1342 double sin_theta =
sqrt (1 - cos_theta * cos_theta);
1343 for (
int j=1; j<=Bx.num_col(); j++)
1344 Bx(i,j) *= - sin_theta;
1385 const vector<Constraint>& constraints,
1435 const vector<Constraint>& constraints,
1449 _constraints (constraints),
1451 _pt (constraints, ev)
1485 Bx =
Matrix (Bx.num_row(), Bx.num_col(), 0);
1486 By =
Matrix (By.num_row(), By.num_col(), 0);
1489 const double p_eps = 1e-10;
1491 if (_ev.has_neutrino() && _ev.nu().z() > _args.e_com()) {
1495 int nobjs = _ev.nobjs ();
1498 for (
int j=0; j<nobjs; j++) {
1499 if (_ev.obj(j).p.perp() <= p_eps || _ev.obj(j).p.e() <= p_eps) {
1504 if (! calculate_mass_constraints (_ev, _pt, _constraints, _args.use_e(),
1508 if (_ev.has_neutrino())
1509 convert_neutrino (_ev, _args.use_e(), Bx, By);
1510 else if (!_args.ignore_met())
1513 calculate_kt_constraints (_ev, _args.use_e(),
F, Bx);
1517 for (
int j=0; j<nobjs; j++) {
1518 ddtheta_to_ddeta (obj_index (j) +
eta_offs,
1519 _ev.obj(j).p.cosTheta(),
1524 for (
int j=0; j<nobjs; j++) {
1525 const FE_Obj& obj = _ev.obj (j);
1528 double pmu2 = obj.
p.vect().mag2();
1529 int ndx = obj_index (j) +
p_offs;
1530 for (
int k=1;
k<=Bx.num_col();
k++)
1531 Bx(ndx,
k) = - Bx(ndx,
k) * pmu2;
1591 const double p_eps = 1e-10;
1592 const double eta_max = 10;
1595 for (
int j=0; j<nobjs; j++)
1596 if (
x(obj_index (j) +
p_offs) < p_eps ||
1597 fabs(
x(obj_index (j) +
eta_offs)) > eta_max) {
1633 double calculate_sigm (
const Matrix& Q,
1649 double sig2 =
scalar (Bx.T() * Q * Bx);
1651 if (By.num_row() > 0) {
1652 sig2 +=
scalar (By.T() * R * By);
1653 sig2 += 2 *
scalar (Bx.T() * S * By);
1683 void calculate_mass (Fourvec_Event& ev,
1684 const vector<Constraint>& mass_constraint,
1685 const Fourvec_Constrainer_Args& args,
1710 if (mass_constraint.size () == 0) {
1717 int n_measured_vars = ev.nobjs()*3 + 2;
1718 int n_unmeasured_vars = 0;
1719 if (ev.has_neutrino ()) n_unmeasured_vars = 1;
1722 Matrix Bx (n_measured_vars, 1);
1723 Matrix By (n_unmeasured_vars, 1);
1725 Fourvec_Constraint_Calculator cc (ev, mass_constraint, args);
1726 cc.calculate_constraints (F, Bx, By);
1731 m =
sqrt (
F(1) * 2);
1746 sigm = calculate_sigm (Q, R, S, Bx, By);
1782 int nobjs = ev.
nobjs ();
1783 int n_measured_vars = nobjs * 3;
1784 int n_unmeasured_vars = 0;
1788 n_measured_vars += 2;
1791 n_unmeasured_vars = 1;
1796 Matrix G_i (n_measured_vars, n_measured_vars);
1813 double chisq = fitter.fit (cc,
1814 xm, x, ym, y, G_i, Y,
1818 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.
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...
virtual bool eval(const Column_Vector &x, const Column_Vector &y, Row_Vector &F, Matrix &Bx, Matrix &By)
Evaluate constraints at the point described by x and y (well-measured and poorly-measured variables...
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.