CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_6_1_2_SLHC2/src/GeneratorInterface/ExternalDecays/src/TauolaInterface.cc

Go to the documentation of this file.
00001 /* for old tauola27 
00002 #include <iostream>
00003 
00004 #include "GeneratorInterface/Pythia6Interface/interface/Pythia6Service.h"
00005 
00006 #include "GeneratorInterface/ExternalDecays/interface/TauolaInterface.h"
00007 #include "GeneratorInterface/ExternalDecays/interface/TauolaWrapper.h"
00008 
00009 #include "FWCore/ServiceRegistry/interface/Service.h"
00010 #include "FWCore/Utilities/interface/RandomNumberGenerator.h"
00011 
00012 #include "HepMC/GenEvent.h"
00013 #include "HepMC/IO_HEPEVT.h"
00014 #include "HepMC/HEPEVT_Wrapper.h"
00015 
00016 #include "SimGeneral/HepPDTRecord/interface/ParticleDataTable.h"
00017 
00018 #include "GeneratorInterface/ExternalDecays/interface/DecayRandomEngine.h"
00019 
00020 using namespace gen;
00021 using namespace edm;
00022 using namespace std;
00023 
00024 extern "C" {
00025 
00026   void ranmar_( float *rvec, int *lenv )
00027   {
00028 
00029       for(int i = 0; i < *lenv; i++)
00030          *rvec++ = decayRandomEngine->flat();
00031 
00032       return;
00033 
00034   }
00035   
00036   void rmarin_( int*, int*, int* )
00037   {
00038 
00039      return;
00040 
00041   }
00042 
00043 }
00044 
00045 //
00046 //   General Note: While there're no explicit calls or otherwise "links" to Pythia6 anywhere,
00047 //   we're using Pythia6Service here because we run pretauola rather than "core" tauola;
00048 //   pretauola is an extension on top of tauola, which is tied to Pythia6 via several routines;
00049 //   most heavily use one is PYR - we can't avoid it (other Pythia6-tied routines we avoid)
00050 //
00051 
00052 TauolaInterface::TauolaInterface( const ParameterSet& pset )
00053    : fIsInitialized(false)
00054 {
00055    fPy6Service = new Pythia6Service;
00056 
00057    fPolarization = pset.getParameter<bool>("UseTauolaPolarization") ? 1 : 0 ;
00058 
00059    // set Tauola defaults
00060    //
00061    ki_taumod_.pjak1 = -1;
00062    ki_taumod_.pjak2 = -1;
00063    ki_taumod_.mdtau = -1;
00064    
00065    // read tau decay mode switches
00066    //
00067    ParameterSet cards = pset.getParameter< ParameterSet >("InputCards");
00068    ki_taumod_.pjak1 = cards.getParameter< int >( "pjak1" );
00069    ki_taumod_.pjak2 = cards.getParameter< int >( "pjak2" );
00070    ki_taumod_.mdtau = cards.getParameter< int >( "mdtau" );
00071    
00072 } 
00073 
00074 TauolaInterface::~TauolaInterface()
00075 {
00076    delete fPy6Service;
00077 }
00078 
00079 void TauolaInterface::init( const edm::EventSetup& es )
00080 {
00081    
00082    if ( fIsInitialized ) return; // do init only once
00083    
00084    if ( ki_taumod_.mdtau <= -1 ) // actually, need to throw exception !
00085       return ;
00086    
00087    fPDGs.push_back( 15 ) ;
00088    es.getData( fPDGTable ) ;
00089 
00090         cout << "----------------------------------------------" << endl;
00091         cout << "Initializing Tauola" << endl;
00092         if ( fPolarization == 0 )
00093         {
00094            cout << "Tauola: Polarization disabled" << endl;
00095         } 
00096         else if ( fPolarization == 1 )
00097         {
00098            cout << "Tauola: Polarization enabled" << endl;
00099         }
00100 
00101 // FIXME !!!
00102 // This is a temporary hack - we're re-using master generator's seed to init RANMAR
00103 // FIXME !!!
00104 //   This is now off because ranmar has been overriden (see code above) to use pyr_(...)
00105 //   - this way we're using guaranteed initialized rndm generator... BUT !!! in the long
00106 //   run we may want a separate random stream for tauola...
00107 
00108 //   Service<RandomNumberGenerator> rng;
00109 //   int seed = rng->mySeed() ;
00110 //   int ntot=0, ntot2=0;
00111 //   rmarin_( &seed, &ntot, &ntot2 );
00112 
00113    int mode = -2;
00114    taurep_( &mode ) ;
00115    mode = -1;
00116    // tauola_( &mode, &fPolarization );
00117    // tauola_srs_( &mode, &fPolarization );
00118    //
00119    // We're using the call(...) method here because it'll make sure that Py6 
00120    // is initialized, and that's done only once, and will grab exatly that instance
00121    //
00122    fPy6Service->call( tauola_srs_, &mode, &fPolarization ); 
00123    
00124    fIsInitialized = true;
00125    
00126    return;
00127 }
00128 
00129 HepMC::GenEvent* TauolaInterface::decay( HepMC::GenEvent* evt )
00130 {
00131    
00132    // event record convertor
00133    //
00134    HepMC::IO_HEPEVT conv;
00135    
00136    if ( !fIsInitialized ) return conv.read_next_event();
00137    
00138    // We are using random numbers, we are fetched through Pythia6Service
00139    // (through ranmar_ below) -> so grab the instance during decay()
00140 
00141    Pythia6Service::InstanceWrapper pythia6InstanceGuard( fPy6Service );
00142 
00143    // fill up HEPEVT common block
00144    //
00145    // IDEALLY, this should be the way to go
00146    // BUT !!! this utility fills it up in the "reshuffled" order,
00147    // and later on Tauola chocks on it 
00148    //
00149    // Needs to be sorted out, eith in HepMC, or in Tauola, or both !!!
00150    // 
00151    // At present, this thing blindly relies on the assumption that
00152    // HEPEVT is always there - which wont be the case with Py8 or Hwg++
00153    //
00154    //HepMC::IO_HEPEVT conv;
00155    //conv.write_event( evt ) ;
00156    
00157    int numPartBeforeTauola = HepMC::HEPEVT_Wrapper::number_entries();
00158    // HepMC::HEPEVT_Wrapper::print_hepevt();
00159    
00160    int mode = 0;
00161    // tauola_( &mode, &fPolarization );
00162    fPy6Service->call( tauola_srs_, &mode, &fPolarization );
00163    
00164    int numPartAfterTauola = HepMC::HEPEVT_Wrapper::number_entries();
00165    // HepMC::HEPEVT_Wrapper::print_hepevt();
00166    
00167    // before we do the conversion, we need to deal with decay vertexes
00168    // since Tauola knows nothing about lifetimes, all decay vertexes are set to 0. 
00169    // nees to set them properly, knowing lifetime !
00170    // here we do it on HEPEVT record, also for consistency, although it's probably
00171    // even easier to deal with HepMC::GenEvent record  
00172    
00173    // find 1st "non-doc" tau
00174    //
00175    bool foundTau = false;
00176    for ( int ip=1; ip<=numPartAfterTauola; ip++ )
00177    {
00178       if ( std::abs( HepMC::HEPEVT_Wrapper::id( ip ) ) == 15
00179            && HepMC::HEPEVT_Wrapper::status( ip ) != 3 )
00180       {
00181          foundTau = true;
00182          break;
00183       }
00184    }
00185    
00186    if ( !foundTau )
00187    {
00188       // no tau found
00189       // just give up here
00190       //
00191       return conv.read_next_event();
00192    }
00193    
00194    std::vector<int> PrntIndx;
00195    
00196    for ( int ip=numPartAfterTauola; ip>numPartBeforeTauola; ip-- ) // Fortran indexing !
00197    {
00198       
00199       // first of all, find out how many generations in decay chain
00200       //
00201       PrntIndx.clear();
00202       int Prnt = HepMC::HEPEVT_Wrapper::first_parent(ip);
00203       ip -= (HepMC::HEPEVT_Wrapper::number_children(Prnt)-1); // such that we don't go the same part again
00204       PrntIndx.push_back( Prnt );
00205       while ( abs( HepMC::HEPEVT_Wrapper::id(Prnt) ) != 15 ) // shortcut; need to loop over fPDGs...
00206       {
00207          int Prnt1 = HepMC::HEPEVT_Wrapper::first_parent( Prnt );
00208          Prnt = Prnt1;
00209          // such that the tau always appear at the start of the list
00210          PrntIndx.insert( PrntIndx.begin(), Prnt );
00211          ip -= HepMC::HEPEVT_Wrapper::number_children(Prnt); // such that we don't go the same part again
00212       }
00213       for ( size_t iprt=0; iprt<PrntIndx.size(); iprt++ )
00214       {  
00215           int Indx = PrntIndx[iprt];
00216           int PartID = HepMC::HEPEVT_Wrapper::id( Indx );
00217           const HepPDT::ParticleData* 
00218              PData = fPDGTable->particle(HepPDT::ParticleID(abs(PartID))) ;
00219          //
00220          // prob = exp(-t/lifetime) ==> t = -lifetime * log(prob)
00221          //
00222          float prob = 0.;
00223          int length=1;
00224          ranmar_(&prob,&length);
00225          double lifetime = PData->lifetime().value();
00226          //
00227          // in case of Py6, this would be copied into V(5,i)
00228          // for HEPEVT, need to check...
00229          //
00230          double ct = -lifetime * std::log(prob);
00231          //
00232          double ee = HepMC::HEPEVT_Wrapper::e( Indx );
00233          double px = HepMC::HEPEVT_Wrapper::px( Indx );
00234          double py = HepMC::HEPEVT_Wrapper::py( Indx );
00235          double pz = HepMC::HEPEVT_Wrapper::pz( Indx );
00236          // double pp = std::sqrt( px*px + py*py + pz*pz );
00237          double mass = HepMC::HEPEVT_Wrapper::m( Indx );
00238          //
00239          // this is in py6 terms:
00240          //  VDCY(J)=V(IP,J)+V(IP,5)*P(IP,J)/P(IP,5)
00241          //
00242          double VxDec = HepMC::HEPEVT_Wrapper::x( Indx );
00243          VxDec += ct * (px/mass);
00244          double VyDec = HepMC::HEPEVT_Wrapper::y( Indx );
00245          VyDec += ct * (py/mass);
00246          double VzDec = HepMC::HEPEVT_Wrapper::z( Indx );
00247          VzDec += ct * (pz/mass);
00248          double VtDec = HepMC::HEPEVT_Wrapper::t( Indx );
00249          VtDec += ct * (ee/mass);
00250          for ( int idau=HepMC::HEPEVT_Wrapper::first_child( Indx );
00251                    idau<=HepMC::HEPEVT_Wrapper::last_child( Indx ); idau++ )
00252          {
00253             HepMC::HEPEVT_Wrapper::set_position( idau, VxDec, VyDec, VzDec, VtDec );
00254          }
00255       }
00256    }
00257    
00258    return conv.read_next_event();
00259       
00260 }
00261 
00262 void TauolaInterface::statistics()
00263 {
00264    int mode = 1;
00265    // tauola_( &mode, &fPolarization ) ;
00266    // tauola_srs_( &mode, &fPolarization ) ;
00267    fPy6Service->call( tauola_srs_, &mode, &fPolarization );
00268    return;
00269 }
00270 
00271 */
00272 
00273 /* this is the code for the new Tauola++ */
00274 
00275 #include <iostream>
00276 
00277 #include "GeneratorInterface/ExternalDecays/interface/TauolaInterface.h"
00278 
00279 #include "Tauola.h"
00280 #include "TauolaHepMCEvent.h"
00281 #include "Log.h"
00282 
00283 #include "FWCore/ServiceRegistry/interface/Service.h"
00284 #include "FWCore/Utilities/interface/RandomNumberGenerator.h"
00285 #include "FWCore/Utilities/interface/Exception.h"
00286 
00287 #include "CLHEP/Random/RandomEngine.h"
00288 
00289 #include "HepMC/GenEvent.h"
00290 #include "HepMC/IO_HEPEVT.h"
00291 #include "HepMC/HEPEVT_Wrapper.h"
00292 
00293 #include "SimGeneral/HepPDTRecord/interface/ParticleDataTable.h"
00294 
00295 // #include "GeneratorInterface/ExternalDecays/interface/DecayRandomEngine.h"
00296 
00297 
00298 extern "C" {
00299 
00300   void gen::ranmar_( float *rvec, int *lenv )
00301   {
00302       TauolaInterface* instance = TauolaInterface::getInstance();
00303       for(int i = 0; i < *lenv; i++)
00304          // *rvec++ = decayRandomEngine->flat();
00305          *rvec++ = instance->flat();
00306       return;
00307   }
00308   
00309   void gen::rmarin_( int*, int*, int* )
00310   {
00311      return;
00312   }
00313 
00314 }
00315 
00316 using namespace gen;
00317 using namespace edm;
00318 using namespace std;
00319 
00320 TauolaInterface* TauolaInterface::fInstance = 0;
00321 
00322 
00323 TauolaInterface::TauolaInterface()
00324    : fPolarization(false), fPSet(0), fIsInitialized(false), fMDTAU(-1), fSelectDecayByEvent(false)
00325 {
00326    
00327    Service<RandomNumberGenerator> rng;
00328    if(!rng.isAvailable()) {
00329     throw cms::Exception("Configuration")
00330        << "The RandomNumberProducer module requires the RandomNumberGeneratorService\n"
00331           "which appears to be absent.  Please add that service to your configuration\n"
00332           "or remove the modules that require it." << std::endl;
00333    }
00334    
00335    fRandomEngine = &rng->getEngine();
00336 
00337 }
00338 
00339 
00340 //TauolaInterface::TauolaInterface( const ParameterSet& pset )
00341 //   : fIsInitialized(false)
00342 //{
00343 //
00344 //   Tauola::setDecayingParticle(15);
00345 //   // --> ??? Tauola::setRadiation(false);
00346 //
00347 //   // polarization switch 
00348 //   //
00349 //   // fPolarization = pset.getParameter<bool>("UseTauolaPolarization") ? 1 : 0 ;
00350 //   fPolarization = pset.getParameter<bool>("UseTauolaPolarization");
00351 //   
00352 //   // read tau decay mode switches
00353 //   //
00354 //   ParameterSet cards = pset.getParameter< ParameterSet >("InputCards");
00355 //   Tauola::setSameParticleDecayMode( cards.getParameter< int >( "pjak1" ) ) ;
00356 //   Tauola::setOppositeParticleDecayMode( cards.getParameter< int >( "pjak2" ) ) ;
00357 //
00358 //   Tauola::setTauLifetime(0.0);
00359 //   Tauola::spin_correlation.setAll(fPolarization);
00360 //
00361 //   // some more options, copied over from an example 
00362 //   // - maybe will use later...
00363 //   //
00364 //   //Tauola::setEtaK0sPi(0,0,0); // switches to decay eta K0_S and pi0 1/0 on/off. 
00365 //   //
00366 //
00367 //} 
00368 
00369 
00370 TauolaInterface* TauolaInterface::getInstance()
00371 {
00372 
00373    if ( fInstance == 0 ) fInstance = new TauolaInterface() ;
00374    return fInstance;
00375 
00376 }
00377 
00378 
00379 TauolaInterface::~TauolaInterface()
00380 {
00381 
00382    if ( fPSet != 0 ) delete fPSet;
00383    if ( fInstance == this ) fInstance = 0;
00384 
00385 }
00386 
00387 void TauolaInterface::setPSet( const ParameterSet& pset )
00388 {
00389 
00390    if ( fPSet != 0 ) 
00391    {
00392       throw cms::Exception("TauolaInterfaceError")
00393          << "Attempt to override Tauola an existing ParameterSet\n"
00394          << std::endl;   
00395    }
00396    
00397    fPSet = new ParameterSet(pset);
00398    
00399    return;
00400 
00401 }
00402 
00403 void TauolaInterface::init( const edm::EventSetup& es )
00404 {
00405    
00406    if ( fIsInitialized ) return; // do init only once
00407    
00408    if ( fPSet == 0 ) 
00409    {
00410 
00411       throw cms::Exception("TauolaInterfaceError")
00412          << "Attempt to initialize Tauola with an empty ParameterSet\n"
00413          << std::endl;   
00414    }
00415    
00416    fIsInitialized = true;
00417       
00418    es.getData( fPDGTable ) ;
00419 
00420    Tauola::setDecayingParticle(15);
00421    // --> ??? Tauola::setRadiation(false);
00422 
00423    // polarization switch 
00424    //
00425    // fPolarization = fPSet->getParameter<bool>("UseTauolaPolarization") ? 1 : 0 ;
00426    fPolarization = fPSet->getParameter<bool>("UseTauolaPolarization");
00427    
00428    // read tau decay mode switches
00429    //
00430    ParameterSet cards = fPSet->getParameter< ParameterSet >("InputCards");
00431    
00432    fMDTAU = cards.getParameter< int >( "mdtau" );
00433 
00434    if ( fMDTAU == 0 || fMDTAU == 1 )
00435    {
00436       Tauola::setSameParticleDecayMode( cards.getParameter< int >( "pjak1" ) ) ;
00437       Tauola::setOppositeParticleDecayMode( cards.getParameter< int >( "pjak2" ) ) ;
00438    }
00439 
00440    Tauola::setTauLifetime(0.0);
00441    Tauola::spin_correlation.setAll(fPolarization);
00442 
00443    // some more options, copied over from an example 
00444    // - maybe will use later...
00445    //
00446    //Tauola::setEtaK0sPi(0,0,0); // switches to decay eta K0_S and pi0 1/0 on/off. 
00447    //
00448 
00449 //
00450 //   const HepPDT::ParticleData* 
00451 //         PData = fPDGTable->particle(HepPDT::ParticleID( abs(Tauola::getDecayingParticle()) )) ;
00452 //   double lifetime = PData->lifetime().value();
00453 //   Tauola::setTauLifetime( lifetime );
00454 
00455    fPDGs.push_back( Tauola::getDecayingParticle() );
00456 
00457    Tauola::setRandomGenerator(&gen::TauolappInterface_RandGetter);         
00458    Tauola::initialize();
00459 
00460    Tauola::spin_correlation.setAll(fPolarization);// Tauola switches this on during Tauola::initialise(); so we add this here to keep it on/off
00461 
00462    // override decay modes if needs be
00463    //
00464    // we have to do it AFTER init because otherwises branching ratios are NOT filled in
00465    //
00466    if ( fMDTAU != 0 && fMDTAU != 1 )
00467    {
00468       decodeMDTAU( fMDTAU );
00469    }
00470 
00471    Log::LogWarning(false);
00472    
00473    return;
00474 }
00475 
00476 float TauolaInterface::flat()
00477 {
00478 
00479    if ( !fPSet )
00480    {
00481       // throw
00482       throw cms::Exception("TauolaInterfaceError")
00483          << "Attempt to run random number generator of un-initialized Tauola\n"
00484          << std::endl;   
00485    }
00486    
00487    if ( !fIsInitialized ) 
00488    {
00489       // throw
00490       throw cms::Exception("TauolaInterfaceError")
00491          << "Attempt to run random number generator of un-initialized Tauola\n"
00492          << std::endl;   
00493    }
00494    
00495    return fRandomEngine->flat();
00496 
00497 }
00498 
00499 HepMC::GenEvent* TauolaInterface::decay( HepMC::GenEvent* evt )
00500 {
00501       
00502    if ( !fIsInitialized ) return evt;
00503    
00504    int NPartBefore = evt->particles_size();
00505    int NVtxBefore  = evt->vertices_size();
00506    
00507    // what do we do if Hep::GenEvent size is larger than 10K ???
00508    // Tauola (& Photos, BTW) can only handle up to 10K via HEPEVT,
00509    // and in case of CMS, it's only up to 4K !!!
00510    //
00511    // if ( NPartBefore > 10000 ) return evt;
00512    //
00513    
00514    // override decay mode if needs be
00515    if ( fSelectDecayByEvent )
00516    {
00517       selectDecayByMDTAU();
00518    }
00519    
00520     //construct tmp TAUOLA event
00521     //
00522     TauolaHepMCEvent * t_event = new TauolaHepMCEvent(evt);
00523    
00524     // another option: if one lets Pythia or another master gen to decay taus, 
00525     //                 we have to undecay them first
00526     // t_event->undecayTaus();
00527     
00528     // run Tauola on the tmp event - HepMC::GenEvernt will be MODIFIED !!!
00529     //
00530     t_event->decayTaus();
00531     
00532     // delet tmp Tauola event
00533     //
00534     delete t_event; 
00535     
00536     // do we also need to apply the lifetime and vtx position shift ??? 
00537     // (see TauolaInterface, for example)
00538     //
00539     // NOTE: the procedure ASSYMES that vertex barcoding is COUNTIUOUS/SEQUENTIAL,
00540     // and that the abs(barcode) corresponds to vertex "plain indexing"
00541     //
00542     for ( int iv=NVtxBefore+1; iv<=evt->vertices_size(); iv++ )
00543     {
00544        HepMC::GenVertex* GenVtx = evt->barcode_to_vertex(-iv);
00545        HepMC::GenParticle* GenPart = *(GenVtx->particles_in_const_begin());
00546        HepMC::GenVertex* ProdVtx = GenPart->production_vertex();
00547        HepMC::FourVector PMom = GenPart->momentum();
00548        double mass = GenPart->generated_mass();
00549        const HepPDT::ParticleData* 
00550              PData = fPDGTable->particle(HepPDT::ParticleID(abs(GenPart->pdg_id()))) ;
00551        double lifetime = PData->lifetime().value();
00552        float prob = 0.;
00553        int length=1;
00554        ranmar_(&prob,&length);
00555        double ct = -lifetime * std::log(prob);
00556        double VxDec = GenVtx->position().x();
00557        VxDec += ct * (PMom.px()/mass);
00558        VxDec += ProdVtx->position().x();
00559        double VyDec = GenVtx->position().y();
00560        VyDec += ct * (PMom.py()/mass);
00561        VyDec += ProdVtx->position().y();
00562        double VzDec = GenVtx->position().z();
00563        VzDec += ct * (PMom.pz()/mass);
00564        VzDec += ProdVtx->position().z();
00565        double VtDec = GenVtx->position().t();
00566        VtDec += ct * (PMom.e()/mass);
00567        VtDec += ProdVtx->position().t();
00568        GenVtx->set_position( HepMC::FourVector(VxDec,VyDec,VzDec,VtDec) ); 
00569        //
00570        // now find decay products with funky barcode, weed out and replace with clones of sensible barcode
00571        // we can NOT change the barcode while iterating, because iterators do depend on the barcoding
00572        // thus we have to take a 2-step procedure
00573        //
00574        std::vector<int> BCodes;
00575        BCodes.clear();
00576        for (HepMC::GenVertex::particle_iterator pitr= GenVtx->particles_begin(HepMC::children);
00577                                                pitr != GenVtx->particles_end(HepMC::children); ++pitr) 
00578        {
00579           if ( (*pitr)->barcode() > 10000 )
00580           {
00581              BCodes.push_back( (*pitr)->barcode() );
00582           }
00583        }
00584        if ( BCodes.size() > 0 )
00585        {
00586           for ( size_t ibc=0; ibc<BCodes.size(); ibc++ )
00587           {
00588              HepMC::GenParticle* p1 = evt->barcode_to_particle( BCodes[ibc] );
00589              int nbc = p1->barcode() - 10000 + NPartBefore;
00590              p1->suggest_barcode( nbc );
00591           }
00592        }             
00593     }
00594         
00595     return evt;
00596       
00597 }
00598 
00599 void TauolaInterface::statistics()
00600 {
00601    return;
00602 }
00603 
00604 void TauolaInterface::decodeMDTAU( int mdtau )
00605 {
00606 
00607    // Note-1:
00608    // I have to hack the common block directly because set<...>DecayMode(...)
00609    // only changes it in the Tauola++ instance but does NOT passes it over
00610    // to the Fortran core - this it does only one, via initialize() stuff...
00611    //
00612    // So I'll do both ways of settings, just for consistency...
00613    // but I probably need to communicate it to the Tauola(++) team...
00614    //
00615    
00616    // Note-2: 
00617    // originally, the 1xx settings are meant for tau's from hard event,
00618    // and the 2xx settings are for any tau in the event record;
00619    //
00620    // later one, we'll have to take this into account...
00621    // but first I'll have to sort out what happens in the 1xx case
00622    // to tau's coming outside of hard event (if any in the record)   
00623    //
00624    
00625    if ( mdtau == 101 || mdtau == 201 )
00626    {
00627       // override with electron mode for both tau's
00628       //
00629       jaki_.jak1 = 1;
00630       jaki_.jak2 = 1;
00631       Tauola::setSameParticleDecayMode( 1 ) ;
00632       Tauola::setOppositeParticleDecayMode( 1 ) ;
00633       return;
00634    }
00635    
00636    if ( mdtau == 102 || mdtau == 202 )
00637    {
00638       // override with muon mode for both tau's
00639       //
00640       jaki_.jak1 = 2;
00641       jaki_.jak2 = 2;
00642       Tauola::setSameParticleDecayMode( 2 ) ;
00643       Tauola::setOppositeParticleDecayMode( 2 ) ;
00644       return;
00645    }
00646 
00647    if ( mdtau == 111 || mdtau == 211 )
00648    {
00649       // override with electron mode for 1st tau 
00650       // and any mode for 2nd tau
00651       //
00652       jaki_.jak1 = 1;
00653       jaki_.jak2 = 0;
00654       Tauola::setSameParticleDecayMode( 1 ) ;
00655       Tauola::setOppositeParticleDecayMode( 0 ) ;
00656       return;
00657    }
00658 
00659    if ( mdtau == 112 || mdtau == 212 )
00660    {
00661       // override with muon mode for the 1st tau 
00662       // and any mode for the 2nd tau
00663       //
00664       jaki_.jak1 = 2;
00665       jaki_.jak2 = 0;
00666       Tauola::setSameParticleDecayMode( 2 ) ;
00667       Tauola::setOppositeParticleDecayMode( 0 ) ;
00668       return;
00669    }
00670    
00671    if ( mdtau == 121 || mdtau == 221 )
00672    {
00673       // override with any mode for the 1st tau 
00674       // and electron mode for the 2nd tau
00675       //
00676       jaki_.jak1 = 0;
00677       jaki_.jak2 = 1;
00678       Tauola::setSameParticleDecayMode( 0 ) ;
00679       Tauola::setOppositeParticleDecayMode( 1 ) ;
00680       return;
00681    }
00682    
00683    if ( mdtau == 122 || mdtau == 222 )
00684    {
00685       // override with any mode for the 1st tau 
00686       // and muon mode for the 2nd tau
00687       //
00688       jaki_.jak1 = 0;
00689       jaki_.jak2 = 2;
00690       Tauola::setSameParticleDecayMode( 0 ) ;
00691       Tauola::setOppositeParticleDecayMode( 2 ) ;
00692       return;
00693    }
00694 
00695    if ( mdtau == 140 || mdtau == 240 )
00696    {
00697       // override with pi+/- nutau mode for both tau's 
00698       //
00699       jaki_.jak1 = 3;
00700       jaki_.jak2 = 3;
00701       Tauola::setSameParticleDecayMode( 3 ) ;
00702       Tauola::setOppositeParticleDecayMode( 3 ) ;
00703       return;
00704    }
00705 
00706    if ( mdtau == 141 || mdtau == 241 )
00707    {
00708       // override with pi+/- nutau mode for the 1st tau 
00709       // and any mode for the 2nd tau
00710       //
00711       jaki_.jak1 = 3;
00712       jaki_.jak2 = 0;
00713       Tauola::setSameParticleDecayMode( 3 ) ;
00714       Tauola::setOppositeParticleDecayMode( 0 ) ;
00715       return;
00716    }
00717 
00718    if ( mdtau == 142 || mdtau == 242 )
00719    {
00720       // override with any mode for the 1st tau 
00721       // and pi+/- nutau mode for 2nd tau
00722       //
00723       jaki_.jak1 = 0;
00724       jaki_.jak2 = 3;
00725       Tauola::setSameParticleDecayMode( 0 ) ;
00726       Tauola::setOppositeParticleDecayMode( 3 ) ;
00727       return;
00728    }
00729    
00730    // OK, we come here for semi-inclusive modes
00731    //
00732    
00733    // First of all, leptons and hadron modes sums
00734    //
00735    // re-scale branching ratios, just in case...
00736    //
00737    double sumBra = 0;
00738    
00739    // the number of decay modes is hardcoded at 22 because that's what it is right now in Tauola
00740    // in the future, perhaps an asscess method would be useful - communicate to Tauola team...
00741    //
00742    
00743    for ( int i=0; i<22; i++ )
00744    {
00745       sumBra += taubra_.gamprt[i];
00746    }
00747    if ( sumBra == 0. ) return ; // perhaps need to throw ?
00748    for ( int i=0; i<22; i++ )
00749    {
00750       double newBra = taubra_.gamprt[i] / sumBra;
00751       Tauola::setTauBr( i+1, newBra ); 
00752    }
00753    sumBra = 1.0;
00754    
00755    double sumLeptonBra = taubra_.gamprt[0] + taubra_.gamprt[1];
00756    double sumHadronBra = sumBra - sumLeptonBra;
00757    
00758    for ( int i=0; i<2; i++ )
00759    {
00760       fLeptonModes.push_back( i+1 );
00761       fScaledLeptonBrRatios.push_back( (taubra_.gamprt[i]/sumLeptonBra) );  
00762    }
00763    for ( int i=2; i<22; i++ )
00764    {
00765       fHadronModes.push_back( i+1 );
00766       fScaledHadronBrRatios.push_back( (taubra_.gamprt[i]/sumHadronBra) ); 
00767    }
00768 
00769    fSelectDecayByEvent = true;
00770    return;
00771       
00772 }
00773 
00774 void TauolaInterface::selectDecayByMDTAU()
00775 {
00776 
00777    
00778    if ( fMDTAU == 100 || fMDTAU == 200 )
00779    {
00780       int mode = selectLeptonic();
00781       jaki_.jak1 = mode;
00782       Tauola::setSameParticleDecayMode( mode );
00783       mode = selectLeptonic();
00784       jaki_.jak2 = mode;
00785       Tauola::setOppositeParticleDecayMode( mode );
00786       return ;
00787    }
00788    
00789    int modeL = selectLeptonic();
00790    int modeH = selectHadronic();
00791    
00792    if ( fMDTAU == 110 || fMDTAU == 210 )
00793    {
00794       jaki_.jak1 = modeL;
00795       jaki_.jak2 = 0;
00796       Tauola::setSameParticleDecayMode( modeL );
00797       Tauola::setOppositeParticleDecayMode( 0 );
00798       return ;
00799    }
00800    
00801    if ( fMDTAU == 120 || fMDTAU == 22 )
00802    {
00803       jaki_.jak1 = 0;
00804       jaki_.jak2 = modeL;
00805       Tauola::setSameParticleDecayMode( 0 );
00806       Tauola::setOppositeParticleDecayMode( modeL );
00807       return;      
00808    }
00809    
00810    if ( fMDTAU == 114 || fMDTAU == 214 )
00811    {
00812       jaki_.jak1 = modeL;
00813       jaki_.jak2 = modeH;
00814       Tauola::setSameParticleDecayMode( modeL );
00815       Tauola::setOppositeParticleDecayMode( modeH );
00816       return;      
00817    }
00818 
00819    if ( fMDTAU == 124 || fMDTAU == 224 )
00820    {
00821       jaki_.jak1 = modeH;
00822       jaki_.jak2 = modeL;
00823       Tauola::setSameParticleDecayMode( modeH );
00824       Tauola::setOppositeParticleDecayMode( modeL );
00825       return;      
00826    }
00827 
00828    if ( fMDTAU == 115 || fMDTAU == 215 )
00829    {
00830       jaki_.jak1 = 1;
00831       jaki_.jak2 = modeH;
00832       Tauola::setSameParticleDecayMode( 1 );
00833       Tauola::setOppositeParticleDecayMode( modeH );
00834       return;      
00835    }
00836 
00837    if ( fMDTAU == 125 || fMDTAU == 225 )
00838    {
00839       jaki_.jak1 = modeH;
00840       jaki_.jak2 = 1;
00841       Tauola::setSameParticleDecayMode( modeH );
00842       Tauola::setOppositeParticleDecayMode( 1 );
00843       return;      
00844    }
00845 
00846    if ( fMDTAU == 116 || fMDTAU == 216 )
00847    {
00848       jaki_.jak1 = 2;
00849       jaki_.jak2 = modeH;
00850       Tauola::setSameParticleDecayMode( 2 );
00851       Tauola::setOppositeParticleDecayMode( modeH );
00852       return;      
00853    }
00854 
00855    if ( fMDTAU == 126 || fMDTAU == 226 )
00856    {
00857       jaki_.jak1 = modeH;
00858       jaki_.jak2 = 2;
00859       Tauola::setSameParticleDecayMode( modeH );
00860       Tauola::setOppositeParticleDecayMode( 2 );
00861       return;      
00862    }
00863 
00864    if ( fMDTAU == 130 || fMDTAU == 230 )
00865    {
00866       jaki_.jak1 = modeH;
00867       jaki_.jak2 = selectHadronic();
00868       Tauola::setSameParticleDecayMode( modeH );
00869       Tauola::setOppositeParticleDecayMode( jaki_.jak2 );
00870       return;      
00871    }
00872 
00873    if ( fMDTAU == 131 || fMDTAU == 231 )
00874    {
00875       jaki_.jak1 = modeH;
00876       jaki_.jak2 = 0;
00877       Tauola::setSameParticleDecayMode( modeH );
00878       Tauola::setOppositeParticleDecayMode( 0 );
00879       return;      
00880    }
00881 
00882    if ( fMDTAU == 132 || fMDTAU == 232 )
00883    {
00884       jaki_.jak1 = 0;
00885       jaki_.jak2 = modeH;
00886       Tauola::setSameParticleDecayMode( 0 );
00887       Tauola::setOppositeParticleDecayMode( modeH );
00888       return;      
00889    }
00890    
00891    // unlikely that we get here on unknown mdtau 
00892    // - there's a protection earlier
00893    // but if we do, just set defaults
00894    // probably need to spit a warning...
00895    //
00896    Tauola::setSameParticleDecayMode( 0 );
00897    Tauola::setOppositeParticleDecayMode( 0 );
00898       
00899    return;
00900    
00901 
00902 }
00903 
00904 int TauolaInterface::selectLeptonic()
00905 {
00906    
00907    float prob = flat();
00908    
00909    if ( prob > 0. && prob <= fScaledLeptonBrRatios[0] ) 
00910    {
00911       return 1;
00912    }
00913    else if ( prob > fScaledLeptonBrRatios[1] && prob <=1. )
00914    {
00915       return 2;
00916    }
00917       
00918    return 0;
00919 }
00920 
00921 int TauolaInterface::selectHadronic()
00922 {
00923 
00924    float prob = 0.;
00925    int len = 1;
00926    ranmar_(&prob,&len);
00927    
00928    double sumBra = fScaledHadronBrRatios[0];
00929    if ( prob > 0. && prob <= sumBra ) 
00930    {
00931       return fHadronModes[0];
00932    }
00933    else
00934    {
00935       int NN = fScaledHadronBrRatios.size();
00936       for ( int i=1; i<NN; i++ )
00937       {
00938          if ( prob > sumBra && prob <= (sumBra+fScaledHadronBrRatios[i]) ) 
00939          {
00940             return fHadronModes[i];
00941          }
00942          sumBra += fScaledHadronBrRatios[i];
00943       }
00944    }
00945    
00946    return 0;
00947 
00948 }
00949 
00950 double gen::TauolappInterface_RandGetter(){
00951   TauolaInterface* instance = TauolaInterface::getInstance();
00952   return  (double)instance->flat();
00953 }
00954 
00955 /* */