00001
00002 #include "Alignment/TwoBodyDecay/interface/TwoBodyDecayDerivatives.h"
00003 #include "Alignment/TwoBodyDecay/interface/TwoBodyDecayModel.h"
00004
00005 #include "FWCore/Utilities/interface/Exception.h"
00006
00007 #include <algorithm>
00008
00009 using namespace std;
00010
00011
00012 TwoBodyDecayDerivatives::TwoBodyDecayDerivatives( double mPrimary, double mSecondary ) :
00013 thePrimaryMass( mPrimary ), theSecondaryMass( mSecondary ) {}
00014
00015
00016 TwoBodyDecayDerivatives::~TwoBodyDecayDerivatives() {}
00017
00018
00019 const pair< AlgebraicMatrix, AlgebraicMatrix >
00020 TwoBodyDecayDerivatives::derivatives( const TwoBodyDecay & tbd ) const
00021 {
00022 return derivatives( tbd.decayParameters() );
00023 }
00024
00025 const pair< AlgebraicMatrix, AlgebraicMatrix >
00026 TwoBodyDecayDerivatives::derivatives( const TwoBodyDecayParameters & param ) const
00027 {
00028
00029 pair< AlgebraicMatrix, AlgebraicMatrix > dqsdpx = this->dqsdpx( param );
00030 pair< AlgebraicMatrix, AlgebraicMatrix > dqsdpy = this->dqsdpy( param );
00031 pair< AlgebraicMatrix, AlgebraicMatrix > dqsdpz = this->dqsdpz( param );
00032 pair< AlgebraicMatrix, AlgebraicMatrix > dqsdtheta = this->dqsdtheta( param );
00033 pair< AlgebraicMatrix, AlgebraicMatrix > dqsdphi = this->dqsdphi( param );
00034 pair< AlgebraicMatrix, AlgebraicMatrix > dqsdm = this->dqsdm( param );
00035
00036 AlgebraicMatrix dqplusdz( 3, dimension );
00037 dqplusdz.sub( 1, px, dqsdpx.first );
00038 dqplusdz.sub( 1, py, dqsdpy.first );
00039 dqplusdz.sub( 1, pz, dqsdpz.first );
00040 dqplusdz.sub( 1, theta, dqsdtheta.first );
00041 dqplusdz.sub( 1, phi, dqsdphi.first );
00042 dqplusdz.sub( 1, mass, dqsdm.first );
00043
00044 AlgebraicMatrix dqminusdz( 3, dimension );
00045 dqminusdz.sub( 1, px, dqsdpx.second );
00046 dqminusdz.sub( 1, py, dqsdpy.second );
00047 dqminusdz.sub( 1, pz, dqsdpz.second );
00048 dqminusdz.sub( 1, theta, dqsdtheta.second );
00049 dqminusdz.sub( 1, phi, dqsdphi.second );
00050 dqminusdz.sub( 1, mass, dqsdm.second );
00051
00052 return make_pair( dqplusdz, dqminusdz );
00053 }
00054
00055
00056 const pair< AlgebraicMatrix, AlgebraicMatrix >
00057 TwoBodyDecayDerivatives::selectedDerivatives( const TwoBodyDecay & tbd, const vector< bool > & selector ) const
00058 {
00059 return selectedDerivatives( tbd.decayParameters(), selector );
00060 }
00061
00062
00063 const pair< AlgebraicMatrix, AlgebraicMatrix >
00064 TwoBodyDecayDerivatives::selectedDerivatives( const TwoBodyDecayParameters & param, const vector< bool > & selector ) const
00065 {
00066 if ( selector.size() != dimension )
00067 {
00068 throw cms::Exception( "BadConfig" ) << "@SUB=TwoBodyDecayDerivatives::selectedDerivatives"
00069 << "selector has bad dimension (size=" << selector.size() << ").";
00070 }
00071
00072 int nSelected = count( selector.begin(), selector.end(), true );
00073 int iSelected = 1;
00074
00075 AlgebraicMatrix dqplusdz( 3, nSelected );
00076 AlgebraicMatrix dqminusdz( 3, nSelected );
00077 pair< AlgebraicMatrix, AlgebraicMatrix > dqsdzi;
00078
00079 for ( unsigned int i = 1; i <= dimension; i++ )
00080 {
00081 if ( selector[i] )
00082 {
00083 dqsdzi = this->dqsdzi( param, DerivativeParameterName(i) );
00084 dqplusdz.sub( 1, iSelected, dqsdzi.first );
00085 dqminusdz.sub( 1, iSelected, dqsdzi.second );
00086 iSelected++;
00087 }
00088 }
00089
00090 return make_pair( dqplusdz, dqminusdz );
00091 }
00092
00093
00094 const pair< AlgebraicMatrix, AlgebraicMatrix > TwoBodyDecayDerivatives::dqsdpx( const TwoBodyDecayParameters & param ) const
00095 {
00096 double px = param[TwoBodyDecayParameters::px];
00097 double py = param[TwoBodyDecayParameters::py];
00098 double pz = param[TwoBodyDecayParameters::pz];
00099 double theta = param[TwoBodyDecayParameters::theta];
00100 double phi = param[TwoBodyDecayParameters::phi];
00101
00102
00103 double pT2 = px*px + py*py;
00104 double p2 = pT2 + pz*pz;
00105 double pT = sqrt( pT2 );
00106 double p = sqrt( p2 );
00107
00108 double sphi = sin( phi );
00109 double cphi = cos( phi );
00110 double stheta = sin( theta );
00111 double ctheta = cos( theta );
00112
00113
00114 double c1 = 0.5*thePrimaryMass/theSecondaryMass;
00115 double c2 = sqrt( c1*c1 - 1. );
00116 double c3 = 0.5*c2*ctheta/c1;
00117 double c4 = sqrt( p2 + thePrimaryMass*thePrimaryMass );
00118
00119
00120 AlgebraicMatrix pplus( 3, 1 );
00121 pplus[0][0] = theSecondaryMass*c2*stheta*cphi;
00122 pplus[1][0] = theSecondaryMass*c2*stheta*sphi;
00123 pplus[2][0] = 0.5*p + c3*c4;
00124
00125
00126 AlgebraicMatrix pminus( 3, 1 );
00127 pminus[0][0] = -pplus[0][0];
00128 pminus[1][0] = -pplus[1][0];
00129 pminus[2][0] = 0.5*p - c3*c4;
00130
00131
00132 AlgebraicMatrix dRotMatdpx( 3, 3 );
00133
00134 dRotMatdpx[0][0] = pz/(pT*p)*(1.-px*px*(1./pT2+1./p2));
00135 dRotMatdpx[0][1] = px*py/(pT*pT2);
00136 dRotMatdpx[0][2] = (1.-px*px/p2)/p;
00137
00138 dRotMatdpx[1][0] = -px*py*pz/(pT*p)*(1./pT2+1./p2);
00139 dRotMatdpx[1][1] = (1.-px*px/pT2)/pT;
00140 dRotMatdpx[1][2] = -px*py/(p*p2);
00141
00142 dRotMatdpx[2][0] = -(1./pT-pT/p2)*px/p;
00143 dRotMatdpx[2][1] = 0.;
00144 dRotMatdpx[2][2] = -px*pz/(p*p2);
00145
00146
00147 double dpplusdpx = px*( 0.5/p + c3/c4 );
00148
00149 AlgebraicMatrix dqplusdpx = dRotMatdpx*pplus;
00150 dqplusdpx[0][0] += px*dpplusdpx/p;
00151 dqplusdpx[1][0] += py*dpplusdpx/p;
00152 dqplusdpx[2][0] += pz*dpplusdpx/p;
00153
00154
00155 double dpminusdpx = px*( 0.5/p - c3/c4 );
00156
00157 AlgebraicMatrix dqminusdpx = dRotMatdpx*pminus;
00158 dqminusdpx[0][0] += px*dpminusdpx/p;
00159 dqminusdpx[1][0] += py*dpminusdpx/p;
00160 dqminusdpx[2][0] += pz*dpminusdpx/p;
00161
00162
00163 return make_pair( dqplusdpx, dqminusdpx );
00164 }
00165
00166
00167 const pair< AlgebraicMatrix, AlgebraicMatrix > TwoBodyDecayDerivatives::dqsdpy( const TwoBodyDecayParameters & param ) const
00168 {
00169 double px = param[TwoBodyDecayParameters::px];
00170 double py = param[TwoBodyDecayParameters::py];
00171 double pz = param[TwoBodyDecayParameters::pz];
00172 double theta = param[TwoBodyDecayParameters::theta];
00173 double phi = param[TwoBodyDecayParameters::phi];
00174
00175
00176 double pT2 = px*px + py*py;
00177 double p2 = pT2 + pz*pz;
00178 double pT = sqrt( pT2 );
00179 double p = sqrt( p2 );
00180
00181 double sphi = sin( phi );
00182 double cphi = cos( phi );
00183 double stheta = sin( theta );
00184 double ctheta = cos( theta );
00185
00186
00187 double c1 = 0.5*thePrimaryMass/theSecondaryMass;
00188 double c2 = sqrt( c1*c1 - 1. );
00189 double c3 = 0.5*c2*ctheta/c1;
00190 double c4 = sqrt( p2 + thePrimaryMass*thePrimaryMass );
00191
00192
00193 AlgebraicMatrix pplus( 3, 1 );
00194 pplus[0][0] = theSecondaryMass*c2*stheta*cphi;
00195 pplus[1][0] = theSecondaryMass*c2*stheta*sphi;
00196 pplus[2][0] = 0.5*p + c3*c4;
00197
00198
00199 AlgebraicMatrix pminus( 3, 1 );
00200 pminus[0][0] = -pplus[0][0];
00201 pminus[1][0] = -pplus[1][0];
00202 pminus[2][0] = 0.5*p - c3*c4;
00203
00204
00205 AlgebraicMatrix dRotMatdpy( 3, 3 );
00206
00207 dRotMatdpy[0][0] = -px*py*pz/(pT*p)*(1./pT2+1./p2);
00208 dRotMatdpy[0][1] = (py*py/pT2-1.)/pT;
00209 dRotMatdpy[0][2] = -px*py/(p*p2);
00210
00211 dRotMatdpy[1][0] = pz/(pT*p)*(1.-py*py*(1./pT2+1./p2));
00212 dRotMatdpy[1][1] = -px*py/(pT*pT2);
00213 dRotMatdpy[1][2] = (1.-py*py/p2)/p;
00214
00215 dRotMatdpy[2][0] = -(1./pT-pT/p2)*py/p;
00216 dRotMatdpy[2][1] = 0.;
00217 dRotMatdpy[2][2] = -py*pz/(p*p2);
00218
00219
00220 double dpplusdpy = py*( 0.5/p + c3/c4 );
00221
00222 AlgebraicMatrix dqplusdpy = dRotMatdpy*pplus;
00223 dqplusdpy[0][0] += px*dpplusdpy/p;
00224 dqplusdpy[1][0] += py*dpplusdpy/p;
00225 dqplusdpy[2][0] += pz*dpplusdpy/p;
00226
00227
00228 double dpminusdpy = py*( 0.5/p - c3/c4 );
00229
00230 AlgebraicMatrix dqminusdpy = dRotMatdpy*pminus;
00231 dqminusdpy[0][0] += px*dpminusdpy/p;
00232 dqminusdpy[1][0] += py*dpminusdpy/p;
00233 dqminusdpy[2][0] += pz*dpminusdpy/p;
00234
00235
00236 return make_pair( dqplusdpy, dqminusdpy );
00237 }
00238
00239
00240 const pair< AlgebraicMatrix, AlgebraicMatrix > TwoBodyDecayDerivatives::dqsdpz( const TwoBodyDecayParameters & param ) const
00241 {
00242 double px = param[TwoBodyDecayParameters::px];
00243 double py = param[TwoBodyDecayParameters::py];
00244 double pz = param[TwoBodyDecayParameters::pz];
00245 double theta = param[TwoBodyDecayParameters::theta];
00246 double phi = param[TwoBodyDecayParameters::phi];
00247
00248
00249 double pT2 = px*px + py*py;
00250 double p2 = pT2 + pz*pz;
00251 double pT = sqrt( pT2 );
00252 double p = sqrt( p2 );
00253
00254 double sphi = sin( phi );
00255 double cphi = cos( phi );
00256 double stheta = sin( theta );
00257 double ctheta = cos( theta );
00258
00259
00260 double c1 = 0.5*thePrimaryMass/theSecondaryMass;
00261 double c2 = sqrt( c1*c1 - 1. );
00262 double c3 = 0.5*c2*ctheta/c1;
00263 double c4 = sqrt( p2 + thePrimaryMass*thePrimaryMass );
00264
00265
00266 AlgebraicMatrix pplus( 3, 1 );
00267 pplus[0][0] = theSecondaryMass*c2*stheta*cphi;
00268 pplus[1][0] = theSecondaryMass*c2*stheta*sphi;
00269 pplus[2][0] = 0.5*p + c3*c4;
00270
00271
00272 AlgebraicMatrix pminus( 3, 1 );
00273 pminus[0][0] = -pplus[0][0];
00274 pminus[1][0] = -pplus[1][0];
00275 pminus[2][0] = 0.5*p - c3*c4;
00276
00277
00278 AlgebraicMatrix dRotMatdpz( 3, 3 );
00279
00280 dRotMatdpz[0][0] = px/(pT*p)*(1.-pz*pz/p2);
00281 dRotMatdpz[0][1] = 0.;
00282 dRotMatdpz[0][2] = -px*pz/(p*p2);
00283
00284 dRotMatdpz[1][0] = py/(p*pT)*(1.-pz*pz/p2);
00285 dRotMatdpz[1][1] = 0.;
00286 dRotMatdpz[1][2] = -py*pz/(p*p2);
00287
00288 dRotMatdpz[2][0] = pT*pz/(p*p2);
00289 dRotMatdpz[2][1] = 0.;
00290 dRotMatdpz[2][2] = (1.-pz*pz/p2)/p;
00291
00292
00293 double dpplusdpz = pz*( 0.5/p + c3/c4 );
00294
00295 AlgebraicMatrix dqplusdpz = dRotMatdpz*pplus;
00296 dqplusdpz[0][0] += px*dpplusdpz/p;
00297 dqplusdpz[1][0] += py*dpplusdpz/p;
00298 dqplusdpz[2][0] += pz*dpplusdpz/p;
00299
00300
00301 double dpminusdpz = pz*( 0.5/p - c3/c4 );
00302
00303 AlgebraicMatrix dqminusdpz = dRotMatdpz*pminus;
00304 dqminusdpz[0][0] += px*dpminusdpz/p;
00305 dqminusdpz[1][0] += py*dpminusdpz/p;
00306 dqminusdpz[2][0] += pz*dpminusdpz/p;
00307
00308
00309 return make_pair( dqplusdpz, dqminusdpz );
00310 }
00311
00312
00313 const pair< AlgebraicMatrix, AlgebraicMatrix > TwoBodyDecayDerivatives::dqsdtheta( const TwoBodyDecayParameters & param ) const
00314 {
00315 double px = param[TwoBodyDecayParameters::px];
00316 double py = param[TwoBodyDecayParameters::py];
00317 double pz = param[TwoBodyDecayParameters::pz];
00318 double theta = param[TwoBodyDecayParameters::theta];
00319 double phi = param[TwoBodyDecayParameters::phi];
00320
00321
00322 double pT2 = px*px + py*py;
00323 double p2 = pT2 + pz*pz;
00324
00325 double sphi = sin( phi );
00326 double cphi = cos( phi );
00327 double stheta = sin( theta );
00328 double ctheta = cos( theta );
00329
00330
00331 double c1 = 0.5*thePrimaryMass/theSecondaryMass;
00332 double c2 = sqrt( c1*c1 - 1. );
00333 double c3 = -0.5*c2*stheta/c1;
00334 double c4 = sqrt( p2 + thePrimaryMass*thePrimaryMass );
00335
00336
00337 AlgebraicMatrix dpplusdtheta( 3, 1 );
00338 dpplusdtheta[0][0] = theSecondaryMass*c2*ctheta*cphi;
00339 dpplusdtheta[1][0] = theSecondaryMass*c2*ctheta*sphi;
00340 dpplusdtheta[2][0] = c3*c4;
00341
00342
00343 AlgebraicMatrix dpminusdtheta( 3, 1 );
00344 dpminusdtheta[0][0] = -theSecondaryMass*c2*ctheta*cphi;
00345 dpminusdtheta[1][0] = -theSecondaryMass*c2*ctheta*sphi;
00346 dpminusdtheta[2][0] = -c3*c4;
00347
00348 TwoBodyDecayModel decayModel;
00349 AlgebraicMatrix rotMat = decayModel.rotationMatrix( px, py, pz );
00350
00351 AlgebraicMatrix dqplusdtheta = rotMat*dpplusdtheta;
00352 AlgebraicMatrix dqminusdtheta = rotMat*dpminusdtheta;
00353
00354 return make_pair( dqplusdtheta, dqminusdtheta );
00355 }
00356
00357
00358 const pair< AlgebraicMatrix, AlgebraicMatrix > TwoBodyDecayDerivatives::dqsdphi( const TwoBodyDecayParameters & param ) const
00359 {
00360 double px = param[TwoBodyDecayParameters::px];
00361 double py = param[TwoBodyDecayParameters::py];
00362 double pz = param[TwoBodyDecayParameters::pz];
00363 double theta = param[TwoBodyDecayParameters::theta];
00364 double phi = param[TwoBodyDecayParameters::phi];
00365
00366 double sphi = sin( phi );
00367 double cphi = cos( phi );
00368 double stheta = sin( theta );
00369
00370
00371 double c1 = 0.5*thePrimaryMass/theSecondaryMass;
00372 double c2 = sqrt( c1*c1 - 1. );
00373
00374
00375 AlgebraicMatrix dpplusdphi( 3, 1 );
00376 dpplusdphi[0][0] = -theSecondaryMass*c2*stheta*sphi;
00377 dpplusdphi[1][0] = theSecondaryMass*c2*stheta*cphi;
00378 dpplusdphi[2][0] = 0.;
00379
00380
00381 AlgebraicMatrix dpminusdphi( 3, 1 );
00382 dpminusdphi[0][0] = theSecondaryMass*c2*stheta*sphi;
00383 dpminusdphi[1][0] = -theSecondaryMass*c2*stheta*cphi;
00384 dpminusdphi[2][0] = 0.;
00385
00386 TwoBodyDecayModel decayModel;
00387 AlgebraicMatrix rotMat = decayModel.rotationMatrix( px, py, pz );
00388
00389 AlgebraicMatrix dqplusdphi = rotMat*dpplusdphi;
00390 AlgebraicMatrix dqminusdphi = rotMat*dpminusdphi;
00391
00392 return make_pair( dqplusdphi, dqminusdphi );
00393 }
00394
00395
00396 const pair< AlgebraicMatrix, AlgebraicMatrix > TwoBodyDecayDerivatives::dqsdm( const TwoBodyDecayParameters & param ) const
00397 {
00398 double px = param[TwoBodyDecayParameters::px];
00399 double py = param[TwoBodyDecayParameters::py];
00400 double pz = param[TwoBodyDecayParameters::pz];
00401 double theta = param[TwoBodyDecayParameters::theta];
00402 double phi = param[TwoBodyDecayParameters::phi];
00403
00404 double pT2 = px*px + py*py;
00405 double p2 = pT2 + pz*pz;
00406
00407 double sphi = sin( phi );
00408 double cphi = cos( phi );
00409 double ctheta = cos( theta );
00410 double stheta = sin( theta );
00411
00412
00413 double c1 = 0.5*thePrimaryMass/theSecondaryMass;
00414 double c2 = 1./sqrt( c1*c1 - 1. );
00415 double m2 = thePrimaryMass*thePrimaryMass;
00416
00417
00418 AlgebraicMatrix dpplusdm( 3, 1 );
00419 dpplusdm[0][0] = c2*0.5*c1*stheta*cphi;
00420 dpplusdm[1][0] = c2*0.5*c1*stheta*sphi;
00421 dpplusdm[2][0] = c2*theSecondaryMass*( c1*c1 + p2/m2 )/sqrt( p2 + m2 )*ctheta;
00422
00423
00424 AlgebraicMatrix dpminusdm( 3, 1 );
00425 dpminusdm[0][0] = -dpplusdm[0][0];
00426 dpminusdm[1][0] = -dpplusdm[1][0];
00427 dpminusdm[2][0] = -dpplusdm[2][0];
00428
00429 TwoBodyDecayModel decayModel;
00430 AlgebraicMatrix rotMat = decayModel.rotationMatrix( px, py, pz );
00431
00432 AlgebraicMatrix dqplusdm = rotMat*dpplusdm;
00433 AlgebraicMatrix dqminusdm = rotMat*dpminusdm;
00434
00435 return make_pair( dqplusdm, dqminusdm );
00436 }
00437
00438
00439 const pair< AlgebraicMatrix, AlgebraicMatrix >
00440 TwoBodyDecayDerivatives::dqsdzi( const TwoBodyDecayParameters & param, const DerivativeParameterName & i ) const
00441 {
00442 switch ( i )
00443 {
00444 case TwoBodyDecayDerivatives::px :
00445 return dqsdpx( param );
00446 break;
00447 case TwoBodyDecayDerivatives::py :
00448 return dqsdpy( param );
00449 break;
00450 case TwoBodyDecayDerivatives::pz :
00451 return dqsdpz( param );
00452 break;
00453 case TwoBodyDecayDerivatives::theta :
00454 return dqsdtheta( param );
00455 break;
00456 case TwoBodyDecayDerivatives::phi :
00457 return dqsdphi( param );
00458 break;
00459 case TwoBodyDecayDerivatives::mass :
00460 return dqsdm( param );
00461 break;
00462 default:
00463 throw cms::Exception( "BadConfig" ) << "@SUB=TwoBodyDecayDerivatives::dqsdzi"
00464 << "no decay parameter related to selector (" << i << ").";
00465 };
00466
00467 return make_pair( AlgebraicMatrix( 3, 1, 0 ), AlgebraicMatrix( 3, 1, 0 ) );
00468 }