diff --git a/CepGen/Cards/LpairHandler.cpp b/CepGen/Cards/LpairHandler.cpp
index 1682054..fc81d0c 100644
--- a/CepGen/Cards/LpairHandler.cpp
+++ b/CepGen/Cards/LpairHandler.cpp
@@ -1,217 +1,217 @@
 #include "CepGen/Cards/LpairHandler.h"
 #include "CepGen/Core/ParametersList.h"
 #include "CepGen/Core/Exception.h"
 
 #include "CepGen/Physics/PDG.h"
 #include "CepGen/StructureFunctions/StructureFunctions.h"
 #include "CepGen/StructureFunctions/LHAPDF.h"
 
 #include "CepGen/Processes/ProcessesHandler.h"
 
 #include "CepGen/Hadronisers/Pythia8Hadroniser.h"
 
 #include <fstream>
 
 namespace CepGen
 {
   namespace Cards
   {
     const int LpairHandler::kInvalid = 99999;
 
     //----- specialization for LPAIR input cards
 
     LpairHandler::LpairHandler( const char* file ) :
       proc_params_( new ParametersList ),
       str_fun_( 11 ), hi_1_( { 0, 0 } ), hi_2_( { 0, 0 } )
     {
       std::ifstream f( file, std::fstream::in );
       if ( !f.is_open() )
         throw CG_FATAL( "LpairHandler" ) << "Failed to parse file \"" << file << "%s\".";
 
       init( &params_ );
 
       //--- parse all fields
       std::unordered_map<std::string, std::string> m_params;
       std::string key, value;
       std::ostringstream os;
       while ( f >> key >> value ) {
         if ( key[0] == '#' ) // FIXME need to ensure there is no extra space before!
           continue;
         setParameter( key, value );
         m_params.insert( { key, value } );
         if ( getDescription( key ) != "null" )
           os << "\n>> " << key << " = " << std::setw( 15 ) << getParameter( key )
              << " (" << getDescription( key ) << ")";
       }
       f.close();
 
       //--- parse the process name
       auto proc = CepGen::ProcessesHandler::get().build( proc_name_, *proc_params_ );
       params_.setProcess( std::move( proc ) );
 
       //--- parse the structure functions code
       const unsigned long kLHAPDFCodeDec = 10000000, kLHAPDFPartDec = 1000000;
       if ( str_fun_ / kLHAPDFCodeDec == 1 ) { // SF from parton
         params_.kinematics.structure_functions = sf::Parameterisation::build( sf::Type::LHAPDF );
         auto sf = dynamic_cast<sf::LHAPDF*>( params_.kinematics.structure_functions.get() );
         const unsigned long icode = str_fun_ % kLHAPDFCodeDec;
         sf->params.pdf_code = icode % kLHAPDFPartDec;
         sf->params.mode = (sf::LHAPDF::Parameters::Mode)( icode / kLHAPDFPartDec ); // 0, 1, 2
       }
       else
         params_.kinematics.structure_functions = sf::Parameterisation::build( (sf::Type)str_fun_ );
 
       //--- parse the integration algorithm name
       if ( integr_type_ == "plain" )
         params_.integrator.type = Integrator::Type::plain;
       else if ( integr_type_ == "Vegas" )
         params_.integrator.type = Integrator::Type::Vegas;
       else if ( integr_type_ == "MISER" )
         params_.integrator.type = Integrator::Type::MISER;
       else if ( integr_type_ != "" )
         throw CG_FATAL( "LpairHandler" ) << "Unrecognized integrator type: " << integr_type_ << "!";
 
       //--- parse the hadronisation algorithm name
       if ( hadr_name_ == "pythia8" )
-        params_.setHadroniser( new Hadroniser::Pythia8Hadroniser( params_, ParametersList() ) );
+        params_.setHadroniser( new hadroniser::Pythia8Hadroniser( params_, ParametersList() ) );
 
       if ( m_params.count( "IEND" ) )
         setValue<bool>( "IEND", ( std::stoi( m_params["IEND"] ) > 1 ) );
 
       //--- check if we are dealing with heavy ions for incoming states
       HeavyIon hi1{ hi_1_.first, (Element)hi_1_.second }, hi2{ hi_2_.first, (Element)hi_2_.second };
       if ( hi1 )
         params_.kinematics.incoming_beams.first.pdg = hi1;
       if ( hi2 )
         params_.kinematics.incoming_beams.second.pdg = hi2;
 
       CG_INFO( "LpairHandler" ) << "File '" << file << "' succesfully opened!\n\t"
         << "The following parameters are set:" << os.str();
     }
 
     void
     LpairHandler::init( Parameters* params )
     {
       //-------------------------------------------------------------------------------------------
       // Process/integration/hadronisation parameters
       //-------------------------------------------------------------------------------------------
 
       registerParameter<std::string>( "PROC", "Process name to simulate", &proc_name_ );
       registerParameter<std::string>( "ITYP", "Integration algorithm", &integr_type_ );
       registerParameter<std::string>( "HADR", "Hadronisation algorithm", &hadr_name_ );
       registerParameter<std::string>( "KMRG", "KMR grid interpolation path", &params_.kinematics.kmr_grid_path );
 
       //-------------------------------------------------------------------------------------------
       // General parameters
       //-------------------------------------------------------------------------------------------
 
       registerParameter<bool>( "IEND", "Generation type", &params->generation.enabled );
       registerParameter<bool>( "NTRT", "Smoothen the integrand", &params->generation.treat );
       registerParameter<int>( "DEBG", "Debugging verbosity", (int*)&Logger::get().level );
       registerParameter<int>( "NCVG", "Number of function calls", (int*)&params->integrator.ncvg );
       registerParameter<int>( "ITVG", "Number of integration iterations", (int*)&params->integrator.vegas.iterations );
       registerParameter<int>( "SEED", "Random generator seed", (int*)&params->integrator.rng_seed );
       registerParameter<int>( "NTHR", "Number of threads to use for events generation", (int*)&params->generation.num_threads );
       registerParameter<int>( "MODE", "Subprocess' mode", (int*)&params->kinematics.mode );
       registerParameter<int>( "NCSG", "Number of points to probe", (int*)&params->generation.num_points );
       registerParameter<int>( "NGEN", "Number of events to generate", (int*)&params->generation.maxgen );
       registerParameter<int>( "NPRN", "Number of events before printout", (int*)&params->generation.gen_print_every );
 
       //-------------------------------------------------------------------------------------------
       // Process-specific parameters
       //-------------------------------------------------------------------------------------------
 
       registerParameter<int>( "METH", "Computation method (kT-factorisation)", &proc_params_->operator[]<int>( "method" ) );
       registerParameter<int>( "IPOL", "Polarisation states to consider", &proc_params_->operator[]<int>( "polarisationStates" ) );
 
       //-------------------------------------------------------------------------------------------
       // Process kinematics parameters
       //-------------------------------------------------------------------------------------------
 
       registerParameter<int>( "PMOD", "Outgoing primary particles' mode", &str_fun_ );
       registerParameter<int>( "EMOD", "Outgoing primary particles' mode", &str_fun_ );
       registerParameter<int>( "PAIR", "Outgoing particles' PDG id", (int*)&proc_params_->operator[]<int>( "pair" ) );
 
       registerParameter<int>( "INA1", "Heavy ion atomic weight (1st incoming beam)", (int*)&hi_1_.first );
       registerParameter<int>( "INZ1", "Heavy ion atomic number (1st incoming beam)", (int*)&hi_1_.second );
       registerParameter<int>( "INA2", "Heavy ion atomic weight (1st incoming beam)", (int*)&hi_2_.first );
       registerParameter<int>( "INZ2", "Heavy ion atomic number (1st incoming beam)", (int*)&hi_2_.second );
       registerParameter<double>( "INP1", "Momentum (1st primary particle)", &params->kinematics.incoming_beams.first.pz );
       registerParameter<double>( "INP2", "Momentum (2nd primary particle)", &params->kinematics.incoming_beams.second.pz );
       registerParameter<double>( "INPP", "Momentum (1st primary particle)", &params->kinematics.incoming_beams.first.pz );
       registerParameter<double>( "INPE", "Momentum (2nd primary particle)", &params->kinematics.incoming_beams.second.pz );
       registerParameter<double>( "PTCT", "Minimal transverse momentum (single central outgoing particle)", &params->kinematics.cuts.central.pt_single.min() );
       registerParameter<double>( "MSCT", "Minimal central system mass", &params->kinematics.cuts.central.mass_sum.min() );
       registerParameter<double>( "ECUT", "Minimal energy (single central outgoing particle)", &params->kinematics.cuts.central.energy_single.min() );
       registerParameter<double>( "ETMN", "Minimal pseudo-rapidity (central outgoing particles)", &params->kinematics.cuts.central.eta_single.min() );
       registerParameter<double>( "ETMX", "Maximal pseudo-rapidity (central outgoing particles)", &params->kinematics.cuts.central.eta_single.max() );
       registerParameter<double>( "YMIN", "Minimal rapidity (central outgoing particles)", &params->kinematics.cuts.central.rapidity_single.min() );
       registerParameter<double>( "YMAX", "Maximal rapidity (central outgoing particles)", &params->kinematics.cuts.central.rapidity_single.max() );
       registerParameter<double>( "Q2MN", "Minimal Q² = -q² (exchanged parton)", &params->kinematics.cuts.initial.q2.min() );
       registerParameter<double>( "Q2MX", "Maximal Q² = -q² (exchanged parton)", &params->kinematics.cuts.initial.q2.max() );
       registerParameter<double>( "MXMN", "Minimal invariant mass of proton remnants", &params->kinematics.cuts.remnants.mass_single.min() );
       registerParameter<double>( "MXMX", "Maximal invariant mass of proton remnants", &params->kinematics.cuts.remnants.mass_single.max() );
     }
 
     void
     LpairHandler::store( const char* file )
     {
       std::ofstream f( file, std::fstream::out | std::fstream::trunc );
       if ( !f.is_open() ) {
         CG_ERROR( "LpairHandler" ) << "Failed to open file \"" << file << "%s\" for writing.";
       }
       for ( const auto& it : p_strings_ )
         if ( it.second.value )
           f << it.first << " = " << *it.second.value << "\n";
       for ( const auto& it : p_ints_ )
         if ( it.second.value )
           f << it.first << " = " << *it.second.value << "\n";
       for ( const auto& it : p_doubles_ )
         if ( it.second.value )
           f << it.first << " = " << *it.second.value << "\n";
       for ( const auto& it : p_bools_ )
         if ( it.second.value )
           f << it.first << " = " << *it.second.value << "\n";
       f.close();
     }
 
     void
     LpairHandler::setParameter( const std::string& key, const std::string& value )
     {
       try { setValue<double>( key.c_str(), std::stod( value ) ); } catch ( std::invalid_argument& ) {}
       try { setValue<int>( key.c_str(), std::stoi( value ) ); } catch ( std::invalid_argument& ) {}
       //setValue<bool>( key.c_str(), std::stoi( value ) );
       setValue<std::string>( key.c_str(), value );
     }
 
     std::string
     LpairHandler::getParameter( std::string key ) const
     {
       double dd = getValue<double>( key.c_str() );
       if ( dd != -999. )
         return std::to_string( dd );
 
       int ui = getValue<int>( key.c_str() );
       if ( ui != 999 )
         return std::to_string( ui );
 
       //if ( out = getValue<bool>( key.c_str() )  );
 
       return getValue<std::string>( key.c_str() );
     }
 
     std::string
     LpairHandler::getDescription( std::string key ) const
     {
       if ( p_strings_.count( key ) )
         return p_strings_.find( key )->second.description;
       if ( p_ints_.count( key ) )
         return p_ints_.find( key )->second.description;
       if ( p_doubles_.count( key ) )
         return p_doubles_.find( key )->second.description;
       if ( p_bools_.count( key ) )
         return p_bools_.find( key )->second.description;
       return "null";
     }
   }
 }
diff --git a/CepGen/Cards/PythonHandler.cpp b/CepGen/Cards/PythonHandler.cpp
index 3393003..83a7f77 100644
--- a/CepGen/Cards/PythonHandler.cpp
+++ b/CepGen/Cards/PythonHandler.cpp
@@ -1,404 +1,404 @@
 #include "CepGen/Cards/PythonHandler.h"
 #include "CepGen/Core/Exception.h"
 
 #ifdef PYTHON
 
 #include "CepGen/Core/TamingFunction.h"
 #include "CepGen/Core/Exception.h"
 #include "CepGen/Core/ParametersList.h"
 
 #include "CepGen/Processes/ProcessesHandler.h"
 
 #include "CepGen/StructureFunctions/StructureFunctions.h"
 #include "CepGen/StructureFunctions/LHAPDF.h"
 #include "CepGen/StructureFunctions/MSTWGrid.h"
 #include "CepGen/StructureFunctions/Schaefer.h"
 
 #include "CepGen/Hadronisers/Pythia8Hadroniser.h"
 
 #include <algorithm>
 
 #if PY_MAJOR_VERSION < 3
 #  define PYTHON2
 #endif
 
 namespace CepGen
 {
   namespace Cards
   {
     //----- specialization for CepGen input cards
     PythonHandler::PythonHandler( const char* file )
     {
       setenv( "PYTHONPATH", ".:..:Cards", 1 );
       std::string filename = getPythonPath( file );
       const size_t fn_len = filename.length()+1;
 
       //Py_DebugFlag = 1;
       //Py_VerboseFlag = 1;
 
 #ifdef PYTHON2
       char* sfilename = new char[fn_len];
       snprintf( sfilename, fn_len, "%s", filename.c_str() );
 #else
       wchar_t* sfilename = new wchar_t[fn_len];
       swprintf( sfilename, fn_len, L"%s", filename.c_str() );
 #endif
       if ( sfilename )
         Py_SetProgramName( sfilename );
 
       Py_InitializeEx( 1 );
 
       if ( sfilename )
         delete [] sfilename;
       if ( !Py_IsInitialized() )
         throw CG_FATAL( "PythonHandler" ) << "Failed to initialise the Python cards parser!";
 
       CG_INFO( "PythonHandler" )
         << "Initialised the Python cards parser\n\t"
         << "Python version: " << Py_GetVersion() << "\n\t"
         << "Platform: " << Py_GetPlatform() << ".";
 
       PyObject* cfg = PyImport_ImportModule( filename.c_str() ); // new
       if ( !cfg )
         throwPythonError( Form( "Failed to parse the configuration card %s", file ) );
 
       PyObject* process = PyObject_GetAttrString( cfg, PROCESS_NAME ); // new
       if ( !process )
         throwPythonError( Form( "Failed to extract a \"%s\" keyword from the configuration card %s", PROCESS_NAME, file ) );
 
       //--- list of process-specific parameters
       ParametersList proc_params;
       fillParameter( process, "processParameters", proc_params );
 
       //--- type of process to consider
       PyObject* pproc_name = getElement( process, MODULE_NAME ); // borrowed
       if ( !pproc_name )
         throwPythonError( Form( "Failed to extract the process name from the configuration card %s", file ) );
       const std::string proc_name = get<std::string>( pproc_name );
 
       //--- process mode
       params_.kinematics.mode = (KinematicsMode)proc_params.get<int>( "mode", (int)KinematicsMode::invalid );
 
       auto proc = CepGen::ProcessesHandler::get().build( proc_name, proc_params );
       params_.setProcess( std::move( proc ) );
 
       //--- process kinematics
       PyObject* pin_kinematics = getElement( process, "inKinematics" ); // borrowed
       if ( pin_kinematics )
         parseIncomingKinematics( pin_kinematics );
 
       PyObject* pout_kinematics = getElement( process, "outKinematics" ); // borrowed
       if ( pout_kinematics )
         parseOutgoingKinematics( pout_kinematics );
 
       //--- taming functions
       PyObject* ptam = getElement( process, "tamingFunctions" ); // borrowed
       if ( ptam )
         parseTamingFunctions( ptam );
 
       Py_CLEAR( process );
 
       PyObject* plog = PyObject_GetAttrString( cfg, "logger" ); // new
       if ( plog ) {
         parseLogging( plog );
         Py_CLEAR( plog );
       }
 
       //--- hadroniser parameters
       PyObject* phad = PyObject_GetAttrString( cfg, "hadroniser" ); // new
       if ( phad ) {
         parseHadroniser( phad );
         Py_CLEAR( phad );
       }
 
       //--- generation parameters
       PyObject* pint = PyObject_GetAttrString( cfg, "integrator" ); // new
       if ( pint ) {
         parseIntegrator( pint );
         Py_CLEAR( pint );
       }
 
       PyObject* pgen = PyObject_GetAttrString( cfg, "generator" ); // new
       if ( pgen ) {
         parseGenerator( pgen );
         Py_CLEAR( pgen );
       }
 
       //--- finalisation
       Py_CLEAR( cfg );
     }
 
     PythonHandler::~PythonHandler()
     {
       if ( Py_IsInitialized() )
         Py_Finalize();
     }
 
     void
     PythonHandler::parseIncomingKinematics( PyObject* kin )
     {
       //--- retrieve the beams PDG ids
       std::vector<double> beams_pz;
       fillParameter( kin, "pz", beams_pz );
       if ( beams_pz.size() == 2 ) {
         params_.kinematics.incoming_beams.first.pz = beams_pz.at( 0 );
         params_.kinematics.incoming_beams.second.pz = beams_pz.at( 1 );
       }
       //--- retrieve the beams longitudinal momentum
       std::vector<int> beams_pdg;
       fillParameter( kin, "pdgIds", beams_pdg );
       if ( beams_pdg.size() == 2 ) {
         params_.kinematics.incoming_beams.first.pdg = (PDG)beams_pdg.at( 0 );
         params_.kinematics.incoming_beams.second.pdg = (PDG)beams_pdg.at( 1 );
       }
       double sqrt_s = -1.;
       fillParameter( kin, "cmEnergy", sqrt_s );
       fillParameter( kin, "kmrGridPath", params_.kinematics.kmr_grid_path );
       if ( sqrt_s != -1. )
         params_.kinematics.setSqrtS( sqrt_s );
       PyObject* psf = getElement( kin, "structureFunctions" ); // borrowed
       if ( psf )
         parseStructureFunctions( psf, params_.kinematics.structure_functions );
       std::vector<int> kt_fluxes;
       fillParameter( kin, "ktFluxes", kt_fluxes );
       if ( kt_fluxes.size() > 0 )
         params_.kinematics.incoming_beams.first.kt_flux = (KTFlux)kt_fluxes.at( 0 );
       if ( kt_fluxes.size() > 1 )
         params_.kinematics.incoming_beams.second.kt_flux = (KTFlux)kt_fluxes.at( 1 );
       std::vector<int> hi_beam1, hi_beam2;
       fillParameter( kin, "heavyIonA", hi_beam1 );
       if ( hi_beam1.size() == 2 )
         params_.kinematics.incoming_beams.first.pdg = HeavyIon{ (unsigned short)hi_beam1[0], (Element)hi_beam1[1] };
       fillParameter( kin, "heavyIonB", hi_beam2 );
       if ( hi_beam2.size() == 2 )
         params_.kinematics.incoming_beams.second.pdg = HeavyIon{ (unsigned short)hi_beam2[0], (Element)hi_beam2[1] };
     }
 
     void
     PythonHandler::parseStructureFunctions( PyObject* psf, std::shared_ptr<sf::Parameterisation>& sf_handler )
     {
       int str_fun = 0;
       fillParameter( psf, "id", str_fun );
       sf_handler = sf::Parameterisation::build( (sf::Type)str_fun );
       switch( (sf::Type)str_fun ) {
         case sf::Type::LHAPDF: {
           auto sf = std::dynamic_pointer_cast<sf::LHAPDF>( params_.kinematics.structure_functions );
           fillParameter( psf, "pdfSet", sf->params.pdf_set );
           fillParameter( psf, "numFlavours", (unsigned int&)sf->params.num_flavours );
           fillParameter( psf, "pdfMember", (unsigned int&)sf->params.pdf_member );
           fillParameter( psf, "mode", (unsigned int&)sf->params.mode );
         } break;
         case sf::Type::MSTWgrid: {
           auto sf = std::dynamic_pointer_cast<mstw::Grid>( params_.kinematics.structure_functions );
           fillParameter( psf, "gridPath", sf->params.grid_path );
         } break;
         case sf::Type::Schaefer: {
           auto sf = std::dynamic_pointer_cast<sf::Schaefer>( params_.kinematics.structure_functions );
           fillParameter( psf, "Q2cut", sf->params.q2_cut );
           std::vector<double> w2_lims;
           fillParameter( psf, "W2limits", w2_lims );
           if ( w2_lims.size() != 0 ) {
             if ( w2_lims.size() != 2 )
               throwPythonError( Form( "Invalid size for W2limits attribute: %d != 2!", w2_lims.size() ) );
             else {
               sf->params.w2_lo = *std::min_element( w2_lims.begin(), w2_lims.end() );
               sf->params.w2_hi = *std::max_element( w2_lims.begin(), w2_lims.end() );
             }
           }
           PyObject* pcsf = getElement( psf, "continuumSF" ); // borrowed
           if ( pcsf )
             parseStructureFunctions( pcsf, sf->params.continuum_model );
           PyObject* ppsf = getElement( psf, "perturbativeSF" ); // borrowed
           if ( ppsf )
             parseStructureFunctions( ppsf, sf->params.perturbative_model );
           PyObject* prsf = getElement( psf, "resonancesSF" ); // borrowed
           if ( prsf )
             parseStructureFunctions( prsf, sf->params.resonances_model );
           fillParameter( psf, "higherTwist", (bool&)sf->params.higher_twist );
         } break;
         default: break;
       }
     }
 
     void
     PythonHandler::parseOutgoingKinematics( PyObject* kin )
     {
       PyObject* pparts = getElement( kin, "minFinalState" ); // borrowed
       if ( pparts && PyTuple_Check( pparts ) )
         for ( unsigned short i = 0; i < PyTuple_Size( pparts ); ++i )
           params_.kinematics.minimum_final_state.emplace_back( (PDG)get<int>( PyTuple_GetItem( pparts, i ) ) );
 
       PyObject* pcuts = getElement( kin, "cuts" ); // borrowed
       if ( pcuts )
         parseParticlesCuts( pcuts );
 
       // for LPAIR/collinear matrix elements
       fillLimits( kin, "q2", params_.kinematics.cuts.initial.q2 );
 
       // for the kT factorised matrix elements
       fillLimits( kin, "qt", params_.kinematics.cuts.initial.qt );
       fillLimits( kin, "phiqt", params_.kinematics.cuts.initial.phi_qt );
       fillLimits( kin, "ptdiff", params_.kinematics.cuts.central.pt_diff );
       fillLimits( kin, "phiptdiff", params_.kinematics.cuts.central.phi_pt_diff );
       fillLimits( kin, "rapiditydiff", params_.kinematics.cuts.central.rapidity_diff );
 
       // generic phase space limits
       fillLimits( kin, "rapidity", params_.kinematics.cuts.central.rapidity_single );
       fillLimits( kin, "eta", params_.kinematics.cuts.central.eta_single );
       fillLimits( kin, "pt", params_.kinematics.cuts.central.pt_single );
 
       fillLimits( kin, "ptsum", params_.kinematics.cuts.central.pt_sum );
       fillLimits( kin, "invmass", params_.kinematics.cuts.central.mass_sum );
 
       fillLimits( kin, "mx", params_.kinematics.cuts.remnants.mass_single );
     }
 
     void
     PythonHandler::parseParticlesCuts( PyObject* cuts )
     {
       if ( !PyDict_Check( cuts ) )
         throwPythonError( "Particle cuts object should be a dictionary!" );
       PyObject* pkey = nullptr, *pvalue = nullptr;
       Py_ssize_t pos = 0;
       while ( PyDict_Next( cuts, &pos, &pkey, &pvalue ) ) {
         const PDG pdg = (PDG)get<int>( pkey );
         fillLimits( pvalue, "pt", params_.kinematics.cuts.central_particles[pdg].pt_single );
         fillLimits( pvalue, "energy", params_.kinematics.cuts.central_particles[pdg].energy_single );
         fillLimits( pvalue, "eta", params_.kinematics.cuts.central_particles[pdg].eta_single );
         fillLimits( pvalue, "rapidity", params_.kinematics.cuts.central_particles[pdg].rapidity_single );
       }
     }
 
     void
     PythonHandler::parseLogging( PyObject* log )
     {
       fillParameter( log, "level", (int&)Logger::get().level );
       std::vector<std::string> enabled_modules;
       fillParameter( log, "enabledModules", enabled_modules );
       for ( const auto& mod : enabled_modules )
         Logger::get().addExceptionRule( mod );
     }
 
     void
     PythonHandler::parseIntegrator( PyObject* integr )
     {
       if ( !PyDict_Check( integr ) )
         throwPythonError( "Integrator object should be a dictionary!" );
       PyObject* palgo = getElement( integr, MODULE_NAME ); // borrowed
       if ( !palgo )
         throwPythonError( "Failed to retrieve the integration algorithm name!" );
       std::string algo = get<std::string>( palgo );
       if ( algo == "plain" )
         params_.integrator.type = Integrator::Type::plain;
       else if ( algo == "Vegas" ) {
         params_.integrator.type = Integrator::Type::Vegas;
         fillParameter( integr, "alpha", (double&)params_.integrator.vegas.alpha );
         fillParameter( integr, "iterations", params_.integrator.vegas.iterations );
         fillParameter( integr, "mode", (int&)params_.integrator.vegas.mode );
         fillParameter( integr, "verbosity", (int&)params_.integrator.vegas.verbose );
         std::string vegas_logging_output = "cerr";
         fillParameter( integr, "loggingOutput", vegas_logging_output );
         if ( vegas_logging_output == "cerr" )
           // redirect all debugging information to the error stream
           params_.integrator.vegas.ostream = stderr;
         else if ( vegas_logging_output == "cout" )
           // redirect all debugging information to the standard stream
           params_.integrator.vegas.ostream = stdout;
         else
           params_.integrator.vegas.ostream = fopen( vegas_logging_output.c_str(), "w" );
       }
       else if ( algo == "MISER" ) {
         params_.integrator.type = Integrator::Type::MISER;
         fillParameter( integr, "estimateFraction", (double&)params_.integrator.miser.estimate_frac );
         fillParameter( integr, "minCalls", params_.integrator.miser.min_calls );
         fillParameter( integr, "minCallsPerBisection", params_.integrator.miser.min_calls_per_bisection );
         fillParameter( integr, "alpha", (double&)params_.integrator.miser.alpha );
         fillParameter( integr, "dither", (double&)params_.integrator.miser.dither );
       }
       else
         throwPythonError( Form( "Invalid integration algorithm: %s", algo.c_str() ) );
 
       fillParameter( integr, "numFunctionCalls", params_.integrator.ncvg );
       fillParameter( integr, "seed", (unsigned long&)params_.integrator.rng_seed );
       unsigned int rng_engine;
       fillParameter( integr, "rngEngine", rng_engine );
       switch ( rng_engine ) {
         case 0: default: params_.integrator.rng_engine = (gsl_rng_type*)gsl_rng_mt19937; break;
         case 1: params_.integrator.rng_engine = (gsl_rng_type*)gsl_rng_taus2; break;
         case 2: params_.integrator.rng_engine = (gsl_rng_type*)gsl_rng_gfsr4; break;
         case 3: params_.integrator.rng_engine = (gsl_rng_type*)gsl_rng_ranlxs0; break;
       }
       fillParameter( integr, "chiSqCut", params_.integrator.vegas_chisq_cut );
     }
 
     void
     PythonHandler::parseGenerator( PyObject* gen )
     {
       if ( !PyDict_Check( gen ) )
         throwPythonError( "Generation information object should be a dictionary!" );
       params_.generation.enabled = true;
       fillParameter( gen, "treat", params_.generation.treat );
       fillParameter( gen, "numEvents", params_.generation.maxgen );
       fillParameter( gen, "printEvery", params_.generation.gen_print_every );
       fillParameter( gen, "numThreads", params_.generation.num_threads );
       fillParameter( gen, "numPoints", params_.generation.num_points );
     }
 
     void
     PythonHandler::parseTamingFunctions( PyObject* tf )
     {
       if ( !PyList_Check( tf ) )
         throwPythonError( "Taming functions list should be a list!" );
 
       for ( Py_ssize_t i = 0; i < PyList_Size( tf ); ++i ) {
         PyObject* pit = PyList_GetItem( tf, i ); // borrowed
         if ( !pit )
           continue;
         if ( !PyDict_Check( pit ) )
           throwPythonError( Form( "Item %d has invalid type %s", i, pit->ob_type->tp_name ) );
         PyObject* pvar = getElement( pit, "variable" ), *pexpr = getElement( pit, "expression" ); // borrowed
         params_.taming_functions->add( get<std::string>( pvar ).c_str(), get<std::string>( pexpr ).c_str() );
       }
     }
 
     void
     PythonHandler::parseHadroniser( PyObject* hadr )
     {
       if ( !PyDict_Check( hadr ) )
         throwPythonError( "Hadroniser object should be a dictionary!" );
 
       PyObject* pname = getElement( hadr, MODULE_NAME ); // borrowed
       if ( !pname )
         throwPythonError( "Hadroniser name is required!" );
       std::string hadr_name = get<std::string>( pname );
 
       //--- list of module-specific parameters
       ParametersList mod_params;
       fillParameter( hadr, "moduleParameters", mod_params );
 
       if ( hadr_name == "pythia8" )
-        params_.setHadroniser( new Hadroniser::Pythia8Hadroniser( params_, mod_params ) );
+        params_.setHadroniser( new hadroniser::Pythia8Hadroniser( params_, mod_params ) );
       else
         throwPythonError( Form( "Unrecognised hadronisation algorithm: \"%s\"!", hadr_name.c_str() ) );
 
       auto h = params_.hadroniser();
       { //--- before calling the init() method
         std::vector<std::string> config;
         fillParameter( hadr, "preConfiguration", config );
         h->readStrings( config );
       }
       h->init();
       { //--- after init() has been called
         std::vector<std::string> config;
         fillParameter( hadr, "processConfiguration", config );
         for ( const auto& block : config ) {
           std::vector<std::string> config_blk;
           fillParameter( hadr, block.c_str(), config_blk );
           h->readStrings( config_blk );
         }
       }
     }
   }
 }
 
 #endif
diff --git a/CepGen/Core/Integrand.cpp b/CepGen/Core/Integrand.cpp
index 678cea4..2e4f9ad 100644
--- a/CepGen/Core/Integrand.cpp
+++ b/CepGen/Core/Integrand.cpp
@@ -1,202 +1,201 @@
 #include "CepGen/Core/Timer.h"
 #include "CepGen/Core/Exception.h"
 #include "CepGen/Core/TamingFunction.h"
 #include "CepGen/Event/Event.h"
 #include "CepGen/Event/Particle.h"
 #include "CepGen/Physics/Kinematics.h"
 #include "CepGen/Physics/PDG.h"
 
 #include "CepGen/Processes/GenericProcess.h"
 #include "CepGen/Hadronisers/GenericHadroniser.h"
 
 #include "CepGen/Parameters.h"
 
 #include <sstream>
 #include <fstream>
 
 namespace CepGen
 {
   namespace Integrand
   {
     Logger::Level log_level;
     Timer tmr;
 
     double
     eval( double* x, size_t ndim, void* params )
     {
       log_level = Logger::get().level;
       std::shared_ptr<Event> ev;
 
       Parameters* p = static_cast<Parameters*>( params );
       if ( !p )
         throw CG_FATAL( "Integrand" ) << "Failed to retrieve the run parameters!";
 
-      Process::GenericProcess* proc = p->process();
+      process::GenericProcess* proc = p->process();
       if ( !proc )
         throw CG_FATAL( "Integrand" ) << "Failed to retrieve the process!";
 
       //=============================================================================================
       // start the timer
       //=============================================================================================
 
       tmr.reset();
 
       //=============================================================================================
       // prepare the event content prior to the process generation
       //=============================================================================================
 
       if ( proc->hasEvent() ) {
         ev = proc->event();
 
         if ( proc->first_run ) {
           CG_DEBUG( "Integrand" )
             << "Computation launched for " << p->processName() << " process "
             << "0x" << std::hex << p->process() << std::dec << ".\n\t"
             << "Process mode considered: " << p->kinematics.mode << "\n\t"
             << "  pz(p1) = " << p->kinematics.incoming_beams.first.pz << "\n\t"
             << "  pz(p2) = " << p->kinematics.incoming_beams.second.pz << "\n\t"
             << "  structure functions: " << p->kinematics.structure_functions;
 
           p->clearRunStatistics();
           proc->first_run = false;
         } // passed the first-run preparation
 
         proc->clearEvent();
       } // event is not empty
 
       //=============================================================================================
       // specify the phase space point to probe
       //=============================================================================================
 
       proc->setPoint( ndim, x );
 
       //=============================================================================================
       // from this step on, the phase space point is supposed to be set
       //=============================================================================================
 
       p->process()->beforeComputeWeight();
       double integrand = p->process()->computeWeight();
 
       //=============================================================================================
       // invalidate any unphysical behaviour
       //=============================================================================================
 
       if ( integrand <= 0. )
         return 0.;
 
       //=============================================================================================
       // speed up the integration process if no event needs to be generated
       //=============================================================================================
 
       if ( !p->storage()
         && !p->taming_functions
         && !p->hadroniser()
         &&  p->kinematics.cuts.central_particles.size() == 0 )
         return integrand;
 
       //=============================================================================================
       // fill in the process' Event object
       //=============================================================================================
 
       p->process()->fillKinematics();
 
       //=============================================================================================
       // once the kinematics variables have been populated, can apply the collection of taming functions
       //=============================================================================================
 
       if ( p->taming_functions ) {
         if ( p->taming_functions->has( "m_central" )
           || p->taming_functions->has( "pt_central" ) ) {
 
           // build the kinematics of the central system
           Particle::Momentum central_system;
           for ( const auto& part : ev->getByRole( Particle::CentralSystem ) )
             central_system += part.momentum();
 
           // tame the cross-section by the reweighting function
           if ( p->taming_functions->has( "m_central" ) )
             integrand *= p->taming_functions->eval( "m_central", central_system.mass() );
           if ( p->taming_functions->has( "pt_central" ) )
             integrand *= p->taming_functions->eval( "pt_central", central_system.pt() );
         }
         if ( p->taming_functions->has( "q2" ) ) {
           integrand *= p->taming_functions->eval( "q2", -ev->getOneByRole( Particle::Parton1 ).momentum().mass() );
           integrand *= p->taming_functions->eval( "q2", -ev->getOneByRole( Particle::Parton2 ).momentum().mass() );
         }
       }
 
       if ( integrand <= 0. )
         return 0.;
 
       //=============================================================================================
       // set the CepGen part of the event generation
       //=============================================================================================
 
       if ( p->storage() )
         ev->time_generation = tmr.elapsed();
 
       //=============================================================================================
       // event hadronisation and resonances decay
       //=============================================================================================
 
       if ( p->hadroniser() ) {
         double br = -1.;
         if ( !p->hadroniser()->run( *ev, br, p->storage() ) || br == 0. )
           return 0.;
         integrand *= br; // branching fraction for all decays
       }
 
       //=============================================================================================
       // apply cuts on final state system (after hadronisation!)
       // (watch out your cuts, as this might be extremely time-consuming...)
       //=============================================================================================
 
       if ( p->kinematics.cuts.central_particles.size() > 0 ) {
         for ( const auto& part : ev->getByRole( Particle::CentralSystem ) ) {
           // retrieve all cuts associated to this final state particle
           if ( p->kinematics.cuts.central_particles.count( part.pdgId() ) == 0 )
             continue;
           const auto& cuts_pdgid = p->kinematics.cuts.central_particles.at( part.pdgId() );
           // apply these cuts on the given particle
           if ( !cuts_pdgid.pt_single.passes( part.momentum().pt() ) )
             return 0.;
           if ( !cuts_pdgid.energy_single.passes( part.momentum().energy() ) )
             return 0.;
           if ( !cuts_pdgid.eta_single.passes( part.momentum().eta() ) )
             return 0.;
           if ( !cuts_pdgid.rapidity_single.passes( part.momentum().rapidity() ) )
             return 0.;
         }
       }
 
       //=============================================================================================
       // store the last event in the parameters for its usage by the end user
       //=============================================================================================
 
       if ( p->storage() ) {
         p->process()->last_event = ev;
         p->process()->last_event->time_total = tmr.elapsed();
 
         CG_DEBUG( "Integrand" )
           << "[process 0x" << std::hex << p->process() << std::dec << "] "
           << "Individual time (gen+hadr+cuts): " << p->process()->last_event->time_total*1.e3 << " ms";
       }
 
       //=============================================================================================
       // a bit of useful debugging
       //=============================================================================================
 
       if ( CG_EXCEPT_MATCH( "Integrand", debugInsideLoop ) ) {
         std::ostringstream oss;
         for ( unsigned short i = 0; i < ndim; ++i )
           oss << Form( "%10.8f ", x[i] );
         CG_DEBUG( "Integrand" )
           << "f value for dim-" << ndim << " point ( " << oss.str() << "): "
           << integrand;
       }
 
       return integrand;
     }
   }
 }
-
diff --git a/CepGen/Core/Parameters.cpp b/CepGen/Core/Parameters.cpp
index a2fc6cf..b1bca39 100644
--- a/CepGen/Core/Parameters.cpp
+++ b/CepGen/Core/Parameters.cpp
@@ -1,257 +1,257 @@
 #include "CepGen/Parameters.h"
 
 #include "CepGen/Core/ParametersList.h"
 #include "CepGen/Core/Exception.h"
 #include "CepGen/Core/TamingFunction.h"
 
 #include "CepGen/Physics/PDG.h"
 #include "CepGen/Processes/GenericProcess.h"
 #include "CepGen/Hadronisers/GenericHadroniser.h"
 
 #include "CepGen/StructureFunctions/StructureFunctions.h"
 
 #include <iomanip>
 
 namespace CepGen
 {
   Parameters::Parameters() :
     general( new ParametersList ),
     taming_functions( new TamingFunctionsCollection ),
     store_( false ), total_gen_time_( 0. ), num_gen_events_( 0 )
   {}
 
   Parameters::Parameters( Parameters& param ) :
     general( param.general ),
     kinematics( param.kinematics ), integrator( param.integrator ), generation( param.generation ),
     taming_functions( param.taming_functions ),
     process_( std::move( param.process_ ) ),
     hadroniser_( std::move( param.hadroniser_ ) ),
     store_( false ), total_gen_time_( param.total_gen_time_ ), num_gen_events_( param.num_gen_events_ )
   {}
 
   Parameters::Parameters( const Parameters& param ) :
     general( param.general ),
     kinematics( param.kinematics ), integrator( param.integrator ), generation( param.generation ),
     taming_functions( param.taming_functions ),
     store_( false ), total_gen_time_( param.total_gen_time_ ), num_gen_events_( param.num_gen_events_ )
   {}
 
   Parameters::~Parameters() // required for unique_ptr initialisation!
   {}
 
   void
   Parameters::setThetaRange( float thetamin, float thetamax )
   {
     kinematics.cuts.central.eta_single = {
       Particle::thetaToEta( thetamax ),
       Particle::thetaToEta( thetamin )
     };
 
     CG_DEBUG( "Parameters" )
       << "eta in range: " << kinematics.cuts.central.eta_single
       << " => theta(min) = " << thetamin << ", theta(max) = " << thetamax << ".";
   }
 
   void
   Parameters::clearRunStatistics()
   {
     total_gen_time_ = 0.;
     num_gen_events_ = 0;
   }
 
   void
   Parameters::addGenerationTime( double gen_time )
   {
     total_gen_time_ += gen_time;
     num_gen_events_++;
   }
 
-  Process::GenericProcess*
+  process::GenericProcess*
   Parameters::process()
   {
     return process_.get();
   }
 
   std::string
   Parameters::processName() const
   {
     if ( !process_ )
       return "no process";
     return process_->name();
   }
 
   void
-  Parameters::setProcess( std::unique_ptr<Process::GenericProcess> proc )
+  Parameters::setProcess( std::unique_ptr<process::GenericProcess> proc )
   {
     process_ = std::move( proc );
   }
 
   void
-  Parameters::setProcess( Process::GenericProcess* proc )
+  Parameters::setProcess( process::GenericProcess* proc )
   {
     if ( !proc )
       throw CG_FATAL( "Parameters" )
         << "Trying to clone an invalid process!";
     process_.reset( proc );
   }
 
-  Hadroniser::GenericHadroniser*
+  hadroniser::GenericHadroniser*
   Parameters::hadroniser()
   {
     return hadroniser_.get();
   }
 
   std::string
   Parameters::hadroniserName() const
   {
     if ( !hadroniser_ )
       return "";
     return hadroniser_->name();
   }
 
   void
-  Parameters::setHadroniser( Hadroniser::GenericHadroniser* hadr )
+  Parameters::setHadroniser( hadroniser::GenericHadroniser* hadr )
   {
     hadroniser_.reset( hadr );
   }
 
   std::ostream&
   operator<<( std::ostream& os, const Parameters* p )
   {
     const bool pretty = true;
 
     const int wb = 90, wt = 40;
     os
       << "Parameters dump" << std::left << "\n\n"
       << std::setfill('_') << std::setw( wb+3 ) << "_/¯¯RUN¯INFORMATION¯¯\\_" << std::setfill( ' ' ) << "\n"
       << std::right << std::setw( wb ) << std::left << std::endl
       << std::setw( wt ) << "Process to generate";
     if ( p->process_ ) {
       os << ( pretty ? boldify( p->process_->name().c_str() ) : p->process_->name() ) << "\n"
          << std::setw( wt ) << "" << p->process_->description();
     }
     else
       os << ( pretty ? boldify( "no process!" ) : "no process!" );
     os
       << "\n"
       << std::setw( wt ) << "Events generation? "
       << ( pretty ? yesno( p->generation.enabled ) : std::to_string( p->generation.enabled ) ) << "\n"
       << std::setw( wt ) << "Number of events to generate"
       << ( pretty ? boldify( p->generation.maxgen ) : std::to_string( p->generation.maxgen ) ) << "\n";
     if ( p->generation.num_threads > 1 )
       os
         << std::setw( wt ) << "Number of threads" << p->generation.num_threads << "\n";
     os
       << std::setw( wt ) << "Number of points to try per bin" << p->generation.num_points << "\n"
       << std::setw( wt ) << "Integrand treatment"
       << ( pretty ? yesno( p->generation.treat ) : std::to_string( p->generation.treat ) ) << "\n"
       << std::setw( wt ) << "Verbosity level " << Logger::get().level << "\n";
     if ( p->hadroniser_ ) {
       os
         << "\n"
         << std::setfill( '-' ) << std::setw( wb+6 )
         << ( pretty ? boldify( " Hadronisation algorithm " ) : "Hadronisation algorithm" ) << std::setfill( ' ' ) << "\n\n"
         << std::setw( wt ) << "Name"
         << ( pretty ? boldify( p->hadroniser_->name().c_str() ) : p->hadroniser_->name() ) << "\n";
     }
     os
       << "\n"
       << std::setfill( '-' ) << std::setw( wb+6 )
       << ( pretty ? boldify( " Integration parameters " ) : "Integration parameters" ) << std::setfill( ' ' ) << "\n\n";
     std::ostringstream int_algo; int_algo << p->integrator.type;
     os
       << std::setw( wt ) << "Integration algorithm"
       << ( pretty ? boldify( int_algo.str().c_str() ) : int_algo.str() ) << "\n"
       << std::setw( wt ) << "Number of function calls" << p->integrator.ncvg << "\n"
       << std::setw( wt ) << "Random number generator seed" << p->integrator.rng_seed << "\n";
     if ( p->integrator.rng_engine )
       os
         << std::setw( wt ) << "Random number generator engine"
         << p->integrator.rng_engine->name << "\n";
     std::ostringstream proc_mode; proc_mode << p->kinematics.mode;
     os
       << "\n"
       << std::setfill('_') << std::setw( wb+3 )
       << "_/¯¯EVENTS¯KINEMATICS¯¯\\_" << std::setfill( ' ' ) << "\n\n"
       << std::setw( wt ) << "Incoming particles"
       << p->kinematics.incoming_beams.first << ",\n" << std::setw( wt ) << ""
       << p->kinematics.incoming_beams.second << "\n";
     if ( p->kinematics.mode != KinematicsMode::invalid )
       os << std::setw( wt ) << "Subprocess mode" << ( pretty ? boldify( proc_mode.str().c_str() ) : proc_mode.str() ) << "\n";
     if ( p->kinematics.mode != KinematicsMode::ElasticElastic )
       os << std::setw( wt ) << "Structure functions" << *p->kinematics.structure_functions << "\n";
     os
       << "\n"
       << std::setfill( '-' ) << std::setw( wb+6 ) << ( pretty ? boldify( " Incoming partons " ) : "Incoming partons" ) << std::setfill( ' ' ) << "\n\n";
     for ( const auto& lim : p->kinematics.cuts.initial.list() ) // map(particles class, limits)
       if ( lim.second.valid() )
         os << std::setw( wt ) << lim.first << lim.second << "\n";
     os
       << "\n"
       << std::setfill( '-' ) << std::setw( wb+6 ) << ( pretty ? boldify( " Outgoing central system " ) : "Outgoing central system" ) << std::setfill( ' ' ) << "\n\n";
     for ( const auto& lim : p->kinematics.cuts.central.list() )
       if ( lim.second.valid() )
         os << std::setw( wt ) << lim.first << lim.second << "\n";
     if ( p->kinematics.cuts.central_particles.size() > 0 ) {
       os << std::setw( wt ) << ( pretty ? boldify( ">>> per-particle cuts:" ) : ">>> per-particle cuts:" ) << "\n";
       for ( const auto& part_per_lim : p->kinematics.cuts.central_particles ) {
         os << " * all single " << std::setw( wt-3 ) << part_per_lim.first << "\n";
         for ( const auto& lim : part_per_lim.second.list() )
           if ( lim.second.valid() )
             os << "   - " << std::setw( wt-5 ) << lim.first << lim.second << "\n";
       }
     }
     os << "\n";
     os << std::setfill( '-' ) << std::setw( wb+6 ) << ( pretty ? boldify( " Proton / remnants " ) : "Proton / remnants" ) << std::setfill( ' ' ) << "\n\n";
     for ( const auto& lim : p->kinematics.cuts.remnants.list() )
       os << std::setw( wt ) << lim.first << lim.second << "\n";
     return os;
   }
 
   std::ostream&
   operator<<( std::ostream& os, const Parameters& p )
   {
     return os << &p;
   }
 
   //-----------------------------------------------------------------------------------------------
 
   Parameters::Integration::Integration() :
     type( Integrator::Type::Vegas ), ncvg( 500000 ),
     rng_seed( 0 ), rng_engine( (gsl_rng_type*)gsl_rng_mt19937 ),
     vegas_chisq_cut( 1.5 ),
     result( -1. ), err_result( -1. )
   {
     const size_t ndof = 10;
     {
       std::shared_ptr<gsl_monte_vegas_state> tmp_state( gsl_monte_vegas_alloc( ndof ), gsl_monte_vegas_free );
       gsl_monte_vegas_params_get( tmp_state.get(), &vegas );
     }
     {
       std::shared_ptr<gsl_monte_miser_state> tmp_state( gsl_monte_miser_alloc( ndof ), gsl_monte_miser_free );
       gsl_monte_miser_params_get( tmp_state.get(), &miser );
     }
   }
 
   Parameters::Integration::Integration( const Integration& rhs ) :
     type( rhs.type ), ncvg( rhs.ncvg ),
     rng_seed( rhs.rng_seed ), rng_engine( rhs.rng_engine ),
     vegas( rhs.vegas ), vegas_chisq_cut( rhs.vegas_chisq_cut ),
     miser( rhs.miser ),
     result( -1. ), err_result( -1. )
   {}
 
   Parameters::Integration::~Integration()
   {
     //if ( vegas.ostream && vegas.ostream != stdout && vegas.ostream != stderr )
     //  fclose( vegas.ostream );
   }
 
   //-----------------------------------------------------------------------------------------------
 
   Parameters::Generation::Generation() :
     enabled( false ), maxgen( 0 ),
     symmetrise( false ), treat( false ), ngen( 0 ), gen_print_every( 10000 ),
     num_threads( 2 ), num_points( 100 )
   {}
 }
diff --git a/CepGen/Hadronisers/GenericHadroniser.cpp b/CepGen/Hadronisers/GenericHadroniser.cpp
index b2049da..8b297ec 100644
--- a/CepGen/Hadronisers/GenericHadroniser.cpp
+++ b/CepGen/Hadronisers/GenericHadroniser.cpp
@@ -1,54 +1,53 @@
 #include "CepGen/Hadronisers/GenericHadroniser.h"
 
 #include "CepGen/Core/Exception.h"
 #include "CepGen/Core/ParametersList.h"
 
 namespace CepGen
 {
-  namespace Hadroniser
+  namespace hadroniser
   {
     GenericHadroniser::GenericHadroniser( const char* name, const ParametersList& plist ) :
       name_( name ),
       seed_      ( plist.get<int>( "seed", -1ll ) ),
       max_trials_( plist.get<int>( "maxTrials", 1 ) )
     {
       CG_DEBUG( "Hadroniser:init" )
         << "\"" << name_ << "\"-type hadroniser built with:\n\t"
         << "* seed = " << seed_ << "\n\t"
         << "* maximum trials: " << max_trials_;
     }
 
     void
     GenericHadroniser::readStrings( const std::vector<std::string>& params ) {
       if ( params.empty() )
         return;
       std::ostringstream os;
       for ( const auto& p : params ) {
         readString( p );
         os << "\n\t  '" << p << "'";
       }
       CG_DEBUG( "Hadroniser:configure" )
         << "Feeding \"" << name_ << "\" hadroniser with:"
         << os.str();
     }
 
     std::string
     GenericHadroniser::name() const
     {
       return name_;
     }
   }
 
   std::ostream&
-  operator<<( std::ostream& os, const Hadroniser::GenericHadroniser& hadr )
+  operator<<( std::ostream& os, const hadroniser::GenericHadroniser& hadr )
   {
     return os << hadr.name().c_str();
   }
 
   std::ostream&
-  operator<<( std::ostream& os, const Hadroniser::GenericHadroniser* hadr )
+  operator<<( std::ostream& os, const hadroniser::GenericHadroniser* hadr )
   {
     return os << hadr->name().c_str();
   }
 }
-
diff --git a/CepGen/Hadronisers/GenericHadroniser.h b/CepGen/Hadronisers/GenericHadroniser.h
index b7b7440..082fe9c 100644
--- a/CepGen/Hadronisers/GenericHadroniser.h
+++ b/CepGen/Hadronisers/GenericHadroniser.h
@@ -1,70 +1,70 @@
 #ifndef CepGen_Hadronisers_GenericHadroniser_h
 #define CepGen_Hadronisers_GenericHadroniser_h
 
 #include <vector>
 #include <memory>
 #include <iostream>
 
 namespace CepGen
 {
   class Event;
   class Particle;
   class Parameters;
   class ParametersList;
   /// Location for all hadronisers to be run downstream to the events generation
-  namespace Hadroniser
+  namespace hadroniser
   {
     /**
      * \brief Class template to define any hadroniser as a general object with defined methods
      * \author Laurent Forthomme <laurent.forthomme@cern.ch>
      * \date January 2014
      */
     class GenericHadroniser
     {
       public:
         /// Write out all hadroniser attributes in output stream
         friend std::ostream& operator<<( std::ostream& os, const GenericHadroniser& hadr );
         /// Write out all hadroniser attributes in output stream
         friend std::ostream& operator<<( std::ostream& os, const GenericHadroniser* hadr );
 
         /// Default constructor for an undefined hadroniser
         explicit GenericHadroniser( const char* name, const ParametersList& );
         virtual ~GenericHadroniser() {}
 
         /// Parse a configuration string
         virtual void readString( const char* ) {}
         /// Parse a configuration string
         virtual void readString( const std::string& param ) { readString( param.c_str() ); }
         /// Parse a list of configuration strings
         virtual void readStrings( const std::vector<std::string>& params );
         /// Initialise the event hadroniser before its running
         virtual void init() = 0;
         /** \brief Hadronise a full event
          * \param[inout] ev Event to hadronise
          * \param[inout] weight Event weight after hadronisation
          * \param[in] full Perform the full state hadronisation (incl. remnants fragmentation)
          * \return Boolean stating whether or not the hadronisation occured successfully
          */
         virtual bool run( Event& ev, double& weight, bool full ) = 0;
         /// Specify the process cross section, in pb
         virtual void setCrossSection( double xsec, double xsec_err ) {}
 
         /// \brief Specify a random numbers generator seed for the hadroniser
         /// \param[in] seed A RNG seed
         void setSeed( long long seed ) { seed_ = seed; }
 
         /// Return a human-readable name for this hadroniser
         std::string name() const;
 
       protected:
         /// Name of the hadroniser
         std::string name_;
         /// Random numbers generator seed for the hadroniser
         long long seed_;
         /// Maximal number of trials for the hadronisation of the proton(s) remnants
         unsigned short max_trials_;
     };
   }
 }
 
 #endif
diff --git a/CepGen/Hadronisers/Pythia8Hadroniser.cpp b/CepGen/Hadronisers/Pythia8Hadroniser.cpp
index 85964dd..ca6afb6 100644
--- a/CepGen/Hadronisers/Pythia8Hadroniser.cpp
+++ b/CepGen/Hadronisers/Pythia8Hadroniser.cpp
@@ -1,464 +1,464 @@
 #include "CepGen/Hadronisers/Pythia8Hadroniser.h"
 
 #include "CepGen/Parameters.h"
 #include "CepGen/Physics/Kinematics.h"
 #include "CepGen/Physics/Constants.h"
 #include "CepGen/Physics/PDG.h"
 
 #include "CepGen/Core/ParametersList.h"
 #include "CepGen/Core/Exception.h"
 #include "CepGen/Core/utils.h"
 
 #include "CepGen/Event/Event.h"
 #include "CepGen/Event/Particle.h"
 
 #include "CepGen/Version.h"
 
 namespace CepGen
 {
-  namespace Hadroniser
+  namespace hadroniser
   {
 #ifdef PYTHIA8
     Pythia8::Vec4
     momToVec4( const Particle::Momentum& mom )
     {
       return Pythia8::Vec4( mom.px(), mom.py(), mom.pz(), mom.energy() );
     }
 #endif
 
     Pythia8Hadroniser::Pythia8Hadroniser( const Parameters& params, const ParametersList& plist ) :
       GenericHadroniser( "pythia8", plist ),
 #ifdef PYTHIA8
       pythia_( new Pythia8::Pythia ), lhaevt_( new LHAEvent( &params ) ),
 #endif
       full_evt_( false ), offset_( 0 ), first_evt_( true ), params_( &params )
     {
 #ifdef PYTHIA8
       pythia_->setLHAupPtr( (Pythia8::LHAup*)lhaevt_.get() );
       pythia_->settings.parm( "Beams:idA", (short)params.kinematics.incoming_beams.first.pdg );
       pythia_->settings.parm( "Beams:idB", (short)params.kinematics.incoming_beams.second.pdg );
       // specify we will be using a LHA input
       pythia_->settings.mode( "Beams:frameType", 5 );
       pythia_->settings.parm( "Beams:eCM", params.kinematics.sqrtS() );
 #endif
       for ( const auto& pdgid : params.kinematics.minimum_final_state )
         min_ids_.emplace_back( (unsigned short)pdgid );
     }
 
     Pythia8Hadroniser::~Pythia8Hadroniser()
     {
 #ifdef PYTHIA8
       pythia_->settings.writeFile( "last_pythia_config.cmd", false );
 #endif
     }
 
     void
     Pythia8Hadroniser::readString( const char* param )
     {
 #ifdef PYTHIA8
       if ( !pythia_->readString( param ) )
         throw CG_FATAL( "Pythia8Hadroniser" ) << "The Pythia8 core failed to parse the following setting:\n\t" << param;
 #endif
     }
 
     void
     Pythia8Hadroniser::init()
     {
 #ifdef PYTHIA8
       if ( pythia_->settings.flag( "ProcessLevel:all" ) != full_evt_ )
         pythia_->settings.flag( "ProcessLevel:all", full_evt_ );
 
       if ( seed_ == -1ll )
         pythia_->settings.flag( "Random:setSeed", false );
       else {
         pythia_->settings.flag( "Random:setSeed", true );
         pythia_->settings.mode( "Random:seed", seed_ );
       }
 
       switch ( params_->kinematics.mode ) {
         case KinematicsMode::ElasticElastic: {
           pythia_->settings.mode( "BeamRemnants:unresolvedHadron", 3 );
         } break;
         case KinematicsMode::InelasticElastic: {
           pythia_->settings.mode( "BeamRemnants:unresolvedHadron", 2 );
         } break;
         case KinematicsMode::ElasticInelastic: {
           pythia_->settings.mode( "BeamRemnants:unresolvedHadron", 1 );
         } break;
         case KinematicsMode::InelasticInelastic: default: {
           pythia_->settings.mode( "BeamRemnants:unresolvedHadron", 0 );
         } break;
       }
 
       if ( !pythia_->init() )
         throw CG_FATAL( "Pythia8Hadroniser" )
           << "Failed to initialise the Pythia8 core!\n\t"
           << "See the message above for more details.";
 #else
       throw CG_FATAL( "Pythia8Hadroniser" )
         << "Pythia8 is not linked to this instance!";
 #endif
     }
 
     void
     Pythia8Hadroniser::setCrossSection( double xsec, double xsec_err )
     {
 #ifdef PYTHIA8
       lhaevt_->setCrossSection( 0, xsec, xsec_err );
 #endif
     }
 
     bool
     Pythia8Hadroniser::run( Event& ev, double& weight, bool full )
     {
       //--- initialise the event weight before running any decay algorithm
       weight = 1.;
 
 #ifdef PYTHIA8
       if ( !full && !pythia_->settings.flag( "ProcessLevel:resonanceDecays" ) )
         return true;
 
       //--- switch full <-> partial event
       if ( full != full_evt_ ) {
         full_evt_ = full;
         init();
       }
 
       //===========================================================================================
       // convert our event into a custom LHA format
       //===========================================================================================
 
       lhaevt_->feedEvent( ev, full, params_->kinematics.mode );
       //if ( full ) lhaevt_->listEvent();
 
       //===========================================================================================
       // launch the hadronisation / resonances decays, and update the event accordingly
       //===========================================================================================
 
       ev.num_hadronisation_trials = 0;
       while ( true ) {
         if ( ev.num_hadronisation_trials++ > max_trials_ )
           return false;
         //--- run the hadronisation/fragmentation algorithm
         if ( pythia_->next() ) {
           //--- hadronisation successful
           if ( first_evt_ && full ) {
             offset_ = 0;
             for ( unsigned short i = 1; i < pythia_->event.size(); ++i )
               if ( pythia_->event[i].status() == -12 ) // skip the incoming particles
                 offset_++;
             first_evt_ = false;
           }
           break;
         }
       }
 
       //===========================================================================================
       // update the event content with Pythia's output
       //===========================================================================================
 
       updateEvent( ev, weight, full );
       return true;
 #else
       throw CG_FATAL( "Pythia8Hadroniser" ) << "Pythia8 is not linked to this instance!";
 #endif
     }
 
 #ifdef PYTHIA8
     Particle&
     Pythia8Hadroniser::addParticle( Event& ev, const Pythia8::Particle& py_part, const Pythia8::Vec4& mom, unsigned short role ) const
     {
       Particle& op = ev.addParticle( (Particle::Role)role );
       op.setPdgId( static_cast<PDG>( abs( py_part.id() ) ), py_part.charge() );
       op.setStatus( py_part.isFinal()
         ? Particle::Status::FinalState
         : Particle::Status::Propagator );
       op.setMomentum( Particle::Momentum( mom.px(), mom.py(), mom.pz(), mom.e() ) );
       op.setMass( mom.mCalc() );
       lhaevt_->addCorresp( py_part.index()-offset_, op.id() );
       return op;
     }
 
     void
     Pythia8Hadroniser::updateEvent( Event& ev, double& weight, bool full ) const
     {
       for ( unsigned short i = 1+offset_; i < pythia_->event.size(); ++i ) {
         const Pythia8::Particle& p = pythia_->event[i];
         const unsigned short cg_id = lhaevt_->cepgenId( i-offset_ );
         if ( cg_id != LHAEvent::invalid_id ) {
           //----- particle already in the event
           Particle& cg_part = ev[cg_id];
           //--- fragmentation result
           if ( cg_part.role() == Particle::OutgoingBeam1
             || cg_part.role() == Particle::OutgoingBeam2 ) {
             cg_part.setStatus( Particle::Status::Fragmented );
             continue;
           }
           //--- particle is not what we expect
           if ( p.idAbs() != abs( cg_part.integerPdgId() ) ) {
             CG_INFO( "Pythia8Hadroniser:update" ) << "LHAEVT event content:";
             lhaevt_->listEvent();
             CG_INFO( "Pythia8Hadroniser:update" ) << "Pythia event content:";
             pythia_->event.list();
             CG_INFO( "Pythia8Hadroniser:update" ) << "CepGen event content:";
             ev.dump();
             CG_INFO( "Pythia8Hadroniser:update" ) << "Correspondence:";
             lhaevt_->dumpCorresp();
 
             throw CG_FATAL( "Pythia8Hadroniser:update" )
               << "Event list corruption detected for (Pythia/CepGen) particle " << i << "/" << cg_id << ":\n\t"
               << "should be " << abs( p.id() ) << ", "
               << "got " << cg_part.integerPdgId() << "!";
           }
           //--- resonance decayed; apply branching ratio for this decay
           if ( p.particleDataEntry().sizeChannels() > 0 ) {
             weight *= p.particleDataEntry().pickChannel().bRatio();
             cg_part.setStatus( Particle::Status::Resonance );
           }
         }
         else {
           //----- new particle to be added
           const unsigned short role = findRole( ev, p );
           switch ( (Particle::Role)role ) {
             default: break;
             case Particle::OutgoingBeam1: {
               ev.getByRole( Particle::OutgoingBeam1 )[0].setStatus( Particle::Status::Fragmented );
               if ( abs( p.status() ) != 61 )
                 break;
             } // no break!
             case Particle::OutgoingBeam2: {
               ev.getByRole( Particle::OutgoingBeam2 )[0].setStatus( Particle::Status::Fragmented );
               if ( abs( p.status() ) != 61 )
                 break;
             } // no break!
           }
           // found the role ; now we can add the particle
           Particle& cg_part = addParticle( ev, p, p.p(), role );
           for ( const auto& moth_id : p.motherList() ) {
             if ( moth_id <= offset_ )
               continue;
             const unsigned short moth_cg_id = lhaevt_->cepgenId( moth_id-offset_ );
             if ( moth_cg_id != LHAEvent::invalid_id )
               cg_part.addMother( ev[moth_cg_id] );
             else
               cg_part.addMother( addParticle( ev, pythia_->event[moth_id], p.p(), role ) );
             if ( !p.isFinal() ) {
               if ( p.isResonance() || p.daughterList().size() > 0 )
                 cg_part.setStatus( Particle::Status::Resonance );
               else
                 cg_part.setStatus( Particle::Status::Undefined );
             }
           }
         }
       }
     }
 
     unsigned short
     Pythia8Hadroniser::findRole( const Event& ev, const Pythia8::Particle& p ) const
     {
       for ( const auto& par_id : p.motherList() ) {
         if ( par_id == 1 && offset_ > 0 )
           return (unsigned short)Particle::OutgoingBeam1;
         if ( par_id == 2 && offset_ > 0 )
           return (unsigned short)Particle::OutgoingBeam2;
         const unsigned short par_cg_id = lhaevt_->cepgenId( par_id-offset_ );
         if ( par_cg_id != LHAEvent::invalid_id )
           return (unsigned short)ev.at( par_cg_id ).role();
         return findRole( ev, pythia_->event[par_id] );
       }
       return (unsigned short)Particle::UnknownRole;
     }
 #endif
   }
 
   //================================================================================================
   // Custom LHA event definition
   //================================================================================================
 
 #ifdef PYTHIA8
   const double LHAEvent::mp_ = ParticleProperties::mass( PDG::proton );
   const double LHAEvent::mp2_ = LHAEvent::mp_*LHAEvent::mp_;
 
   LHAEvent::LHAEvent( const Parameters* params ) :
     LHAup( 3 ), params_( params )
   {
     addProcess( 0, 1., 1., 1.e3 );
     if ( params_ ) {
       setBeamA( (short)params_->kinematics.incoming_beams.first.pdg, params_->kinematics.incoming_beams.first.pz );
       setBeamB( (short)params_->kinematics.incoming_beams.second.pdg, params_->kinematics.incoming_beams.second.pz );
     }
   }
 
   void
   LHAEvent::setCrossSection( int id, double xsec, double xsec_err )
   {
     setXSec( id, xsec );
     setXErr( id, xsec_err );
     //listInit();
   }
 
   void
   LHAEvent::feedEvent( const Event& ev, bool full, const KinematicsMode& mode )
   {
     const double scale = ev.getOneByRole( Particle::Intermediate ).mass();
     setProcess( 0, 1., scale, Constants::alphaEM, Constants::alphaQCD );
 
     const Particle& part1 = ev.getOneByRole( Particle::Parton1 ), &part2 = ev.getOneByRole( Particle::Parton2 );
     const Particle& op1 = ev.getOneByRole( Particle::OutgoingBeam1 ), &op2 = ev.getOneByRole( Particle::OutgoingBeam2 );
     const double q2_1 = -part1.momentum().mass2(), q2_2 = -part2.momentum().mass2();
     const double x1 = q2_1/( q2_1+op1.mass2()-mp2_ ), x2 = q2_2/( q2_2+op2.mass2()-mp2_ );
 
     unsigned short quark1_id = 0, quark2_id = 0;
     unsigned short quark1_pdgid = part1.integerPdgId(), quark2_pdgid = part2.integerPdgId();
 
-    const Pythia8::Vec4 mom_part1( Hadroniser::momToVec4( part1.momentum() ) ), mom_part2( Hadroniser::momToVec4( part2.momentum() ) );
+    const Pythia8::Vec4 mom_part1( hadroniser::momToVec4( part1.momentum() ) ), mom_part2( hadroniser::momToVec4( part2.momentum() ) );
 
     if ( !full ) {
       //=============================================================================================
       // incoming partons
       //=============================================================================================
 
       addCorresp( sizePart(), part1.id() );
       addParticle( quark1_pdgid, -2, quark1_id, 0, 0, 0, mom_part1.px(), mom_part1.py(), mom_part1.pz(), mom_part1.e(), mom_part1.mCalc(), 0., 0. );
 
       addCorresp( sizePart(), part2.id() );
       addParticle( quark2_pdgid, -2, quark2_id, 0, 0, 0, mom_part2.px(), mom_part2.py(), mom_part2.pz(), mom_part2.e(), mom_part2.mCalc(), 0., 0. );
     }
     else { // full event content (with collinear partons)
       const bool inel1 = ( mode == KinematicsMode::InelasticElastic || mode == KinematicsMode::InelasticInelastic );
       const bool inel2 = ( mode == KinematicsMode::ElasticInelastic || mode == KinematicsMode::InelasticInelastic );
 
       Pythia8::Vec4 mom_iq1 = mom_part1, mom_iq2 = mom_part2;
       unsigned short colour_index = 501, quark1_colour = 0, quark2_colour = 0;
       //FIXME select quark flavours accordingly
       if ( inel1 ) {
         quark1_pdgid = 2;
         quark1_colour = colour_index++;
-        mom_iq1 = Hadroniser::momToVec4( x1*ev.getOneByRole( Particle::IncomingBeam1 ).momentum() );
+        mom_iq1 = hadroniser::momToVec4( x1*ev.getOneByRole( Particle::IncomingBeam1 ).momentum() );
       }
       if ( inel2 ) {
         quark2_pdgid = 2;
         quark2_colour = colour_index++;
-        mom_iq2 = Hadroniser::momToVec4( x2*ev.getOneByRole( Particle::IncomingBeam2 ).momentum() );
+        mom_iq2 = hadroniser::momToVec4( x2*ev.getOneByRole( Particle::IncomingBeam2 ).momentum() );
       }
 
       //--- flavour / x value of hard-process initiators
       setIdX( part1.integerPdgId(), part2.integerPdgId(), x1, x2 );
 
       //===========================================================================================
       // incoming valence quarks
       //===========================================================================================
 
       quark1_id = sizePart();
       addCorresp( quark1_id, op1.id() );
       addParticle( quark1_pdgid, -1, 0, 0, quark1_colour, 0, mom_iq1.px(), mom_iq1.py(), mom_iq1.pz(), mom_iq1.e(), mom_iq1.mCalc(), 0., 1. );
 
       quark2_id = sizePart();
       addCorresp( quark2_id, op2.id() );
       addParticle( quark2_pdgid, -1, 0, 0, quark2_colour, 0, mom_iq2.px(), mom_iq2.py(), mom_iq2.pz(), mom_iq2.e(), mom_iq2.mCalc(), 0., 1. );
 
       //===========================================================================================
       // outgoing valence quarks
       //===========================================================================================
 
       if ( inel1 ) {
         const Pythia8::Vec4 mom_oq1 = mom_iq1-mom_part1;
         addParticle( quark1_pdgid, 1, quark1_id, quark2_id, quark1_colour, 0, mom_oq1.px(), mom_oq1.py(), mom_oq1.pz(), mom_oq1.e(), mom_oq1.mCalc(), 0., 1. );
       }
       if ( inel2 ) {
         const Pythia8::Vec4 mom_oq2 = mom_iq2-mom_part2;
         addParticle( quark2_pdgid, 1, quark1_id, quark2_id, quark2_colour, 0, mom_oq2.px(), mom_oq2.py(), mom_oq2.pz(), mom_oq2.e(), mom_oq2.mCalc(), 0., 1. );
       }
     }
 
     //=============================================================================================
     // central system
     //=============================================================================================
 
     for ( const auto& p : ev.getByRole( Particle::CentralSystem ) ) {
       const auto mothers = p.mothers();
       unsigned short moth1_id = 1, moth2_id = 2;
       if ( !full ) {
         moth1_id = moth2_id = 0;
         if ( mothers.size() > 0 ) {
           const unsigned short moth1_cg_id = *mothers.begin();
           moth1_id = pythiaId( moth1_cg_id );
           if ( moth1_id == invalid_id ) {
             const Particle& moth = ev.at( moth1_cg_id );
             if ( moth.mothers().size() > 0 )
               moth1_id = pythiaId( *moth.mothers().begin() );
             if ( moth.mothers().size() > 1 )
               moth2_id = pythiaId( *moth.mothers().rbegin() );
           }
           if ( mothers.size() > 1 ) {
             const unsigned short moth2_cg_id = *mothers.rbegin();
             moth2_id = pythiaId( moth2_cg_id );
             if ( moth2_id == invalid_id ) {
               const Particle& moth = ev.at( moth2_cg_id );
               moth.dump();
               moth2_id = pythiaId( *moth.mothers().rbegin() );
             }
           }
         }
       }
       const Pythia8::Vec4 mom_part( p.momentum().px(), p.momentum().py(), p.momentum().pz(), p.momentum().energy() );
       addCorresp( sizePart(), p.id() );
       addParticle( p.integerPdgId(), 1, moth1_id, moth2_id, 0, 0, mom_part.px(), mom_part.py(), mom_part.pz(), mom_part.e(), mom_part.mCalc(), 0., 0., 0. );
     }
     setPdf( quark1_pdgid, quark2_pdgid, x1, x2, scale, 0., 0., false );
   }
 
   bool
   LHAEvent::setInit()
   {
     return true;
   }
 
   bool
   LHAEvent::setEvent( int )
   {
     return true;
   }
 
   void
   LHAEvent::setProcess( int id, double xsec, double q2_scale, double alpha_qed, double alpha_qcd )
   {
     LHAup::setProcess( id, xsec, q2_scale, alpha_qed, alpha_qcd );
     py_cg_corresp_.clear();
   }
 
   unsigned short
   LHAEvent::cepgenId( unsigned short py_id ) const
   {
     for ( const auto& py_cg : py_cg_corresp_ )
       if ( py_cg.first == py_id )
         return py_cg.second;
     return invalid_id;
   }
 
   unsigned short
   LHAEvent::pythiaId( unsigned short cg_id ) const
   {
     for ( const auto& py_cg : py_cg_corresp_ )
       if ( py_cg.second == cg_id )
         return py_cg.first;
     return invalid_id;
   }
 
   void
   LHAEvent::addCorresp( unsigned short py_id, unsigned short cg_id )
   {
     py_cg_corresp_.emplace_back( py_id, cg_id );
   }
 
   void
   LHAEvent::dumpCorresp() const
   {
     std::ostringstream oss;
     oss << "List of Pythia <-> CepGen particle ids correspondance";
     for ( const auto& py_cg : py_cg_corresp_ )
       oss << "\n\t" << py_cg.first << " <-> " << py_cg.second;
     CG_INFO( "LHAEvent:dump" ) << oss.str();
   }
 #endif
 }
diff --git a/CepGen/Hadronisers/Pythia8Hadroniser.h b/CepGen/Hadronisers/Pythia8Hadroniser.h
index dfdbcbc..d4dea88 100644
--- a/CepGen/Hadronisers/Pythia8Hadroniser.h
+++ b/CepGen/Hadronisers/Pythia8Hadroniser.h
@@ -1,84 +1,84 @@
 #ifndef CepGen_Hadronisers_Pythia8Hadroniser_h
 #define CepGen_Hadronisers_Pythia8Hadroniser_h
 
 #include "CepGen/Hadronisers/GenericHadroniser.h"
 
 #ifdef PYTHIA8
 #include <Pythia8/Pythia.h>
 #include <memory>
 #endif
 
 #include <unordered_map>
 #include <vector>
 
 namespace CepGen
 {
   class Particle;
   class ParametersList;
   enum class KinematicsMode;
 #ifdef PYTHIA8
   class LHAEvent : public Pythia8::LHAup
   {
     public:
       explicit LHAEvent( const Parameters* );
       void feedEvent( const Event& ev, bool full, const KinematicsMode& );
       bool setInit() override;
       bool setEvent( int ) override;
       void setCrossSection( int id, double xsec, double xsec_err );
       void setProcess( int id, double xsec, double q2_scale, double alpha_qed, double alpha_qcd );
 
       unsigned short cepgenId( unsigned short py_id ) const;
       unsigned short pythiaId( unsigned short cg_id ) const;
       void addCorresp( unsigned short py_id, unsigned short cg_id );
       void dumpCorresp() const;
 
       static constexpr unsigned short invalid_id = 999;
     private:
       static const double mp_, mp2_;
       std::vector<std::pair<unsigned short, unsigned short> > py_cg_corresp_;
       const Parameters* params_;
   };
 #endif
 
-  namespace Hadroniser
+  namespace hadroniser
   {
     /**
      * Full interface to the Pythia8 hadronisation algorithm. It can be used in a single particle decay mode as well as a full event hadronisation using the string model, as in Jetset.
      * \brief Pythia8 hadronisation algorithm
      */
     class Pythia8Hadroniser : public GenericHadroniser
     {
       public:
         explicit Pythia8Hadroniser( const Parameters&, const ParametersList& );
         ~Pythia8Hadroniser();
 
         void readString( const char* param ) override;
         void init() override;
         bool run( Event& ev, double& weight, bool full ) override;
 
         void setCrossSection( double xsec, double xsec_err ) override;
 
         bool fullEvent() const { return full_evt_; }
         void setFullEvent( bool full = true ) { full_evt_ = full; }
 
       private:
         static constexpr unsigned short invalid_idx_ = 999;
         std::vector<unsigned short> min_ids_;
         std::unordered_map<short,short> py_cg_corresp_;
 #ifdef PYTHIA8
         unsigned short findRole( const Event& ev, const Pythia8::Particle& p ) const;
         void updateEvent( Event& ev, double& weight, bool full ) const;
         Particle& addParticle( Event& ev, const Pythia8::Particle&, const Pythia8::Vec4& mom, unsigned short ) const;
         /// A Pythia8 core to be wrapped
         std::unique_ptr<Pythia8::Pythia> pythia_;
         std::unique_ptr<LHAEvent> lhaevt_;
 #endif
         bool full_evt_;
         unsigned short offset_;
         bool first_evt_;
         const Parameters* params_; // not owning
     };
   }
 }
 
 #endif
diff --git a/CepGen/Parameters.h b/CepGen/Parameters.h
index 2e12481..a9c0e4c 100644
--- a/CepGen/Parameters.h
+++ b/CepGen/Parameters.h
@@ -1,147 +1,147 @@
 #ifndef CepGen_Parameters_h
 #define CepGen_Parameters_h
 
 #include "CepGen/Core/Integrator.h"
 #include "CepGen/Physics/Kinematics.h"
 
 #include <memory>
 
 #include <gsl/gsl_monte_vegas.h>
 #include <gsl/gsl_monte_miser.h>
 
 namespace CepGen
 {
   class Event;
   class TamingFunctionsCollection;
   class ParametersList;
-  namespace Process { class GenericProcess; }
-  namespace Hadroniser { class GenericHadroniser; }
+  namespace process { class GenericProcess; }
+  namespace hadroniser { class GenericHadroniser; }
   /// List of parameters used to start and run the simulation job
   class Parameters
   {
     public:
       Parameters();
       /// Copy constructor (transfers ownership to the process/hadroniser!)
       Parameters( Parameters& );
       /// Const copy constructor (all but the process and the hadroniser)
       Parameters( const Parameters& );
       ~Parameters(); // required for unique_ptr initialisation!
       /// Set the polar angle range for the produced leptons
       /// \param[in] thetamin The minimal value of \f$\theta\f$ for the outgoing leptons
       /// \param[in] thetamax The maximal value of \f$\theta\f$ for the outgoing leptons
       void setThetaRange( float thetamin, float thetamax );
       /// Dump the input parameters in the terminal
       friend std::ostream& operator<<( std::ostream& os, const Parameters* );
       friend std::ostream& operator<<( std::ostream& os, const Parameters& );
 
       std::shared_ptr<ParametersList> general;
 
       //----- process to compute
 
       /// Process for which the cross-section will be computed and the events will be generated
-      Process::GenericProcess* process();
+      process::GenericProcess* process();
       /// Name of the process considered
       std::string processName() const;
       /// Set the process to study
-      void setProcess( std::unique_ptr<Process::GenericProcess> proc );
+      void setProcess( std::unique_ptr<process::GenericProcess> proc );
       /// Set the process to study
-      void setProcess( Process::GenericProcess* proc );
+      void setProcess( process::GenericProcess* proc );
 
       //----- events kinematics
 
       /// Events kinematics for phase space definition
       Kinematics kinematics;
 
       //----- VEGAS
 
       /// Collection of integrator parameters
       struct Integration
       {
         Integration();
         Integration( const Integration& );
         ~Integration();
         Integrator::Type type;
         /// Number of function calls to be computed for each point
         unsigned int ncvg; // ??
         /// Random number generator seed
         long rng_seed;
         /// Random number generator engine
         gsl_rng_type* rng_engine;
         gsl_monte_vegas_params vegas;
         double vegas_chisq_cut;
         gsl_monte_miser_params miser;
         double result, err_result;
       };
       /// Integrator parameters
       Integration integrator;
 
       //----- events generation
 
       /// Collection of events generation parameters
       struct Generation
       {
         Generation();
         /// Are we generating events ? (true) or are we only computing the cross-section ? (false)
         bool enabled;
         /// Maximal number of events to generate in this run
         unsigned int maxgen;
         /// Do we want the events to be symmetrised with respect to the \f$z\f$-axis ?
         bool symmetrise;
         /// Is the integrand to be smoothed for events generation?
         bool treat;
         /// Number of events already generated in this run
         unsigned int ngen;
         /// Frequency at which the events are displayed to the end-user
         unsigned int gen_print_every;
         /// Number of threads to perform the integration
         unsigned int num_threads;
         /// Number of points to "shoot" in each integration bin by the algorithm
         unsigned int num_points;
       };
       /// Events generation parameters
       Generation generation;
 
       /// Specify if the generated events are to be stored
       void setStorage( bool store ) { store_ = store; }
       /// Are the events generated in this run to be stored in the output file ?
       bool storage() const { return store_; }
 
       //----- hadronisation algorithm
 
       /// Hadronisation algorithm to use for the proton(s) fragmentation
-      Hadroniser::GenericHadroniser* hadroniser();
+      hadroniser::GenericHadroniser* hadroniser();
       /// Name of the hadroniser (if applicable)
       std::string hadroniserName() const;
       /// Set the hadronisation algorithm
-      void setHadroniser( Hadroniser::GenericHadroniser* hadr );
+      void setHadroniser( hadroniser::GenericHadroniser* hadr );
 
       //----- taming functions
 
       /// Functionals to be used to account for rescattering corrections (implemented within the process)
       std::shared_ptr<TamingFunctionsCollection> taming_functions;
 
       //----- run statistics
 
       /// Reset the total generation time and the number of events generated for this run
       void clearRunStatistics();
       /// Add a new timing into the total generation time
       /// \param[in] gen_time Time to add (in seconds)
       void addGenerationTime( double gen_time );
       /// Return the total generation time for this run (in seconds)
       inline double totalGenerationTime() const { return total_gen_time_; }
       /// Total number of events already generated in this run
       inline unsigned int numGeneratedEvents() const { return num_gen_events_; }
 
     private:
-      std::unique_ptr<Process::GenericProcess> process_;
-      std::unique_ptr<Hadroniser::GenericHadroniser> hadroniser_;
+      std::unique_ptr<process::GenericProcess> process_;
+      std::unique_ptr<hadroniser::GenericHadroniser> hadroniser_;
 
       bool store_;
       /// Total generation time (in seconds)
       double total_gen_time_;
       /// Number of events already generated
       unsigned int num_gen_events_;
   };
 }
 
 #endif
diff --git a/CepGen/Processes/FortranKTProcess.cpp b/CepGen/Processes/FortranKTProcess.cpp
index ca67259..9124417 100644
--- a/CepGen/Processes/FortranKTProcess.cpp
+++ b/CepGen/Processes/FortranKTProcess.cpp
@@ -1,167 +1,166 @@
 #include "CepGen/Processes/FortranKTProcess.h"
 #include "CepGen/Processes/Fortran/KTStructures.h"
 
 #include "CepGen/Core/ParametersList.h"
 
 #include "CepGen/StructureFunctions/StructureFunctions.h"
 #include "CepGen/Event/Event.h"
 
 #include "CepGen/Physics/KTFlux.h"
 #include "CepGen/Physics/Constants.h"
 #include "CepGen/Physics/PDG.h"
 
 extern "C"
 {
   extern CepGen::KTBlock::Constants constants_;
   extern CepGen::KTBlock::Parameters params_;
   extern CepGen::KTBlock::KTKinematics ktkin_;
   extern CepGen::KTBlock::Cuts kincuts_;
   extern CepGen::KTBlock::Event evtkin_;
 }
 
 namespace CepGen
 {
-  namespace Process
+  namespace process
   {
     FortranKTProcess::FortranKTProcess( const ParametersList& params, const char* name, const char* descr, std::function<void( double& )> func ) :
       GenericKTProcess( params, name, descr, { { PDG::photon, PDG::photon } }, { PDG::muon, PDG::muon } ),
       pair_( params.get<int>( "pair", 13 ) ),
       method_( params.get<int>( "method", 1 ) ),
       func_( func )
     {
       constants_.m_p = GenericProcess::mp_;
       constants_.units = Constants::GeV2toBarn;
       constants_.pi = M_PI;
       constants_.alpha_em = Constants::alphaEM;
     }
 
     void
     FortranKTProcess::preparePhaseSpace()
     {
       mom_ip1_ = event_->getOneByRole( Particle::IncomingBeam1 ).momentum();
       mom_ip2_ = event_->getOneByRole( Particle::IncomingBeam2 ).momentum();
 
       registerVariable( y1_, Mapping::linear, cuts_.cuts.central.rapidity_single, { -6., 6. }, "First central particle rapidity" );
       registerVariable( y2_, Mapping::linear, cuts_.cuts.central.rapidity_single, { -6., 6. }, "Second central particle rapidity" );
       registerVariable( pt_diff_, Mapping::linear, cuts_.cuts.central.pt_diff, { 0., 50. }, "Transverse momentum difference between central particles" );
       registerVariable( phi_pt_diff_, Mapping::linear, cuts_.cuts.central.phi_pt_diff, { 0., 2.*M_PI }, "Central particles azimuthal angle difference" );
 
       //===========================================================================================
       // feed phase space cuts to the common block
       //===========================================================================================
 
       cuts_.cuts.central.pt_single.save( (bool&)kincuts_.ipt, kincuts_.pt_min, kincuts_.pt_max );
       cuts_.cuts.central.energy_single.save( (bool&)kincuts_.iene, kincuts_.ene_min, kincuts_.ene_max );
       cuts_.cuts.central.eta_single.save( (bool&)kincuts_.ieta, kincuts_.eta_min, kincuts_.eta_max );
       cuts_.cuts.central.mass_sum.save( (bool&)kincuts_.iinvm, kincuts_.invm_min, kincuts_.invm_max );
       cuts_.cuts.central.pt_sum.save( (bool&)kincuts_.iptsum, kincuts_.ptsum_min, kincuts_.ptsum_max );
       cuts_.cuts.central.rapidity_diff.save( (bool&)kincuts_.idely, kincuts_.dely_min, kincuts_.dely_max );
 
       //===========================================================================================
       // feed run parameters to the common block
       //===========================================================================================
 
       params_.icontri = (int)cuts_.mode;
       params_.imethod = method_;
       params_.sfmod = (int)cuts_.structure_functions->type;
       params_.pdg_l = pair_;
 
       //-------------------------------------------------------------------------------------------
       // incoming beams information
       //-------------------------------------------------------------------------------------------
 
       params_.inp1 = cuts_.incoming_beams.first.pz;
       params_.inp2 = cuts_.incoming_beams.second.pz;
       const HeavyIon in1 = (HeavyIon)cuts_.incoming_beams.first.pdg;
       if ( in1 ) {
         params_.a_nuc1 = in1.A;
         params_.z_nuc1 = (unsigned short)in1.Z;
         if ( params_.z_nuc1 > 1 ) {
           event_->getOneByRole( Particle::IncomingBeam1 ).setPdgId( (PDG)in1 );
           event_->getOneByRole( Particle::OutgoingBeam1 ).setPdgId( (PDG)in1 );
         }
       }
       else
         params_.a_nuc1 = params_.z_nuc1 = 1;
 
       const HeavyIon in2 = (HeavyIon)cuts_.incoming_beams.second.pdg;
       if ( in2 ) {
         params_.a_nuc2 = in2.A;
         params_.z_nuc2 = (unsigned short)in2.Z;
         if ( params_.z_nuc2 > 1 ) {
           event_->getOneByRole( Particle::IncomingBeam2 ).setPdgId( (PDG)in2 );
           event_->getOneByRole( Particle::OutgoingBeam2 ).setPdgId( (PDG)in2 );
         }
       }
       else
         params_.a_nuc2 = params_.z_nuc2 = 1;
 
       //-------------------------------------------------------------------------------------------
       // intermediate partons information
       //-------------------------------------------------------------------------------------------
 
       params_.iflux1 = (int)cuts_.incoming_beams.first.kt_flux;
       params_.iflux2 = (int)cuts_.incoming_beams.second.kt_flux;
       if ( (KTFlux)params_.iflux1 == KTFlux::P_Gluon_KMR )
         event_->getOneByRole( Particle::Parton1 ).setPdgId( PDG::gluon );
       if ( (KTFlux)params_.iflux2 == KTFlux::P_Gluon_KMR )
         event_->getOneByRole( Particle::Parton2 ).setPdgId( PDG::gluon );
     }
 
     double
     FortranKTProcess::computeKTFactorisedMatrixElement()
     {
       ktkin_.q1t = qt1_;
       ktkin_.q2t = qt2_;
       ktkin_.phiq1t = phi_qt1_;
       ktkin_.phiq2t = phi_qt2_;
       ktkin_.y1 = y1_;
       ktkin_.y2 = y2_;
       ktkin_.ptdiff = pt_diff_;
       ktkin_.phiptdiff = phi_pt_diff_;
       ktkin_.m_x = MX_;
       ktkin_.m_y = MY_;
 
       //--- compute the event weight
       double weight = 0.;
       func_( weight );
       return weight;
     }
 
     void
     FortranKTProcess::fillCentralParticlesKinematics()
     {
       //===========================================================================================
       // outgoing beam remnants
       //===========================================================================================
 
       PX_ = Particle::Momentum( evtkin_.px );
       PY_ = Particle::Momentum( evtkin_.py );
       // express these momenta per nucleon
       PX_ *= 1./params_.a_nuc1;
       PY_ *= 1./params_.a_nuc2;
 
       //===========================================================================================
       // intermediate partons
       //===========================================================================================
 
       const Particle::Momentum mom_par1 = mom_ip1_-PX_, mom_par2 = mom_ip2_-PY_;
       event_->getOneByRole( Particle::Parton1 ).setMomentum( mom_par1 );
       event_->getOneByRole( Particle::Parton2 ).setMomentum( mom_par2 );
       event_->getOneByRole( Particle::Intermediate ).setMomentum( mom_par1+mom_par2 );
 
       //===========================================================================================
       // central system
       //===========================================================================================
 
       Particles& oc = event_->getByRole( Particle::CentralSystem );
       for ( int i = 0; i < evtkin_.nout; ++i ) {
         Particle& p = oc[i];
         p.setPdgId( evtkin_.pdg[i] );
         p.setStatus( Particle::Status::FinalState );
         p.setMomentum( Particle::Momentum( evtkin_.pc[i] ) );
       }
     }
   }
 }
-
diff --git a/CepGen/Processes/FortranKTProcess.h b/CepGen/Processes/FortranKTProcess.h
index b36674a..f00bd37 100644
--- a/CepGen/Processes/FortranKTProcess.h
+++ b/CepGen/Processes/FortranKTProcess.h
@@ -1,38 +1,37 @@
 #ifndef CepGen_Processes_FortranKTProcess_h
 #define CepGen_Processes_FortranKTProcess_h
 
 #include "CepGen/Processes/GenericKTProcess.h"
 #include <functional>
 
 namespace CepGen
 {
-  namespace Process
+  namespace process
   {
     /// Compute the matrix element for a generic \f$k_T\f$-factorised process defined in a Fortran subroutine
     class FortranKTProcess : public GenericKTProcess
     {
       public:
         FortranKTProcess( const ParametersList& params, const char* name, const char* descr, std::function<void(double&)> func );
         ProcessPtr clone( const ParametersList& params ) const override { return ProcessPtr( new FortranKTProcess( *this ) ); }
 
       private:
         void preparePhaseSpace() override;
         double computeKTFactorisedMatrixElement() override;
         void fillCentralParticlesKinematics() override;
 
         int pair_; ///< Outgoing particles type
         int method_; ///< Computation method for the process
         std::function<void(double&)> func_; ///< Subroutine to be called for weight computation
         double y1_; ///< First outgoing particle rapidity
         double y2_; ///< Second outgoing particle rapidity
         double pt_diff_; ///< Transverse momentum balance between outgoing particles
         double phi_pt_diff_; ///< Azimutal angle difference between outgoing particles
 
         Particle::Momentum mom_ip1_; ///< First incoming beam momentum
         Particle::Momentum mom_ip2_; ///< Second incoming beam momentum
     };
   }
 }
 
 #endif
-
diff --git a/CepGen/Processes/FortranProcesses.h b/CepGen/Processes/FortranProcesses.h
index ec832b8..54e0db5 100644
--- a/CepGen/Processes/FortranProcesses.h
+++ b/CepGen/Processes/FortranProcesses.h
@@ -1,18 +1,17 @@
 #ifndef CepGen_Processes_FortranProcesses_h
 #define CepGen_Processes_FortranProcesses_h
 
 #include "CepGen/Processes/FortranKTProcess.h"
 #include "CepGen/Processes/ProcessesHandler.h"
 
 #include "CepGen/Core/ParametersList.h"
 
 #define DECLARE_FORTRAN_SUBROUTINE( method ) \
   extern "C" { extern void method ## _( double& ); }
 #define PROCESS_F77_NAME( name ) F77_ ## name
 #define REGISTER_FORTRAN_PROCESS( name, method, description ) \
-  struct PROCESS_F77_NAME( name ) : public CepGen::Process::FortranKTProcess { \
-    PROCESS_F77_NAME( name )() : CepGen::Process::FortranKTProcess( CepGen::ParametersList(), STRINGIFY( name ), description, method ## _ ) {} }; \
+  struct PROCESS_F77_NAME( name ) : public CepGen::process::FortranKTProcess { \
+    PROCESS_F77_NAME( name )() : CepGen::process::FortranKTProcess( CepGen::ParametersList(), STRINGIFY( name ), description, method ## _ ) {} }; \
   REGISTER_PROCESS( name, PROCESS_F77_NAME( name ) )
 
 #endif
-
diff --git a/CepGen/Processes/GamGamLL.cpp b/CepGen/Processes/GamGamLL.cpp
index 34ad076..52c0661 100644
--- a/CepGen/Processes/GamGamLL.cpp
+++ b/CepGen/Processes/GamGamLL.cpp
@@ -1,1150 +1,1149 @@
 #include "CepGen/Processes/GamGamLL.h"
 
 #include "CepGen/Event/Event.h"
 
 #include "CepGen/Core/Exception.h"
 
 #include "CepGen/Physics/Constants.h"
 #include "CepGen/Physics/FormFactors.h"
 #include "CepGen/Physics/PDG.h"
 
 #include "CepGen/Processes/ProcessesHandler.h"
 
 namespace CepGen
 {
-  namespace Process
+  namespace process
   {
     //---------------------------------------------------------------------------------------------
 
     GamGamLL::Masses::Masses() :
       MX2_( 0. ), MY2_( 0. ), Ml2_( 0. ),
       w12_( 0. ), w31_( 0. ), dw31_( 0. ), w52_( 0. ), dw52_( 0. )
     {}
 
     //---------------------------------------------------------------------------------------------
 
     GamGamLL::GamGamLL( const ParametersList& params ) :
       GenericProcess( "lpair", "pp → p(*) ( ɣɣ → l⁺l¯ ) p(*)" ),
       n_opt_( params.get<int>( "nopt", 0 ) ),
       pair_( params.get<int>( "pair", 0 ) ),
       ep1_( 0. ), ep2_( 0. ), p_cm_( 0. ),
       ec4_( 0. ), pc4_( 0. ), mc4_( 0. ), w4_( 0. ),
       p12_( 0. ), p1k2_( 0. ), p2k1_( 0. ),
       p13_( 0. ), p14_( 0. ), p25_( 0. ),
       q1dq_( 0. ), q1dq2_( 0. ),
       s1_( 0. ), s2_( 0. ),
       epsi_( 0. ),
       g5_( 0. ), g6_( 0. ), a5_( 0. ), a6_( 0. ), bb_( 0. ),
       gram_( 0. ),
       dd1_( 0. ), dd2_( 0. ), dd3_( 0. ), dd4_( 0. ), dd5_( 0. ),
       delta_( 0. ),
       g4_( 0. ), sa1_( 0. ), sa2_( 0. ),
       sl1_( 0. ),
       cos_theta4_( 0. ), sin_theta4_( 0. ),
       al4_( 0. ), be4_( 0. ), de3_( 0. ), de5_( 0. ),
       pt4_( 0. ),
       jacobian_( 0. )
     {}
 
     //---------------------------------------------------------------------------------------------
 
     void
     GamGamLL::addEventContent()
     {
       GenericProcess::setEventContent( {
         { Particle::IncomingBeam1, PDG::proton },
         { Particle::IncomingBeam2, PDG::proton },
         { Particle::Parton1, PDG::photon },
         { Particle::Parton2, PDG::photon }
       }, {
         { Particle::OutgoingBeam1, { PDG::proton } },
         { Particle::OutgoingBeam2, { PDG::proton } },
         { Particle::CentralSystem, { (PDG)pair_, (PDG)pair_ } }
       } );
     }
 
     unsigned int
     GamGamLL::numDimensions() const
     {
       switch ( cuts_.mode ) {
         case KinematicsMode::ElectronProton: default:
           throw CG_FATAL( "GamGamLL" )
             << "Process mode " << cuts_.mode << " not (yet) supported! "
             << "Please contact the developers to consider an implementation.";
         case KinematicsMode::ElasticElastic:
           return 7;
         case KinematicsMode::ElasticInelastic:
         case KinematicsMode::InelasticElastic:
           return 8;
         case KinematicsMode::InelasticInelastic:
           return 9;
       }
     }
 
     //---------------------------------------------------------------------------------------------
 
     void
     GamGamLL::setKinematics( const Kinematics& kin )
     {
       GenericProcess::setKinematics( kin );
 
       masses_.Ml2_ = event_->getByRole( Particle::CentralSystem )[0].mass2();
 
       w_limits_ = cuts_.cuts.central.mass_single;
       if ( !w_limits_.hasMax() )
         w_limits_.max() = s_;
       // The minimal energy for the central system is its outgoing leptons' mass energy (or wmin_ if specified)
       if ( !w_limits_.hasMin() )
         w_limits_.min() = 4.*masses_.Ml2_;
       // The maximal energy for the central system is its CM energy with the outgoing particles' mass energy substracted (or wmax if specified)
       w_limits_.max() = std::min( pow( sqs_-MX_-MY_, 2 ), w_limits_.max() );
 
       CG_DEBUG_LOOP( "GamGamLL:setKinematics" )
         << "w limits = " << w_limits_ << "\n\t"
         << "wmax/wmin = " << w_limits_.max()/w_limits_.min();
 
       q2_limits_ = cuts_.cuts.initial.q2;
       mx_limits_ = cuts_.cuts.remnants.mass_single;
     }
 
     //---------------------------------------------------------------------------------------------
 
     bool
     GamGamLL::pickin()
     {
       CG_DEBUG_LOOP( "GamGamLL" )
         << "Optimised mode? " << n_opt_;
 
       jacobian_ = 0.;
 
       w4_ = mc4_*mc4_;
 
       // sig1 = sigma and sig2 = sigma' in [1]
       const double sig = mc4_+MY_;
       double sig1 = sig*sig,
              sig2 = sig1;
 
       CG_DEBUG_LOOP( "GamGamLL" )
         << "mc4 = " << mc4_ << "\n\t"
         << "sig1 = " << sig1 << "\n\t"
         << "sig2 = " << sig2;
 
       // Mass difference between the first outgoing particle
       // and the first incoming particle
       masses_.w31_ = masses_.MX2_-w1_;
       // Mass difference between the second outgoing particle
       // and the second incoming particle
       masses_.w52_ = masses_.MY2_-w2_;
       // Mass difference between the two incoming particles
       masses_.w12_ = w1_-w2_;
       // Mass difference between the central two-photons system
       // and the second outgoing particle
       const double d6 = w4_-masses_.MY2_;
 
       CG_DEBUG_LOOP( "GamGamLL" )
         << "w1 = " << w1_ << "\n\t"
         << "w2 = " << w2_ << "\n\t"
         << "w3 = " << masses_.MX2_ << "\n\t"
         << "w4 = " << w4_ << "\n\t"
         << "w5 = " << masses_.MY2_;;
 
       CG_DEBUG_LOOP( "GamGamLL" )
         << "w31 = " << masses_.w31_ << "\n\t"
         << "w52 = " << masses_.w52_ << "\n\t"
         << "w12 = " << masses_.w12_;;
 
       const double ss = s_+masses_.w12_;
 
       const double rl1 = ss*ss-4.*w1_*s_; // lambda(s, m1**2, m2**2)
       if ( rl1 <= 0. ) {
         CG_WARNING( "GamGamLL" ) << "rl1 = " << rl1 << " <= 0";
         return false;
       }
       sl1_ = sqrt( rl1 );
 
       s2_ = 0.;
       double ds2 = 0.;
       if ( n_opt_ == 0 ) {
         const double smax = s_+masses_.MX2_-2.*MX_*sqs_;
         map( x(2), Limits( sig1, smax ), s2_, ds2, "s2" );
         sig1 = s2_; //FIXME!!!!!!!!!!!!!!!!!!!!
       }
 
       CG_DEBUG_LOOP( "GamGamLL" )
         << "s2 = " << s2_;
 
       const double sp = s_+masses_.MX2_-sig1,
                    d3 = sig1-w2_;
 
       const double rl2 = sp*sp-4.*s_*masses_.MX2_; // lambda(s, m3**2, sigma)
       if ( rl2 <= 0. ) {
         CG_DEBUG( "GamGamLL" ) << "rl2 = " << rl2 << " <= 0";
         return false;
       }
       const double sl2 = sqrt( rl2 );
 
       double t1_max = w1_+masses_.MX2_-( ss*sp+sl1_*sl2 )/( 2.*s_ ), // definition from eq. (A.4) in [1]
              t1_min = ( masses_.w31_*d3+( d3-masses_.w31_ )*( d3*w1_-masses_.w31_*w2_ )/s_ )/t1_max; // definition from eq. (A.5) in [1]
 
       // FIXME dropped in CDF version
       if ( t1_max > -q2_limits_.min() ) {
         CG_WARNING( "GamGamLL" ) << "t1max = " << t1_max << " > -q2min = " << ( -q2_limits_.min() );
         return false;
       }
       if ( t1_min < -q2_limits_.max() && q2_limits_.hasMax() ) {
         CG_DEBUG( "GamGamLL" ) << "t1min = " << t1_min << " < -q2max = " << -q2_limits_.max();
         return false;
       }
       if ( t1_max < -q2_limits_.max() && q2_limits_.hasMax() )
         t1_max = -q2_limits_.max();
       if ( t1_min > -q2_limits_.min() && q2_limits_.hasMin() )
         t1_min = -q2_limits_.min();
       /////
 
       // t1, the first photon propagator, is defined here
       t1_ = 0.;
       double dt1 = 0.;
       map( x(0), Limits( t1_min, t1_max ), t1_, dt1, "t1" );
       // changes wrt mapt1 : dx->-dx
       dt1 *= -1.;
 
       CG_DEBUG_LOOP( "GamGamLL" )
         << "Definition of t1 = " << t1_ << " according to\n\t"
         << "(t1min, t1max) = (" << t1_min << ", " << t1_max << ")";
 
       dd4_ = w4_-t1_;
 
       const double d8 = t1_-w2_, t13 = t1_-w1_-masses_.MX2_;
 
       sa1_ = -pow( t1_-masses_.w31_, 2 )/4.+w1_*t1_;
       if ( sa1_ >= 0. ) {
         CG_WARNING( "GamGamLL" ) << "sa1_ = " << sa1_ << " >= 0";
         return false;
       }
 
       const double sl3 = sqrt( -sa1_ );
 
       // one computes splus and (s2x=s2max)
       double splus, s2max;
       if ( w1_ != 0. ) {
         const double inv_w1 = 1./w1_;
         const double sb = masses_.MX2_ + 0.5 * ( s_*( t1_-masses_.w31_ )+masses_.w12_*t13 )*inv_w1,
                      sd = sl1_*sl3*inv_w1,
                      se =( s_*( t1_*( s_+t13-w2_ )-w2_*masses_.w31_ )+masses_.MX2_*( masses_.w12_*d8+w2_*masses_.MX2_ ) )*inv_w1;
 
         if ( fabs( ( sb-sd )/sd ) >= 1. ) {
           splus = sb-sd;
           s2max = se/splus;
         }
         else {
           s2max = sb+sd;
           splus = se/s2max;
         }
       }
       else { // 3
         s2max = ( s_*( t1_*( s_+d8-masses_.MX2_ )-w2_*masses_.MX2_ )+w2_*masses_.MX2_*( w2_+masses_.MX2_-t1_ ) )/( ss*t13 );
         splus = sig2;
       }
       // 4
       double s2x = s2max;
 
       CG_DEBUG_LOOP( "GamGamLL" )
         << "s2x = s2max = " << s2x;
 
       if ( n_opt_ < 0 ) { // 5
         if ( splus > sig2 ) {
           sig2 = splus;
           CG_DEBUG_LOOP( "GamGamLL" )
             << "sig2 truncated to splus = " << splus;
         }
         if ( n_opt_ < -1 )
           map( x(2), Limits( sig2, s2max ), s2_, ds2, "s2" );
         else
           mapla( t1_, w2_, x(2), sig2, s2max, s2_, ds2 ); // n_opt_==-1
         s2x = s2_;
       }
       else if ( n_opt_ == 0 )
         s2x = s2_; // 6
 
       CG_DEBUG_LOOP( "GamGamLL" )
         << "s2x = " << s2x;
 
       // 7
       const double r1 = s2x-d8, r2 = s2x-d6;
 
       const double rl4 = ( r1*r1-4.*w2_*s2x )*( r2*r2-4.*masses_.MY2_*s2x );
       if ( rl4 <= 0. ) {
         CG_DEBUG_LOOP( "GamGamLL" )
           << "rl4 = " << rl4 << " <= 0";
         return false;
       }
       const double sl4 = sqrt( rl4 );
 
       // t2max, t2min definitions from eq. (A.12) and (A.13) in [1]
       const double t2_max = w2_+masses_.MY2_-( r1*r2+sl4 )/s2x * 0.5,
                    t2_min = ( masses_.w52_*dd4_+( dd4_-masses_.w52_ )*( dd4_*w2_-masses_.w52_*t1_ )/s2x )/t2_max;
 
       // t2, the second photon propagator, is defined here
       t2_ = 0.;
       double dt2 = 0.;
       map( x(1), Limits( t2_min, t2_max ), t2_, dt2, "t2" );
       // changes wrt mapt2 : dx->-dx
 
       dt2 *= -1.;
 
       // \f$\delta_6=m_4^2-m_5^2\f$ as defined in Vermaseren's paper
       const double tau = t1_-t2_,
                    r3 = dd4_-t2_,
                    r4 = masses_.w52_-t2_;
 
       CG_DEBUG_LOOP( "GamGamLL" )
         << "r1 = " << r1 << "\n\t"
         << "r2 = " << r2 << "\n\t"
         << "r3 = " << r3 << "\n\t"
         << "r4 = " << r4;
 
       const double b = r3*r4-2.*( t1_+w2_ )*t2_;
       const double c = t2_*d6*d8+( d6-d8 )*( d6*w2_-d8*masses_.MY2_ );
 
       const double t25 = t2_-w2_-masses_.MY2_;
 
       sa2_ = -0.25 * r4*r4 + w2_*t2_;
       if ( sa2_ >= 0. ) {
         CG_WARNING( "GamGamLL" )
           <<  "sa2_ = " << sa2_ << " >= 0";
         return false;
       }
 
       const double sl6 = 2.*sqrt( -sa2_ );
 
       g4_ = -r3*r3/4.+t1_*t2_;
       if ( g4_ >= 0. ) {
         CG_WARNING( "GamGamLL" ) << "g4_ = " << g4_ << " >= 0";
         return false;
       }
 
       const double sl7 = 2.*sqrt( -g4_ ),
                    sl5 = sl6*sl7;
 
       double s2p, s2min;
       if ( fabs( ( sl5-b )/sl5 ) >= 1. ) {
         s2p = 0.5 * ( sl5-b )/t2_;
         s2min = c/( t2_*s2p );
       }
       else { // 8
         s2min = 0.5 * ( -sl5-b )/t2_;
         s2p = c/( t2_*s2min );
       }
       // 9
       if ( n_opt_ > 1 )
         map( x( 2 ), Limits( s2min, s2max ), s2_, ds2, "s2" );
       else if ( n_opt_ == 1 )
         mapla( t1_, w2_, x( 2 ), s2min, s2max, s2_, ds2 );
 
       const double ap = -0.25*pow( s2_+d8, 2 )+s2_*t1_;
 
       CG_DEBUG_LOOP( "GamGamLL" )
         << "s2 = " << s2_ << ", s2max = " << s2max << ", splus = " << splus;
 
       if ( w1_ != 0. )
         dd1_ = -0.25 * ( s2_-s2max ) * ( s2_-splus ) * w1_; // 10
       else
         dd1_ =  0.25 * ( s2_-s2max ) * ss * t13;
       // 11
       dd2_ = -0.25 * t2_*( s2_-s2p )*( s2_-s2min );
 
       CG_DEBUG_LOOP( "GamGamLL" )
         << "t2    = " << t2_ << "\n\t"
         << "s2    = " << s2_ << "\n\t"
         << "s2p   = " << s2p << "\n\t"
         << "s2min = " << s2min << "\n\t"
         << "dd2   = " << dd2_;;
 
       const double yy4 = cos( M_PI*x( 3 ) );
       const double dd = dd1_*dd2_;
       p12_ = 0.5 * ( s_-w1_-w2_ );
       const double st = s2_-t1_-w2_;
       const double delb = ( 2.*w2_*r3+r4*st )*( 4.*p12_*t1_-( t1_-masses_.w31_ )*st )/( 16.*ap );
 
       if ( dd <= 0. ) {
         CG_DEBUG_LOOP( "GamGamLL" )
           << std::scientific
           << "dd = " << dd << " <= 0\n\t"
           << "dd1 = " << dd1_ << "\t"
           << "dd2 = " << dd2_ << std::fixed;
         return false;
       }
 
       delta_ = delb - yy4*st*sqrt( dd )/ ap * 0.5;
       s1_ = t2_+w1_+( 2.*p12_*r3-4.*delta_ )/st;
 
       if ( ap >= 0. ) {
         CG_DEBUG_LOOP( "GamGamLL" )
           <<  "ap = " << ap << " >= 0";
         return false;
       }
 
       jacobian_ = ds2 * dt1 * dt2 * 0.125 * M_PI*M_PI/( sl1_*sqrt( -ap ) );
 
       CG_DEBUG_LOOP( "GamGamLL" )
         << "Jacobian = " << std::scientific << jacobian_ << std::fixed;
 
       gram_ = ( 1.-yy4*yy4 )*dd/ap;
 
       p13_ = -0.5 * t13;
       p14_ =  0.5 * ( tau+s1_-masses_.MX2_ );
       p25_ = -0.5 * t25;
 
       p1k2_ = 0.5 * ( s1_-t2_-w1_ );
       p2k1_ = 0.5 * st;
 
       if ( w2_ != 0. ) {
         const double inv_w2 = 1./w2_;
         const double sbb = 0.5 * ( s_*( t2_-masses_.w52_ )-masses_.w12_*t25 )*inv_w2 + masses_.MY2_,
                      sdd = 0.5 * sl1_*sl6*inv_w2,
                      see = ( s_*( t2_*( s_+t25-w1_ )-w1_*masses_.w52_ )+masses_.MY2_*( w1_*masses_.MY2_-masses_.w12_*( t2_-w1_ ) ) )*inv_w2;
         double s1m = 0., s1p = 0.;
         if ( sbb/sdd >= 0. ) {
           s1p = sbb+sdd;
           s1m = see/s1p;
         }
         else {
           s1m = sbb-sdd;
           s1p = see/s1m;
         } // 12
         dd3_ = -0.25 * w2_*( s1p-s1_ )*( s1m-s1_ ); // 13
       }
       else { // 14
         const double s1p = ( s_*( t2_*( s_-masses_.MY2_+t2_-w1_ )-w1_*masses_.MY2_ )+w1_*masses_.MY2_*( w1_+masses_.MY2_-t2_ ) )/( t25*( s_-masses_.w12_ ) );
         dd3_ = -0.25 * t25*( s_-masses_.w12_ )*( s1p-s1_ );
       }
       // 15
       //const double acc3 = (s1p-s1_)/(s1p+s1_);
 
       const double ssb = t2_+0.5 * w1_-r3*( masses_.w31_-t1_ )/t1_,
                    ssd = sl3*sl7/t1_,
                    sse = ( t2_-w1_ )*( w4_-masses_.MX2_ )+( t2_-w4_+masses_.w31_ )*( ( t2_-w1_)*masses_.MX2_-(w4_-masses_.MX2_)*w1_)/t1_;
 
       double s1pp, s1pm;
       if ( ssb/ssd >= 0. ) {
         s1pp = ssb+ssd;
         s1pm = sse/s1pp;
       }
       else { // 16
         s1pm = ssb-ssd;
         s1pp = sse/s1pm;
       }
       // 17
       dd4_ = -0.25 * t1_*( s1_-s1pp )*( s1_-s1pm );
       //const double acc4 = ( s1_-s1pm )/( s1_+s1pm );
       dd5_ = dd1_+dd3_+( ( p12_*( t1_-masses_.w31_ )*0.5-w1_*p2k1_ )*( p2k1_*( t2_-masses_.w52_ )-w2_*r3 )
                         -delta_*( 2.*p12_*p2k1_-w2_*( t1_-masses_.w31_ ) ) ) / p2k1_;
 
       return true;
     }
 
     //---------------------------------------------------------------------------------------------
 
     bool
     GamGamLL::orient()
     {
       if ( !pickin() || jacobian_ == 0. ) {
         CG_DEBUG_LOOP( "GamGamLL" )
           << "Pickin failed! Jacobian = " << jacobian_;
         return false;
       }
 
       const double re = 0.5 / sqs_;
       ep1_ = re*( s_+masses_.w12_ );
       ep2_ = re*( s_-masses_.w12_ );
 
       CG_DEBUG_LOOP( "GamGamLL" )
         << std::scientific
         << " re = " << re << "\n\t"
         << "w12_ = " << masses_.w12_
         << std::fixed;
       CG_DEBUG_LOOP( "GamGamLL" )
         << "Incoming particles' energy = " << ep1_ << ", " << ep2_;
 
       p_cm_ = re*sl1_;
 
       de3_ = re*(s2_-masses_.MX2_+masses_.w12_);
       de5_ = re*(s1_-masses_.MY2_-masses_.w12_);
 
       // Final state energies
       const double ep3 = ep1_-de3_,
                    ep5 = ep2_-de5_;
       ec4_ = de3_+de5_;
 
       if ( ec4_ < mc4_ ) {
         CG_WARNING( "GamGamLL" )
           << "ec4_ = " << ec4_ << " < mc4_ = " << mc4_ << "\n\t"
           << "==> de3 = " << de3_ << ", de5 = " << de5_;
         return false;
       }
 
       // What if the protons' momenta are not along the z-axis?
       pc4_ = sqrt( ec4_*ec4_-mc4_*mc4_ );
 
       if ( pc4_ == 0. ) {
         CG_WARNING( "GamGamLL" ) << "pzc4 is null and should not be...";
         return false;
       }
 
       const double pp3 = sqrt( ep3*ep3-masses_.MX2_ ), pt3 = sqrt( dd1_/s_ )/p_cm_,
                    pp5 = sqrt( ep5*ep5-masses_.MY2_ ), pt5 = sqrt( dd3_/s_ )/p_cm_;
 
       CG_DEBUG_LOOP( "GamGamLL" )
         << "Central system's energy: E4 = " << ec4_ << "\n\t"
         << "               momentum: p4 = " << pc4_ << "\n\t"
         << "         invariant mass: m4 = " << mc4_ << "\n\t"
         << "Outgoing particles' energy: E3 = " << ep3 << "\n\t"
         << "                            E5 = " << ep5;
 
       const double sin_theta3 = pt3/pp3,
                    sin_theta5 = pt5/pp5;
 
       CG_DEBUG_LOOP( "GamGamLL" )
         << std::scientific
         << "sin_theta3 = " << sin_theta3 << "\n\t"
         << "sin_theta5 = " << sin_theta5
         << std::fixed;
 
       if ( sin_theta3 > 1. ) {
         CG_WARNING( "GamGamLL" )
           << "sin_theta3 = " << sin_theta3 << " > 1";
         return false;
       }
       if ( sin_theta5 > 1. ) {
         CG_WARNING( "GamGamLL" )
           << "sin_theta5 = " << sin_theta5 << " > 1";
         return false;
       }
 
       double ct3 = sqrt( 1.-sin_theta3*sin_theta3 ),
              ct5 = sqrt( 1.-sin_theta5*sin_theta5 );
 
       if ( ep1_*ep3 < p13_ )
         ct3 *= -1.;
       if ( ep2_*ep5 > p25_ )
         ct5 *= -1.;
 
       CG_DEBUG_LOOP( "GamGamLL" )
         << "ct3 = " << ct3 << "\n\t"
         << "ct5 = " << ct5;
 
       if ( dd5_ < 0. ) {
         CG_WARNING( "GamGamLL" )
           <<  "dd5 = " << dd5_ << " < 0";
         return false;
       }
 
       // Centre of mass system kinematics (theta4 and phi4)
       pt4_ = sqrt( dd5_/s_ )/p_cm_;
       sin_theta4_ = pt4_/pc4_;
 
       if ( sin_theta4_ > 1. ) {
         CG_WARNING( "GamGamLL" )
           << "st4 = " << sin_theta4_ << " > 1";
         return false;
       }
 
       cos_theta4_ = sqrt( 1.-sin_theta4_*sin_theta4_ );
       if ( ep1_*ec4_ < p14_ )
         cos_theta4_ *= -1.;
 
       al4_ = 1.-cos_theta4_;
       be4_ = 1.+cos_theta4_;
 
       if ( cos_theta4_ < 0. ) be4_ = sin_theta4_*sin_theta4_/al4_;
       else                    al4_ = sin_theta4_*sin_theta4_/be4_;
 
       CG_DEBUG_LOOP( "GamGamLL" )
         << "ct4 = " << cos_theta4_ << "\n\t"
         << "al4 = " << al4_ << ", be4 = " << be4_;
 
       const double rr  = sqrt( -gram_/s_ )/( p_cm_*pt4_ );
       const double sin_phi3 =  rr / pt3,
                    sin_phi5 = -rr / pt5;
 
       if ( fabs( sin_phi3 ) > 1. ) {
         CG_WARNING( "GamGamLL" )
           << "sin(phi_3) = " << sin_phi3 << " while it must be in [-1 ; 1]";
         return false;
       }
       if ( fabs( sin_phi5 ) > 1. ) {
         CG_WARNING( "GamGamLL" )
           << "sin(phi_5) = " << sin_phi5 << " while it must be in [-1 ; 1]";
         return false;
       }
 
       const double cos_phi3 = -sqrt( 1.-sin_phi3*sin_phi3 ),
                    cos_phi5 = -sqrt( 1.-sin_phi5*sin_phi5 );
 
       p3_lab_ = Particle::Momentum( pp3*sin_theta3*cos_phi3, pp3*sin_theta3*sin_phi3, pp3*ct3, ep3 );
       p5_lab_ = Particle::Momentum( pp5*sin_theta5*cos_phi5, pp5*sin_theta5*sin_phi5, pp5*ct5, ep5 );
 
       const double a1 = p3_lab_.px()-p5_lab_.px();
 
       CG_DEBUG_LOOP( "GamGamLL" )
         << "Kinematic quantities\n\t"
         << "cos(theta3) = " << ct3 << "\t" << "sin(theta3) = " << sin_theta3 << "\n\t"
         << "cos( phi3 ) = " << cos_phi3 << "\t" << "sin( phi3 ) = " << sin_phi3 << "\n\t"
         << "cos(theta4) = " << cos_theta4_ << "\t" << "sin(theta4) = " << sin_theta4_ << "\n\t"
         << "cos(theta5) = " << ct5 << "\t" << "sin(theta5) = " << sin_theta5 << "\n\t"
         << "cos( phi5 ) = " << cos_phi5 << "\t" << "sin( phi5 ) = " << sin_phi5 << "\n\t"
         << "a1 = " << a1;
 
       if ( fabs( pt4_+p3_lab_.px()+p5_lab_.px() ) < fabs( fabs( a1 )-pt4_ ) ) {
         CG_DEBUG_LOOP( "GamGamLL" )
           << "|pt4+pt3*cos(phi3)+pt5*cos(phi5)| < | |a1|-pt4 |\n\t"
           << "pt4 = " << pt4_ << "\t"
           << "pt5 = " << pt5 << "\n\t"
           << "cos(phi3) = " << cos_phi3 << "\t"
           << "cos(phi5) = " << cos_phi5 << "\n\t"
           << "a1 = " << a1;
         return true;
       }
       if ( a1 < 0. ) p5_lab_[0] = -p5_lab_.px();
       else           p3_lab_[0] = -p3_lab_.px();
       return true;
     }
 
     //---------------------------------------------------------------------------------------------
 
     double
     GamGamLL::computeOutgoingPrimaryParticlesMasses( double x, double outmass, double lepmass, double& dw )
     {
       const double mx0 = mp_+ParticleProperties::mass( PDG::piZero ); // 1.07
       const double wx2min = pow( std::max( mx0, mx_limits_.min() ), 2 ),
                    wx2max = pow( std::min( sqs_-outmass-2.*lepmass, mx_limits_.max() ), 2 );
 
       double mx2 = 0., dmx2 = 0.;
       map( x, Limits( wx2min, wx2max ), mx2, dmx2, "mx2" );
 
       CG_DEBUG_LOOP( "GamGamLL" )
         << "mX^2 in range (" << wx2min << ", " << wx2max << "), x = " << x << "\n\t"
         << "mX^2 = " << mx2 << ", d(mX^2) = " << dmx2 << "\n\t"
         << "mX = " << sqrt( mx2 ) << ", d(mX) = " << sqrt( dmx2 );
 
       dw = sqrt( dmx2 );
       return sqrt( mx2 );
     }
 
     //---------------------------------------------------------------------------------------------
 
     void
     GamGamLL::beforeComputeWeight()
     {
       if ( !GenericProcess::is_point_set_ ) return;
 
       const Particle& p1 = event_->getOneByRole( Particle::IncomingBeam1 ),
                      &p2 = event_->getOneByRole( Particle::IncomingBeam2 );
 
       ep1_ = p1.energy();
       ep2_ = p2.energy();
 
       //std::cout << __PRETTY_FUNCTION__ << ":" << w_limits_ << "|" << q2_limits_ << "|" << mx_limits_ << std::endl;
       switch ( cuts_.mode ) {
         case KinematicsMode::ElectronProton: default:
           CG_ERROR( "GamGamLL" ) << "Case not yet supported!"; break;
         case KinematicsMode::ElasticElastic:
           masses_.dw31_ = masses_.dw52_ = 0.; break;
         case KinematicsMode::InelasticElastic: {
           const double m = computeOutgoingPrimaryParticlesMasses( x( 7 ), p1.mass(), sqrt( masses_.Ml2_ ), masses_.dw31_ );
           event_->getOneByRole( Particle::OutgoingBeam1 ).setMass( m );
           event_->getOneByRole( Particle::OutgoingBeam2 ).setMass( ParticleProperties::mass( p2.pdgId() ) );
         } break;
         case KinematicsMode::ElasticInelastic: {
           const double m = computeOutgoingPrimaryParticlesMasses( x( 7 ), p2.mass(), sqrt( masses_.Ml2_ ), masses_.dw52_ );
           event_->getOneByRole( Particle::OutgoingBeam1 ).setMass( ParticleProperties::mass( p1.pdgId() ) );
           event_->getOneByRole( Particle::OutgoingBeam2 ).setMass( m );
         } break;
         case KinematicsMode::InelasticInelastic: {
           const double mx = computeOutgoingPrimaryParticlesMasses( x( 7 ), p2.mass(), sqrt( masses_.Ml2_ ), masses_.dw31_ );
           event_->getOneByRole( Particle::OutgoingBeam1 ).setMass( mx );
           const double my = computeOutgoingPrimaryParticlesMasses( x( 8 ), p1.mass(), sqrt( masses_.Ml2_ ), masses_.dw52_ );
           event_->getOneByRole( Particle::OutgoingBeam2 ).setMass( my );
         } break;
       }
       MX_ = event_->getOneByRole( Particle::OutgoingBeam1 ).mass();
       MY_ = event_->getOneByRole( Particle::OutgoingBeam2 ).mass();
       masses_.MX2_ = MX_*MX_;
       masses_.MY2_ = MY_*MY_;
     }
 
     //---------------------------------------------------------------------------------------------
 
     double
     GamGamLL::computeWeight()
     {
       CG_DEBUG_LOOP( "GamGamLL" )
         << "sqrt(s) = " << sqs_ << " GeV\n\t"
         << "m(X1) = " << MX_ << " GeV\t"
         << "m(X2) = " << MY_ << " GeV";
 
       // compute the two-photon energy for this point
       w4_ = 0.;
       double dw4 = 0.;
       map( x( 4 ), w_limits_, w4_, dw4, "w4" );
       mc4_ = sqrt( w4_ );
 
       CG_DEBUG_LOOP( "GamGamLL" )
         << "Computed value for w4 = " << w4_ << " → mc4 = " << mc4_;
 
       if ( !orient() )
         return 0.;
 
       if ( jacobian_ == 0. ) {
         CG_WARNING( "GamGamLL" ) << "dj = " << jacobian_;
         return 0.;
       }
 
       if ( t1_ > 0. ) {
         CG_WARNING( "GamGamLL" ) << "t1 = " << t1_ << " > 0";
         return 0.;
       }
       if ( t2_ > 0. ) {
         CG_WARNING( "GamGamLL" ) << "t2 = " << t2_ << " > 0";
         return 0.;
       }
 
       const double ecm6 = w4_ / ( 2.*mc4_ ),
                    pp6cm = sqrt( ecm6*ecm6-masses_.Ml2_ );
 
       jacobian_ *= dw4*pp6cm/( mc4_*Constants::sconstb*s_ );
 
       // Let the most obscure part of this code begin...
 
       const double e1mp1 = w1_ / ( ep1_+p_cm_ ),
                    e3mp3 = masses_.MX2_ / ( p3_lab_.energy()+p3_lab_.p() );
 
       const double al3 = pow( sin( p3_lab_.theta() ), 2 )/( 1.+( p3_lab_.theta() ) );
 
       // 2-photon system kinematics ?!
       const double eg = ( w4_+t1_-t2_ )/( 2.*mc4_ );
       double pg = sqrt( eg*eg-t1_ );
 
       const double pgx = -p3_lab_.px()*cos_theta4_-sin_theta4_*( de3_-e1mp1 + e3mp3 + p3_lab_.p()*al3 ),
                    pgy = -p3_lab_.py(),
                    pgz = mc4_*de3_/( ec4_+pc4_ )-ec4_*de3_*al4_/mc4_-p3_lab_.px()*ec4_*sin_theta4_/mc4_+ec4_*cos_theta4_/mc4_*( p3_lab_.p()*al3+e3mp3-e1mp1 );
 
       CG_DEBUG_LOOP( "GamGamLL" ) << "pg = " << Particle::Momentum( pgx, pgy, pgz );
 
       const double pgp = sqrt( pgx*pgx + pgy*pgy ), // outgoing proton (3)'s transverse momentum
                    pgg = sqrt( pgp*pgp + pgz*pgz ); // outgoing proton (3)'s momentum
       if ( pgg > pgp*0.9 && pgg > pg )
         pg = pgg; //FIXME ???
 
       // angles for the 2-photon system ?!
       const double cpg = pgx/pgp, spg = pgy/pgp;
       const double stg = pgp/pg;
 
       const int theta_sign = ( pgz>0. ) ? 1 : -1;
       const double ctg = theta_sign*sqrt( 1.-stg*stg );
 
       double xx6 = x( 5 );
 
       const double amap = 0.5 * ( w4_-t1_-t2_ ),
                    bmap = 0.5 * sqrt( ( pow( w4_-t1_-t2_, 2 )-4.*t1_*t2_ )*( 1.-4.*masses_.Ml2_/w4_ ) ),
                    ymap = ( amap+bmap )/( amap-bmap ),
                    beta = pow( ymap, 2.*xx6-1. );
       xx6 = 0.5 * ( 1. + amap/bmap*( beta-1. )/( beta+1. ) );
       xx6 = std::max( 0., std::min( xx6, 1. ) ); // xx6 in [0., 1.]
 
       CG_DEBUG_LOOP( "GamGamLL" )
         << "amap = " << amap << "\n\t"
         << "bmap = " << bmap << "\n\t"
         << "ymap = " << ymap << "\n\t"
         << "beta = " << beta;
 
       // 3D rotation of the first outgoing lepton wrt the CM system
       const double theta6cm = acos( 1.-2.*xx6 );
 
       // match the Jacobian
       jacobian_ *= ( amap+bmap*cos( theta6cm ) );
       jacobian_ *= ( amap-bmap*cos( theta6cm ) );
       jacobian_ /= amap;
       jacobian_ /= bmap;
       jacobian_ *= log( ymap );
       jacobian_ *= 0.5;
 
       CG_DEBUG_LOOP( "GamGamLL" ) << "Jacobian = " << jacobian_;
 
       CG_DEBUG_LOOP( "GamGamLL" )
         << "ctcm6 = " << cos( theta6cm ) << "\n\t"
         << "stcm6 = " << sin( theta6cm );
 
       const double phi6cm = 2.*M_PI*x( 6 );
 
       // First outgoing lepton's 3-momentum in the centre of mass system
       Particle::Momentum p6cm = Particle::Momentum::fromPThetaPhi( pp6cm, theta6cm, phi6cm );
 
       CG_DEBUG_LOOP( "GamGamLL" ) << "p3cm6 = " << p6cm;
 
       const double h1 = stg*p6cm.pz()+ctg*p6cm.px();
       const double pc6z = ctg*p6cm.pz()-stg*p6cm.px(), pc6x = cpg*h1-spg*p6cm.py();
 
       const double qcx = 2.*pc6x, qcz = 2.*pc6z;
       // qcy == QCY is never defined
 
       const double el6 = ( ec4_*ecm6+pc4_*pc6z ) / mc4_,
                    h2  = ( ec4_*pc6z+pc4_*ecm6 ) / mc4_;
 
       CG_DEBUG_LOOP( "GamGamLL" ) << "h1 = " << h1 << "\n\th2 = " << h2;
 
       // first outgoing lepton's 3-momentum
       const double p6x = cos_theta4_*pc6x+sin_theta4_*h2,
                    p6y = cpg*p6cm.py()+spg*h1,
                    p6z = cos_theta4_*h2-sin_theta4_*pc6x;
 
       // first outgoing lepton's kinematics
       p6_cm_ = Particle::Momentum( p6x, p6y, p6z, el6 );
       CG_DEBUG_LOOP( "GamGamLL" ) << "p6(cm) = " << p6_cm_;
 
       const double hq = ec4_*qcz/mc4_;
 
       const Particle::Momentum qve(
         cos_theta4_*qcx+sin_theta4_*hq,
         2.*p6y,
         cos_theta4_*hq-sin_theta4_*qcx,
         pc4_*qcz/mc4_ // energy
       );
 
       // Available energy for the second lepton is the 2-photon system's energy with the first lepton's energy removed
       const double el7 = ec4_-el6;
 
       CG_DEBUG_LOOP( "GamGamLL" )
         << "Outgoing kinematics\n\t"
         << " first outgoing lepton: p = " << p6_cm_.p() << ", E = " << p6_cm_.energy() << "\n\t"
         << "second outgoing lepton: p = " << p7_cm_.p() << ", E = " << p7_cm_.energy();;
 
       // Second outgoing lepton's 3-momentum
       const double p7x = -p6x + pt4_,
                    p7y = -p6y,
                    p7z = -p6z + pc4_*cos_theta4_;
 
       // second outgoing lepton's kinematics
       p7_cm_ = Particle::Momentum( p7x, p7y, p7z, el7 );
 
       //p6_cm_ = Particle::Momentum(pl6*st6*cp6, pl6*st6*sp6, pl6*ct6, el6);
       //p7_cm_ = Particle::Momentum(pl7*st7*cp7, pl7*st7*sp7, pl7*ct7, el7);
 
       q1dq_ = eg*( 2.*ecm6-mc4_ )-2.*pg*p6cm.pz();
       q1dq2_ = ( w4_-t1_-t2_ ) * 0.5;
 
       const double phi3 = p3_lab_.phi(), cos_phi3 = cos( phi3 ), sin_phi3 = sin( phi3 ),
                    phi5 = p5_lab_.phi(), cos_phi5 = cos( phi5 ), sin_phi5 = sin( phi5 );
 
       bb_ = t1_*t2_+( w4_*pow( sin( theta6cm ), 2 ) + 4.*masses_.Ml2_*pow( cos( theta6cm ), 2 ) )*pg*pg;
 
       const double c1 = p3_lab_.pt() * ( qve.px()*sin_phi3  - qve.py()*cos_phi3   ),
                    c2 = p3_lab_.pt() * ( qve.pz()*ep1_ - qve.energy() *p_cm_ ),
                    c3 = ( masses_.w31_*ep1_*ep1_ + 2.*w1_*de3_*ep1_ - w1_*de3_*de3_ + p3_lab_.pt2()*ep1_*ep1_ ) / ( p3_lab_.energy()*p_cm_ + p3_lab_.pz()*ep1_ );
 
       const double b1 = p5_lab_.pt() * ( qve.px()*sin_phi5  - qve.py()*cos_phi5   ),
                    b2 = p5_lab_.pt() * ( qve.pz()*ep2_ + qve.energy() *p_cm_ ),
                    b3 = ( masses_.w52_*ep2_*ep2_ + 2.*w2_*de5_*ep2_ - w2_*de5_*de5_ + p5_lab_.pt2()*ep2_*ep2_ ) / ( ep2_*p5_lab_.pz() - p5_lab_.energy()*p_cm_ );
 
       const double r12 =  c2*sin_phi3 + qve.py()*c3,
                    r13 = -c2*cos_phi3 - qve.px()*c3;
 
       const double r22 =  b2*sin_phi5 + qve.py()*b3,
                    r23 = -b2*cos_phi5 - qve.px()*b3;
 
       epsi_ = p12_*c1*b1 + r12*r22 + r13*r23;
 
       g5_ = w1_*c1*c1 + r12*r12 + r13*r13;
       g6_ = w2_*b1*b1 + r22*r22 + r23*r23;
 
       const double pt3 = p3_lab_.pt(), pt5 = p5_lab_.pt();
       a5_ = -( qve.px()*cos_phi3 + qve.py()*sin_phi3 )*pt3*p1k2_
             -( ep1_*qve.energy()-p_cm_*qve.pz() )*( cos_phi3*cos_phi5 + sin_phi3*sin_phi5 )*pt3*pt5
             +( de5_*qve.pz()+qve.energy()*( p_cm_+p5_lab_.pz() ) )*c3;
       a6_ = -( qve.px()*cos_phi5 + qve.py()*sin_phi5 )*pt5*p2k1_
             -( ep2_*qve.energy()+p_cm_*qve.pz() )*( cos_phi3*cos_phi5 + sin_phi3*sin_phi5 )*pt3*pt5
             +( de3_*qve.pz()-qve.energy()*( p_cm_-p3_lab_.pz() ) )*b3;
 
       CG_DEBUG_LOOP( "GamGamLL" )
         << "a5 = " << a5_ << "\n\t"
         << "a6 = " << a6_;
 
       ////////////////////////////////////////////////////////////////
       // END of GAMGAMLL subroutine in the FORTRAN version
       ////////////////////////////////////////////////////////////////
 
       const Particle::Momentum cm = event_->getOneByRole( Particle::IncomingBeam1 ).momentum()
                                   + event_->getOneByRole( Particle::IncomingBeam2 ).momentum();
 
       ////////////////////////////////////////////////////////////////
       // INFO from f.f
       ////////////////////////////////////////////////////////////////
 
       const double gamma = cm.energy() / sqs_, betgam = cm.pz() / sqs_;
 
       //--- kinematics computation for both leptons
 
       p6_cm_.betaGammaBoost( gamma, betgam );
       p7_cm_.betaGammaBoost( gamma, betgam );
 
       //--- cut on mass of final hadronic system (MX/Y)
 
       if ( mx_limits_.valid() ) {
         if ( ( cuts_.mode == KinematicsMode::InelasticElastic
             || cuts_.mode == KinematicsMode::InelasticInelastic )
           && !mx_limits_.passes( MX_ ) )
           return 0.;
         if ( ( cuts_.mode == KinematicsMode::ElasticInelastic
             || cuts_.mode == KinematicsMode::InelasticInelastic )
           && !mx_limits_.passes( MY_ ) )
           return 0.;
       }
 
       //--- cut on the proton's Q2 (first photon propagator T1)
 
       if ( !cuts_.cuts.initial.q2.passes( -t1_ ) )
         return 0.;
 
       //--- cuts on outgoing leptons' kinematics
 
       if ( !cuts_.cuts.central.mass_sum.passes( ( p6_cm_+p7_cm_ ).mass() ) )
         return 0.;
 
       //----- cuts on the individual leptons
 
       if ( cuts_.cuts.central.pt_single.valid() ) {
         const Limits& pt_limits = cuts_.cuts.central.pt_single;
         if ( !pt_limits.passes( p6_cm_.pt() ) || !pt_limits.passes( p7_cm_.pt() ) )
           return 0.;
       }
 
       if ( cuts_.cuts.central.energy_single.valid() ) {
         const Limits& energy_limits = cuts_.cuts.central.energy_single;
         if ( !energy_limits.passes( p6_cm_.energy() ) || !energy_limits.passes( p7_cm_.energy() ) )
           return 0.;
       }
 
       if ( cuts_.cuts.central.eta_single.valid() ) {
         const Limits& eta_limits = cuts_.cuts.central.eta_single;
         if ( !eta_limits.passes( p6_cm_.eta() ) || !eta_limits.passes( p7_cm_.eta() ) )
           return 0.;
       }
 
       //--- compute the structure functions factors
 
       switch ( cuts_.mode ) { // inherited from CDF version
         case KinematicsMode::ElectronProton: default: jacobian_ *= periPP( 1, 2 ); break; // ep case
         case KinematicsMode::ElasticElastic:          jacobian_ *= periPP( 2, 2 ); break; // elastic case
         case KinematicsMode::InelasticElastic:        jacobian_ *= periPP( 3, 2 )*( masses_.dw31_*masses_.dw31_ ); break;
         case KinematicsMode::ElasticInelastic:        jacobian_ *= periPP( 3, 2 )*( masses_.dw52_*masses_.dw52_ ); break; // single-dissociative case
         case KinematicsMode::InelasticInelastic:      jacobian_ *= periPP( 3, 3 )*( masses_.dw31_*masses_.dw31_ )*( masses_.dw52_*masses_.dw52_ ); break; // double-dissociative case
       }
 
       //--- compute the event weight using the Jacobian
 
       return Constants::GeV2toBarn*jacobian_;
     }
 
     //---------------------------------------------------------------------------------------------
 
     void
     GamGamLL::fillKinematics( bool )
     {
       const Particle::Momentum cm = event_->getOneByRole( Particle::IncomingBeam1 ).momentum() + event_->getOneByRole( Particle::IncomingBeam2 ).momentum();
 
       const double gamma  = cm.energy()/sqs_, betgam = cm.pz()/sqs_;
 
       Particle::Momentum plab_ip1 = Particle::Momentum( 0., 0.,  p_cm_, ep1_ ).betaGammaBoost( gamma, betgam );
       Particle::Momentum plab_ip2 = Particle::Momentum( 0., 0., -p_cm_, ep2_ ).betaGammaBoost( gamma, betgam );
       p3_lab_.betaGammaBoost( gamma, betgam );
       p5_lab_.betaGammaBoost( gamma, betgam );
 
       //----- parameterise a random rotation around z-axis
       const int rany = ( rand() >= 0.5 * RAND_MAX ) ? 1 : -1,
                 ransign = ( rand() >= 0.5 * RAND_MAX ) ? 1 : -1;
       const double ranphi = ( 0.5 * rand()/RAND_MAX )*2.*M_PI;
 
       Particle::Momentum plab_ph1 = ( plab_ip1-p3_lab_ ).rotatePhi( ranphi, rany );
       Particle::Momentum plab_ph2 = ( plab_ip2-p5_lab_ ).rotatePhi( ranphi, rany );
 
       p3_lab_.rotatePhi( ranphi, rany );
       p5_lab_.rotatePhi( ranphi, rany );
       p6_cm_.rotatePhi( ranphi, rany );
       p7_cm_.rotatePhi( ranphi, rany );
 
       /*if ( symmetrise_ && rand() >= .5*RAND_MAX ) {
         p6_cm_.mirrorZ();
         p7_cm_.mirrorZ();
       }*/
 
       //----- incoming protons
       event_->getOneByRole( Particle::IncomingBeam1 ).setMomentum( plab_ip1 );
       event_->getOneByRole( Particle::IncomingBeam2 ).setMomentum( plab_ip2 );
 
       //----- first outgoing proton
       Particle& op1 = event_->getOneByRole( Particle::OutgoingBeam1 );
 
       op1.setMomentum( p3_lab_ );
       switch ( cuts_.mode ) {
         case KinematicsMode::ElasticElastic:
         case KinematicsMode::ElasticInelastic:
         default:
           op1.setStatus( Particle::Status::FinalState ); // stable proton
           break;
         case KinematicsMode::InelasticElastic:
         case KinematicsMode::InelasticInelastic:
           op1.setStatus( Particle::Status::Unfragmented ); // fragmenting remnants
           op1.setMass( MX_ );
           break;
       }
 
       //----- second outgoing proton
       Particle& op2 = event_->getOneByRole( Particle::OutgoingBeam2 );
       op2.setMomentum( p5_lab_ );
       switch ( cuts_.mode ) {
         case KinematicsMode::ElasticElastic:
         case KinematicsMode::InelasticElastic:
         default:
           op2.setStatus( Particle::Status::FinalState ); // stable proton
           break;
         case KinematicsMode::ElasticInelastic:
         case KinematicsMode::InelasticInelastic:
           op2.setStatus( Particle::Status::Unfragmented ); // fragmenting remnants
           op2.setMass( MY_ );
           break;
       }
 
       //----- first incoming photon
       Particle& ph1 = event_->getOneByRole( Particle::Parton1 );
       ph1.setMomentum( plab_ph1 );
 
       //----- second incoming photon
       Particle& ph2 = event_->getOneByRole( Particle::Parton2 );
       ph2.setMomentum( plab_ph2 );
 
       Particles& central_system = event_->getByRole( Particle::CentralSystem );
 
       //----- first outgoing lepton
       Particle& ol1 = central_system[0];
       ol1.setPdgId( ol1.pdgId(), ransign );
       ol1.setMomentum( p6_cm_ );
       ol1.setStatus( Particle::Status::FinalState );
 
       //----- second outgoing lepton
       Particle& ol2 = central_system[1];
       ol2.setPdgId( ol2.pdgId(), -ransign );
       ol2.setMomentum( p7_cm_ );
       ol2.setStatus( Particle::Status::FinalState );
 
       //----- intermediate two-lepton system
       event_->getOneByRole( Particle::Intermediate ).setMomentum( p6_cm_+p7_cm_ );
     }
 
     //---------------------------------------------------------------------------------------------
 
     double
     GamGamLL::periPP( int nup_, int ndown_ )
     {
       CG_DEBUG_LOOP( "GamGamLL" )
         << " Nup  = " << nup_ << "\n\t"
         << "Ndown = " << ndown_;
 
       FormFactors fp1, fp2;
       formFactors( -t1_, -t2_, fp1, fp2 );
 
       CG_DEBUG_LOOP( "GamGamLL" )
         << "u1 = " << fp1.FM << "\n\t"
         << "u2 = " << fp1.FE << "\n\t"
         << "v1 = " << fp2.FM << "\n\t"
         << "v2 = " << fp2.FE;
 
       const double qqq = q1dq_*q1dq_,
                    qdq = 4.*masses_.Ml2_-w4_;
       const double t11 = 64. *(  bb_*( qqq-g4_-qdq*( t1_+t2_+2.*masses_.Ml2_ ) )-2.*( t1_+2.*masses_.Ml2_ )*( t2_+2.*masses_.Ml2_ )*qqq ) * t1_*t2_, // magnetic-magnetic
                    t12 = 128.*( -bb_*( dd2_+g6_ )-2.*( t1_+2.*masses_.Ml2_ )*( sa2_*qqq+a6_*a6_ ) ) * t1_, // electric-magnetic
                    t21 = 128.*( -bb_*( dd4_+g5_ )-2.*( t2_+2.*masses_.Ml2_ )*( sa1_*qqq+a5_*a5_ ) ) * t2_, // magnetic-electric
                    t22 = 512.*(  bb_*( delta_*delta_-gram_ )-pow( epsi_-delta_*( qdq+q1dq2_ ), 2 )-sa1_*a6_*a6_-sa2_*a5_*a5_-sa1_*sa2_*qqq ); // electric-electric
 
       const double peripp = ( fp1.FM*fp2.FM*t11 + fp1.FE*fp2.FM*t21 + fp1.FM*fp2.FE*t12 + fp1.FE*fp2.FE*t22 ) / pow( 2.*t1_*t2_*bb_, 2 );
 
       CG_DEBUG_LOOP( "GamGamLL" )
         << "t11 = " << t11 << "\t"
         << "t12 = " << t12 << "\n\t"
         << "t21 = " << t21 << "\t"
         << "t22 = " << t22 << "\n\t"
         << "=> PeriPP = " << peripp;
 
       return peripp;
     }
 
     void
     GamGamLL::map( double expo, const Limits& lim, double& out, double& dout, const std::string& var_name_ )
     {
       const double y = lim.max()/lim.min();
       out = lim.min()*pow( y, expo );
       dout = out*log( y );
       CG_DEBUG_LOOP( "GamGamLL:map" )
         << "Mapping variable \"" << var_name_ << "\"\n\t"
         << "limits = " << lim << "\n\t"
         << "max/min = " << y << "\n\t"
         << "exponent = " << expo << "\n\t"
         << "output = " << out << "\n\t"
         << "d(output) = " << dout;
     }
 
     void
     GamGamLL::mapla( double y, double z, int u, double xm, double xp, double& x, double& d )
     {
       const double xmb = xm-y-z, xpb = xp-y-z;
       const double c = -4.*y*z;
       const double alp = sqrt( xpb*xpb + c ), alm = sqrt( xmb*xmb + c );
       const double am = xmb+alm, ap = xpb+alp;
       const double yy = ap/am, zz = pow( yy, u );
 
       x = y + z + ( am*zz - c / ( am*zz ) ) / 2.;
       const double ax = sqrt( pow( x-y-z, 2 ) + c );
       d = ax*log( yy );
     }
 
     void
     GamGamLL::formFactors( double q1, double q2, FormFactors& fp1, FormFactors& fp2 ) const
     {
       const double mx2 = MX_*MX_, my2 = MY_*MY_;
 
       switch ( cuts_.mode ) {
         case KinematicsMode::ElectronElectron: default: {
           fp1 = FormFactors::trivial(); // electron (trivial) form factor
           fp2 = FormFactors::trivial(); // electron (trivial) form factor
         } break;
         case KinematicsMode::ProtonElectron: {
           fp1 = FormFactors::protonElastic( -t1_ ); // proton elastic form factor
           fp2 = FormFactors::trivial(); // electron (trivial) form factor
         } break;
         case KinematicsMode::ElectronProton: {
           fp1 = FormFactors::trivial(); // electron (trivial) form factor
           fp2 = FormFactors::protonElastic( -t2_ ); // proton elastic form factor
         } break;
         case KinematicsMode::ElasticElastic: {
           fp1 = FormFactors::protonElastic( -t1_ ); // proton elastic form factor
           fp2 = FormFactors::protonElastic( -t2_ ); // proton elastic form factor
         } break;
         case KinematicsMode::ElasticInelastic: {
           fp1 = FormFactors::protonElastic( -t1_ );
           fp2 = FormFactors::protonInelastic( -t2_, w2_, my2, *cuts_.structure_functions );
         } break;
         case KinematicsMode::InelasticElastic: {
           fp1 = FormFactors::protonInelastic( -t1_, w1_, mx2, *cuts_.structure_functions );
           fp2 = FormFactors::protonElastic( -t2_ );
         } break;
         case KinematicsMode::InelasticInelastic: {
           fp1 = FormFactors::protonInelastic( -t1_, w1_, mx2, *cuts_.structure_functions );
           fp2 = FormFactors::protonInelastic( -t2_, w2_, my2, *cuts_.structure_functions );
         } break;
       }
     }
     // register process and define aliases
     REGISTER_PROCESS( lpair, GamGamLL )
     REGISTER_PROCESS( gamgamll, GamGamLL )
   }
 }
-
diff --git a/CepGen/Processes/GamGamLL.h b/CepGen/Processes/GamGamLL.h
index b2039a3..20d7d22 100644
--- a/CepGen/Processes/GamGamLL.h
+++ b/CepGen/Processes/GamGamLL.h
@@ -1,221 +1,221 @@
 #ifndef CepGen_Processes_GamGamLL_h
 #define CepGen_Processes_GamGamLL_h
 
 #include "CepGen/Processes/GenericProcess.h"
 #include "CepGen/Core/ParametersList.h"
 
 namespace CepGen
 {
-  namespace Process
+  namespace process
   {
     /**
      * Full class of methods and objects to compute the full analytic matrix element
      * \cite Vermaseren:1982cz for the \f$\gamma\gamma\to\ell^{+}\ell^{-}\f$ process
      * according to a set of kinematic constraints provided for the incoming and
      * outgoing particles (the Kinematics object).
      * The \a f function created by this Process child has its \a _ndim -dimensional
      * coordinates mapped as :
      * - 0 = \f$t_1\f$, first incoming photon's virtuality
      * - 1 = \f$t_2\f$, second incoming photon's virtuality
      * - 2 = \f$s_2\f$ mapping
      * - 3 = yy4 = \f$\cos\left(\pi x_3\right)\f$ definition
      * - 4 = \f$w_4\f$, the two-photon system's invariant mass
      * - 5 = xx6 = \f$\frac{1}{2}\left(1-\cos\theta^{\rm CM}_6\right)\f$ definition (3D rotation of the first outgoing lepton with respect to the two-photon centre-of-mass system). If the \a nm_ optimisation flag is set this angle coefficient value becomes
      *   \f[\frac{1}{2}\left(\frac{a_{\rm map}}{b_{\rm map}}\frac{\beta-1}{\beta+1}+1\right)\f]
      *   with \f$a_{\rm map}=\frac{1}{2}\left(w_4-t_1-t_2\right)\f$, \f$b_{\rm map}=\frac{1}{2}\sqrt{\left(\left(w_4-t_1-t_2\right)^2-4t_1t_2\right)\left(1-4\frac{w_6}{w_4}\right)}\f$, and \f$\beta=\left(\frac{a_{\rm map}+b_{\rm map}}{a_{\rm map}-b_{\rm map}}\right)^{2x_5-1}\f$
      *   and the Jacobian element is scaled by a factor \f$\frac{1}{2}\frac{\left(a_{\rm map}^2-b_{\rm map}^2\cos^2\theta^{\rm CM}_6\right)}{a_{\rm map}b_{\rm map}}\log\left(\frac{a_{\rm map}+b_{\rm map}}{a_{\rm map}-b_{\rm map}}\right)\f$
      * - 6 = _phicm6_, or \f$\phi_6^{\rm CM}\f$ the rotation angle of the dilepton system in the centre-of-mass
      *   system
      * - 7 = \f$x_q\f$, \f$w_X\f$ mappings, as used in the single- and double-dissociative
      *   cases only
      * \brief Compute the matrix element for a CE \f$\gamma\gamma\to\ell^{+}\ell^{-}\f$
      *  process
      */
     class GamGamLL : public GenericProcess
     {
       public:
         /// \brief Class constructor: set the mandatory parameters before integration and events generation
         /// \param[in] params General process parameters (nopt = Optimisation, legacy from LPAIR)
         explicit GamGamLL( const ParametersList& params = ParametersList() );
         ProcessPtr clone( const ParametersList& params ) const override { return ProcessPtr( new GamGamLL( params ) ); }
 
         void addEventContent() override;
         void beforeComputeWeight() override;
         double computeWeight() override;
         unsigned int numDimensions() const override;
         void setKinematics( const Kinematics& cuts ) override;
         void fillKinematics( bool ) override;
         /// Compute the ougoing proton remnant mass
         /// \param[in] x A random number (between 0 and 1)
         /// \param[in] outmass The maximal outgoing particles' invariant mass
         /// \param[in] lepmass The outgoing leptons' mass
         /// \param[out] dw The size of the integration bin
         /// \return Mass of the outgoing proton remnant
         double computeOutgoingPrimaryParticlesMasses( double x, double outmass, double lepmass, double& dw );
         /// Set all the kinematic variables for the outgoing proton remnants, and prepare the hadronisation
         /// \param[in] part Particle to "prepare" for the hadronisation to be performed
         void prepareHadronisation( Particle *part );
 
       private:
         /**
          * Calculate energies and momenta of the
          *  1st, 2nd (resp. the "proton-like" and the "electron-like" incoming particles),
          *  3rd (the "proton-like" outgoing particle),
          *  4th (the two-photons central system), and
          *  5th (the "electron-like" outgoing particle) particles in the overall centre-of-mass frame.
          * \brief Energies/momenta computation for the various particles, in the CM system
          * \return Success state of the operation
          */
         bool orient();
         /**
          * Compute the expression of the matrix element squared for the \f$\gamma\gamma\rightarrow\ell^{+}\ell^{-}\f$ process.
          * It returns the value of the convolution of the form factor or structure functions with the central two-photons matrix element squared.
          * \brief Computes the matrix element squared for the requested process
          * \return Full matrix element for the two-photon production of a pair of spin\f$-\frac{1}{2}-\f$point particles.
          *  It is noted as \f[
          *  M = \frac{1}{4bt_1 t_2}\sum_{i=1}^2\sum_{j=1}^2 u_i v_j t_{ij} = \frac{1}{4}\frac{u_1 v_1 t_{11}+u_2 v_1 t_{21}+u_1 v_2 t_{12}+u_2 v_2 t_{22}}{t_1 t_2 b}
          * \f] where \f$b\f$ = \a bb_ is defined in \a ComputeWeight as : \f[
          *  b = t_1 t_2+\left(w_{\gamma\gamma}\sin^2{\theta^{\rm CM}_6}+4m_\ell\cos^2{\theta^{\rm CM}_6}\right) p_g^2
          * \f]
          */
         double periPP( int, int );
         /**
          * Describe the kinematics of the process \f$p_1+p_2\to p_3+p_4+p_5\f$ in terms of Lorentz-invariant variables.
          * These variables (along with others) will then be fed into the \a PeriPP method (thus are essential for the evaluation of the full matrix element).
          * \return Success state of the operation
          */
         bool pickin();
 
         /// Internal switch for the optimised code version (LPAIR legacy ; unimplemented here)
         int n_opt_;
         int pair_;
 
         Limits w_limits_;
         Limits q2_limits_;
         Limits mx_limits_;
         struct Masses
         {
           Masses();
           /// squared mass of the first proton-like outgoing particle
           double MX2_;
           /// squared mass of the second proton-like outgoing particle
           double MY2_;
           /// squared mass of the outgoing leptons
           double Ml2_;
           /// \f$\delta_2=m_1^2-m_2^2\f$ as defined in Vermaseren's paper
           /// \cite Vermaseren:1982cz for the full definition of this quantity
           double w12_;
 
           /// \f$\delta_1=m_3^2-m_1^2\f$ as defined in Vermaseren's paper
           /// \cite Vermaseren:1982cz for the full definition of this quantity
           double w31_;
           double dw31_;
           /// \f$\delta_4=m_5^2-m_2^2\f$ as defined in Vermaseren's paper
           /// \cite Vermaseren:1982cz for the full definition of this quantity
           double w52_;
           double dw52_;
         };
         Masses masses_;
 
         /// energy of the first proton-like incoming particle
         double ep1_;
         /// energy of the second proton-like incoming particle
         double ep2_;
         double p_cm_;
 
         /// energy of the two-photon central system
         double ec4_;
         /// 3-momentum norm of the two-photon central system
         double pc4_;
         /// mass of the two-photon central system
         double mc4_;
         /// squared mass of the two-photon central system
         double w4_;
 
         /// \f$p_{12} = \frac{1}{2}\left(s-m_{p_1}^2-m_{p_2}^2\right)\f$
         double p12_;
         double p1k2_, p2k1_;
         /// \f$p_{13} = -\frac{1}{2}\left(t_1-m_{p_1}^2-m_{p_3}^2\right)\f$
         double p13_;
         double p14_, p25_;
 
         double q1dq_, q1dq2_;
 
         double s1_, s2_;
 
         double epsi_;
         double g5_, g6_;
         double a5_, a6_;
         double bb_;
 
         double gram_;
         double dd1_, dd2_, dd3_;
         /// \f$\delta_5=m_4^2-t_1\f$ as defined in Vermaseren's paper
         /// \cite Vermaseren:1982cz for the full definition of this quantity
         double dd4_;
         double dd5_;
         /**
          * Invariant used to tame divergences in the matrix element computation. It is defined as
          * \f[\Delta = \left(p_1\cdot p_2\right)\left(q_1\cdot q_2\right)-\left(p_1\cdot q_2\right)\left(p_2\cdot q_1\right)\f]
          * with \f$p_i, q_i\f$ the 4-momenta associated to the incoming proton-like particle and to the photon emitted from it.
          */
         double delta_;
         double g4_;
         double sa1_, sa2_;
 
         double sl1_;
 
         /// cosine of the polar angle for the two-photons centre-of-mass system
         double cos_theta4_;
         /// sine of the polar angle for the two-photons centre-of-mass system
         double sin_theta4_;
 
         double al4_;
         double be4_;
         double de3_, de5_;
         double pt4_;
 
         /// Kinematics of the first incoming proton
         Particle::Momentum p1_lab_;
         /// Kinematics of the second incoming proton
         Particle::Momentum p2_lab_;
         /// Kinematics of the first outgoing proton
         Particle::Momentum p3_lab_;
         /// Kinematics of the two-photon system (in the two-proton CM)
         Particle::Momentum p4_lab_;
         /// Kinematics of the second outgoing proton
         Particle::Momentum p5_lab_;
         /// Kinematics of the first outgoing lepton (in the two-proton CM)
         Particle::Momentum p6_cm_;
         /// Kinematics of the second outgoing lepton (in the two-proton CM)
         Particle::Momentum p7_cm_;
         double jacobian_;
 
       private:
         /**
          * Define modified variables of integration to avoid peaks integrations (see \cite Vermaseren:1982cz for details)
          * Return a set of two modified variables of integration to maintain the stability of the integrant. These two new variables are :
          * - \f$y_{out} = x_{min}\left(\frac{x_{max}}{x_{min}}\right)^{exp}\f$ the new variable
          * - \f$\mathrm dy_{out} = x_{min}\left(\frac{x_{max}}{x_{min}}\right)^{exp}\log\frac{x_{min}}{x_{max}}\f$, the new variable's differential form
          * \brief Redefine the variables of integration in order to avoid the strong peaking of the integrant
          * \param[in] expo Exponant
          * \param[in] lim Min/maximal value of the variable
          * \param[out] out The new variable definition
          * \param[out] dout The bin width the new variable definition
          * \param[in] var_name The variable name
          * \note This method overrides the set of `mapxx` subroutines in ILPAIR, with a slight difference according to the sign of the
          *  \f$\mathrm dy_{out}\f$ parameter :
          *  - left unchanged :
          * > `mapw2`, `mapxq`, `mapwx`, `maps2`
          *  - opposite sign :
          * > `mapt1`, `mapt2`
          */
         void map( double expo, const Limits& lim, double& out, double& dout, const std::string& var_name = "" );
         void mapla( double y, double z, int u, double xm, double xp, double& x, double& d );
         /// Compute the electric/magnetic form factors for the two considered \f$Q^{2}\f$ momenta transfers
         void formFactors( double q1, double q2, FormFactors& fp1, FormFactors& fp2 ) const;
     };
   }
 }
 
 #endif
diff --git a/CepGen/Processes/GenericKTProcess.cpp b/CepGen/Processes/GenericKTProcess.cpp
index df22774..90fb99a 100644
--- a/CepGen/Processes/GenericKTProcess.cpp
+++ b/CepGen/Processes/GenericKTProcess.cpp
@@ -1,370 +1,370 @@
 #include "CepGen/Processes/GenericKTProcess.h"
 
 #include "CepGen/Core/Exception.h"
 #include "CepGen/Core/ParametersList.h"
 
 #include "CepGen/Event/Event.h"
 
 #include "CepGen/StructureFunctions/StructureFunctions.h"
 #include "CepGen/StructureFunctions/SigmaRatio.h"
 
 #include "CepGen/Physics/Constants.h"
 #include "CepGen/Physics/KTFlux.h"
 #include "CepGen/Physics/FormFactors.h"
 #include "CepGen/Physics/PDG.h"
 
 #include <iomanip>
 
 namespace CepGen
 {
-  namespace Process
+  namespace process
   {
     GenericKTProcess::GenericKTProcess( const ParametersList& params,
                                         const std::string& name,
                                         const std::string& description,
                                         const std::array<PDG,2>& partons,
                                         const std::vector<PDG>& central ) :
       GenericProcess( name, description+" (kT-factorisation approach)" ),
       num_dimensions_( 0 ), kt_jacobian_( 0. ),
       qt1_( 0. ), phi_qt1_( 0. ), qt2_( 0. ), phi_qt2_( 0. ),
       kIntermediateParts( partons ), kProducedParts( central )
     {}
 
     void
     GenericKTProcess::addEventContent()
     {
       GenericProcess::setEventContent(
         { // incoming state
           { Particle::IncomingBeam1, PDG::proton },
           { Particle::IncomingBeam2, PDG::proton },
           { Particle::Parton1, kIntermediateParts[0] },
           { Particle::Parton2, kIntermediateParts[1] }
         },
         { // outgoing state
           { Particle::OutgoingBeam1, { PDG::proton } },
           { Particle::OutgoingBeam2, { PDG::proton } },
           { Particle::CentralSystem, kProducedParts }
         }
       );
       setExtraContent();
     }
 
     unsigned int
     GenericKTProcess::numDimensions() const
     {
       return num_dimensions_;
     }
 
     void
     GenericKTProcess::setKinematics( const Kinematics& kin )
     {
       cuts_ = kin;
 
       const KTFlux flux1 = (KTFlux)cuts_.incoming_beams.first.kt_flux,
                    flux2 = (KTFlux)cuts_.incoming_beams.second.kt_flux;
 
       if ( cuts_.mode == KinematicsMode::invalid ) {
         bool el1 = ( flux1 == KTFlux::P_Photon_Elastic
                   || flux1 == KTFlux::HI_Photon_Elastic
                   || flux1 == KTFlux::P_Gluon_KMR );
         bool el2 = ( flux2 == KTFlux::P_Photon_Elastic
                   || flux2 == KTFlux::HI_Photon_Elastic
                   || flux2 == KTFlux::P_Gluon_KMR );
         if ( el1 && el2 )
           cuts_.mode = KinematicsMode::ElasticElastic;
         else if ( el1 )
           cuts_.mode = KinematicsMode::ElasticInelastic;
         else if ( el2 )
           cuts_.mode = KinematicsMode::InelasticElastic;
         else
           cuts_.mode = KinematicsMode::InelasticInelastic;
       }
       else {
         //==========================================================================================
         // ensure the first incoming flux is compatible with the kinematics mode
         //==========================================================================================
         if ( ( cuts_.mode == KinematicsMode::ElasticElastic
             || cuts_.mode == KinematicsMode::ElasticInelastic )
           && ( flux1 != KTFlux::P_Photon_Elastic ) ) {
           cuts_.incoming_beams.first.kt_flux = ( (HeavyIon)cuts_.incoming_beams.first.pdg )
             ? KTFlux::HI_Photon_Elastic
             : KTFlux::P_Photon_Elastic;
           CG_DEBUG( "GenericKTProcess:kinematics" )
             << "Set the kt flux for first incoming photon to \""
             << cuts_.incoming_beams.first.kt_flux << "\".";
         }
         else if ( flux1 != KTFlux::P_Photon_Inelastic
                && flux1 != KTFlux::P_Photon_Inelastic_Budnev ) {
           if ( (HeavyIon)cuts_.incoming_beams.first.pdg )
             throw CG_FATAL( "GenericKTProcess:kinematics" )
               << "Inelastic photon emission from HI not yet supported!";
           cuts_.incoming_beams.first.kt_flux = KTFlux::P_Photon_Inelastic_Budnev;
           CG_DEBUG( "GenericKTProcess:kinematics" )
             << "Set the kt flux for first incoming photon to \""
             << cuts_.incoming_beams.first.kt_flux << "\".";
         }
         //==========================================================================================
         // ensure the second incoming flux is compatible with the kinematics mode
         //==========================================================================================
         if ( ( cuts_.mode == KinematicsMode::ElasticElastic
             || cuts_.mode == KinematicsMode::InelasticElastic )
           && ( flux2 != KTFlux::P_Photon_Elastic ) ) {
           cuts_.incoming_beams.second.kt_flux = ( (HeavyIon)cuts_.incoming_beams.second.pdg )
             ? KTFlux::HI_Photon_Elastic
             : KTFlux::P_Photon_Elastic;
           CG_DEBUG( "GenericKTProcess:kinematics" )
             << "Set the kt flux for second incoming photon to \""
             << cuts_.incoming_beams.second.kt_flux << "\".";
         }
         else if ( flux2 != KTFlux::P_Photon_Inelastic
                && flux2 != KTFlux::P_Photon_Inelastic_Budnev ) {
           if ( (HeavyIon)cuts_.incoming_beams.second.pdg )
             throw CG_FATAL( "GenericKTProcess:kinematics" )
               << "Inelastic photon emission from HI not yet supported!";
           cuts_.incoming_beams.second.kt_flux = KTFlux::P_Photon_Inelastic_Budnev;
           CG_DEBUG( "GenericKTProcess:kinematics" )
             << "Set the kt flux for second incoming photon to \""
             << cuts_.incoming_beams.second.kt_flux << "\".";
         }
       }
 
       //============================================================================================
       // initialise the "constant" (wrt x) part of the Jacobian
       //============================================================================================
 
       kt_jacobian_ = 1.;
       num_dimensions_ = 0;
       mapped_variables_.clear();
 
       //============================================================================================
       // register the incoming partons' variables
       //============================================================================================
 
       registerVariable( qt1_, Mapping::logarithmic, cuts_.cuts.initial.qt, { 1.e-10, 500. }, "First incoming parton virtuality" );
       registerVariable( qt2_, Mapping::logarithmic, cuts_.cuts.initial.qt, { 1.e-10, 500. }, "Second incoming parton virtuality" );
       registerVariable( phi_qt1_, Mapping::linear, cuts_.cuts.initial.phi_qt, { 0., 2.*M_PI }, "First incoming parton azimuthal angle" );
       registerVariable( phi_qt2_, Mapping::linear, cuts_.cuts.initial.phi_qt, { 0., 2.*M_PI }, "Second incoming parton azimuthal angle" );
 
       //============================================================================================
       // register all process-dependent variables
       //============================================================================================
 
       preparePhaseSpace();
 
       //============================================================================================
       // register the outgoing remnants' variables
       //============================================================================================
 
       MX_ = MY_ = event_->getOneByRole( Particle::IncomingBeam1 ).mass();
       if ( cuts_.mode == KinematicsMode::InelasticElastic || cuts_.mode == KinematicsMode::InelasticInelastic )
         registerVariable( MX_, Mapping::square, cuts_.cuts.remnants.mass_single, { 1.07, 1000. }, "Positive z proton remnant mass" );
       if ( cuts_.mode == KinematicsMode::ElasticInelastic || cuts_.mode == KinematicsMode::InelasticInelastic )
         registerVariable( MY_, Mapping::square, cuts_.cuts.remnants.mass_single, { 1.07, 1000. }, "Negative z proton remnant mass" );
 
       prepareKinematics();
     }
 
     double
     GenericKTProcess::computeWeight()
     {
       if ( mapped_variables_.size() == 0 )
         throw CG_FATAL( "GenericKTProcess:weight" )
           << "No variables are mapped with this process!";
       if ( kt_jacobian_ == 0. )
         throw CG_FATAL( "GenericKTProcess:weight" )
           << "Point-independant component of the Jacobian for this "
           << "kt-factorised process is null.\n\t"
           << "Please check the validity of the phase space!";
 
       //============================================================================================
       // generate and initialise all variables, and auxiliary (x-dependent) part of the Jacobian
       // for this phase space point.
       //============================================================================================
 
       const double aux_jacobian = generateVariables();
       if ( aux_jacobian <= 0. )
         return 0.;
 
       //============================================================================================
       // compute the integrand and combine together into a single weight for the phase space point.
       //============================================================================================
 
       const double integrand = computeKTFactorisedMatrixElement();
       if ( integrand <= 0. )
         return 0.;
 
       const double weight = ( kt_jacobian_*aux_jacobian ) * integrand;
 
       CG_DEBUG_LOOP( "GenericKTProcess:weight" )
         << "Jacobian: " << kt_jacobian_ << " * " << aux_jacobian
         << " = " << ( kt_jacobian_*aux_jacobian ) << ".\n\t"
         << "Integrand = " << integrand << "\n\t"
         << "dW = " << weight << ".";
 
       return weight;
     }
 
     std::pair<double,double>
     GenericKTProcess::incomingFluxes( double x1, double q1t2, double x2, double q2t2 ) const
     {
       //--- compute fluxes according to modelling specified in parameters card
       std::pair<double,double> fluxes = {
         ktFlux( (KTFlux)cuts_.incoming_beams.first.kt_flux, x1, q1t2, *cuts_.structure_functions, MX_ ),
         ktFlux( (KTFlux)cuts_.incoming_beams.second.kt_flux, x2, q2t2, *cuts_.structure_functions, MY_ )
       };
 
       CG_DEBUG_LOOP( "GenericKTProcess:fluxes" )
         << "KT fluxes: " << fluxes.first << " / " << fluxes.second << ".";
       return fluxes;
     }
 
     void
     GenericKTProcess::registerVariable( double& out, const Mapping& type,
                                         const Limits& in, Limits default_limits,
                                         const char* description )
     {
       Limits lim = in;
       out = 0.; // reset the variable
       if ( !in.valid() ) {
         CG_DEBUG( "GenericKTProcess:registerVariable" )
           << description << " could not be retrieved from the user configuration!\n\t"
           << "Setting it to the default value: " << default_limits << ".";
         lim = default_limits;
       }
       if ( type == Mapping::logarithmic )
         lim = {
           std::max( log( lim.min() ), -10. ),
           std::min( log( lim.max() ), +10. )
         };
       mapped_variables_.emplace_back( MappingVariable{ description, lim, out, type, num_dimensions_++ } );
       switch ( type ) {
         case Mapping::square:
           kt_jacobian_ *= 2.*lim.range();
           break;
         default:
           kt_jacobian_ *= lim.range();
           break;
       }
       CG_DEBUG( "GenericKTProcess:registerVariable" )
         << description << " has been mapped to variable " << num_dimensions_ << ".\n\t"
         << "Allowed range for integration: " << lim << ".\n\t"
         << "Variable integration mode: " << type << ".";
     }
 
     void
     GenericKTProcess::dumpVariables() const
     {
       std::ostringstream os;
       for ( const auto& var : mapped_variables_ )
         os << "\n\t(" << var.index << ") " << var.type << " mapping (" << var.description << ") in range " << var.limits;
       CG_INFO( "GenericKTProcess:dumpVariables" )
         << "List of variables handled by this kt-factorised process:"
         << os.str();
     }
 
     double
     GenericKTProcess::generateVariables() const
     {
       double jacobian = 1.;
       for ( const auto& cut : mapped_variables_ ) {
         if ( !cut.limits.valid() )
           continue;
         const double xv = x( cut.index ); // between 0 and 1
         switch ( cut.type ) {
           case Mapping::linear: {
             cut.variable = cut.limits.x( xv );
           } break;
           case Mapping::logarithmic: {
             cut.variable = exp( cut.limits.x( xv ) );
             jacobian *= cut.variable;
           } break;
           case Mapping::square: {
             cut.variable = cut.limits.x( xv );
             jacobian *= cut.variable;
           } break;
         }
       }
       if ( CG_EXCEPT_MATCH( "KtProcess:vars", debugInsideLoop ) ) {
         std::ostringstream oss;
         for ( const auto& cut : mapped_variables_ ) {
           oss << "variable " << cut.index
               << " in range " << std::left << std::setw( 20 ) << cut.limits << std::right
               << " has value " << cut.variable << "\n\t";
         }
         CG_DEBUG_LOOP( "KtProcess:vars" ) << oss.str();
       }
       return jacobian;
     }
 
     void
     GenericKTProcess::fillKinematics( bool )
     {
       fillCentralParticlesKinematics(); // process-dependent!
       fillPrimaryParticlesKinematics();
     }
 
     void
     GenericKTProcess::fillPrimaryParticlesKinematics()
     {
       //============================================================================================
       //     outgoing protons
       //============================================================================================
 
       Particle& op1 = event_->getOneByRole( Particle::OutgoingBeam1 ),
                &op2 = event_->getOneByRole( Particle::OutgoingBeam2 );
 
       op1.setMomentum( PX_ );
       op2.setMomentum( PY_ );
 
       switch ( cuts_.mode ) {
         case KinematicsMode::ElasticElastic:
           op1.setStatus( Particle::Status::FinalState );
           op2.setStatus( Particle::Status::FinalState );
           break;
         case KinematicsMode::ElasticInelastic:
           op1.setStatus( Particle::Status::FinalState );
           op2.setStatus( Particle::Status::Unfragmented ); op2.setMass( MY_ );
           break;
         case KinematicsMode::InelasticElastic:
           op1.setStatus( Particle::Status::Unfragmented ); op1.setMass( MX_ );
           op2.setStatus( Particle::Status::FinalState );
           break;
         case KinematicsMode::InelasticInelastic:
           op1.setStatus( Particle::Status::Unfragmented ); op1.setMass( MX_ );
           op2.setStatus( Particle::Status::Unfragmented ); op2.setMass( MY_ );
           break;
         default: {
           throw CG_FATAL( "GenericKTProcess" )
             << "This kT factorisation process is intended for p-on-p collisions! Aborting.";
         } break;
       }
 
       //============================================================================================
       //     incoming partons (photons, pomerons, ...)
       //============================================================================================
 
       Particle& g1 = event_->getOneByRole( Particle::Parton1 );
       g1.setMomentum( event_->getOneByRole( Particle::IncomingBeam1 ).momentum()-PX_, true );
 
       Particle& g2 = event_->getOneByRole( Particle::Parton2 );
       g2.setMomentum( event_->getOneByRole( Particle::IncomingBeam2 ).momentum()-PY_, true );
 
       //============================================================================================
       //     two-parton system
       //============================================================================================
 
       event_->getOneByRole( Particle::Intermediate ).setMomentum( g1.momentum()+g2.momentum() );
     }
 
     std::ostream&
     operator<<( std::ostream& os, const GenericKTProcess::Mapping& type )
     {
       switch ( type ) {
         case GenericKTProcess::Mapping::linear: return os << "linear";
         case GenericKTProcess::Mapping::logarithmic: return os << "logarithmic";
         case GenericKTProcess::Mapping::square: return os << "squared";
       }
       return os;
     }
   }
 }
diff --git a/CepGen/Processes/GenericKTProcess.h b/CepGen/Processes/GenericKTProcess.h
index a1fd04c..2a99ddd 100644
--- a/CepGen/Processes/GenericKTProcess.h
+++ b/CepGen/Processes/GenericKTProcess.h
@@ -1,143 +1,142 @@
 #ifndef CepGen_Processes_GenericKTProcess_h
 #define CepGen_Processes_GenericKTProcess_h
 
 #include "GenericProcess.h"
 
 namespace CepGen
 {
   class ParametersList;
-  namespace Process
+  namespace process
   {
     /**
      * A generic kT-factorisation process.
      * \note
      * - First 4 dimensions of the phase space are required for the
      *    incoming partons' virtualities (radial and azimuthal coordinates).
      * - Last 0-2 dimensions may be used for the scattered diffractive
      *    system(s)' invariant mass definition.
      * \brief Class template to define any kT-factorisation process
      * \author Laurent Forthomme <laurent.forthomme@cern.ch>
      * \date Apr 2016
      */
     class GenericKTProcess : public GenericProcess
     {
       public:
         /// Class constructor
         /// \param[in] params Parameters list
         /// \param[in] name Generic process name
         /// \param[in] description Human-readable kT-factorised process name
         /// \param[in] partons First and second incoming parton
         /// \param[in] output Produced final state particles
         GenericKTProcess( const ParametersList& params,
                           const std::string& name,
                           const std::string& description,
                           const std::array<PDG,2>& partons,
                           const std::vector<PDG>& output );
 
         /// Populate the event content with the generated process' topology
         void addEventContent() override;
         /// Retrieve the total number of dimensions on which the integration is being performet
         unsigned int numDimensions() const override;
         /// Retrieve the event weight in the phase space
         double computeWeight() override;
         /// Populate the event content with the generated process' kinematics
         void fillKinematics( bool ) override;
         /// List all variables handled by this generic process
         void dumpVariables() const;
 
       protected:
         /// Set the kinematics associated to the phase space definition
         void setKinematics( const Kinematics& kin ) override;
         /// Set the kinematics of the central system before any point computation
         virtual void setExtraContent() {}
         /// Prepare the central part of the Jacobian (only done once, as soon as the kinematics is set)
         virtual void preparePhaseSpace() = 0;
         /// kT-factorised matrix element (event weight)
         /// \return Weight of the point in the phase space to the integral
         virtual double computeKTFactorisedMatrixElement() = 0;
         /// Compute the unintegrated photon fluxes (for inelastic distributions, interpolation on double logarithmic grid)
         std::pair<double,double> incomingFluxes( double, double, double, double ) const;
         /// Set the kinematics of the incoming and outgoing protons (or remnants)
         void fillPrimaryParticlesKinematics();
         /// Set the kinematics of the outgoing central system
         virtual void fillCentralParticlesKinematics() = 0;
 
         /// Type of mapping to apply on the variable
         enum class Mapping
         {
           /// a linear \f${\rm d}x\f$ mapping
           linear = 0,
           /// a logarithmic \f$\frac{{\rm d}x}{x} = {\rm d}(\log x)\f$ mapping
           logarithmic,
           /// a square \f${\rm d}x^2=2x\cdot{\rm d}x\f$ mapping
           square
         };
         friend std::ostream& operator<<( std::ostream&, const Mapping& );
         /// Register a variable to be handled and populated whenever
         ///  a new phase space point weight is to be calculated.
         /// \note To be run once per generation (before any point computation)
         /// \param[out] out Reference to the variable to be mapped
         /// \param[in] type Type of mapping to apply
         /// \param[in] in Integration limits
         /// \param[in] default_limits Limits to apply if none retrieved from the user configuration
         /// \param[in] description Human-readable description of the variable
         void registerVariable( double& out, const Mapping& type, const Limits& in, Limits default_limits, const char* description );
         /// Generate and initialise all variables handled by this process
         /// \return Phase space point-dependent component of the Jacobian weight of the point in the phase space for integration
         /// \note To be run at each point computation (therefore, to be optimised!)
         double generateVariables() const;
         /// Number of dimensions on which to perform the integration
         unsigned short num_dimensions_;
 
         /// Phase space point-independant component of the Jacobian weight of the point in the phase space for integration
         double kt_jacobian_;
 
         /// Log-virtuality range of the intermediate parton
         Limits log_qt_limits_;
         /// Intermediate azimuthal angle range
         Limits phi_qt_limits_;
         /// Invariant mass range for the scattered excited system
         Limits mx_limits_;
 
         /// Virtuality of the first intermediate parton (photon, pomeron, ...)
         double qt1_;
         /// Azimuthal rotation of the first intermediate parton's transverse virtuality
         double phi_qt1_;
         /// Virtuality of the second intermediate parton (photon, pomeron, ...)
         double qt2_;
         /// Azimuthal rotation of the second intermediate parton's transverse virtuality
         double phi_qt2_;
 
         /// First outgoing proton
         Particle::Momentum PX_;
         /// Second outgoing proton
         Particle::Momentum PY_;
 
         /// Handler to a variable mapped by this process
         struct MappingVariable
         {
           /// Human-readable description of the variable
           std::string description;
           /// Kinematic limits to apply on the variable
           Limits limits;
           /// Reference to the process variable to generate/map
           double& variable;
           /// Interpolation type
           Mapping type;
           /// Corresponding integration variable
           unsigned short index;
         };
         /// Collection of variables to be mapped at the weight generation stage
         std::vector<MappingVariable> mapped_variables_;
 
       private:
         /// First and second intermediate parton (photon, pomeron, ...)
         std::array<PDG,2> kIntermediateParts;
         /// Type of particles produced in the final state
         std::vector<PDG> kProducedParts;
     };
   }
 }
 
 #endif
-
diff --git a/CepGen/Processes/GenericProcess.cpp b/CepGen/Processes/GenericProcess.cpp
index 84fe7c4..7f3f719 100644
--- a/CepGen/Processes/GenericProcess.cpp
+++ b/CepGen/Processes/GenericProcess.cpp
@@ -1,228 +1,228 @@
 #include "CepGen/Processes/GenericProcess.h"
 
 #include "CepGen/Core/Exception.h"
 
 #include "CepGen/Event/Event.h"
 
 #include "CepGen/Physics/ParticleProperties.h"
 #include "CepGen/Physics/Constants.h"
 #include "CepGen/Physics/FormFactors.h"
 #include "CepGen/Physics/PDG.h"
 
 namespace CepGen
 {
-  namespace Process
+  namespace process
   {
     const double GenericProcess::mp_ = ParticleProperties::mass( PDG::proton );
     const double GenericProcess::mp2_ = GenericProcess::mp_*GenericProcess::mp_;
 
     GenericProcess::GenericProcess( const std::string& name, const std::string& description, bool has_event ) :
       name_( name ), description_( description ),
       first_run( true ),
       s_( -1. ), sqs_( -1. ),
       MX_( -1. ), MY_( -1. ), w1_( -1. ), w2_( -1. ),
       t1_( -1. ), t2_( -1. ),
       has_event_( has_event ), event_( new Event ),
       is_point_set_( false )
     {}
 
     GenericProcess::GenericProcess( const GenericProcess& proc ) :
       name_( proc.name_ ), description_( proc.description_ ),
       first_run( proc.first_run ),
       s_( proc.s_ ), sqs_( proc.sqs_ ),
       MX_( proc.MX_ ), MY_( proc.MY_ ), w1_( proc.w1_ ), w2_( proc.w2_ ),
       t1_( -1. ), t2_( -1. ), cuts_( proc.cuts_ ),
       has_event_( proc.has_event_ ), event_( new Event( *proc.event_.get() ) ),
       is_point_set_( false )
     {}
 
     GenericProcess&
     GenericProcess::operator=( const GenericProcess& proc )
     {
       name_ = proc.name_; description_ = proc.description_;
       first_run = proc.first_run;
       s_ = proc.s_; sqs_ = proc.sqs_;
       MX_ = proc.MX_; MY_ = proc.MY_; w1_ = proc.w1_; w2_ = proc.w2_;
       cuts_ = proc.cuts_;
       has_event_ = proc.has_event_; event_.reset( new Event( *proc.event_.get() ) );
       is_point_set_ = false;
       return *this;
     }
 
     void
     GenericProcess::setPoint( const unsigned int ndim, double* x )
     {
       x_ = std::vector<double>( x, x+ndim );
       is_point_set_ = true;
 
       if ( CG_EXCEPT_MATCH( "Process:dumpPoint", debugInsideLoop ) )
         dumpPoint();
     }
 
     double
     GenericProcess::x( unsigned int idx ) const
     {
       if ( idx >= x_.size() )
         return -1.;
       return x_[idx];
     }
 
     void
     GenericProcess::clearEvent()
     {
       event_->restore();
     }
 
     void
     GenericProcess::setKinematics( const Kinematics& cuts )
     {
       cuts_ = cuts;
       prepareKinematics();
     }
 
     void
     GenericProcess::prepareKinematics()
     {
       if ( !isKinematicsDefined() )
         throw CG_FATAL( "GenericProcess" ) << "Kinematics not properly defined for the process.";
 
       // at some point introduce non head-on colliding beams?
       Particle::Momentum p1( 0., 0.,  cuts_.incoming_beams.first.pz ), p2( 0., 0., -cuts_.incoming_beams.second.pz );
       // on-shell beam particles
       p1.setMass( ParticleProperties::mass( cuts_.incoming_beams.first.pdg ) );
       p2.setMass( ParticleProperties::mass( cuts_.incoming_beams.second.pdg ) );
       setIncomingKinematics( p1, p2 );
 
       sqs_ = CMEnergy( p1, p2 );
       s_ = sqs_*sqs_;
 
       w1_ = p1.mass2();
       w2_ = p2.mass2();
 
       CG_DEBUG( "GenericProcess" ) << "Kinematics successfully prepared! sqrt(s) = " << sqs_ << ".";
     }
 
     void
     GenericProcess::dumpPoint() const
     {
       std::ostringstream os;
       for ( unsigned short i = 0; i < x_.size(); ++i ) {
         os << Form( "  x(%2d) = %8.6f\n\t", i, x_[i] );
       }
       CG_INFO( "GenericProcess" )
         << "Number of integration parameters: " << x_.size() << "\n\t"
         << os.str() << ".";
     }
 
     void
     GenericProcess::setEventContent( const IncomingState& ini, const OutgoingState& fin )
     {
       if ( !has_event_ )
         return;
 
       event_->clear();
       //----- add the particles in the event
 
       //--- incoming state
       for ( const auto& ip : ini ) {
         Particle& p = event_->addParticle( ip.first );
         p.setPdgId( ip.second, ParticleProperties::charge( ip.second ) );
         p.setMass( ParticleProperties::mass( ip.second ) );
         if ( ip.first == Particle::IncomingBeam1
           || ip.first == Particle::IncomingBeam2 )
           p.setStatus( Particle::Status::PrimordialIncoming );
         if ( ip.first == Particle::Parton1
           || ip.first == Particle::Parton2 )
           p.setStatus( Particle::Status::Incoming );
       }
       //--- central system (if not already there)
       const auto& central_system = ini.find( Particle::CentralSystem );
       if ( central_system == ini.end() ) {
         Particle& p = event_->addParticle( Particle::Intermediate );
         p.setPdgId( PDG::invalid );
         p.setStatus( Particle::Status::Propagator );
       }
       //--- outgoing state
       for ( const auto& opl : fin ) { // pair(role, list of PDGids)
         for ( const auto& pdg : opl.second ) {
           Particle& p = event_->addParticle( opl.first );
           p.setPdgId( pdg, ParticleProperties::charge( pdg ) );
           p.setMass( ParticleProperties::mass( pdg ) );
         }
       }
 
       //----- define the particles parentage
 
       const Particles parts = event_->particles();
       for ( const auto& p : parts ) {
         Particle& part = event_->operator[]( p.id() );
         switch ( part.role() ) {
           case Particle::OutgoingBeam1:
           case Particle::Parton1:
             part.addMother( event_->getOneByRole( Particle::IncomingBeam1 ) );
             break;
           case Particle::OutgoingBeam2:
           case Particle::Parton2:
             part.addMother( event_->getOneByRole( Particle::IncomingBeam2 ) );
             break;
           case Particle::Intermediate:
             part.addMother( event_->getOneByRole( Particle::Parton1 ) );
             part.addMother( event_->getOneByRole( Particle::Parton2 ) );
             break;
           case Particle::CentralSystem:
             part.addMother( event_->getOneByRole( Particle::Intermediate ) );
             break;
           default: break;
         }
       }
 
       //----- freeze the event as it is
 
       event_->freeze();
       last_event = event_;
     }
 
     void
     GenericProcess::setIncomingKinematics( const Particle::Momentum& p1, const Particle::Momentum& p2 )
     {
       if ( !has_event_ )
         return;
 
       event_->getOneByRole( Particle::IncomingBeam1 ).setMomentum( p1 );
       event_->getOneByRole( Particle::IncomingBeam2 ).setMomentum( p2 );
     }
 
     bool
     GenericProcess::isKinematicsDefined()
     {
       if ( !has_event_ )
         return true;
 
       // check the incoming state
       bool is_incoming_state_set =
         ( !event_->getByRole( Particle::IncomingBeam1 ).empty()
        && !event_->getByRole( Particle::IncomingBeam2 ).empty() );
 
       // check the outgoing state
       bool is_outgoing_state_set =
         ( !event_->getByRole( Particle::OutgoingBeam1 ).empty()
        && !event_->getByRole( Particle::OutgoingBeam2 ).empty()
        && !event_->getByRole( Particle::CentralSystem ).empty() );
 
       // combine both states
       return is_incoming_state_set && is_outgoing_state_set;
     }
 
     std::ostream&
     operator<<( std::ostream& os, const GenericProcess& proc )
     {
       return os << proc.name().c_str();
     }
 
     std::ostream&
     operator<<( std::ostream& os, const GenericProcess* proc )
     {
       return os << proc->name().c_str();
     }
   }
 }
diff --git a/CepGen/Processes/GenericProcess.h b/CepGen/Processes/GenericProcess.h
index 34936b3..135cf14 100644
--- a/CepGen/Processes/GenericProcess.h
+++ b/CepGen/Processes/GenericProcess.h
@@ -1,167 +1,167 @@
 #ifndef CepGen_Processes_GenericProcess_h
 #define CepGen_Processes_GenericProcess_h
 
 #include "CepGen/Event/Particle.h"
 #include "CepGen/Physics/Kinematics.h"
 
 #include <vector>
 #include <memory>
 
 namespace CepGen
 {
   class Event;
   class FormFactors;
   class ParametersList;
   /// Location for all physics processes to be generated
-  namespace Process
+  namespace process
   {
     /// \brief Class template to define any process to compute using this MC integrator/events generator
     /// \author Laurent Forthomme <laurent.forthomme@cern.ch>
     /// \date Jan 2014
     class GenericProcess
     {
       public:
         /// Default constructor for an undefined process
         /// \param[in] name Process name
         /// \param[in] description Human-readable description of the process
         /// \param[in] has_event Do we generate the associated event structure?
         GenericProcess( const std::string& name, const std::string& description = "<invalid process>", bool has_event = true );
         /// Copy constructor for a user process
         GenericProcess( const GenericProcess& );
         virtual ~GenericProcess() = default;
 
         /// Assignment operator
         GenericProcess& operator=( const GenericProcess& );
 
         /// Human-readable format dump of a GenericProcess object
         friend std::ostream& operator<<( std::ostream& os, const GenericProcess& proc );
         /// Human-readable format dump of a pointer to a GenericProcess object
         friend std::ostream& operator<<( std::ostream& os, const GenericProcess* proc );
 
         /// Generic map of particles with their role in the process
         typedef std::map<Particle::Role,PDG> ParticlesRoleMap;
         /// Pair of particle with their associated role in the process
         typedef std::pair<Particle::Role,PDG> ParticleWithRole;
         /// Map of all incoming state particles in the process
         typedef ParticlesRoleMap IncomingState;
         /// Map of all outgoing particles in the process
         typedef std::map<Particle::Role,std::vector<PDG> > OutgoingState;
 
         /// Copy all process attributes into a new object
         virtual std::unique_ptr<GenericProcess> clone( const ParametersList& ) const = 0;
 
         /// Restore the Event object to its initial state
         void clearEvent();
         /// Set the kinematics of the incoming state particles
         void setIncomingKinematics( const Particle::Momentum& p1, const Particle::Momentum& p2 );
         /// Compute the incoming state kinematics
         void prepareKinematics();
 
       public:
         /// Set the incoming and outgoing state to be expected in the process
         inline virtual void addEventContent() {}
         /// Set the list of kinematic cuts to apply on the outgoing particles' final state
         /// \param[in] cuts The Cuts object containing the kinematic parameters
         virtual void setKinematics( const Kinematics& cuts );
         /// Return the number of dimensions on which the integration has to be performed
         /// \return Number of dimensions on which to integrate
         virtual unsigned int numDimensions() const = 0;
 
         /// Prepare the process for its integration over the whole phase space
         inline virtual void beforeComputeWeight() {}
         /// Compute the weight for this point in the phase-space
         virtual double computeWeight() = 0;
         /// Fill the Event object with the particles' kinematics
         /// \param[in] symmetrise Symmetrise the event? (randomise the production of positively- and negatively-charged outgoing central particles)
         virtual void fillKinematics( bool symmetrise = false ) = 0;
 
       public:
         /**
          * Sets the phase space point to compute the weight associated to it.
          * \brief Sets the phase space point to compute
          * \param[in] ndim The number of dimensions of the point in the phase space
          * \param[in] x[] The (\a ndim_)-dimensional point in the phase space on which the kinematics and the cross-section are computed
          */
         void setPoint( const unsigned int ndim, double* x );
         /// Dump the evaluated point's coordinates in the standard output stream
         void dumpPoint() const;
         /// Complete list of Particle with their role in the process for the point considered in the phase space, returned as an Event object.
         /// \return Event object containing all the generated Particle objects
         inline std::shared_ptr<Event> event() const { return event_; }
 
         ///Get the number of dimensions on which the integration is performed
         inline const unsigned int ndim() const { return x_.size(); }
         /// Get the value of a component of the d-dimensional point considered
         double x( unsigned int idx ) const;
         /// Name of the process considered
         inline const std::string& name() const { return name_; }
         /// Human-readable description of the process
         inline const std::string& description() const { return description_; }
 
         /// Does the process contain (and hold) an event?
         bool hasEvent() const { return has_event_; }
         /// Pointer to the last event produced in this run
         std::shared_ptr<Event> last_event;
 
       protected:
         static const double mp_; ///< Proton mass, in GeV/c\f${}^2\f$
         static const double mp2_; ///< Squared proton mass, in GeV\f${}^2\f$/c\f${}^4\f$
 
         /// Set the incoming and outgoing states to be defined in this process (and prepare the Event object accordingly)
         void setEventContent( const IncomingState& ini, const OutgoingState& fin );
 
         // ---
 
         /// Name of the process
         std::string name_;
         /// Process human-readable description
         std::string description_;
 
       public:
         /// Is it the first time the process is computed?
         bool first_run;
 
       protected:
         /// Array of double precision floats representing the point on which the weight in the cross-section is computed
         std::vector<double> x_;
         /// \f$s\f$, squared centre of mass energy of the incoming particles' system, in \f$\mathrm{GeV}^2\f$
         double s_;
         /// \f$\sqrt s\f$, centre of mass energy of the incoming particles' system (in GeV)
         double sqs_;
         /// Invariant mass of the first proton-like outgoing particle (or remnant)
         double MX_;
         /// Invariant mass of the second proton-like outgoing particle (or remnant)
         double MY_;
         /// \f$m_1^2\f$, squared mass of the first proton-like incoming particle
         double w1_;
         /// \f$m_2^2\f$, squared mass of the second proton-like incoming particle
         double w2_;
         /// Virtuality of the first incoming photon
         double t1_;
         /// Virtuality of the second incoming photon
         double t2_;
 
         /// Set of cuts to apply on the final phase space
         Kinematics cuts_;
         /// Does the process contain (and hold) an event?
         bool has_event_;
         /// Event object containing all the information on the in- and outgoing particles
         std::shared_ptr<Event> event_;
         /// Is the phase space point set?
         bool is_point_set_;
 
       private:
         /**
          * Is the system's kinematics well defined and compatible with the process ?
          * This check is mandatory to perform the d-dimensional point's cross-section computation.
          * \brief Is the system's kinematics well defined?
          * \return A boolean stating if the input kinematics and the final states are well-defined
          */
         bool isKinematicsDefined();
     };
   }
   /// Helper typedef for a Process unique pointer
-  typedef std::unique_ptr<Process::GenericProcess> ProcessPtr;
+  typedef std::unique_ptr<process::GenericProcess> ProcessPtr;
 }
 
 #endif
diff --git a/CepGen/Processes/PPtoFF.cpp b/CepGen/Processes/PPtoFF.cpp
index f876e49..ab21577 100644
--- a/CepGen/Processes/PPtoFF.cpp
+++ b/CepGen/Processes/PPtoFF.cpp
@@ -1,379 +1,378 @@
 #include "CepGen/Processes/PPtoFF.h"
 
 #include "CepGen/Event/Event.h"
 
 #include "CepGen/Physics/Constants.h"
 #include "CepGen/Physics/FormFactors.h"
 #include "CepGen/Physics/PDG.h"
 
 #include "CepGen/Core/Exception.h"
 #include <iomanip>
 
 #include "CepGen/Processes/ProcessesHandler.h"
 
 namespace CepGen
 {
-  namespace Process
+  namespace process
   {
     PPtoFF::PPtoFF( const ParametersList& params ) :
       GenericKTProcess( params, "pptoff", "ɣɣ → f⁺f¯", { { PDG::photon, PDG::photon } }, { PDG::muon, PDG::muon } ),
       pair_( params.get<int>( "pair", 0 ) ),
       method_( params.get<int>( "method", 1 ) ),
       y1_( 0. ), y2_( 0. ), pt_diff_( 0. ), phi_pt_diff_( 0. )
     {}
 
     void
     PPtoFF::preparePhaseSpace()
     {
       registerVariable( y1_, Mapping::linear, cuts_.cuts.central.rapidity_single, { -6., 6. }, "First outgoing fermion rapidity" );
       registerVariable( y2_, Mapping::linear, cuts_.cuts.central.rapidity_single, { -6., 6. }, "Second outgoing fermion rapidity" );
       registerVariable( pt_diff_, Mapping::linear, cuts_.cuts.central.pt_diff, { 0., 50. }, "Fermions transverse momentum difference" );
       registerVariable( phi_pt_diff_, Mapping::linear, cuts_.cuts.central.phi_pt_diff, { 0., 2.*M_PI }, "Fermions azimuthal angle difference" );
 
       if ( (PDG)pair_ == PDG::invalid )
         throw CG_FATAL( "PPtoFF:prepare" )
           << "Invalid fermion pair selected: " << pair_ << "!";
 
       const PDG pdg_f = (PDG)pair_;
       mf_ = ParticleProperties::mass( pdg_f );
       mf2_ = mf_*mf_;
       qf_ = ParticleProperties::charge( pdg_f );
       colf_ = ParticleProperties::colours( pdg_f );
       CG_DEBUG( "PPtoFF:prepare" )
         << "Produced particles (" << pdg_f << ") "
         << "with mass = " << mf_ << " GeV, "
         << "and charge = " << std::setprecision( 2 ) << qf_ << " e";
       CG_DEBUG( "PPtoFF:mode" )
         << "matrix element computation method: " << method_ << ".";
     }
 
     double
     PPtoFF::computeKTFactorisedMatrixElement()
     {
       //=================================================================
       //     matrix element computation
       //=================================================================
 
       //--- central partons
       const Particle::Momentum q1t( qt1_*cos( phi_qt1_ ), qt1_*sin( phi_qt1_ ), 0. );
       const Particle::Momentum q2t( qt2_*cos( phi_qt2_ ), qt2_*sin( phi_qt2_ ), 0. );
 
       CG_DEBUG_LOOP( "PPtoFF" ) << "q(1/2)t = " << q1t << ", " << q2t << ".";
 
       //--- two-parton system
       const Particle::Momentum ptsum = q1t+q2t;
       const Particle::Momentum ptdiff( pt_diff_*cos( phi_pt_diff_ ), pt_diff_*sin( phi_pt_diff_ ), 0. );
 
       //--- outgoing fermions
       const Particle::Momentum p1_cm = 0.5*( ptsum+ptdiff ), p2_cm = 0.5*( ptsum-ptdiff );
 
       //=================================================================
       //     a window in single particle transverse momentum
       //=================================================================
 
       const Limits& pt_limits = cuts_.cuts.central.pt_single;
       if ( !pt_limits.passes( p1_cm.pt() ) || !pt_limits.passes( p2_cm.pt() ) )
         return 0.;
 
       //=================================================================
       //     a window in transverse momentum difference
       //=================================================================
 
       if ( !cuts_.cuts.central.pt_diff.passes( fabs( p1_cm.pt()-p2_cm.pt() ) ) )
         return 0.;
 
       //=================================================================
       //     a window in rapidity distance
       //=================================================================
 
       if ( !cuts_.cuts.central.rapidity_diff.passes( fabs( y1_-y2_ ) ) )
         return 0.;
 
       //=================================================================
       //     auxiliary quantities
       //=================================================================
 
       // transverse mass for the two fermions
       const double amt1 = std::hypot( p1_cm.pt(), mf_ ), amt2 = std::hypot( p2_cm.pt(), mf_ );
       const double alpha1 = amt1/sqs_*exp( y1_ ), beta1  = amt1/sqs_*exp( -y1_ ),
                    alpha2 = amt2/sqs_*exp( y2_ ), beta2  = amt2/sqs_*exp( -y2_ );
 
       CG_DEBUG_LOOP( "PPtoFF" )
         << "Sudakov parameters:\n\t"
         << "  alpha(1/2) = " << alpha1 << ", " << alpha2 << "\n\t"
         << "   beta(1/2) = " << beta1 << ", " << beta2 << ".";
 
       const double x1 = alpha1+alpha2, x2 = beta1+beta2;
       if ( x1 <= 0. || x1 > 1. || x2 <= 0. || x2 > 1. )
         return 0.; // sanity check
 
       //=================================================================
       //     additional conditions for energy-momentum conservation
       //=================================================================
 
       const double s1_eff = x1*s_-qt1_*qt1_, s2_eff = x2*s_-qt2_*qt2_;
       const double invm = sqrt( amt1*amt1 + amt2*amt2 + 2.*amt1*amt2*cosh(y1_-y2_) - ptsum.pt2() );
       CG_DEBUG_LOOP( "PPtoFF" )
         << "s(1/2)eff = " << s1_eff << ", " << s2_eff << " GeV²\n\t"
         << "central system's invariant mass = " << invm << " GeV.";
 
       if ( ( cuts_.mode == KinematicsMode::ElasticInelastic
           || cuts_.mode == KinematicsMode::InelasticInelastic )
         && ( sqrt( s1_eff ) <= ( MY_+invm ) ) )
         return 0.;
       if ( ( cuts_.mode == KinematicsMode::InelasticElastic
           || cuts_.mode == KinematicsMode::InelasticInelastic )
         && ( sqrt( s2_eff ) <= ( MX_+invm ) ) )
         return 0.;
 
       //=================================================================
       //     four-momenta of the outgoing protons (or remnants)
       //=================================================================
 
       const Particle::Momentum& ak1 = event_->getOneByRole( Particle::IncomingBeam1 ).momentum(),
                                &ak2 = event_->getOneByRole( Particle::IncomingBeam2 ).momentum();
       CG_DEBUG_LOOP( "PPtoFF" )
         << "incoming particles: p(1/2) = " << ak1 << ", " << ak2 << ".";
 
       const double px_plus  = ( 1.-x1 )*M_SQRT2*ak1.p(),
                    px_minus = ( MX_*MX_ + q1t.pt2() )*0.5/px_plus;
 
       const double py_minus = ( 1.-x2 )*M_SQRT2*ak2.p(),
                    py_plus  = ( MY_*MY_ + q2t.pt2() )*0.5/py_minus;
 
       CG_DEBUG_LOOP( "PPtoFF" )
         << "px± = " << px_plus << ", " << px_minus << "\n\t"
         << "py± = " << py_plus << ", " << py_minus << ".";
 
       PX_ = Particle::Momentum( -q1t.px(), -q1t.py(), ( px_plus-px_minus )*M_SQRT1_2, ( px_plus+px_minus )*M_SQRT1_2 );
       PY_ = Particle::Momentum( -q2t.px(), -q2t.py(), ( py_plus-py_minus )*M_SQRT1_2, ( py_plus+py_minus )*M_SQRT1_2 );
 
       CG_DEBUG_LOOP( "PPtoFF" )
         << "First remnant:  " << PX_ << ", mass = " << PX_.mass() << "\n\t"
         << "Second remnant: " << PY_ << ", mass = " << PY_.mass() << ".";
 
       if ( fabs( PX_.mass()-MX_ ) > 1.e-6 )
         throw CG_FATAL( "PPtoFF" ) << "Invalid X system mass: " << PX_.mass() << "/" << MX_ << ".";
       if ( fabs( PY_.mass()-MY_ ) > 1.e-6 )
         throw CG_FATAL( "PPtoFF" ) << "Invalid Y system mass: " << PY_.mass() << "/" << MY_ << ".";
 
       //=================================================================
       //     four-momenta of the outgoing l^+ and l^-
       //=================================================================
 
       const Particle::Momentum p1 = p1_cm + alpha1*ak1 + beta1*ak2;
       const Particle::Momentum p2 = p2_cm + alpha2*ak1 + beta2*ak2;
       CG_DEBUG_LOOP( "PPtoFF" )
         << "unboosted first fermion:  " << p1 << ", mass = " << p1.mass() << "\n\t"
         << "          second fermion: " << p2 << ", mass = " << p2.mass() << ".";
 
       p_f1_ = Particle::Momentum::fromPxPyYM( p1_cm.px(), p1_cm.py(), y2_, mf_ );
       p_f2_ = Particle::Momentum::fromPxPyYM( p2_cm.px(), p2_cm.py(), y1_, mf_ );
 
       CG_DEBUG_LOOP( "PPtoFF" )
         << "First fermion:  " << p_f1_ << ", mass = " << p_f1_.mass() << "\n\t"
         << "Second fermion: " << p_f2_ << ", mass = " << p_f2_.mass() << ".";
 
       if ( fabs( p_f1_.mass()-mf_ ) > 1.e-4 )
         throw CG_FATAL( "PPtoFF" ) << "Invalid fermion 1 mass: " << p_f1_.mass() << "/" << mf_ << ".";
       if ( fabs( p_f2_.mass()-mf_ ) > 1.e-4 )
         throw CG_FATAL( "PPtoFF" ) << "Invalid fermion 2 mass: " << p_f2_.mass() << "/" << mf_ << ".";
 
       //=================================================================
       //     matrix elements
       //=================================================================
       double amat2 = 0.;
 
       //=================================================================
       //     How matrix element is calculated
       //=================================================================
 
       if ( method_ == 0 ) {
         //===============================================================
         //     Mendelstam variables
         //===============================================================
 
         //const double shat = s_*x1*x2; // approximation
         const double shat = ( q1t+q2t ).mass2(); // exact formula
         //const double mll = sqrt( shat );
         const double that1 = ( q1t-p1 ).mass2(), that2 = ( q2t-p2 ).mass2();
         const double uhat1 = ( q1t-p2 ).mass2(), uhat2 = ( q2t-p1 ).mass2();
         const double that = 0.5*( that1+that2 ), uhat = 0.5*( uhat1+uhat2 );
 
         amat2 = onShellME( shat, that, uhat );
 
         CG_DEBUG_LOOP( "PPtoFF:onShell" )
           << "that(1/2) = " << that1 << " / " << that2 << "\n\t"
           << "uhat(1/2) = " << uhat1 << " / " << uhat2 << "\n\t"
           << "squared matrix element: " << amat2 << ".";
       }
 
       else if ( method_ == 1 ) {
         const double t1abs = ( q1t.pt2() + x1*( MX_*MX_-mp2_ )+x1*x1*mp2_ )/( 1.-x1 ),
                      t2abs = ( q2t.pt2() + x2*( MY_*MY_-mp2_ )+x2*x2*mp2_ )/( 1.-x2 );
         const double z1p = alpha1/x1, z1m = alpha2/x1,
                      z2p = beta1 /x2, z2m = beta2 /x2;
         CG_DEBUG_LOOP( "PPtoFF:offShell" )
           << "z(1/2)p = " << z1p << ", " << z2p << "\n\t"
           << "z(1/2)m = " << z1m << ", " << z2m << ".";
         amat2 = offShellME( t1abs, t2abs, z1m, z1p, z2m, z2p, q1t, q2t ) * pow( x1*x2*s_, 2 );
       }
 
       //============================================
       //     unintegrated photon distributions
       //============================================
 
       const std::pair<double,double> fluxes
         = GenericKTProcess::incomingFluxes( x1, q1t.pt2(), x2, q2t.pt2() );
 
       CG_DEBUG_LOOP( "PPtoFF" )
         << "Incoming photon fluxes for (x/kt2) = "
         << "(" << x1 << "/" << q1t.pt2() << "), "
         << "(" << x2 << "/" << q2t.pt2() << "):\n\t"
         << fluxes.first << ", " << fluxes.second << ".";
 
       //=================================================================
       //     factor 2.*pi from integration over phi_sum
       //     factor 1/4 from jacobian of transformations
       //     factors 1/pi and 1/pi due to integration over
       //       d^2 kappa_1 d^2 kappa_2 instead d kappa_1^2 d kappa_2^2
       //=================================================================
 
       const double g_em = 4.*M_PI*Constants::alphaEM*qf_*qf_;
       const double aintegral = amat2 * colf_ * ( g_em*g_em )
                              * 1. / pow( 4.*M_PI*( x1*x2*s_ ), 2 )
                              * fluxes.first*M_1_PI * fluxes.second*M_1_PI * 0.25
                              * Constants::GeV2toBarn;
 
       //=================================================================
       return aintegral*qt1_*qt2_*pt_diff_;
       //=================================================================
     }
 
     void
     PPtoFF::fillCentralParticlesKinematics()
     {
       // randomise the charge of the outgoing fermions
       short sign = ( drand() > 0.5 ) ? +1 : -1;
 
       //=================================================================
       //     first outgoing fermion
       //=================================================================
       Particle& of1 = event_->getByRole( Particle::CentralSystem )[0];
       of1.setPdgId( of1.pdgId(), sign );
       of1.setStatus( Particle::Status::FinalState );
       of1.setMomentum( p_f1_ );
 
       //=================================================================
       //     second outgoing fermion
       //=================================================================
       Particle& of2 = event_->getByRole( Particle::CentralSystem )[1];
       of2.setPdgId( of2.pdgId(), -sign );
       of2.setStatus( Particle::Status::FinalState );
       of2.setMomentum( p_f2_ );
     }
 
     double
     PPtoFF::onShellME( double shat, double that, double uhat ) const
     {
       CG_DEBUG_LOOP( "PPtoFF:onShell" )
         << "shat: " << shat << ", that: " << that << ", uhat: " << uhat << ".";
 
       //=================================================================
       //     on-shell formula for M^2
       //=================================================================
       const double ml4 = mf2_*mf2_, ml8 = ml4*ml4;
 
       const double term1  =  6. *ml8,
                    term2  = -3. *ml4 *that*that,
                    term3  = -14.*ml4 *that*uhat,
                    term4  = -3. *ml4 *uhat*uhat,
                    term5  =      mf2_*that*that*that,
                    term6  =  7.* mf2_*that*that*uhat,
                    term7  =  7.* mf2_*that*uhat*uhat,
                    term8  =      mf2_*uhat*uhat*uhat,
                    term9  =          -that*that*that*uhat,
                    term10 =          -that*uhat*uhat*uhat;
 
       return -2.*( term1+term2+term3+term4+term5
                   +term6+term7+term8+term9+term10 )/( pow( ( mf2_-that )*( mf2_-uhat ), 2) );
     }
 
     double
     PPtoFF::offShellME( double t1abs, double t2abs, double z1m, double z1p, double z2m, double z2p, const Particle::Momentum& q1, const Particle::Momentum& q2 ) const
     {
       //=================================================================
       //     Wolfgang's formulae
       //=================================================================
 
       const double z1 = z1p*z1m, z2 = z2p*z2m;
       const double eps12 = mf2_+z1*t1abs, eps22 = mf2_+z2*t2abs;
 
       const Particle::Momentum ak1 = ( z1m*p_f1_-z1p*p_f2_ ), ak2 = ( z2m*p_f1_-z2p*p_f2_ );
       const Particle::Momentum ph_p1 = ak1+z1p*q2, ph_m1 = ak1-z1m*q2;
       const Particle::Momentum ph_p2 = ak2+z2p*q1, ph_m2 = ak2-z2m*q1;
 
       const Particle::Momentum phi1(
         ph_p1.px()/( ph_p1.pt2()+eps12 )-ph_m1.px()/( ph_m1.pt2()+eps12 ),
         ph_p1.py()/( ph_p1.pt2()+eps12 )-ph_m1.py()/( ph_m1.pt2()+eps12 ),
         0.,
         1./( ph_p1.pt2()+eps12 )-1./( ph_m1.pt2()+eps12 )
       );
 
       const Particle::Momentum phi2(
         ph_p2.px()/( ph_p2.pt2()+eps22 )-ph_m2.px()/( ph_m2.pt2()+eps22 ),
         ph_p2.py()/( ph_p2.pt2()+eps22 )-ph_m2.py()/( ph_m2.pt2()+eps22 ),
         0.,
         1./( ph_p2.pt2()+eps22 )-1./( ph_m2.pt2()+eps22 )
       );
 
       const double dot1 = phi1.threeProduct( q1 )/qt1_, cross1 = phi1.crossProduct( q1 )/qt1_;
       const double dot2 = phi2.threeProduct( q2 )/qt2_, cross2 = phi2.crossProduct( q2 )/qt2_;
       CG_DEBUG_LOOP( "PPtoFF:offShell" )
         << "phi1 = " << phi1 << "\n\t"
         << "phi2 = " << phi2 << "\n\t"
         << "(dot):   " << dot1 << " / " << dot2 << "\n\t"
         << "(cross): " << cross1 << " / " << cross2 << ".";
 
       //=================================================================
       //     six terms in Wolfgang's formula for
       //     off-shell gamma gamma --> l^+ l^-
       //=================================================================
 
       const unsigned short imat1 = 1, imat2 = 1;
       const unsigned short itermLL = 1, itermTT = 1, itermLT = 1, itermtt = 1;
 
       const double aux2_1 = itermLL * ( mf2_ + 4.*z1*z1*t1abs ) * phi1.energy2()
                            +itermTT * ( ( z1p*z1p + z1m*z1m )*( dot1*dot1 + cross1*cross1 ) )
                            +itermtt * ( cross1*cross1 - dot1*dot1 )
                            -itermLT * 4.*z1*( z1p-z1m ) * phi1.energy() * q1.threeProduct( phi1 );
 
       const double aux2_2 = itermLL * ( mf2_ + 4.*z2*z2*t2abs ) * phi2.energy2()
                            +itermTT * ( ( z2p*z2p + z2m*z2m )*( dot2*dot2 + cross2*cross2 ) )
                            +itermtt * ( cross2*cross2 - dot2*dot2 )
                            -itermLT * 4.*z2*( z2p-z2m ) * phi2.energy() * q2.threeProduct( phi2 );
 
       //=================================================================
       //     convention of matrix element as in our kt-factorization
       //     for heavy flavours
       //=================================================================
 
       const double amat2_1 = aux2_1*2.*z1*q1.pt2()/( q1.pt2()*q2.pt2() ),
                    amat2_2 = aux2_2*2.*z2*q2.pt2()/( q1.pt2()*q2.pt2() );
 
       //=================================================================
       //     symmetrization
       //=================================================================
 
       CG_DEBUG_LOOP( "PPtoFF:offShell" )
         << "aux2(1/2) = " << aux2_1 << " / " << aux2_2 << "\n\t"
         << "amat2(1/2), amat2 = " << amat2_1 << " / " << amat2_2 << " / " << ( 0.5*( imat1*amat2_1 + imat2*amat2_2 ) ) << ".";
 
       return 0.5*( imat1*amat2_1 + imat2*amat2_2 );
     }
     // register process and define aliases
     REGISTER_PROCESS( pptoll, PPtoFF )
     REGISTER_PROCESS( pptoff, PPtoFF )
   }
 }
-
diff --git a/CepGen/Processes/PPtoFF.h b/CepGen/Processes/PPtoFF.h
index 52d32d1..d5e696c 100644
--- a/CepGen/Processes/PPtoFF.h
+++ b/CepGen/Processes/PPtoFF.h
@@ -1,55 +1,54 @@
 #ifndef CepGen_Processes_PPtoFF_h
 #define CepGen_Processes_PPtoFF_h
 
 #include "CepGen/Processes/GenericKTProcess.h"
 #include "CepGen/Core/ParametersList.h"
 
 namespace CepGen
 {
-  namespace Process
+  namespace process
   {
     /// Compute the matrix element for a CE \f$\gamma\gamma\rightarrow f\bar f\f$ process using \f$k_T\f$-factorization approach
     class PPtoFF : public GenericKTProcess
     {
       public:
         PPtoFF( const ParametersList& params = ParametersList() );
         ProcessPtr clone( const ParametersList& params ) const override { return ProcessPtr( new PPtoFF( params ) ); }
 
       private:
         void preparePhaseSpace() override;
         /// \note IncQQbar in pptoll
         double computeKTFactorisedMatrixElement() override;
         void fillCentralParticlesKinematics() override;
 
         /// Rapidity range for the outgoing fermions
         double onShellME( double shat, double that, double uhat ) const;
         double offShellME( double, double, double, double, double, double, const Particle::Momentum&, const Particle::Momentum& ) const;
 
         /// PDG id of the fermion pair produced
         int pair_;
         int method_;
 
         Limits rap_limits_;
         /// Rapidity of the first outgoing fermion
         double y1_;
         /// Rapidity of the first outgoing fermion
         double y2_;
 
         /// Transverse momentum difference for the two outgoing fermions
         double pt_diff_;
 
         /// Azimuthal angle difference for the two outgoing fermions
         double phi_pt_diff_;
 
         double mf_, mf2_, qf_;
         unsigned short colf_;
         /// First outgoing fermion's momentum
         Particle::Momentum p_f1_;
         /// Second outgoing fermion's momentum
         Particle::Momentum p_f2_;
     };
   }
 }
 
 #endif
-
diff --git a/CepGen/Processes/PPtoWW.cpp b/CepGen/Processes/PPtoWW.cpp
index f2f5871..4ccf458 100644
--- a/CepGen/Processes/PPtoWW.cpp
+++ b/CepGen/Processes/PPtoWW.cpp
@@ -1,394 +1,393 @@
 #include "CepGen/Processes/PPtoWW.h"
 
 #include "CepGen/Event/Event.h"
 
 #include "CepGen/Physics/Constants.h"
 #include "CepGen/Physics/FormFactors.h"
 #include "CepGen/Physics/PDG.h"
 
 #include "CepGen/Core/Exception.h"
 
 #include <assert.h>
 
 #include "CepGen/Processes/ProcessesHandler.h"
 
 namespace CepGen
 {
-  namespace Process
+  namespace process
   {
     const double PPtoWW::mw_ = ParticleProperties::mass( PDG::W );
     const double PPtoWW::mw2_ = PPtoWW::mw_*PPtoWW::mw_;
 
     PPtoWW::PPtoWW( const ParametersList& params ) :
       GenericKTProcess( params, "pptoww", "ɣɣ → W⁺W¯", { { PDG::photon, PDG::photon } }, { PDG::W, PDG::W } ),
       method_( params.get<int>( "method", 1 ) ),
       pol_state_( (Polarisation)params.get<int>( "polarisationStates", 0 ) ),
       y1_( 0. ), y2_( 0. ), pt_diff_( 0. ), phi_pt_diff_( 0. )
     {}
 
     void
     PPtoWW::preparePhaseSpace()
     {
       registerVariable( y1_, Mapping::linear, cuts_.cuts.central.rapidity_single, { -6., 6. }, "First outgoing W rapidity" );
       registerVariable( y2_, Mapping::linear, cuts_.cuts.central.rapidity_single, { -6., 6. }, "Second outgoing W rapidity" );
       registerVariable( pt_diff_, Mapping::linear, cuts_.cuts.central.pt_diff, { 0., 500. }, "Ws transverse momentum difference" );
       registerVariable( phi_pt_diff_, Mapping::linear, cuts_.cuts.central.phi_pt_diff, { 0., 2.*M_PI }, "Ws azimuthal angle difference" );
 
       switch ( pol_state_ ) {
         case Polarisation::LL: pol_w1_ = pol_w2_ = { 0 }; break;
         case Polarisation::LT: pol_w1_ = { 0 }; pol_w2_ = { -1, 1 }; break;
         case Polarisation::TL: pol_w1_ = { -1, 1 }; pol_w2_ = { 0 }; break;
         case Polarisation::TT: pol_w1_ = pol_w2_ = { -1, 1 }; break;
         default:
         case Polarisation::full: pol_w1_ = pol_w2_ = { -1, 0, 1 }; break;
       }
       CG_DEBUG( "PPtoWW:mode" )
         << "matrix element computation method: " << method_ << ".";
     }
 
     double
     PPtoWW::computeKTFactorisedMatrixElement()
     {
       //=================================================================
       //     matrix element computation
       //=================================================================
       //const double stild = s_/2.*(1+sqrt(1.-(4*pow(mp2_, 2))/s_*s_));
 
       // Inner photons
       const double q1tx = qt1_*cos( phi_qt1_ ), q1ty = qt1_*sin( phi_qt1_ ),
                    q2tx = qt2_*cos( phi_qt2_ ), q2ty = qt2_*sin( phi_qt2_ );
       CG_DEBUG_LOOP( "PPtoWW:qt" )
         << "q1t(x/y) = " << q1tx << " / " << q1ty << "\n\t"
         << "q2t(x/y) = " << q2tx << " / " << q2ty << ".";
 
       // Two-photon system
       const double ptsumx = q1tx+q2tx,
                    ptsumy = q1ty+q2ty,
                    ptsum = sqrt( ptsumx*ptsumx+ptsumy*ptsumy );
 
       const double ptdiffx = pt_diff_*cos( phi_pt_diff_ ),
                    ptdiffy = pt_diff_*sin( phi_pt_diff_ );
 
       // Outgoing leptons
       const double pt1x = ( ptsumx+ptdiffx )*0.5, pt1y = ( ptsumy+ptdiffy )*0.5, pt1 = std::hypot( pt1x, pt1y ),
                    pt2x = ( ptsumx-ptdiffx )*0.5, pt2y = ( ptsumy-ptdiffy )*0.5, pt2 = std::hypot( pt2x, pt2y );
 
       if ( cuts_.cuts.central_particles.count( PDG::W ) > 0
         && cuts_.cuts.central_particles.at( PDG::W ).pt_single.valid() ) {
         const Limits pt_limits = cuts_.cuts.central_particles.at( PDG::W ).pt_single;
         if ( !pt_limits.passes( pt1 ) || !pt_limits.passes( pt2 ) )
           return 0.;
       }
 
       // transverse mass for the two leptons
       const double amt1 = sqrt( pt1*pt1+mw2_ ),
                    amt2 = sqrt( pt2*pt2+mw2_ );
 
       //=================================================================
       //     a window in two-boson invariant mass
       //=================================================================
 
       const double invm = sqrt( amt1*amt1 + amt2*amt2 + 2.*amt1*amt2*cosh( y1_-y2_ ) - ptsum*ptsum );
       if ( !cuts_.cuts.central.mass_sum.passes( invm ) )
         return 0.;
 
       //=================================================================
       //     a window in transverse momentum difference
       //=================================================================
 
       if ( !cuts_.cuts.central.pt_diff.passes( fabs( pt1-pt2 ) ) )
         return 0.;
 
       //=================================================================
       //     a window in rapidity distance
       //=================================================================
 
       if ( !cuts_.cuts.central.rapidity_diff.passes( fabs( y1_-y2_ ) ) )
         return 0.;
 
       //=================================================================
       //     auxiliary quantities
       //=================================================================
 
       const double alpha1 = amt1/sqs_*exp( y1_ ), beta1  = amt1/sqs_*exp( -y1_ ),
                    alpha2 = amt2/sqs_*exp( y2_ ), beta2  = amt2/sqs_*exp( -y2_ );
 
       CG_DEBUG_LOOP( "PPtoWW:sudakov" )
         << "Sudakov parameters:\n\t"
         << "  alpha1/2 = " << alpha1 << " / " << alpha2 << "\n\t"
         << "   beta1/2 = " << beta1 << " / " << beta2 << ".";
 
       const double q1t2 = q1tx*q1tx+q1ty*q1ty, q2t2 = q2tx*q2tx+q2ty*q2ty;
 
       const double x1 = alpha1+alpha2, x2 = beta1+beta2;
 
       const double z1p = alpha1/x1, z1m = alpha2/x1,
                    z2p = beta1 /x2, z2m = beta2 /x2;
       CG_DEBUG_LOOP( "PPtoWW:zeta" )
         << "z(1/2)p = " << z1p << " / " << z2p << "\n\t"
         << "z(1/2)m = " << z1m << " / " << z2m << ".";
 
       if ( x1 > 1. || x2 > 1. )
         return 0.; // sanity check
 
       // FIXME FIXME FIXME
       const double ak10 = event_->getOneByRole( Particle::IncomingBeam1 ).energy(),
                    ak1z = event_->getOneByRole( Particle::IncomingBeam1 ).momentum().pz(),
                    ak20 = event_->getOneByRole( Particle::IncomingBeam2 ).energy(),
                    ak2z = event_->getOneByRole( Particle::IncomingBeam2 ).momentum().pz();
       CG_DEBUG_LOOP( "PPtoWW:incoming" )
         << "incoming particles: p1: " << ak1z << " / " << ak10 << "\n\t"
         << "                    p2: " << ak2z << " / " << ak20 << ".";
 
       //=================================================================
       //     additional conditions for energy-momentum conservation
       //=================================================================
 
       const double s1_eff = x1*s_-qt1_*qt1_, s2_eff = x2*s_-qt2_*qt2_;
       CG_DEBUG_LOOP( "PPtoWW:central" )
         << "s(1/2)_eff = " << s1_eff << " / " << s2_eff << " GeV^2\n\t"
         << "diboson invariant mass = " << invm << " GeV";
 
       if ( ( cuts_.mode == KinematicsMode::ElasticInelastic
           || cuts_.mode == KinematicsMode::InelasticInelastic )
         && ( sqrt( s1_eff ) <= ( MY_+invm ) ) )
         return 0.;
       if ( ( cuts_.mode == KinematicsMode::InelasticElastic
           || cuts_.mode == KinematicsMode::InelasticInelastic )
         && ( sqrt( s2_eff ) <= ( MX_+invm ) ) )
         return 0.;
 
       //const double qcaptx = pcaptx, qcapty = pcapty;
 
       //=================================================================
       //     four-momenta of the outgoing protons (or remnants)
       //=================================================================
 
       const double px_plus  = ( 1.-x1 )*fabs( ak1z )*M_SQRT2,
                    px_minus = ( MX_*MX_ + q1t2 )*0.5/px_plus;
 
       const double py_minus = ( 1.-x2 )*fabs( ak2z )*M_SQRT2, // warning! sign of pz??
                    py_plus  = ( MY_*MY_ + q2t2 )*0.5/py_minus;
 
       CG_DEBUG_LOOP( "PPtoWW:pxy" )
         << "px± = " << px_plus << " / " << px_minus << "\n\t"
         << "py± = " << py_plus << " / " << py_minus << ".";
 
       PX_ = Particle::Momentum( -q1tx, -q1ty, ( px_plus-px_minus )*M_SQRT1_2, ( px_plus+px_minus )*M_SQRT1_2 );
       PY_ = Particle::Momentum( -q2tx, -q2ty, ( py_plus-py_minus )*M_SQRT1_2, ( py_plus+py_minus )*M_SQRT1_2 );
 
       CG_DEBUG_LOOP( "PPtoWW:remnants" )
         << "First remnant:  " << PX_ << ", mass = " << PX_.mass() << "\n\t"
         << "Second remnant: " << PY_ << ", mass = " << PY_.mass() << ".";
 
       /*assert( fabs( PX_.mass()-MX_ ) < 1.e-6 );
       assert( fabs( PY_.mass()-MY_ ) < 1.e-6 );*/
 
       //=================================================================
       //     four-momenta squared of the virtual photons
       //=================================================================
 
       const double ww = 0.5 * ( 1.+sqrt( 1.-4.*mp2_/s_ ) );
 
       // FIXME FIXME FIXME /////////////////////
       const Particle::Momentum q1(
         q1tx, q1ty,
         +0.5 * x1*ww*sqs_*( 1.-q1t2/x1/x1/ww/ww/s_ ),
         +0.5 * x1*ww*sqs_*( 1.+q1t2/x1/x1/ww/ww/s_ ) );
       const Particle::Momentum q2(
         q2tx, q2ty,
         -0.5 * x2*ww*sqs_*( 1.-q2t2/x2/x2/ww/ww/s_ ),
         +0.5 * x2*ww*sqs_*( 1.+q2t2/x2/x2/ww/ww/s_ ) );
       //////////////////////////////////////////
 
       CG_DEBUG_LOOP( "PPtoWW:partons" )
         << "First photon*:  " << q1 << ", mass2 = " << q1.mass2() << "\n\t"
         << "Second photon*: " << q2 << ", mass2 = " << q2.mass2() << ".";
       //const double q12 = q1.mass2(), q22 = q2.mass2();
 
       //=================================================================
       //     four-momenta of the outgoing W^+ and W^-
       //=================================================================
 
       p_w1_ = Particle::Momentum( pt1x, pt1y, alpha1*ak1z + beta1*ak2z, alpha1*ak10 + beta1*ak20 );
       p_w2_ = Particle::Momentum( pt2x, pt2y, alpha2*ak1z + beta2*ak2z, alpha2*ak10 + beta2*ak20 );
 
       CG_DEBUG_LOOP( "PPtoWW:central" )
         << "First W:  " << p_w1_ << ", mass = " << p_w1_.mass() << "\n\t"
         << "Second W: " << p_w2_ << ", mass = " << p_w2_.mass() << ".";
 
       //assert( fabs( p_w1_.mass()-event_->getByRole( Particle::CentralSystem )[0].mass() ) < 1.e-6 );
       //assert( fabs( p_w2_.mass()-event_->getByRole( Particle::CentralSystem )[1].mass() ) < 1.e-6 );
 
       //=================================================================
       //     Mendelstam variables
       //=================================================================
 
       //const double shat = s_*x1*x2; // ishat = 1 (approximation)
       const double shat = ( q1+q2 ).mass2(); // ishat = 2 (exact formula)
 
       const double that1 = ( q1-p_w1_ ).mass2(), that2 = ( q2-p_w2_ ).mass2();
       const double uhat1 = ( q1-p_w2_ ).mass2(), uhat2 = ( q2-p_w1_ ).mass2();
       CG_DEBUG_LOOP( "PPtoWW" )
         << "that(1/2) = " << that1 << " / " << that2 << "\n\t"
         << "uhat(1/2) = " << uhat1 << " / " << uhat2 << ".";
 
       //const double mll = sqrt( shat );
 
       const double that = 0.5*( that1+that2 ), uhat = 0.5*( uhat1+uhat2 );
 
       //=================================================================
       //     matrix elements
       //=================================================================
       double amat2 = 0.;
 
       //=================================================================
       //     How matrix element is calculated
       //=================================================================
 
       CG_DEBUG_LOOP( "PPtoWW" )
         << "matrix element mode: " << method_ << ".";
 
       //=================================================================
       //     matrix element for gamma gamma --> W^+ W^-
       //     (Denner+Dittmaier+Schuster)
       //     (work in collaboration with C. Royon)
       //=================================================================
       if ( method_ == 0 )
         amat2 = onShellME( shat, that, uhat );
 
       //=================================================================
       //     off-shell Nachtmann formulae
       //=================================================================
       else if ( method_ == 1 )
         amat2 = offShellME( shat, that, uhat, phi_qt1_+phi_qt2_, phi_qt1_-phi_qt2_ );
 
       if ( amat2 <= 0. )
         return 0.;
 
       //============================================
       //     unintegrated photon distributions
       //============================================
 
       const std::pair<double,double> fluxes
         = GenericKTProcess::incomingFluxes( x1, q1t2, x2, q2t2 );
 
       CG_DEBUG_LOOP( "PPtoWW:fluxes" )
         << "Incoming photon fluxes for (x/kt2) = "
         << "(" << x1 << "/" << q1t2 << "), "
         << "(" << x2 << "/" << q2t2 << "):\n\t"
         << fluxes.first << ", " << fluxes.second << ".";
 
       //=================================================================
       //     factor 2.*pi from integration over phi_sum
       //     factor 1/4 from jacobian of transformations
       //     factors 1/pi and 1/pi due to integration over
       //       d^2 kappa_1 d^2 kappa_2 instead d kappa_1^2 d kappa_2^2
       //=================================================================
 
       const double aintegral = amat2 / ( 16.*M_PI*M_PI*( x1*x2*s_ )*( x1*x2*s_ ) )
                              * fluxes.first*M_1_PI * fluxes.second*M_1_PI * 0.25
                              * Constants::GeV2toBarn;
       /*const double aintegral = amat2 / ( 16.*M_PI*M_PI*x1*x1*x2*x2*s_*s_ )
                              * fluxes.first*M_1_PI * fluxes.second*M_1_PI
                              * Constants::GeV2toBarn * 0.25;*/
 
       //=================================================================
       return aintegral*qt1_*qt2_*pt_diff_;
       //=================================================================
     }
 
     void
     PPtoWW::fillCentralParticlesKinematics()
     {
       // randomise the charge of the outgoing leptons
       short sign = ( drand() > 0.5 ) ? +1 : -1;
 
       //=================================================================
       //     first outgoing lepton
       //=================================================================
       Particle& ow1 = event_->getByRole( Particle::CentralSystem )[0];
       ow1.setPdgId( ow1.pdgId(), sign );
       ow1.setStatus( Particle::Status::Undecayed );
       ow1.setMomentum( p_w1_ );
 
       //=================================================================
       //     second outgoing lepton
       //=================================================================
       Particle& ow2 = event_->getByRole( Particle::CentralSystem )[1];
       ow2.setPdgId( ow2.pdgId(), -sign );
       ow2.setStatus( Particle::Status::Undecayed );
       ow2.setMomentum( p_w2_ );
     }
 
     double
     PPtoWW::onShellME( double shat, double that, double uhat )
     {
       const double mw4 = mw2_*mw2_;
 
       const double term1 = 2.*shat * ( 2.*shat+3.*mw2_ ) / ( 3.*( mw2_-that )*( mw2_-uhat ) );
       const double term2 = 2.*shat*shat * ( shat*shat + 3.*mw4 ) / ( 3.*pow( mw2_-that, 2 )*pow( mw2_-uhat, 2 ) );
 
       const double auxil_gamgam = 1.-term1+term2;
       const double beta = sqrt( 1.-4.*mw2_/shat );
 
       return 3.*Constants::alphaEM*Constants::alphaEM*beta / ( 2.*shat ) * auxil_gamgam / ( beta/( 64.*M_PI*M_PI*shat ) );
     }
 
     double
     PPtoWW::offShellME( double shat, double that, double uhat, double phi_sum, double phi_diff )
     {
       const double e2 = 4.*M_PI*Constants::alphaEM;
 
       double amat2_0 = 0., amat2_1 = 0., amat2_interf = 0.;
       for ( const auto lam3 : pol_w1_ )
         for ( const auto lam4 : pol_w2_ ) {
           double ampli_pp = amplitudeWW( shat, that, uhat, +1, +1, lam3, lam4 );
           double ampli_mm = amplitudeWW( shat, that, uhat, -1, -1, lam3, lam4 );
           double ampli_pm = amplitudeWW( shat, that, uhat, +1, -1, lam3, lam4 );
           double ampli_mp = amplitudeWW( shat, that, uhat, -1, +1, lam3, lam4 );
           amat2_0 += ampli_pp*ampli_pp + ampli_mm*ampli_mm + 2.*cos( 2.*phi_diff )*ampli_pp*ampli_mm;
           amat2_1 += ampli_pm*ampli_pm + ampli_mp*ampli_mp + 2.*cos( 2.*phi_sum  )*ampli_pm*ampli_mp;
           amat2_interf -= 2.*( cos( phi_sum+phi_diff )*( ampli_pp*ampli_pm+ampli_mm*ampli_mp )
                               +cos( phi_sum-phi_diff )*( ampli_pp*ampli_mp+ampli_mm*ampli_pm ) );
         }
       return e2*e2*( amat2_0+amat2_1+amat2_interf );
     }
 
     double
     PPtoWW::amplitudeWW( double shat, double that, double uhat, short lam1, short lam2, short lam3, short lam4 )
     {
       //--- first compute some kinematic variables
       const double cos_theta = ( that-uhat ) / shat / sqrt( 1.+1.e-10-4.*mw2_/shat ),
                    cos_theta2 = cos_theta*cos_theta;
       const double sin_theta2 = 1.-cos_theta2,
                    sin_theta = sqrt( sin_theta2 );
       const double beta = sqrt( 1.-4.*mw2_/shat ), beta2 = beta*beta;
       const double inv_gamma = sqrt( 1.-beta2 ), gamma = 1./inv_gamma,
                    gamma2 = gamma*gamma, inv_gamma2 = inv_gamma*inv_gamma;
       const double invA = 1./( 1.-beta2*cos_theta2 );
 
       //--- per-helicity amplitude
       // longitudinal-longitudinal
       if ( lam3 == 0 && lam4 == 0 )
         return invA*inv_gamma2*( ( gamma2+1. )*( 1.-lam1*lam2 )*sin_theta2 - ( 1.+lam1*lam2 ) );
       // transverse-longitudinal
       if ( lam4 == 0 )
         return invA*( -M_SQRT2*inv_gamma*( lam1-lam2 )*( 1.+lam1*lam3*cos_theta )*sin_theta );
       // longitudinal-transverse
       if ( lam3 == 0 )
         return invA*( -M_SQRT2*inv_gamma*( lam2-lam1 )*( 1.+lam2*lam4*cos_theta )*sin_theta );
       // transverse-transverse
       if ( lam3 != 0 && lam4 != 0 )
         return -0.5*invA*( 2.*beta*( lam1+lam2 )*( lam3+lam4 )
                           -inv_gamma2*( 1.+lam3*lam4 )*( 2.*lam1*lam2+( 1.-lam1*lam2 ) * cos_theta2 )
                           +( 1.+lam1*lam2*lam3*lam4 )*( 3.+lam1*lam2 )
                           +2.*( lam1-lam2 )*( lam3-lam4 )*cos_theta
                           +( 1.-lam1*lam2 )*( 1.-lam3*lam4 )*cos_theta2 );
       return 0.;
     }
     // register process and define aliases
     REGISTER_PROCESS( pptoww, PPtoWW )
   }
 }
-
diff --git a/CepGen/Processes/PPtoWW.h b/CepGen/Processes/PPtoWW.h
index 0fb2e68..49a10c1 100644
--- a/CepGen/Processes/PPtoWW.h
+++ b/CepGen/Processes/PPtoWW.h
@@ -1,59 +1,58 @@
 #ifndef CepGen_Processes_PPtoWW_h
 #define CepGen_Processes_PPtoWW_h
 
 #include "CepGen/Processes/GenericKTProcess.h"
 #include "CepGen/Core/ParametersList.h"
 
 namespace CepGen
 {
-  namespace Process
+  namespace process
   {
     /// \brief Compute the matrix element for a CE \f$\gamma\gamma\rightarrow W^+W^-\f$ process using \f$k_T\f$-factorization approach
     /// \note The full theoretical description of this process definition may be found in \cite Luszczak:2018ntp.
     class PPtoWW : public GenericKTProcess
     {
       public:
         PPtoWW( const ParametersList& params = ParametersList() );
         ProcessPtr clone( const ParametersList& params ) const override { return ProcessPtr( new PPtoWW( params ) ); }
         enum class Polarisation { full = 0, LL = 1, LT = 2, TL = 3, TT = 4 };
 
       private:
         static const double mw_, mw2_;
 
         void preparePhaseSpace() override;
         double computeKTFactorisedMatrixElement() override;
         void fillCentralParticlesKinematics() override;
 
         double amplitudeWW( double shat, double that, double uhat, short lam1, short lam2, short lam3, short lam4 );
         double onShellME( double shat, double that, double uhat );
         double offShellME( double shat, double that, double uhat, double phi_sum, double phi_diff );
 
         int method_;
         Polarisation pol_state_;
         std::vector<short> pol_w1_, pol_w2_;
 
         /// Rapidity range for the outgoing W bosons
         Limits rap_limits_;
         /// Rapidity of the first outgoing W boson
         double y1_;
         /// Rapidity of the first outgoing W boson
         double y2_;
 
         Limits ptdiff_limits_;
         /// Transverse momentum difference for the two outgoing W bosons
         double pt_diff_;
 
         Limits phi_pt_diff_limits_;
         /// Azimuthal angle difference for the two outgoing W bosons
         double phi_pt_diff_;
 
         /// First outgoing W boson's momentum
         Particle::Momentum p_w1_;
         /// Second outgoing W boson's momentum
         Particle::Momentum p_w2_;
     };
   }
 }
 
 #endif
-
diff --git a/CepGen/Processes/ProcessesHandler.cpp b/CepGen/Processes/ProcessesHandler.cpp
index b5c8ab4..312f2b8 100644
--- a/CepGen/Processes/ProcessesHandler.cpp
+++ b/CepGen/Processes/ProcessesHandler.cpp
@@ -1,44 +1,44 @@
 #include "CepGen/Core/Exception.h"
 #include "CepGen/Core/utils.h"
 #include "CepGen/Core/ParametersList.h"
 
 #include "CepGen/Processes/PPtoFF.h"
 #include "CepGen/Processes/ProcessesHandler.h"
 
 #include <sstream>
 
 namespace CepGen
 {
   ProcessesHandler&
   ProcessesHandler::get()
   {
     static ProcessesHandler instance;
     return instance;
   }
 
   void
-  ProcessesHandler::registerProcess( const std::string& name, const Process::GenericProcess* proc )
+  ProcessesHandler::registerProcess( const std::string& name, const process::GenericProcess* proc )
   {
     map_[name].reset( proc );
     CG_DEBUG( "ProcessesHandler" ) << "Process name \"" << name << "\" registered in database.";
   }
 
   void
   ProcessesHandler::dump() const
   {
     std::ostringstream oss;
     for ( const auto& p : map_ )
       oss << " '" << p.first << "'";
     CG_INFO( "ProcessesHandler:dump" )
       << "List of process(es) handled in the database:" << oss.str();
   }
 
   ProcessPtr
   ProcessesHandler::build( const std::string& name, const ParametersList& params ) const
   {
     if ( map_.count( name ) == 0 )
       throw CG_FATAL( "ProcessesHandler:build" )
         << "Failed to retrieve a process with name \"" << name << "\"!";
     return map_.at( name )->clone( params );
   }
 }
diff --git a/CepGen/Processes/ProcessesHandler.h b/CepGen/Processes/ProcessesHandler.h
index bef448b..f7c23b7 100644
--- a/CepGen/Processes/ProcessesHandler.h
+++ b/CepGen/Processes/ProcessesHandler.h
@@ -1,40 +1,39 @@
 #ifndef CepGen_Processes_ProcessesHandler_h
 #define CepGen_Processes_ProcessesHandler_h
 
 #include "CepGen/Processes/GenericProcess.h"
 #include <unordered_map>
 #include <memory>
 
 #define BUILDERNM( obj ) obj ## Builder
 #define STRINGIFY( name ) #name
 #define REGISTER_PROCESS( name, obj ) \
   struct BUILDERNM( name ) { \
     BUILDERNM( name )() { CepGen::ProcessesHandler::get().registerProcess( STRINGIFY( name ), new obj ); } }; \
   static BUILDERNM( name ) g ## name;
 
 namespace CepGen
 {
   class ParametersList;
-  //namespace Process { class GenericProcess; }
+  //namespace process { class GenericProcess; }
   class ProcessesHandler
   {
     public:
       static ProcessesHandler& get();
       ~ProcessesHandler() = default;
 
-      void registerProcess( const std::string& name, const CepGen::Process::GenericProcess* );
+      void registerProcess( const std::string& name, const CepGen::process::GenericProcess* );
       ProcessPtr build( const std::string& name, const ParametersList& ) const;
       void dump() const;
 
     private:
       explicit ProcessesHandler() = default;
-      std::unordered_map<std::string, std::unique_ptr<const Process::GenericProcess> > map_;
+      std::unordered_map<std::string, std::unique_ptr<const process::GenericProcess> > map_;
 
     public:
       ProcessesHandler( const ProcessesHandler& ) = delete;
       void operator=( const ProcessesHandler& ) = delete;
   };
 }
 
 #endif
-
diff --git a/test/cepgen.cpp b/test/cepgen.cpp
index f036e0a..9cd8999 100644
--- a/test/cepgen.cpp
+++ b/test/cepgen.cpp
@@ -1,74 +1,74 @@
 //--- steering cards
 #include "CepGen/Cards/PythonHandler.h"
 #include "CepGen/Cards/LpairHandler.h"
 
 #include "CepGen/Generator.h"
 #include "CepGen/Core/Exception.h"
 
 //--- necessary include to build the default run
 #include "CepGen/Processes/GamGamLL.h"
 #include "CepGen/Physics/PDG.h"
 
 #include "abort.h"
 
 #include <iostream>
 
 using namespace std;
 
 /**
  * Main caller for this MC generator.
  *  * loads the configuration files' variables if passed as an argument,
  *    or a default LPAIR-like configuration,
  *  * launches the cross-section computation and the events generation.
  * \author Laurent Forthomme <laurent.forthomme@cern.ch>
  */
 int main( int argc, char* argv[] ) {
   //--- first start by defining the generator object
   CepGen::Generator gen;
 
   if ( argc < 2 ) {
     CG_INFO( "main" ) << "No config file provided. Setting the default parameters.";
 
     //--- default run: LPAIR elastic ɣɣ → µ⁺µ¯ at 13 TeV
     CepGen::ParametersList pgen;
     pgen.set<int>( "pair", (int)CepGen::PDG::muon );
-    gen.parameters->setProcess( new CepGen::Process::GamGamLL( pgen ) );
+    gen.parameters->setProcess( new CepGen::process::GamGamLL( pgen ) );
     gen.parameters->kinematics.mode = CepGen::KinematicsMode::ElasticElastic;
     gen.parameters->kinematics.cuts.central.pt_single.min() = 15.;
     gen.parameters->kinematics.cuts.central.eta_single = { -2.5, 2.5 };
     gen.parameters->generation.enabled = true;
     gen.parameters->generation.maxgen = 1e3;
   }
   else {
     CG_INFO( "main" ) << "Reading config file stored in " << argv[1] << ".";
     const std::string extension = CepGen::Cards::Handler::getExtension( argv[1] );
     if ( extension == "card" )
       gen.setParameters( CepGen::Cards::LpairHandler( argv[1] ).parameters() );
 #ifdef PYTHON
     else if ( extension == "py" )
       gen.setParameters( CepGen::Cards::PythonHandler( argv[1] ).parameters() );
 #endif
     else
       throw CG_FATAL( "main" ) << "Unrecognized steering card extension: ." << extension << "!";
   }
 
   //--- list all parameters
   CG_INFO( "main" ) << gen.parameters.get();
 
   AbortHandler ctrl_c;
 
   try {
     //--- let there be a cross-section...
     double xsec = 0., err = 0.;
     gen.computeXsection( xsec, err );
 
     if ( gen.parameters->generation.enabled )
       //--- events generation starts here
       // (one may use a callback function)
       gen.generate();
   } catch ( const CepGen::RunAbortedException& e ) {
     CG_INFO( "main" ) << "Run aborted!";
   }
 
   return 0;
 }