00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00041 #include "TopQuarkAnalysis/TopHitFit/interface/Fourvec_Constrainer.h"
00042 #include "TopQuarkAnalysis/TopHitFit/interface/Fourvec_Event.h"
00043 #include "TopQuarkAnalysis/TopHitFit/interface/Pair_Table.h"
00044 #include "TopQuarkAnalysis/TopHitFit/interface/Chisq_Constrainer.h"
00045 #include "TopQuarkAnalysis/TopHitFit/interface/matutil.h"
00046 #include "TopQuarkAnalysis/TopHitFit/interface/Defaults.h"
00047 #include <cmath>
00048 #include <iostream>
00049
00050
00051 using std::sqrt;
00052 using std::exp;
00053 using std::cos;
00054 using std::sin;
00055 using std::ostream;
00056 using std::vector;
00057
00058
00059 namespace hitfit {
00060
00061
00062
00063
00064
00065
00066
00067 Fourvec_Constrainer_Args::Fourvec_Constrainer_Args (const Defaults& defs)
00068
00069
00070
00071
00072
00073
00074 : _use_e (defs.get_bool ("use_e")),
00075 _e_com (defs.get_float ("e_com")),
00076 _ignore_met (defs.get_bool ("ignore_met")),
00077 _chisq_constrainer_args (defs)
00078 {
00079 }
00080
00081
00082 bool Fourvec_Constrainer_Args::use_e () const
00083
00084
00085
00086
00087 {
00088 return _use_e;
00089 }
00090
00091
00092 double Fourvec_Constrainer_Args::e_com () const
00093
00094
00095
00096
00097 {
00098 return _e_com;
00099 }
00100
00101
00102 bool Fourvec_Constrainer_Args::ignore_met () const
00103
00104
00105
00106
00107 {
00108 return _ignore_met;
00109 }
00110
00111
00112 const Chisq_Constrainer_Args&
00113 Fourvec_Constrainer_Args::chisq_constrainer_args () const
00114
00115
00116
00117 {
00118 return _chisq_constrainer_args;
00119 }
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00141 typedef enum {
00142 p_offs = 0,
00143 phi_offs = 1,
00144 eta_offs = 2
00145 } Offsets;
00146
00151 typedef enum {
00152 x_offs = 0,
00153 y_offs = 1
00154 } Kt_Offsets;
00155
00156
00157
00158
00159
00164 typedef enum {
00165 nu_z = 1
00166 } Unmeasured_Variables;
00167
00168
00169
00170 namespace {
00171
00172
00179 int obj_index (int i)
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190 {
00191 return i*3 + 1;
00192 }
00193
00194
00195 }
00196
00197
00198
00199
00200
00201
00202
00203 Fourvec_Constrainer::Fourvec_Constrainer (const Fourvec_Constrainer_Args& args)
00204
00205
00206
00207
00208
00209
00210 : _args (args)
00211 {
00212 }
00213
00214
00215 void Fourvec_Constrainer::add_constraint (std::string s)
00216
00217
00218
00219
00220
00221
00222
00223 {
00224 _constraints.push_back (Constraint (s));
00225 }
00226
00227
00228 void Fourvec_Constrainer::mass_constraint (std::string s)
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239 {
00240 assert (_mass_constraint.size() == 0);
00241 _mass_constraint.push_back (Constraint (s));
00242 }
00243
00244
00254 std::ostream& operator<< (std::ostream& s, const Fourvec_Constrainer& c)
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265 {
00266 s << "Constraints: (e_com = " << c._args.e_com() << ") ";
00267 if (c._args.use_e())
00268 s << "(E)";
00269 s << "\n";
00270
00271 for (std::vector<Constraint>::size_type i=0; i < c._constraints.size(); i++)
00272 s << " " << c._constraints[i] << "\n";
00273
00274 if (c._mass_constraint.size() > 0) {
00275 s << "Mass constraint:\n";
00276 s << c._mass_constraint[0] << "\n";
00277 }
00278 return s;
00279 }
00280
00281
00282
00283
00284
00285
00286
00287 namespace {
00288
00289
00300 void adjust_fourvecs (Fourvec_Event& ev,
00301 bool use_e_flag)
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311 {
00312 int nobjs = ev.nobjs ();
00313 for (int i=0; i < nobjs; i++) {
00314 const FE_Obj& obj = ev.obj (i);
00315 Fourvec p = obj.p;
00316 if (use_e_flag)
00317 adjust_p_for_mass (p, obj.mass);
00318 else
00319 adjust_e_for_mass (p, obj.mass);
00320 ev.set_obj_p (i, p);
00321 }
00322 }
00323
00324
00341 Fourvec get_p_eta_phi_vec (const Column_Vector& c,
00342 int ndx,
00343 const FE_Obj& obj,
00344 bool use_e_flag)
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358 {
00359
00360 double e, p;
00361
00362 if (use_e_flag) {
00363
00364 e = c(ndx + p_offs);
00365
00366
00367 if (obj.muon_p) e = 1/e;
00368
00369
00370 if (obj.mass == 0)
00371 p = e;
00372 else {
00373 double xx = e*e - obj.mass*obj.mass;
00374 if (xx >= 0)
00375 p = sqrt (xx);
00376 else
00377 p = 0;
00378 }
00379 }
00380 else {
00381
00382 p = c(ndx + p_offs);
00383
00384
00385 if (obj.muon_p) p = 1/p;
00386
00387
00388 e = (obj.mass == 0 ? p : sqrt (obj.mass*obj.mass + p*p));
00389 }
00390
00391
00392 double phi = c(ndx + phi_offs);
00393 double eta = c(ndx + eta_offs);
00394 if (fabs (eta) > 50) {
00395
00396 eta = eta > 0 ? 50 : -50;
00397 }
00398 double exp_eta = exp (eta);
00399 double iexp_eta = 1/exp_eta;
00400 double sin_theta = 2 / (exp_eta + iexp_eta);
00401 double cos_theta = (exp_eta - iexp_eta) / (exp_eta + iexp_eta);
00402
00403
00404 return Fourvec (p * sin_theta * cos (phi),
00405 p * sin_theta * sin (phi),
00406 p * cos_theta,
00407 e);
00408 }
00409
00410
00427 void set_p_eta_phi_vec (const FE_Obj& obj,
00428 Column_Vector& c,
00429 int ndx,
00430 bool use_e_flag)
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442 {
00443 if (use_e_flag)
00444 c(ndx + p_offs) = obj.p.e();
00445 else
00446 c(ndx + p_offs) = obj.p.vect().mag();
00447
00448 if (obj.muon_p) c(ndx + p_offs) = 1/c(ndx + p_offs);
00449 c(ndx + phi_offs) = obj.p.phi();
00450 c(ndx + eta_offs) = obj.p.pseudoRapidity();
00451 }
00452
00453
00463 Matrix error_matrix (double p_sig,
00464 double phi_sig,
00465 double eta_sig)
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477 {
00478 Matrix err (3, 3, 0);
00479 err(1+ p_offs, 1+ p_offs) = p_sig * p_sig;
00480 err(1+phi_offs, 1+phi_offs) = phi_sig * phi_sig;
00481 err(1+eta_offs, 1+eta_offs) = eta_sig * eta_sig;
00482 return err;
00483 }
00484
00485
00511 void pack_event (const Fourvec_Event& ev,
00512 bool use_e_flag,
00513 bool use_kt_flag,
00514 Column_Vector& xm,
00515 Column_Vector& ym,
00516 Matrix& G_i,
00517 Diagonal_Matrix& Y)
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534 {
00535
00536 int nobjs = ev.nobjs ();
00537
00538 int n_measured_vars = nobjs * 3;
00539 if (use_kt_flag)
00540 n_measured_vars += 2;
00541
00542
00543 G_i = Matrix (n_measured_vars, n_measured_vars, 0);
00544
00545
00546 for (int i=0; i<nobjs; i++) {
00547 const FE_Obj& obj = ev.obj (i);
00548 int this_index = obj_index (i);
00549 set_p_eta_phi_vec (obj, xm, this_index, use_e_flag);
00550 G_i.sub (this_index, this_index, error_matrix (obj.p_error,
00551 obj.phi_error,
00552 obj.eta_error));
00553
00554 }
00555
00556 if (use_kt_flag) {
00557
00558 int kt_ndx = obj_index (nobjs);
00559 xm (kt_ndx+x_offs) = ev.kt().x();
00560 xm (kt_ndx+y_offs) = ev.kt().y();
00561
00562
00563 G_i(kt_ndx+x_offs, kt_ndx+x_offs) = ev.kt_x_error() * ev.kt_x_error();
00564 G_i(kt_ndx+y_offs, kt_ndx+y_offs) = ev.kt_y_error() * ev.kt_y_error();
00565 G_i(kt_ndx+x_offs, kt_ndx+y_offs) = ev.kt_xy_covar();
00566 G_i(kt_ndx+y_offs, kt_ndx+x_offs) = ev.kt_xy_covar();
00567 }
00568
00569
00570 if (ev.has_neutrino()) {
00571 ym(nu_z) = ev.nu().z();
00572 Y = Diagonal_Matrix (1, 0);
00573 }
00574 }
00575
00576
00596 void unpack_event (Fourvec_Event& ev,
00597 const Column_Vector& x,
00598 const Column_Vector& y,
00599 bool use_e_flag,
00600 bool use_kt_flag)
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613 {
00614
00615 Fourvec sum = Fourvec(0);
00616 for (int j=0; j<ev.nobjs(); j++) {
00617 const FE_Obj& obj = ev.obj (j);
00618 ev.set_obj_p (j, get_p_eta_phi_vec (x, obj_index (j), obj, use_e_flag));
00619 sum += obj.p;
00620 }
00621
00622
00623 if (use_kt_flag) {
00624 int kt_ndx = obj_index (ev.nobjs());
00625 Fourvec kt = Fourvec (x(kt_ndx+x_offs), x(kt_ndx+y_offs), 0, 0);
00626 Fourvec nu = kt - sum;
00627 if (ev.has_neutrino()) {
00628 nu.setPz (y(nu_z));
00629 adjust_e_for_mass (nu, 0);
00630 ev.set_nu_p (nu);
00631 }
00632 else {
00633 adjust_e_for_mass (nu, 0);
00634 ev.set_x_p (nu);
00635 }
00636 }
00637 }
00638
00639
00640 }
00641
00642
00643
00644
00645
00646
00647
00648 namespace {
00649
00650
00679 double dot_and_gradient (const Fourvec& v1,
00680 const Fourvec& v2,
00681 bool use_e_flag,
00682 double v1_x[3],
00683 double v2_x[3],
00684 bool& badflag)
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700
00701
00702 {
00703
00704 double dot = v1 * v2;
00705
00706 double p1 = v1.vect().mag();
00707 double p2 = v2.vect().mag();
00708 double e1 = v1.e();
00709 double e2 = v2.e();
00710 double pt1 = v1.vect().perp();
00711 double pt2 = v2.vect().perp();
00712
00713
00714 badflag = false;
00715 if (p1 == 0 || p2 == 0 || e1 == 0 || e2 == 0 || pt1 == 0 || pt2 == 0) {
00716 badflag = true;
00717 v1_x[p_offs] = v1_x[phi_offs] = v1_x[eta_offs] = 0;
00718 v2_x[p_offs] = v2_x[phi_offs] = v2_x[eta_offs] = 0;
00719 return false;
00720 }
00721
00722
00723 v1_x[p_offs] = (dot - v1.m2() * e2 / e1) / p1;
00724 v2_x[p_offs] = (dot - v2.m2() * e1 / e2) / p2;
00725
00726 if (use_e_flag) {
00727 v1_x[p_offs] *= e1 / p1;
00728 v2_x[p_offs] *= e2 / p2;
00729 }
00730
00731 v1_x[phi_offs] = v1(1)*v2(0) - v1(0)*v2(1);
00732 v2_x[phi_offs] = -v1_x[phi_offs];
00733
00734 double fac = v1(0)*v2(0) + v1(1)*v2(1);
00735 v1_x[eta_offs] = pt1*v2(2) - v1(2)/pt1 * fac;
00736 v2_x[eta_offs] = pt2*v1(2) - v2(2)/pt2 * fac;
00737
00738 return dot;
00739 }
00740
00741
00763 void addin_obj_gradient (int constraint_no,
00764 int sign,
00765 int base_index,
00766 const double grad[],
00767 Matrix& Bx)
00768
00769
00770
00771
00772
00773
00774
00775
00776
00777
00778
00779
00780
00781
00782
00783
00784
00785 {
00786 Bx(base_index + p_offs, constraint_no) += sign * grad[p_offs];
00787 Bx(base_index + phi_offs, constraint_no) += sign * grad[phi_offs];
00788 Bx(base_index + eta_offs, constraint_no) += sign * grad[eta_offs];
00789 }
00790
00791
00819 void addin_nu_gradient (int constraint_no,
00820 int sign,
00821 int kt_ndx,
00822 const double grad[],
00823 Matrix& Bx, Matrix& By)
00824
00825
00826
00827
00828
00829
00830
00831
00832
00833
00834
00835
00836
00837
00838
00839
00840
00841
00842 {
00843 Bx(kt_ndx+x_offs,constraint_no) += sign*grad[p_offs];
00844 Bx(kt_ndx+y_offs,constraint_no) += sign*grad[phi_offs];
00845 By(nu_z, constraint_no) += sign*grad[eta_offs];
00846 }
00847
00848
00875 void addin_gradient (const Fourvec_Event& ev,
00876 int constraint_no,
00877 int sign,
00878 int obj_no,
00879 const double grad[],
00880 Matrix& Bx,
00881 Matrix& By)
00882
00883
00884
00885
00886
00887
00888
00889
00890
00891
00892
00893
00894
00895
00896
00897
00898
00899
00900
00901 {
00902 if (obj_no >= ev.nobjs()) {
00903 assert (obj_no == ev.nobjs());
00904 addin_nu_gradient (constraint_no, sign, obj_index (obj_no), grad, Bx, By);
00905 }
00906 else
00907 addin_obj_gradient (constraint_no, sign, obj_index (obj_no), grad, Bx);
00908 }
00909
00910
00941 void addin_gradients (const Fourvec_Event& ev,
00942 int constraint_no,
00943 int sign,
00944 int i,
00945 const double igrad[],
00946 int j,
00947 const double jgrad[],
00948 Matrix& Bx,
00949 Matrix& By)
00950
00951
00952
00953
00954
00955
00956
00957
00958
00959
00960
00961
00962
00963
00964
00965
00966
00967
00968
00969
00970 {
00971 addin_gradient (ev, constraint_no, sign, i, igrad, Bx, By);
00972 addin_gradient (ev, constraint_no, sign, j, jgrad, Bx, By);
00973 }
00974
00975
00988 void add_mass_terms (const Fourvec_Event& ev,
00989 const vector<Constraint>& constraints,
00990 Row_Vector& F)
00991
00992
00993
00994
00995
00996
00997
00998
00999
01000
01001
01002 {
01003 for (std::vector<Constraint>::size_type i=0; i<constraints.size(); i++)
01004 F(i+1) += constraints[i].sum_mass_terms (ev);
01005 }
01006
01007
01041 bool calculate_mass_constraints (const Fourvec_Event& ev,
01042 const Pair_Table& pt,
01043 const vector<Constraint>& constraints,
01044 bool use_e_flag,
01045 Row_Vector& F,
01046 Matrix& Bx,
01047 Matrix& By)
01048
01049
01050
01051
01052
01053
01054
01055
01056
01057
01058
01059
01060
01061
01062
01063
01064
01065
01066
01067
01068
01069 {
01070 int npairs = pt.npairs ();
01071 for (int p=0; p < npairs; p++) {
01072 const Objpair& objpair = pt.get_pair (p);
01073 int i = objpair.i();
01074 int j = objpair.j();
01075 double igrad[3], jgrad[3];
01076 bool badflag = false;
01077 double dot = dot_and_gradient (ev.obj (i).p,
01078 ev.obj (j).p,
01079 use_e_flag,
01080 igrad,
01081 jgrad,
01082 badflag);
01083 if (badflag)
01084 return false;
01085
01086 for (std::vector<Constraint>::size_type k=0; k < constraints.size(); k++)
01087 if (objpair.for_constraint (k)) {
01088 F(k+1) += objpair.for_constraint (k) * dot;
01089 addin_gradients (ev, k+1, objpair.for_constraint (k),
01090 i, igrad, j, jgrad, Bx, By);
01091 }
01092
01093 }
01094
01095 add_mass_terms (ev, constraints, F);
01096 return true;
01097 }
01098
01099
01122 void add_nuterm (unsigned ndx,
01123 const Fourvec& v,
01124 Matrix& Bx,
01125 bool use_e_flag,
01126 int kt_ndx)
01127
01128
01129
01130
01131
01132
01133
01134
01135
01136
01137
01138
01139
01140
01141 {
01142 double px = v.px();
01143 double py = v.py();
01144 double cot_theta = v.pz() / v.vect().perp();
01145
01146 for (int j=1; j<=Bx.num_col(); j++) {
01147 double dxnu = Bx(kt_ndx+x_offs, j);
01148 double dynu = Bx(kt_ndx+y_offs, j);
01149
01150 if (dxnu != 0 || dynu != 0) {
01151 double fac = 1 / v.vect().mag();
01152 if (use_e_flag)
01153 fac = v.e() * fac * fac;
01154 Bx(ndx + p_offs, j) -= (px*dxnu + py*dynu) * fac;
01155 Bx(ndx + phi_offs, j) += py*dxnu - px*dynu;
01156 Bx(ndx + eta_offs, j) -= (px*dxnu + py*dynu) * cot_theta;
01157 }
01158 }
01159 }
01160
01161
01185 void convert_neutrino (const Fourvec_Event& ev,
01186 bool use_e_flag,
01187 Matrix& Bx,
01188 Matrix& By)
01189
01190
01191
01192
01193
01194
01195
01196
01197
01198
01199
01200
01201
01202
01203
01204
01205 {
01206 int nconstraints = Bx.num_col ();
01207
01208 const Fourvec& nu = ev.nu ();
01209
01210
01211 double pnu2 = nu.vect().mag2(); double pnu = sqrt (pnu2);
01212 double ptnu2 = nu.vect().perp2(); double ptnu = sqrt (ptnu2);
01213
01214
01215
01216 double thfac = nu.z()/pnu2/ptnu;
01217 double fac[3][3];
01218 fac[0][0] = nu(0)/pnu; fac[0][1] = nu(1)/pnu; fac[0][2] = nu(2)/pnu;
01219 fac[1][0] = - nu(1)/ptnu2; fac[1][1] = nu(0)/ptnu2; fac[1][2] = 0;
01220 fac[2][0] = nu(0)*thfac; fac[2][1] = nu(1)*thfac; fac[2][2] = -ptnu/pnu2;
01221
01222 int kt_ndx = obj_index (ev.nobjs());
01223 for (int j=1; j<=nconstraints; j++) {
01224 double tmp1 = fac[0][0]*Bx(kt_ndx+x_offs,j) +
01225 fac[1][0]*Bx(kt_ndx+y_offs,j) +
01226 fac[2][0]*By(nu_z,j);
01227 Bx(kt_ndx+y_offs,j) = fac[0][1]*Bx(kt_ndx+x_offs,j) +
01228 fac[1][1]*Bx(kt_ndx+y_offs,j) +
01229 fac[2][1]*By(nu_z,j);
01230 By(nu_z,j) = fac[0][2]*Bx(kt_ndx+x_offs,j) + fac[2][2]*By(nu_z,j);
01231
01232 Bx(kt_ndx+x_offs,j) = tmp1;
01233 }
01234
01235
01236 for (int j=0; j<ev.nobjs(); j++) {
01237 add_nuterm (obj_index (j), ev.obj(j).p, Bx, use_e_flag, kt_ndx);
01238 }
01239 }
01240
01241
01262 void calculate_kt_constraints (const Fourvec_Event& ev,
01263 bool use_e_flag,
01264 Row_Vector& F,
01265 Matrix& Bx)
01266
01267
01268
01269
01270
01271
01272
01273
01274
01275
01276
01277
01278
01279
01280 {
01281 Fourvec tmp = Fourvec(0);
01282 int base = F.num_col() - 2;
01283 int nobjs = ev.nobjs();
01284 for (int j=0; j<nobjs; j++) {
01285 const Fourvec& obj = ev.obj (j).p;
01286 tmp += obj;
01287
01288 int ndx = obj_index (j);
01289 double p = obj.vect().mag();
01290 double cot_theta = obj.z() / obj.vect().perp();
01291
01292 Bx(ndx + p_offs, base+1) = obj(0) / p;
01293 Bx(ndx + phi_offs, base+1) = -obj(1);
01294 Bx(ndx + eta_offs, base+1) = obj(0) * cot_theta;
01295
01296 Bx(ndx + p_offs, base+2) = obj(1) / p;
01297 Bx(ndx + phi_offs, base+2) = obj(0);
01298 Bx(ndx + eta_offs, base+2) = obj(1) * cot_theta;
01299
01300 if (use_e_flag) {
01301 Bx(ndx + p_offs, base+1) *= obj.e() / p;
01302 Bx(ndx + p_offs, base+2) *= obj.e() / p;
01303 }
01304 }
01305
01306 int kt_ndx = obj_index (nobjs);
01307 Bx(kt_ndx+x_offs, base+1) = -1;
01308 Bx(kt_ndx+y_offs, base+2) = -1;
01309
01310 F(base+1) = tmp(0) - ev.kt().x ();
01311 F(base+2) = tmp(1) - ev.kt().y ();
01312 }
01313
01314
01328 void ddtheta_to_ddeta (int i, double cos_theta, Matrix& Bx)
01329
01330
01331
01332
01333
01334
01335
01336
01337
01338
01339
01340
01341 {
01342 double sin_theta = sqrt (1 - cos_theta * cos_theta);
01343 for (int j=1; j<=Bx.num_col(); j++)
01344 Bx(i,j) *= - sin_theta;
01345 }
01346
01347
01348 }
01349
01350
01376 class Fourvec_Constraint_Calculator
01377 : public Constraint_Calculator
01378
01379
01380
01381 {
01382 public:
01383
01384 Fourvec_Constraint_Calculator (Fourvec_Event& ev,
01385 const vector<Constraint>& constraints,
01386 const Fourvec_Constrainer_Args& args);
01387 virtual ~Fourvec_Constraint_Calculator () {}
01388
01389
01390
01391
01392
01393
01394
01395
01396
01397 virtual bool eval (const Column_Vector& x,
01398 const Column_Vector& y,
01399 Row_Vector& F,
01400 Matrix& Bx,
01401 Matrix& By);
01402
01403
01404
01405 bool calculate_constraints (Row_Vector& F,
01406 Matrix& Bx,
01407 Matrix& By) const;
01408
01409 private:
01410
01411 Fourvec_Event& _ev;
01412
01413
01414 const vector<Constraint>& _constraints;
01415
01416
01417 const Fourvec_Constrainer_Args& _args;
01418
01419
01420 Pair_Table _pt;
01421 };
01422
01423
01433 Fourvec_Constraint_Calculator::Fourvec_Constraint_Calculator
01434 (Fourvec_Event& ev,
01435 const vector<Constraint>& constraints,
01436 const Fourvec_Constrainer_Args& args)
01437
01438
01439
01440
01441
01442
01443
01444
01445
01446 : Constraint_Calculator (constraints.size() +
01447 ((ev.has_neutrino() || args.ignore_met()) ? 0 : 2)),
01448 _ev (ev),
01449 _constraints (constraints),
01450 _args (args),
01451 _pt (constraints, ev)
01452
01453 {
01454 }
01455
01456
01471 bool
01472 Fourvec_Constraint_Calculator::calculate_constraints (Row_Vector& F,
01473 Matrix& Bx,
01474 Matrix& By) const
01475
01476
01477
01478
01479
01480
01481
01482
01483 {
01484
01485 Bx = Matrix (Bx.num_row(), Bx.num_col(), 0);
01486 By = Matrix (By.num_row(), By.num_col(), 0);
01487 F = Row_Vector (F.num_col(), 0);
01488
01489 const double p_eps = 1e-10;
01490
01491 if (_ev.has_neutrino() && _ev.nu().z() > _args.e_com()) {
01492 return false;
01493 }
01494
01495 int nobjs = _ev.nobjs ();
01496
01497
01498 for (int j=0; j<nobjs; j++) {
01499 if (_ev.obj(j).p.perp() <= p_eps || _ev.obj(j).p.e() <= p_eps) {
01500 return false;
01501 }
01502 }
01503
01504 if (! calculate_mass_constraints (_ev, _pt, _constraints, _args.use_e(),
01505 F, Bx, By))
01506 return false;
01507
01508 if (_ev.has_neutrino())
01509 convert_neutrino (_ev, _args.use_e(), Bx, By);
01510 else if (!_args.ignore_met())
01511 {
01512
01513 calculate_kt_constraints (_ev, _args.use_e(), F, Bx);
01514 }
01515
01516
01517 for (int j=0; j<nobjs; j++) {
01518 ddtheta_to_ddeta (obj_index (j) + eta_offs,
01519 _ev.obj(j).p.cosTheta(),
01520 Bx);
01521 }
01522
01523
01524 for (int j=0; j<nobjs; j++) {
01525 const FE_Obj& obj = _ev.obj (j);
01526 if (obj.muon_p) {
01527
01528 double pmu2 = obj.p.vect().mag2();
01529 int ndx = obj_index (j) + p_offs;
01530 for (int k=1; k<=Bx.num_col(); k++)
01531 Bx(ndx, k) = - Bx(ndx, k) * pmu2;
01532 }
01533 }
01534
01535 return true;
01536 }
01537
01538
01568 bool Fourvec_Constraint_Calculator::eval (const Column_Vector& x,
01569 const Column_Vector& y,
01570 Row_Vector& F,
01571 Matrix& Bx,
01572 Matrix& By)
01573
01574
01575
01576
01577
01578
01579
01580
01581
01582
01583
01584
01585
01586
01587
01588 {
01589 int nobjs = _ev.nobjs();
01590
01591 const double p_eps = 1e-10;
01592 const double eta_max = 10;
01593
01594
01595 for (int j=0; j<nobjs; j++)
01596 if (x(obj_index (j) + p_offs) < p_eps ||
01597 fabs(x(obj_index (j) + eta_offs)) > eta_max) {
01598 return false;
01599 }
01600
01601 unpack_event (_ev, x, y, _args.use_e(),
01602 _ev.has_neutrino() || !_args.ignore_met());
01603
01604 return calculate_constraints (F, Bx, By);
01605 }
01606
01607
01608
01609
01610
01611
01612
01613 namespace {
01614
01615
01633 double calculate_sigm (const Matrix& Q,
01634 const Matrix& R,
01635 const Matrix& S,
01636 const Column_Vector& Bx,
01637 const Column_Vector& By)
01638
01639
01640
01641
01642
01643
01644
01645
01646
01647
01648 {
01649 double sig2 = scalar (Bx.T() * Q * Bx);
01650
01651 if (By.num_row() > 0) {
01652 sig2 += scalar (By.T() * R * By);
01653 sig2 += 2 * scalar (Bx.T() * S * By);
01654 }
01655
01656 assert (sig2 >= 0);
01657 return sqrt (sig2);
01658 }
01659
01660
01683 void calculate_mass (Fourvec_Event& ev,
01684 const vector<Constraint>& mass_constraint,
01685 const Fourvec_Constrainer_Args& args,
01686 double chisq,
01687 const Matrix& Q,
01688 const Matrix& R,
01689 const Matrix& S,
01690 double& m,
01691 double& sigm)
01692
01693
01694
01695
01696
01697
01698
01699
01700
01701
01702
01703
01704
01705
01706
01707
01708 {
01709
01710 if (mass_constraint.size () == 0) {
01711 m = 0;
01712 sigm = 0;
01713 return;
01714 }
01715
01716
01717 int n_measured_vars = ev.nobjs()*3 + 2;
01718 int n_unmeasured_vars = 0;
01719 if (ev.has_neutrino ()) n_unmeasured_vars = 1;
01720
01721 Row_Vector F(1);
01722 Matrix Bx (n_measured_vars, 1);
01723 Matrix By (n_unmeasured_vars, 1);
01724
01725 Fourvec_Constraint_Calculator cc (ev, mass_constraint, args);
01726 cc.calculate_constraints (F, Bx, By);
01727
01728
01729
01730 if (F(1) >= 0.)
01731 m = sqrt (F(1) * 2);
01732 else {
01733 m = 0.;
01734 chisq = -100.;
01735 }
01736
01737
01738
01739 if (chisq < 0)
01740 sigm = 0;
01741 else {
01742
01743 Bx = Bx / (m);
01744 By = By / (m);
01745
01746 sigm = calculate_sigm (Q, R, S, Bx, By);
01747 }
01748 }
01749
01750
01751 }
01752
01753
01754 double Fourvec_Constrainer::constrain (Fourvec_Event& ev,
01755 double& m,
01756 double& sigm,
01757 Column_Vector& pullx,
01758 Column_Vector& pully)
01759
01760
01761
01762
01763
01764
01765
01766
01767
01768
01769
01770
01771
01772
01773
01774
01775
01776
01777
01778 {
01779 adjust_fourvecs (ev, _args.use_e ());
01780
01781 bool use_kt = ev.has_neutrino() || !_args.ignore_met();
01782 int nobjs = ev.nobjs ();
01783 int n_measured_vars = nobjs * 3;
01784 int n_unmeasured_vars = 0;
01785 int n_constraints = _constraints.size ();
01786
01787 if (use_kt) {
01788 n_measured_vars += 2;
01789
01790 if (ev.has_neutrino ())
01791 n_unmeasured_vars = 1;
01792 else
01793 n_constraints += 2;
01794 }
01795
01796 Matrix G_i (n_measured_vars, n_measured_vars);
01797 Diagonal_Matrix Y (n_unmeasured_vars);
01798 Column_Vector x (n_measured_vars);
01799 Column_Vector y (n_unmeasured_vars);
01800 pack_event (ev, _args.use_e(), use_kt, x, y, G_i, Y);
01801
01802 Column_Vector xm = x;
01803 Column_Vector ym = y;
01804
01805
01806 Chisq_Constrainer fitter (_args.chisq_constrainer_args());
01807
01808 Fourvec_Constraint_Calculator cc (ev, _constraints, _args);
01809
01810 Matrix Q;
01811 Matrix R;
01812 Matrix S;
01813 double chisq = fitter.fit (cc,
01814 xm, x, ym, y, G_i, Y,
01815 pullx, pully,
01816 Q, R, S);
01817
01818 unpack_event (ev, x, y, _args.use_e (), use_kt);
01819
01820 calculate_mass (ev, _mass_constraint, _args, chisq, Q, R, S, m, sigm);
01821
01822 return chisq;
01823 }
01824
01825
01826 }