00001 #include "CLHEP/Random/DRand48Engine.h"
00002 #include "CLHEP/Random/RandGauss.h"
00003 #include "CLHEP/Random/Randomize.h"
00004
00005 #include "DataFormats/TrackingRecHit/interface/AlignmentPositionError.h"
00006 #include "FWCore/ServiceRegistry/interface/Service.h"
00007 #include "FWCore/Utilities/interface/RandomNumberGenerator.h"
00008 #include "FWCore/MessageLogger/interface/MessageLogger.h"
00009 #include "FWCore/ParameterSet/interface/ParameterSet.h"
00010
00011 #include "Alignment/CommonAlignment/interface/AlignableComposite.h"
00012 #include "Alignment/CommonAlignment/interface/AlignableModifier.h"
00013
00014
00015
00016 AlignableModifier::AlignableModifier( void )
00017 {
00018
00019 theDRand48Engine = new CLHEP::DRand48Engine();
00020
00021 }
00022
00023
00024
00025 AlignableModifier::~AlignableModifier()
00026 {
00027
00028 delete theDRand48Engine;
00029
00030 }
00031
00032
00033 void AlignableModifier::init_( void )
00034 {
00035
00036
00037 distribution_ = "";
00038 setError_ = false;
00039 setRotations_ = true;
00040 setTranslations_ = true;
00041 scale_ = 1.;
00042 scaleError_ = 1.;
00043 phiX_ = 0.;
00044 phiY_ = 0.;
00045 phiZ_ = 0.;
00046 phiXlocal_ = 0.;
00047 phiYlocal_ = 0.;
00048 phiZlocal_ = 0.;
00049 dX_ = 0.;
00050 dY_ = 0.;
00051 dZ_ = 0.;
00052 dXlocal_ = 0.;
00053 dYlocal_ = 0.;
00054 dZlocal_ = 0.;
00055 twist_ = 0.;
00056 shear_ = 0.;
00057
00058
00059 random_ = true;
00060 gaussian_ = true;
00061
00062 }
00063
00064
00065
00066 const bool AlignableModifier::isPropagated( const std::string& parameterName ) const
00067 {
00068
00069 if ( parameterName == "distribution" ||
00070 parameterName == "setError" ||
00071 parameterName == "scaleError" ||
00072 parameterName == "setRotations" ||
00073 parameterName == "setTranslations" ||
00074 parameterName == "scale"
00075 ) return true;
00076
00077 return false;
00078
00079 }
00080
00081
00082
00084 bool AlignableModifier::modify( Alignable* alignable, const edm::ParameterSet& pSet )
00085 {
00086
00087
00088 this->init_();
00089 int rotX_=0, rotY_=0, rotZ_=0;
00090
00091
00092
00093 m_modified = 0;
00094
00095
00096 std::ostringstream error;
00097 std::vector<std::string> parameterNames = pSet.getParameterNames();
00098 for ( std::vector<std::string>::iterator iParam = parameterNames.begin();
00099 iParam != parameterNames.end(); iParam++ ) {
00100 if ( (*iParam) == "distribution" ) distribution_ = pSet.getParameter<std::string>( *iParam );
00101 else if ( (*iParam) == "setError" ) setError_ = pSet.getParameter<bool>( *iParam );
00102 else if ( (*iParam) == "setRotations") setRotations_ = pSet.getParameter<bool>( *iParam );
00103 else if ( (*iParam) == "setTranslations") setTranslations_ = pSet.getParameter<bool>( *iParam );
00104 else if ( (*iParam) == "scale" ) scale_ = pSet.getParameter<double>( *iParam );
00105 else if ( (*iParam) == "scaleError" ) scaleError_ = pSet.getParameter<double>( *iParam );
00106 else if ( (*iParam) == "phiX" ) phiX_ = pSet.getParameter<double>( *iParam );
00107 else if ( (*iParam) == "phiY" ) phiY_ = pSet.getParameter<double>( *iParam );
00108 else if ( (*iParam) == "phiZ" ) phiZ_ = pSet.getParameter<double>( *iParam );
00109 else if ( (*iParam) == "dX" ) dX_ = pSet.getParameter<double>( *iParam );
00110 else if ( (*iParam) == "dY" ) dY_ = pSet.getParameter<double>( *iParam );
00111 else if ( (*iParam) == "dZ" ) dZ_ = pSet.getParameter<double>( *iParam );
00112 else if ( (*iParam) == "dXlocal" ) dXlocal_ = pSet.getParameter<double>( *iParam );
00113 else if ( (*iParam) == "dYlocal" ) dYlocal_ = pSet.getParameter<double>( *iParam );
00114 else if ( (*iParam) == "dZlocal" ) dZlocal_ = pSet.getParameter<double>( *iParam );
00115 else if ( (*iParam) == "twist" ) twist_ = pSet.getParameter<double>( *iParam );
00116 else if ( (*iParam) == "shear" ) shear_ = pSet.getParameter<double>( *iParam );
00117 else if ( (*iParam) == "localX" ) { phiXlocal_=pSet.getParameter<double>( *iParam ); rotX_++; }
00118 else if ( (*iParam) == "localY" ) { phiYlocal_=pSet.getParameter<double>( *iParam ); rotY_++; }
00119 else if ( (*iParam) == "localZ" ) { phiZlocal_=pSet.getParameter<double>( *iParam ); rotZ_++; }
00120 else if ( (*iParam) == "phiXlocal" ) { phiXlocal_=pSet.getParameter<double>( *iParam ); rotX_++; }
00121 else if ( (*iParam) == "phiYlocal" ) { phiYlocal_=pSet.getParameter<double>( *iParam ); rotY_++; }
00122 else if ( (*iParam) == "phiZlocal" ) { phiZlocal_=pSet.getParameter<double>( *iParam ); rotZ_++; }
00123 else if ( !pSet.existsAs<edm::ParameterSet>(*iParam) ) {
00124 if ( !error.str().length() ) error << "Unknown parameter name(s): ";
00125 error << " " << *iParam;
00126 }
00127 }
00128
00129
00130 if ( rotX_==2 ) throw cms::Exception("BadConfig") << "Found both localX and phiXlocal";
00131 if ( rotY_==2 ) throw cms::Exception("BadConfig") << "Found both localY and phiYlocal";
00132 if ( rotZ_==2 ) throw cms::Exception("BadConfig") << "Found both localZ and phiZlocal";
00133
00134
00135 if ( error.str().length() )
00136 throw cms::Exception("BadConfig") << error.str();
00137
00138
00139 this->setDistribution( distribution_ );
00140
00141
00142
00143
00144 if ( std::abs(dX_) + std::abs(dY_) + std::abs(dZ_) > 0 && setTranslations_ )
00145 this->moveAlignable( alignable, random_, gaussian_, scale_*dX_, scale_*dY_, scale_*dZ_ );
00146
00147
00148 if ( std::abs(dXlocal_) + std::abs(dYlocal_) + std::abs(dZlocal_) > 0 && setTranslations_ )
00149 this->moveAlignableLocal( alignable, random_, gaussian_,
00150 scale_*dXlocal_, scale_*dYlocal_, scale_*dZlocal_ );
00151
00152
00153 if ( std::abs(phiX_) + std::abs(phiY_) + std::abs(phiZ_) > 0 && setRotations_ )
00154 this->rotateAlignable( alignable, random_, gaussian_,
00155 scale_*phiX_, scale_*phiY_, scale_*phiZ_ );
00156
00157
00158 if ( std::abs(phiXlocal_) + std::abs(phiYlocal_) + std::abs(phiZlocal_) > 0 && setRotations_ )
00159 this->rotateAlignableLocal( alignable, random_, gaussian_,
00160 scale_*phiXlocal_, scale_*phiYlocal_, scale_*phiZlocal_ );
00161
00162
00163 if ( std::abs(twist_) > 0 )
00164 edm::LogError("NotImplemented") << "Twist is not implemented yet";
00165
00166
00167 if ( std::abs(shear_) > 0 )
00168 edm::LogError("NotImplemented") << "Shear is not implemented yet";
00169
00170
00171 scaleError_ *= scale_;
00172 if ( setError_ && scaleError_ ) {
00173
00174 if ( !gaussian_ ) scaleError_ *= 0.68;
00175
00176
00177
00178 if ( std::abs(dX_) + std::abs(dY_) + std::abs(dZ_) > 0 && setTranslations_ )
00179 this->addAlignmentPositionError( alignable,
00180 scaleError_*dX_, scaleError_*dY_, scaleError_*dZ_ );
00181
00182
00183 if ( std::abs(dXlocal_) + std::abs(dYlocal_) + std::abs(dZlocal_) > 0 && setTranslations_ )
00184 this->addAlignmentPositionErrorLocal( alignable,
00185 scaleError_*dXlocal_, scaleError_*dYlocal_,
00186 scaleError_*dZlocal_ );
00187
00188
00189 if ( std::abs(phiX_) + std::abs(phiY_) + std::abs(phiZ_) > 0 && setRotations_ )
00190 this->addAlignmentPositionErrorFromRotation( alignable,
00191 scaleError_*phiX_, scaleError_*phiY_,
00192 scaleError_*phiZ_ );
00193
00194
00195 if ( std::abs(phiXlocal_) + std::abs(phiYlocal_) + std::abs(phiZlocal_) > 0
00196 && setRotations_ )
00197 this->addAlignmentPositionErrorFromLocalRotation( alignable,
00198 scaleError_*phiXlocal_,
00199 scaleError_*phiYlocal_,
00200 scaleError_*phiZlocal_ );
00201 }
00202
00203
00204 return ( m_modified > 0 );
00205
00206 }
00207
00208
00209
00210 void AlignableModifier::setDistribution( const std::string& distr )
00211 {
00212
00213 if ( distr == "fixed" ) random_ = false;
00214 else if ( distr == "flat" ) {
00215 random_ = true;
00216 gaussian_ = false;
00217 } else if ( distr == "gaussian" ) {
00218 random_ = true;
00219 gaussian_ = true;
00220 }
00221
00222 }
00223
00224
00225
00227 void AlignableModifier::setSeed( const long seed )
00228 {
00229
00230 long m_seed;
00231
00232 if ( seed > 0 ) m_seed = seed;
00233 else {
00234 edm::Service<edm::RandomNumberGenerator> rng;
00235 m_seed = rng->mySeed();
00236 }
00237
00238 LogDebug("PrintArgs") << "Setting generator seed to " << m_seed;
00239
00240 theDRand48Engine->setSeed( m_seed );
00241
00242 }
00243
00244
00247 void AlignableModifier::moveAlignable( Alignable* alignable, bool random, bool gaussian,
00248 float sigmaX, float sigmaY, float sigmaZ )
00249 {
00250
00251
00252 std::ostringstream message;
00253
00254
00255 GlobalVector moveV( sigmaX, sigmaY, sigmaZ );
00256 if ( random ) {
00257 std::vector<float> randomNumbers;
00258 message << "random ";
00259 if (gaussian) {
00260 randomNumbers = this->gaussianRandomVector( sigmaX, sigmaY, sigmaZ );
00261 message << "gaussian ";
00262 } else {
00263 randomNumbers = this->flatRandomVector( sigmaX, sigmaY, sigmaZ );
00264 message << "flat ";
00265 }
00266 moveV = GlobalVector( randomNumbers[0], randomNumbers[1], randomNumbers[2] );
00267 }
00268
00269 message << " move with sigma " << sigmaX << " " << sigmaY << " " << sigmaZ;
00270
00271 LogDebug("PrintArgs") << message.str();
00272
00273 LogDebug("PrintMovement") << "applied displacement: " << moveV;
00274 alignable->move(moveV);
00275 m_modified++;
00276
00277
00278 }
00279
00280
00283 void AlignableModifier::moveAlignableLocal( Alignable* alignable, bool random, bool gaussian,
00284 float sigmaX, float sigmaY, float sigmaZ )
00285 {
00286
00287
00288 std::ostringstream message;
00289
00290
00291 align::LocalVector moveV( sigmaX, sigmaY, sigmaZ );
00292 if ( random ) {
00293 std::vector<float> randomNumbers;
00294 message << "random ";
00295 if (gaussian) {
00296 randomNumbers = this->gaussianRandomVector( sigmaX, sigmaY, sigmaZ );
00297 message << "gaussian ";
00298 } else {
00299 randomNumbers = this->flatRandomVector( sigmaX, sigmaY, sigmaZ );
00300 message << "flat ";
00301 }
00302 moveV = align::LocalVector( randomNumbers[0], randomNumbers[1], randomNumbers[2] );
00303 }
00304
00305 message << " move with sigma " << sigmaX << " " << sigmaY << " " << sigmaZ;
00306
00307 LogDebug("PrintArgs") << message.str();
00308
00309 LogDebug("PrintMovement") << "applied local displacement: " << moveV;
00310 alignable->move( alignable->surface().toGlobal(moveV) );
00311 m_modified++;
00312
00313
00314 }
00315
00316
00317
00320 void AlignableModifier::rotateAlignable( Alignable* alignable, bool random, bool gaussian,
00321 float sigmaPhiX, float sigmaPhiY, float sigmaPhiZ )
00322 {
00323
00324
00325 std::ostringstream message;
00326
00327
00328 GlobalVector rotV( sigmaPhiX, sigmaPhiY, sigmaPhiZ );
00329 if ( random ) {
00330 std::vector<float> randomNumbers;
00331 message << "random ";
00332 if (gaussian) {
00333 randomNumbers = this->gaussianRandomVector( sigmaPhiX, sigmaPhiY, sigmaPhiZ );
00334 message << "gaussian ";
00335 } else {
00336 randomNumbers = flatRandomVector( sigmaPhiX, sigmaPhiY, sigmaPhiZ );
00337 message << "flat ";
00338 }
00339 rotV = GlobalVector( randomNumbers[0], randomNumbers[1], randomNumbers[2] );
00340 }
00341
00342 message << "global rotation by angles " << sigmaPhiX << " " << sigmaPhiY << " " << sigmaPhiZ;
00343
00344 LogDebug("PrintArgs") << message.str();
00345
00346 LogDebug("PrintMovement") << "applied rotation angles: " << rotV;
00347 if ( std::abs(sigmaPhiX) ) alignable->rotateAroundGlobalX( rotV.x() );
00348 if ( std::abs(sigmaPhiY) ) alignable->rotateAroundGlobalY( rotV.y() );
00349 if ( std::abs(sigmaPhiZ) ) alignable->rotateAroundGlobalZ( rotV.z() );
00350 m_modified++;
00351
00352
00353 }
00354
00355
00358 void
00359 AlignableModifier::rotateAlignableLocal( Alignable* alignable, bool random, bool gaussian,
00360 float sigmaPhiX, float sigmaPhiY, float sigmaPhiZ )
00361 {
00362
00363
00364 std::ostringstream message;
00365
00366
00367 align::LocalVector rotV( sigmaPhiX, sigmaPhiY, sigmaPhiZ );
00368 if ( random ) {
00369 std::vector<float> randomNumbers;
00370 message << "random ";
00371 if (gaussian) {
00372 randomNumbers = this->gaussianRandomVector( sigmaPhiX, sigmaPhiY, sigmaPhiZ );
00373 message << "gaussian ";
00374 } else {
00375 randomNumbers = flatRandomVector( sigmaPhiX, sigmaPhiY, sigmaPhiZ );
00376 message << "flat ";
00377 }
00378 rotV = align::LocalVector( randomNumbers[0], randomNumbers[1], randomNumbers[2] );
00379 }
00380
00381 message << "local rotation by angles " << sigmaPhiX << " " << sigmaPhiY << " " << sigmaPhiZ;
00382
00383 LogDebug("PrintArgs") << message.str();
00384
00385 LogDebug("PrintMovement") << "applied local rotation angles: " << rotV;
00386 if ( std::abs(sigmaPhiX) ) alignable->rotateAroundLocalX( rotV.x() );
00387 if ( std::abs(sigmaPhiY) ) alignable->rotateAroundLocalY( rotV.y() );
00388 if ( std::abs(sigmaPhiZ) ) alignable->rotateAroundLocalZ( rotV.z() );
00389 m_modified++;
00390
00391
00392 }
00393
00394
00395
00396 const std::vector<float>
00397 AlignableModifier::gaussianRandomVector( float sigmaX, float sigmaY, float sigmaZ ) const
00398 {
00399
00400
00401 if ( sigmaX < 0 ) {
00402 edm::LogWarning("BadConfig") << " taking absolute value for gaussian sigma_x";
00403 sigmaX = std::abs(sigmaX);
00404 }
00405 if ( sigmaY < 0 ) {
00406 edm::LogWarning("BadConfig") << " taking absolute value for gaussian sigma_y";
00407 sigmaY = std::abs(sigmaY);
00408 }
00409 if ( sigmaZ < 0 ) {
00410 edm::LogWarning("BadConfig") << " taking absolute value for gaussian sigma_z";
00411 sigmaZ = std::abs(sigmaZ);
00412 }
00413
00414
00415 CLHEP::RandGauss aGaussObjX( *theDRand48Engine, 0., sigmaX );
00416 CLHEP::RandGauss aGaussObjY( *theDRand48Engine, 0., sigmaY );
00417 CLHEP::RandGauss aGaussObjZ( *theDRand48Engine, 0., sigmaZ );
00418
00419 std::vector<float> randomVector;
00420 randomVector.push_back( aGaussObjX.fire() );
00421 randomVector.push_back( aGaussObjY.fire() );
00422 randomVector.push_back( aGaussObjZ.fire() );
00423
00424 return randomVector;
00425
00426 }
00427
00428
00429
00430 const std::vector<float>
00431 AlignableModifier::flatRandomVector( float sigmaX,float sigmaY, float sigmaZ ) const
00432 {
00433
00434
00435 if ( sigmaX < 0 ) {
00436 edm::LogWarning("BadConfig") << " taking absolute value for flat sigma_x";
00437 sigmaX = std::abs(sigmaX);
00438 }
00439 if ( sigmaY < 0 ) {
00440 edm::LogWarning("BadConfig") << " taking absolute value for flat sigma_y";
00441 sigmaY = std::abs(sigmaY);
00442 }
00443 if ( sigmaZ < 0 ) {
00444 edm::LogWarning("BadConfig") << " taking absolute value for flat sigma_z";
00445 sigmaZ = std::abs(sigmaZ);
00446 }
00447
00448 CLHEP::RandFlat aFlatObjX( *theDRand48Engine, -sigmaX, sigmaX );
00449 CLHEP::RandFlat aFlatObjY( *theDRand48Engine, -sigmaY, sigmaY );
00450 CLHEP::RandFlat aFlatObjZ( *theDRand48Engine, -sigmaZ, sigmaZ );
00451
00452 std::vector<float> randomVector;
00453 randomVector.push_back( aFlatObjX.fire() );
00454 randomVector.push_back( aFlatObjY.fire() );
00455 randomVector.push_back( aFlatObjZ.fire() );
00456
00457 return randomVector;
00458
00459 }
00460
00461
00462
00463
00464 void AlignableModifier::addAlignmentPositionError( Alignable* alignable,
00465 float dx, float dy, float dz )
00466 {
00467
00468 LogDebug("PrintArgs") << "Adding an AlignmentPositionError of size "
00469 << dx << " " << dy << " " << dz;
00470
00471 AlignmentPositionError ape(dx,dy,dz);
00472 alignable->addAlignmentPositionError( ape, true );
00473
00474 }
00475
00476
00477
00478 void AlignableModifier::addAlignmentPositionErrorLocal( Alignable* alignable,
00479 float dx, float dy, float dz )
00480 {
00481
00482 LogDebug("PrintArgs") << "Adding a local AlignmentPositionError of size "
00483 << dx << " " << dy << " " << dz;
00484
00485 AlgebraicSymMatrix as(3,0);
00486 as[0][0] = dx*dx; as[1][1] = dy*dy; as[2][2] = dz*dz;
00487 align::RotationType rt = alignable->globalRotation();
00488 AlgebraicMatrix am(3,3);
00489 am[0][0]=rt.xx(); am[0][1]=rt.xy(); am[0][2]=rt.xz();
00490 am[1][0]=rt.yx(); am[1][1]=rt.yy(); am[1][2]=rt.yz();
00491 am[2][0]=rt.zx(); am[2][1]=rt.zy(); am[2][2]=rt.zz();
00492 as=as.similarityT(am);
00493
00494 GlobalError ge( as );
00495 AlignmentPositionError ape( ge );
00496
00497 alignable->addAlignmentPositionError( ape, true );
00498
00499 }
00500
00501
00502
00503
00504 void AlignableModifier::addAlignmentPositionErrorFromRotation( Alignable* alignable,
00505 float phiX, float phiY,
00506 float phiZ )
00507 {
00508
00509 align::RotationType rotx( Basic3DVector<float>(1.0, 0.0, 0.0), phiX );
00510 align::RotationType roty( Basic3DVector<float>(0.0, 1.0, 0.0), phiY );
00511 align::RotationType rotz( Basic3DVector<float>(0.0, 0.0, 1.0), phiZ );
00512 align::RotationType rot = rotz * roty * rotx;
00513
00514 this->addAlignmentPositionErrorFromRotation( alignable, rot );
00515
00516 }
00517
00518
00519
00520 void AlignableModifier::addAlignmentPositionErrorFromLocalRotation( Alignable* alignable,
00521 float phiX, float phiY,
00522 float phiZ )
00523 {
00524
00525 align::RotationType rotx( Basic3DVector<float>(1.0, 0.0, 0.0), phiX );
00526 align::RotationType roty( Basic3DVector<float>(0.0, 1.0, 0.0), phiY );
00527 align::RotationType rotz( Basic3DVector<float>(0.0, 0.0, 1.0), phiZ );
00528 align::RotationType rot = rotz * roty * rotx;
00529
00530 this->addAlignmentPositionErrorFromLocalRotation( alignable, rot );
00531
00532 }
00533
00534
00535
00536 void AlignableModifier::addAlignmentPositionErrorFromRotation( Alignable* alignable,
00537 align::RotationType& rotation )
00538 {
00539
00540 LogDebug("PrintArgs") << "Adding an AlignmentPositionError from Rotation" << std::endl
00541 << rotation;
00542
00543 alignable->addAlignmentPositionErrorFromRotation(rotation, true);
00544
00545 }
00546
00547
00548
00549 void AlignableModifier::addAlignmentPositionErrorFromLocalRotation( Alignable* alignable,
00550 align::RotationType& rotation )
00551 {
00552
00553 LogDebug("PrintArgs") << "Adding an AlignmentPositionError from Local Rotation" << std::endl
00554 << rotation;
00555
00556
00557 alignable->addAlignmentPositionErrorFromLocalRotation(rotation, true);
00558
00559 }
00560